diff --git a/AUTHORS b/AUTHORS
index ad269d3f3b..9e78245506 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -179,6 +179,7 @@ answer newbie questions, and generally made Django that much better:
     SmileyChris <smileychris@gmail.com>
     smurf@smurf.noris.de
     sopel
+    Wiliam Alves de Souza <wiliamsouza83@gmail.com>
     Georgi Stanojevski <glisha@gmail.com>
     Thomas Steinacher <http://www.eggdrop.ch/>
     nowell strite
diff --git a/django/contrib/localflavor/br/__init__.py b/django/contrib/localflavor/br/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/django/contrib/localflavor/br/br_states.py b/django/contrib/localflavor/br/br_states.py
new file mode 100644
index 0000000000..c6ce0a1bb7
--- /dev/null
+++ b/django/contrib/localflavor/br/br_states.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+"""
+A brazilian mapping of state misspellings/abbreviations to normalized
+abbreviations, and an alphabetical list of states for use as `choices
+in a formfield.
+
+This exists in this standalone file so that it's only imported into
+memory when explicitly needed.
+"""
+
+STATE_CHOICES = (
+    ('AC', 'Acre'),
+    ('AL', 'Alagoas'),
+    ('AP', u'Amapá'),
+    ('AM', 'Amazonas'),
+    ('BA', 'Bahia'),
+    ('CE', u'Ceará'),
+    ('DF', 'Distrito Federal'),
+    ('ES', u'Espírito Santo'),
+    ('GO', u'Goiás'),
+    ('MA', u'Maranhão'),
+    ('MT', 'Mato Grosso'),
+    ('MS', 'Mato Grosso do Sul'),
+    ('MG', 'Minas Gerais'),
+    ('PA', u'Pará'),
+    ('PB', u'Paraíba'),
+    ('PR', u'Paraná'),
+    ('PE', 'Pernambuco'),
+    ('PI', u'Piauí'),
+    ('RJ', 'Rio de Janeiro'),
+    ('RN', 'Rio Grande do Norte'),
+    ('RS', 'Rio Grande do Sul'),
+    ('RO', u'Rondônia'),
+    ('RR', 'Roraima'),
+    ('SC', 'Santa Catarina'),
+    ('SP', u'São Paulo'),
+    ('SE', 'Sergipe'),
+    ('TO', 'Tocantins'),
+)
diff --git a/django/contrib/localflavor/br/forms.py b/django/contrib/localflavor/br/forms.py
new file mode 100644
index 0000000000..d3ca28f053
--- /dev/null
+++ b/django/contrib/localflavor/br/forms.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+"""
+BR-specific Form helpers
+"""
+
+from django.newforms import ValidationError
+from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
+from django.newforms.util import smart_unicode
+from django.utils.translation import gettext
+import re
+
+phone_digits_re = re.compile(r'^(\d{2})[-\.]?(\d{4})[-\.]?(\d{4})$')
+
+class BRZipCodeField(RegexField):
+    def __init__(self, *args, **kwargs):
+        super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$',
+            max_length=None, min_length=None,
+            error_message=u'Informe um código postal no formato XXXXX-XXX.',
+            *args, **kwargs)
+
+class BRPhoneNumberField(Field):
+    def clean(self, value):
+        super(BRPhoneNumberField, self).clean(value)
+        if value in EMPTY_VALUES:
+            return u''
+        value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))
+        m = phone_digits_re.search(value)
+        if m:
+            return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3))
+        raise ValidationError(u'Números de telefone devem estar no formato XX-XXXX-XXXX.')
+
+class BRStateSelect(Select):
+    """
+    A Select widget that uses a list of brazilian states/territories
+    as its choices.
+    """
+    def __init__(self, attrs=None):
+        from br_states import STATE_CHOICES # relative import
+        super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
index b2d66469c4..7f9f7fcbef 100644
--- a/tests/regressiontests/forms/tests.py
+++ b/tests/regressiontests/forms/tests.py
@@ -3974,6 +3974,120 @@ u''
 >>> f.clean('')
 u''
 
+# BRZipCodeField ############################################################
+>>> from django.contrib.localflavor.br.forms import BRZipCodeField
+>>> f = BRZipCodeField()
+>>> f.clean('12345-123')
+u'12345-123'
+>>> f.clean('12345_123')
+Traceback (most recent call last):
+...
+ValidationError: [u'Informe um c\xf3digo postal no formato XXXXX-XXX.']
+>>> f.clean('1234-123')
+Traceback (most recent call last):
+...
+ValidationError: [u'Informe um c\xf3digo postal no formato XXXXX-XXX.']
+>>> f.clean('abcde-abc')
+Traceback (most recent call last):
+...
+ValidationError: [u'Informe um c\xf3digo postal no formato XXXXX-XXX.']
+>>> f.clean('12345-')
+Traceback (most recent call last):
+...
+ValidationError: [u'Informe um c\xf3digo postal no formato XXXXX-XXX.']
+>>> f.clean('-123')
+Traceback (most recent call last):
+...
+ValidationError: [u'Informe um c\xf3digo postal no formato XXXXX-XXX.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean(None)
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+
+>>> f = BRZipCodeField(required=False)
+>>> f.clean(None)
+u''
+>>> f.clean('')
+u''
+>>> f.clean('-123')
+Traceback (most recent call last):
+...
+ValidationError: [u'Informe um c\xf3digo postal no formato XXXXX-XXX.']
+>>> f.clean('12345-')
+Traceback (most recent call last):
+...
+ValidationError: [u'Informe um c\xf3digo postal no formato XXXXX-XXX.']
+>>> f.clean('abcde-abc')
+Traceback (most recent call last):
+...
+ValidationError: [u'Informe um c\xf3digo postal no formato XXXXX-XXX.']
+>>> f.clean('1234-123')
+Traceback (most recent call last):
+...
+ValidationError: [u'Informe um c\xf3digo postal no formato XXXXX-XXX.']
+>>> f.clean('12345_123')
+Traceback (most recent call last):
+...
+ValidationError: [u'Informe um c\xf3digo postal no formato XXXXX-XXX.']
+>>> f.clean('12345-123')
+u'12345-123'
+
+# BRPhoneNumberField #########################################################
+
+>>> from django.contrib.localflavor.br.forms import BRPhoneNumberField
+>>> f = BRPhoneNumberField()
+>>> f.clean('41-3562-3464')
+u'41-3562-3464'
+>>> f.clean('4135623464')
+u'41-3562-3464'
+>>> f.clean('41 3562-3464')
+u'41-3562-3464'
+>>> f.clean('41 3562 3464')
+u'41-3562-3464'
+>>> f.clean('(41) 3562 3464')
+u'41-3562-3464'
+>>> f.clean('41.3562.3464')
+u'41-3562-3464'
+>>> f.clean('41.3562-3464')
+u'41-3562-3464'
+>>> f.clean(' (41) 3562.3464')
+u'41-3562-3464'
+>>> f.clean(None)
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+
+>>> f = BRPhoneNumberField(required=False)
+>>> f.clean('')
+u''
+>>> f.clean(None)
+u''
+>>> f.clean(' (41) 3562.3464')
+u'41-3562-3464'
+>>> f.clean('41.3562-3464')
+u'41-3562-3464'
+>>> f.clean('(41) 3562 3464')
+u'41-3562-3464'
+>>> f.clean('4135623464')
+u'41-3562-3464'
+>>> f.clean('41 3562-3464')
+u'41-3562-3464'
+
+# BRStateSelect ##############################################################
+
+>>> from django.contrib.localflavor.br.forms import BRStateSelect
+>>> w = BRStateSelect()
+>>> w.render('states', 'PR')
+u'<select name="states">\n<option value="AC">Acre</option>\n<option value="AL">Alagoas</option>\n<option value="AP">Amap\xe1</option>\n<option value="AM">Amazonas</option>\n<option value="BA">Bahia</option>\n<option value="CE">Cear\xe1</option>\n<option value="DF">Distrito Federal</option>\n<option value="ES">Esp\xedrito Santo</option>\n<option value="GO">Goi\xe1s</option>\n<option value="MA">Maranh\xe3o</option>\n<option value="MT">Mato Grosso</option>\n<option value="MS">Mato Grosso do Sul</option>\n<option value="MG">Minas Gerais</option>\n<option value="PA">Par\xe1</option>\n<option value="PB">Para\xedba</option>\n<option value="PR" selected="selected">Paran\xe1</option>\n<option value="PE">Pernambuco</option>\n<option value="PI">Piau\xed</option>\n<option value="RJ">Rio de Janeiro</option>\n<option value="RN">Rio Grande do Norte</option>\n<option value="RS">Rio Grande do Sul</option>\n<option value="RO">Rond\xf4nia</option>\n<option value="RR">Roraima</option>\n<option value="SC">Santa Catarina</option>\n<option value="SP">S\xe3o Paulo</option>\n<option value="SE">Sergipe</option>\n<option value="TO">Tocantins</option>\n</select>'
+
 #################################
 # Tests of underlying functions #
 #################################