diff --git a/django/contrib/localflavor/jp/__init__.py b/django/contrib/localflavor/jp/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/django/contrib/localflavor/jp/forms.py b/django/contrib/localflavor/jp/forms.py
new file mode 100644
index 0000000000..4d93a21227
--- /dev/null
+++ b/django/contrib/localflavor/jp/forms.py
@@ -0,0 +1,38 @@
+"""
+JP-specific Form helpers
+"""
+
+from django.core import validators
+from django.newforms import ValidationError
+from django.utils.translation import gettext
+from django.newforms.fields import RegexField, Select
+
+import re
+
+class JPPostalCodeField(RegexField):
+ """
+ A form field that validates its input is a Japanese postcode.
+
+ Accepts 7 digits, with or without a hyphen.
+ """
+ def __init__(self, *args, **kwargs):
+ super(JPPostalCodeField, self).__init__(r'^\d{3}-\d{4}$|^\d{7}$',
+ max_length=None, min_length=None,
+ error_message=gettext(u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'),
+ *args, **kwargs)
+
+ def clean(self, value):
+ """
+ Validates the input and returns a string that contains only numbers.
+ Returns an empty string for empty values.
+ """
+ v = super(JPPostalCodeField, self).clean(value)
+ return v.replace('-', '')
+
+class JPPrefectureSelect(Select):
+ """
+ A Select widget that uses a list of Japanese prefectures as its choices.
+ """
+ def __init__(self, attrs=None):
+ from jp_prefectures import JP_PREFECTURES
+ super(JPPrefectureSelect, self).__init__(attrs, choices=JP_PREFECTURES)
diff --git a/django/contrib/localflavor/jp/jp_prefectures.py b/django/contrib/localflavor/jp/jp_prefectures.py
new file mode 100644
index 0000000000..72ac4f9474
--- /dev/null
+++ b/django/contrib/localflavor/jp/jp_prefectures.py
@@ -0,0 +1,51 @@
+from django.utils.translation import gettext_lazy as gettext_lazy
+
+JP_PREFECTURES = (
+ ('hokkaido', gettext_lazy('Hokkaido'),),
+ ('aomori', gettext_lazy('Aomori'),),
+ ('iwate', gettext_lazy('Iwate'),),
+ ('miyagi', gettext_lazy('Miyagi'),),
+ ('akita', gettext_lazy('Akita'),),
+ ('yamagata', gettext_lazy('Yamagata'),),
+ ('fukushima', gettext_lazy('Fukushima'),),
+ ('ibaraki', gettext_lazy('Ibaraki'),),
+ ('tochigi', gettext_lazy('Tochigi'),),
+ ('gunma', gettext_lazy('Gunma'),),
+ ('saitama', gettext_lazy('Saitama'),),
+ ('chiba', gettext_lazy('Chiba'),),
+ ('tokyo', gettext_lazy('Tokyo'),),
+ ('kanagawa', gettext_lazy('Kanagawa'),),
+ ('yamanashi', gettext_lazy('Yamanashi'),),
+ ('nagano', gettext_lazy('Nagano'),),
+ ('niigata', gettext_lazy('Niigata'),),
+ ('toyama', gettext_lazy('Toyama'),),
+ ('ishikawa', gettext_lazy('Ishikawa'),),
+ ('fukui', gettext_lazy('Fukui'),),
+ ('gifu', gettext_lazy('Gifu'),),
+ ('shizuoka', gettext_lazy('Shizuoka'),),
+ ('aichi', gettext_lazy('Aichi'),),
+ ('mie', gettext_lazy('Mie'),),
+ ('shiga', gettext_lazy('Shiga'),),
+ ('kyoto', gettext_lazy('Kyoto'),),
+ ('osaka', gettext_lazy('Osaka'),),
+ ('hyogo', gettext_lazy('Hyogo'),),
+ ('nara', gettext_lazy('Nara'),),
+ ('wakayama', gettext_lazy('Wakayama'),),
+ ('tottori', gettext_lazy('Tottori'),),
+ ('shimane', gettext_lazy('Shimane'),),
+ ('okayama', gettext_lazy('Okayama'),),
+ ('hiroshima', gettext_lazy('Hiroshima'),),
+ ('yamaguchi', gettext_lazy('Yamaguchi'),),
+ ('tokushima', gettext_lazy('Tokushima'),),
+ ('kagawa', gettext_lazy('Kagawa'),),
+ ('ehime', gettext_lazy('Ehime'),),
+ ('kochi', gettext_lazy('Kochi'),),
+ ('fukuoka', gettext_lazy('Fukuoka'),),
+ ('saga', gettext_lazy('Saga'),),
+ ('nagasaki', gettext_lazy('Nagasaki'),),
+ ('kumamoto', gettext_lazy('Kumamoto'),),
+ ('oita', gettext_lazy('Oita'),),
+ ('miyazaki', gettext_lazy('Miyazaki'),),
+ ('kagoshima', gettext_lazy('Kagoshima'),),
+ ('okinawa', gettext_lazy('Okinawa'),),
+)
diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
index ab10d2f3e3..f805a221aa 100644
--- a/tests/regressiontests/forms/tests.py
+++ b/tests/regressiontests/forms/tests.py
@@ -3776,6 +3776,109 @@ including DOM TOM
+# JPPostalCodeField ###############################################################
+
+A form field that validates its input is a Japanese postcode.
+
+Accepts 7 digits(with/out hyphen).
+>>> from django.contrib.localflavor.jp.forms import JPPostalCodeField
+>>> f = JPPostalCodeField()
+>>> f.clean('251-0032')
+u'2510032'
+>>> f.clean('2510032')
+u'2510032'
+>>> f.clean('2510-032')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
+>>> f.clean('251a0032')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
+>>> f.clean('a51-0032')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
+>>> f.clean('25100321')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+
+>>> f = JPPostalCodeField(required=False)
+>>> f.clean('251-0032')
+u'2510032'
+>>> f.clean('2510032')
+u'2510032'
+>>> f.clean('2510-032')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
+>>> f.clean('')
+u''
+>>> f.clean(None)
+u''
+
+# JPPrefectureSelect ###############################################################
+
+A Select widget that uses a list of Japanese prefectures as its choices.
+>>> from django.contrib.localflavor.jp.forms import JPPrefectureSelect
+>>> w = JPPrefectureSelect()
+>>> print w.render('prefecture', 'kanagawa')
+
+
+
#################################
# Tests of underlying functions #
#################################