Index: django/contrib/localflavor/be/be_regions.py
===================================================================
--- django/contrib/localflavor/be/be_regions.py	(revision 0)
+++ django/contrib/localflavor/be/be_regions.py	(revision 0)
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+from django.utils.translation import ugettext_lazy as _
+
+# ISO codes
+REGION_CHOICES = (
+    ('BRU', _('Brussels Capital Region')),
+    ('VLG', _('Flemish Region')),
+    ('WAL', _('Wallonia'))
+)
+
Index: django/contrib/localflavor/be/be_provinces.py
===================================================================
--- django/contrib/localflavor/be/be_provinces.py	(revision 0)
+++ django/contrib/localflavor/be/be_provinces.py	(revision 0)
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from django.utils.translation import ugettext_lazy as _
+
+# ISO codes
+PROVINCE_CHOICES = (
+    ('VAN', _('Antwerp')),
+    ('BRU', _('Brussels')),
+    ('VOV', _('East Flanders')),
+    ('VBR', _('Flemish Brabant')),
+    ('WHT', _('Hainaut')),
+    ('WLG', _('Liege')),
+    ('VLI', _('Limburg')),
+    ('WLX', _('Luxembourg')),
+    ('WNA', _('Namur')),
+    ('WBR', _('Walloon Brabant')),
+    ('VWV', _('West Flanders'))
+)
+
Index: django/contrib/localflavor/be/__init__.py
===================================================================
Index: django/contrib/localflavor/be/forms.py
===================================================================
--- django/contrib/localflavor/be/forms.py	(revision 0)
+++ django/contrib/localflavor/be/forms.py	(revision 0)
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+"""
+Belgium-specific Form helpers
+"""
+
+from django.core.validators import EMPTY_VALUES
+from django.forms import ValidationError
+from django.forms.fields import RegexField, Select
+from django.utils.translation import ugettext_lazy as _
+import re
+
+class BEPostalCodeField(RegexField):
+    """
+    A form field that validates its input as a belgium postal code.
+    
+    Belgium postal code is a 4 digits string. The first digit indicates
+    the province (except for the 3ddd numbers that are shared by the
+    eastern part of Flemish Brabant and Limburg and the and 1ddd that
+    are shared by the Brussels Capital Region, the western part of
+    Flemish Brabant and Walloon Brabant)
+    """
+    default_error_messages = {
+        'invalid': _('Enter a valid postal code in the range and format \
+1XXX - 9XXX.'),
+    }
+
+    def __init__(self, *args, **kwargs):
+        super(BEPostalCodeField, self).__init__(
+                r'^[1-9]\d{3}$',
+                max_length=None, min_length=None, *args, **kwargs)
+
+class BEPhoneNumberField(RegexField):
+    """
+    A form field that validates its input as a belgium phone number.
+
+    Landlines have a seven-digit subscriber number and a one-digit area code,
+    while smaller cities have a six-digit subscriber number and a two-digit 
+    area code. Cell phones have a six-digit subscriber number and a two-digit 
+    area code preceeded by the number 4.
+    0d ddd dd dd, 0d/ddd.dd.dd, 0d.ddd.dd.dd, 
+    0dddddddd - dialling a bigger city
+    0dd dd dd dd, 0dd/dd.dd.dd, 0dd.dd.dd.dd, 
+    0dddddddd - dialling a smaller city
+    04dd ddd dd dd, 04dd/ddd.dd.dd, 
+    04dd.ddd.dd.dd, 04ddddddddd - dialling a mobile number
+    """
+    default_error_messages = {
+        'invalid': _('Enter a valid phone number in one of the formats \
+0x xxx xx xx, 0xx xx xx xx, 04xx xx xx xx, 0x/xxx.xx.xx, 0xx/xx.xx.xx, \
+04xx/xx.xx.xx, 0x.xxx.xx.xx, 0xx.xx.xx.xx, 04xx.xx.xx.xx, 0xxxxxxxx, \
+04xxxxxxxx.'),
+    }
+
+    def __init__(self, *args, **kwargs):
+        super(BEPhoneNumberField, self).__init__(r'^[0]\d{1}[/. ]?\d{3}[. ]\d{2}[. ]?\d{2}$|^[0]\d{2}[/. ]?\d{2}[. ]?\d{2}[. ]?\d{2}$|^[0][4]\d{2}[/. ]?\d{2}[. ]?\d{2}[. ]?\d{2}$',
+            max_length=None, min_length=None, *args, **kwargs)
+
+class BERegionSelect(Select):
+    """
+    A Select widget that uses a list of belgium regions as its choices.
+    """
+    def __init__(self, attrs=None):
+        from be_regions import REGION_CHOICES
+        super(BERegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
+
+class BEProvinceSelect(Select):
+    """
+    A Select widget that uses a list of belgium provinces as its choices.
+    """
+    def __init__(self, attrs=None):
+        from be_provinces import PROVINCE_CHOICES
+        super(BEProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
+
Index: tests/regressiontests/forms/tests.py
===================================================================
--- tests/regressiontests/forms/tests.py	(revision 13984)
+++ tests/regressiontests/forms/tests.py	(working copy)
@@ -40,6 +40,7 @@
 from fields import FieldsTests
 from validators import TestFieldWithValidators
 from widgets import WidgetTests, ClearableFileInputTests
+from localflavor.be import BETests
 
 from input_formats import *
 
Index: tests/regressiontests/forms/localflavor/be.py
===================================================================
--- tests/regressiontests/forms/localflavor/be.py	(revision 0)
+++ tests/regressiontests/forms/localflavor/be.py	(revision 0)
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+# Tests for the contrib/localflavor/ BE form fields.
+
+from django.test import TestCase
+from django.forms import *
+
+from django.contrib.localflavor.be.forms import BEPostalCodeField, BEPhoneNumberField, BERegionSelect, BEProvinceSelect
+
+class BETests(TestCase):
+    """
+    Test case to validate BE localflavor
+    """
+    def assertRaisesErrorWithMessage(self, error, message, callable, *args, **kwargs):
+        self.assertRaises(error, callable, *args, **kwargs)
+        try:
+            callable(*args, **kwargs)
+        except error, e:
+            self.assertEqual(message, str(e))
+
+    def test_postal_code_field(self):
+        f = BEPostalCodeField()
+        self.assertEqual(u'1451', f.clean('1451'))
+        self.assertEqual(u'2540', f.clean('2540'))
+        err_message = "[u'Enter a valid postal code in the range and format 1XXX - 9XXX.']"
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '0287')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '14309')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '873')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '35 74')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '859A')
+        err_message = "[u'This field is required.']"
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '')
+        f = BEPostalCodeField(required=False)
+        self.assertEqual(u'1451', f.clean('1451'))
+        self.assertEqual(u'2540', f.clean('2540'))
+        self.assertEqual(u'', f.clean(''))
+        err_message = "[u'Enter a valid postal code in the range and format 1XXX - 9XXX.']"
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '0287')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '14309')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '873')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '35 74')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '859A')
+
+    def test_phone_number_field(self):
+        f = BEPhoneNumberField()
+        self.assertEqual(u'01 234 56 78', f.clean('01 234 56 78'))
+        self.assertEqual(u'01/234.56.78', f.clean('01/234.56.78'))
+        self.assertEqual(u'01.234.56.78', f.clean('01.234.56.78'))
+        self.assertEqual(u'012 34 56 78', f.clean('012 34 56 78'))
+        self.assertEqual(u'012/34.56.78', f.clean('012/34.56.78'))
+        self.assertEqual(u'012.34.56.78', f.clean('012.34.56.78'))
+        self.assertEqual(u'0412 34 56 78', f.clean('0412 34 56 78'))
+        self.assertEqual(u'0412/34.56.78', f.clean('0412/34.56.78'))
+        self.assertEqual(u'0412.34.56.78', f.clean('0412.34.56.78'))
+        self.assertEqual(u'012345678', f.clean('012345678'))
+        self.assertEqual(u'0412345678', f.clean('0412345678'))
+        err_message = "[u'Enter a valid phone number in one of the formats 0x xxx xx xx, 0xx xx xx xx, 04xx xx xx xx, 0x/xxx.xx.xx, 0xx/xx.xx.xx, 04xx/xx.xx.xx, 0xxxxxxxx, 04xxxxxxxx, 0x.xxx.xx.xx, 0xx.xx.xx.xx, 04xx.xx.xx.xx.']"
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '01234567')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '12/345.67.89')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/345.678.90')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/34.56.789')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '0123/45.67.89')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/345 678 90')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/34 56 789')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012.34 56 789')
+        err_message = "[u'This field is required.']"
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '')
+        f = BEPhoneNumberField(required=False)
+        self.assertEqual(u'01 234 56 78', f.clean('01 234 56 78'))
+        self.assertEqual(u'01/234.56.78', f.clean('01/234.56.78'))
+        self.assertEqual(u'01.234.56.78', f.clean('01.234.56.78'))
+        self.assertEqual(u'012 34 56 78', f.clean('012 34 56 78'))
+        self.assertEqual(u'012/34.56.78', f.clean('012/34.56.78'))
+        self.assertEqual(u'012.34.56.78', f.clean('012.34.56.78'))
+        self.assertEqual(u'0412 34 56 78', f.clean('0412 34 56 78'))
+        self.assertEqual(u'0412/34.56.78', f.clean('0412/34.56.78'))
+        self.assertEqual(u'0412.34.56.78', f.clean('0412.34.56.78'))
+        self.assertEqual(u'012345678', f.clean('012345678'))
+        self.assertEqual(u'0412345678', f.clean('0412345678'))
+        self.assertEqual(u'', f.clean(''))
+        err_message = "[u'Enter a valid phone number in one of the formats 0x xxx xx xx, 0xx xx xx xx, 04xx xx xx xx, 0x/xxx.xx.xx, 0xx/xx.xx.xx, 04xx/xx.xx.xx, 0xxxxxxxx, 04xxxxxxxx, 0x.xxx.xx.xx, 0xx.xx.xx.xx, 04xx.xx.xx.xx.']"
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '01234567')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '12/345.67.89')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/345.678.90')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/34.56.789')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '0123/45.67.89')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/345 678 90')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/34 56 789')
+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012.34 56 789')
+
+    def test_phone_number_field(self):
+        w = BERegionSelect()
+        self.assertEqual(u'<select name="regions">\n<option value="BRU">Brussels Capital Region</option>\n<option value="VLG" selected="selected">Flemish Region</option>\n<option value="WAL">Wallonia</option>\n</select>', w.render('regions', 'VLG'))
+
+    def test_phone_number_field(self):
+        w = BEProvinceSelect()
+        self.assertEqual(u'<select name="provinces">\n<option value="VAN">Antwerp</option>\n<option value="BRU">Brussels</option>\n<option value="VOV">East Flanders</option>\n<option value="VBR">Flemish Brabant</option>\n<option value="WHT">Hainaut</option>\n<option value="WLG" selected="selected">Liege</option>\n<option value="VLI">Limburg</option>\n<option value="WLX">Luxembourg</option>\n<option value="WNA">Namur</option>\n<option value="WBR">Walloon Brabant</option>\n<option value="VWV">West Flanders</option>\n</select>', w.render('provinces', 'WLG'))
+
Index: AUTHORS
===================================================================
--- AUTHORS	(revision 13984)
+++ AUTHORS	(working copy)
@@ -307,6 +307,7 @@
     Simon Litchfield <simon@quo.com.au>
     Daniel Lindsley <polarcowz@gmail.com>
     Trey Long <trey@ktrl.com>
+    Laurent Luce <http://www.laurentluce.com>
     Martin Mahner <http://www.mahner.org/>
     Matt McClanahan <http://mmcc.cx/>
     Stanislaus Madueke
Index: docs/ref/contrib/localflavor.txt
===================================================================
--- docs/ref/contrib/localflavor.txt	(revision 13984)
+++ docs/ref/contrib/localflavor.txt	(working copy)
@@ -39,6 +39,7 @@
     * Argentina_
     * Australia_
     * Austria_
+    * Belgium_
     * Brazil_
     * Canada_
     * Chile_
@@ -85,6 +86,7 @@
 .. _Argentina: `Argentina (ar)`_
 .. _Australia: `Australia (au)`_
 .. _Austria: `Austria (at)`_
+.. _Belgium: `Belgium (be)`_
 .. _Brazil: `Brazil (br)`_
 .. _Canada: `Canada (ca)`_
 .. _Chile: `Chile (cl)`_
@@ -182,6 +184,31 @@
 
     A form field that validates its input as an Austrian social security number.
 
+Belgium (``be``)
+================
+
+.. class:: be.forms.BEPhoneNumberField
+
+    A form field that validates input as a Belgium phone number, with one of 
+    the formats 0x xxx xx xx, 0xx xx xx xx, 04xx xx xx xx, 0x/xxx.xx.xx,
+    0xx/xx.xx.xx, 04xx/xx.xx.xx, 0x.xxx.xx.xx, 0xx.xx.xx.xx, 04xx.xx.xx.xx, 
+    0xxxxxxxx, 04xxxxxxxx.
+
+.. class:: be.forms.BEPostalCodeField
+
+    A form field that validates input as a Belgium postal code, in the range
+    and format 1XXX-9XXX.
+
+.. class:: be.forms.BEProvinceSelect
+
+    A ``Select`` widget that uses a list of Belgium provinces as its
+    choices.
+
+.. class:: be.forms.BERegionSelect
+
+    A ``Select`` widget that uses a list of Belgium regions as its
+    choices.
+
 Brazil (``br``)
 ===============
 
