diff --git a/AUTHORS b/AUTHORS
index 00e0c6fe92..900335efbc 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -184,6 +184,7 @@ answer newbie questions, and generally made Django that much better:
Radek Švarz
Swaroop C H
Aaron Swartz
+ Ville Säävuori
Tyson Tate
Tom Tobin
Joe Topjian
diff --git a/django/contrib/localflavor/fi/__init__.py b/django/contrib/localflavor/fi/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/django/contrib/localflavor/fi/fi_municipalities.py b/django/contrib/localflavor/fi/fi_municipalities.py
new file mode 100644
index 0000000000..965a52d327
--- /dev/null
+++ b/django/contrib/localflavor/fi/fi_municipalities.py
@@ -0,0 +1,427 @@
+# -*- coding: utf-8 -*-
+"""
+An alphabetical list of Finnish municipalities for use as `choices` in a
+formfield.
+
+This exists in this standalone file so that it's only imported into memory
+when explicitly needed.
+"""
+
+MUNICIPALITY_CHOICES = (
+ ('akaa', u"Akaa"),
+ ('alaharma', u"Alahärmä"),
+ ('alajarvi', u"Alajärvi"),
+ ('alastaro', u"Alastaro"),
+ ('alavieska', u"Alavieska"),
+ ('alavus', u"Alavus"),
+ ('anjalankoski', u"Anjalankoski"),
+ ('artjarvi', u"Artjärvi"),
+ ('asikkala', u"Asikkala"),
+ ('askainen', u"Askainen"),
+ ('askola', u"Askola"),
+ ('aura', u"Aura"),
+ ('brando', u"Brändö"),
+ ('dragsfjard', u"Dragsfjärd"),
+ ('eckero', u"Eckerö"),
+ ('elimaki', u"Elimäki"),
+ ('eno', u"Eno"),
+ ('enonkoski', u"Enonkoski"),
+ ('enontekio', u"Enontekiö"),
+ ('espoo', u"Espoo"),
+ ('eura', u"Eura"),
+ ('eurajoki', u"Eurajoki"),
+ ('evijarvi', u"Evijärvi"),
+ ('finstrom', u"Finström"),
+ ('forssa', u"Forssa"),
+ ('foglo', u"Föglö"),
+ ('geta', u"Geta"),
+ ('haapajarvi', u"Haapajärvi"),
+ ('haapavesi', u"Haapavesi"),
+ ('hailuoto', u"Hailuoto"),
+ ('halikko', u"Halikko"),
+ ('halsua', u"Halsua"),
+ ('hamina', u"Hamina"),
+ ('hammarland', u"Hammarland"),
+ ('hankasalmi', u"Hankasalmi"),
+ ('hanko', u"Hanko"),
+ ('harjavalta', u"Harjavalta"),
+ ('hartola', u"Hartola"),
+ ('hattula', u"Hattula"),
+ ('hauho', u"Hauho"),
+ ('haukipudas', u"Haukipudas"),
+ ('hausjarvi', u"Hausjärvi"),
+ ('heinola', u"Heinola"),
+ ('heinavesi', u"Heinävesi"),
+ ('helsinki', u"Helsinki"),
+ ('himanka', u"Himanka"),
+ ('hirvensalmi', u"Hirvensalmi"),
+ ('hollola', u"Hollola"),
+ ('honkajoki', u"Honkajoki"),
+ ('houtskari', u"Houtskari"),
+ ('huittinen', u"Huittinen"),
+ ('humppila', u"Humppila"),
+ ('hyrynsalmi', u"Hyrynsalmi"),
+ ('hyvinkaa', u"Hyvinkää"),
+ ('hameenkoski', u"Hämeenkoski"),
+ ('hameenkyro', u"Hämeenkyrö"),
+ ('hameenlinna', u"Hämeenlinna"),
+ ('ii', u"Ii"),
+ ('iisalmi', u"Iisalmi"),
+ ('iitti', u"Iitti"),
+ ('ikaalinen', u"Ikaalinen"),
+ ('ilmajoki', u"Ilmajoki"),
+ ('ilomantsi', u"Ilomantsi"),
+ ('imatra', u"Imatra"),
+ ('inari', u"Inari"),
+ ('inio', u"Iniö"),
+ ('inkoo', u"Inkoo"),
+ ('isojoki', u"Isojoki"),
+ ('isokyro', u"Isokyrö"),
+ ('jaala', u"Jaala"),
+ ('jalasjarvi', u"Jalasjärvi"),
+ ('janakkala', u"Janakkala"),
+ ('joensuu', u"Joensuu"),
+ ('jokioinen', u"Jokioinen"),
+ ('jomala', u"Jomala"),
+ ('joroinen', u"Joroinen"),
+ ('joutsa', u"Joutsa"),
+ ('joutseno', u"Joutseno"),
+ ('juankoski', u"Juankoski"),
+ ('jurva', u"Jurva"),
+ ('juuka', u"Juuka"),
+ ('juupajoki', u"Juupajoki"),
+ ('juva', u"Juva"),
+ ('jyvaskyla', u"Jyväskylä"),
+ ('jyvaskylan_mlk', u"Jyväskylän maalaiskunta"),
+ ('jamijarvi', u"Jämijärvi"),
+ ('jamsa', u"Jämsä"),
+ ('jamsankoski', u"Jämsänkoski"),
+ ('jarvenpaa', u"Järvenpää"),
+ ('kaarina', u"Kaarina"),
+ ('kaavi', u"Kaavi"),
+ ('kajaani', u"Kajaani"),
+ ('kalajoki', u"Kalajoki"),
+ ('kalvola', u"Kalvola"),
+ ('kangasala', u"Kangasala"),
+ ('kangasniemi', u"Kangasniemi"),
+ ('kankaanpaa', u"Kankaanpää"),
+ ('kannonkoski', u"Kannonkoski"),
+ ('kannus', u"Kannus"),
+ ('karijoki', u"Karijoki"),
+ ('karjaa', u"Karjaa"),
+ ('karjalohja', u"Karjalohja"),
+ ('karkkila', u"Karkkila"),
+ ('karstula', u"Karstula"),
+ ('karttula', u"Karttula"),
+ ('karvia', u"Karvia"),
+ ('kaskinen', u"Kaskinen"),
+ ('kauhajoki', u"Kauhajoki"),
+ ('kauhava', u"Kauhava"),
+ ('kauniainen', u"Kauniainen"),
+ ('kaustinen', u"Kaustinen"),
+ ('keitele', u"Keitele"),
+ ('kemi', u"Kemi"),
+ ('kemijarvi', u"Kemijärvi"),
+ ('keminmaa', u"Keminmaa"),
+ ('kemio', u"Kemiö"),
+ ('kempele', u"Kempele"),
+ ('kerava', u"Kerava"),
+ ('kerimaki', u"Kerimäki"),
+ ('kestila', u"Kestilä"),
+ ('kesalahti', u"Kesälahti"),
+ ('keuruu', u"Keuruu"),
+ ('kihnio', u"Kihniö"),
+ ('kiikala', u"Kiikala"),
+ ('kiikoinen', u"Kiikoinen"),
+ ('kiiminki', u"Kiiminki"),
+ ('kinnula', u"Kinnula"),
+ ('kirkkonummi', u"Kirkkonummi"),
+ ('kisko', u"Kisko"),
+ ('kitee', u"Kitee"),
+ ('kittila', u"Kittilä"),
+ ('kiukainen', u"Kiukainen"),
+ ('kiuruvesi', u"Kiuruvesi"),
+ ('kivijarvi', u"Kivijärvi"),
+ ('kokemaki', u"Kokemäki"),
+ ('kokkola', u"Kokkola"),
+ ('kolari', u"Kolari"),
+ ('konnevesi', u"Konnevesi"),
+ ('kontiolahti', u"Kontiolahti"),
+ ('korpilahti', u"Korpilahti"),
+ ('korppoo', u"Korppoo"),
+ ('korsnas', u"Korsnäs"),
+ ('kortesjarvi', u"Kortesjärvi"),
+ ('koskitl', u"KoskiTl"),
+ ('kotka', u"Kotka"),
+ ('kouvola', u"Kouvola"),
+ ('kristiinankaupunki', u"Kristiinankaupunki"),
+ ('kruunupyy', u"Kruunupyy"),
+ ('kuhmalahti', u"Kuhmalahti"),
+ ('kuhmo', u"Kuhmo"),
+ ('kuhmoinen', u"Kuhmoinen"),
+ ('kumlinge', u"Kumlinge"),
+ ('kuopio', u"Kuopio"),
+ ('kuortane', u"Kuortane"),
+ ('kurikka', u"Kurikka"),
+ ('kuru', u"Kuru"),
+ ('kustavi', u"Kustavi"),
+ ('kuusamo', u"Kuusamo"),
+ ('kuusankoski', u"Kuusankoski"),
+ ('kuusjoki', u"Kuusjoki"),
+ ('kylmakoski', u"Kylmäkoski"),
+ ('kyyjarvi', u"Kyyjärvi"),
+ ('kalvia', u"Kälviä"),
+ ('karkola', u"Kärkölä"),
+ ('karsamaki', u"Kärsämäki"),
+ ('kokar', u"Kökar"),
+ ('koylio', u"Köyliö"),
+ ('lahti', u"Lahti"),
+ ('laihia', u"Laihia"),
+ ('laitila', u"Laitila"),
+ ('lammi', u"Lammi"),
+ ('lapinjarvi', u"Lapinjärvi"),
+ ('lapinlahti', u"Lapinlahti"),
+ ('lappajarvi', u"Lappajärvi"),
+ ('lappeenranta', u"Lappeenranta"),
+ ('lappi', u"Lappi"),
+ ('lapua', u"Lapua"),
+ ('laukaa', u"Laukaa"),
+ ('lavia', u"Lavia"),
+ ('lehtimaki', u"Lehtimäki"),
+ ('leivonmaki', u"Leivonmäki"),
+ ('lemi', u"Lemi"),
+ ('lemland', u"Lemland"),
+ ('lempaala', u"Lempäälä"),
+ ('lemu', u"Lemu"),
+ ('leppavirta', u"Leppävirta"),
+ ('lestijarvi', u"Lestijärvi"),
+ ('lieksa', u"Lieksa"),
+ ('lieto', u"Lieto"),
+ ('liljendal', u"Liljendal"),
+ ('liminka', u"Liminka"),
+ ('liperi', u"Liperi"),
+ ('lohja', u"Lohja"),
+ ('lohtaja', u"Lohtaja"),
+ ('loimaa', u"Loimaa"),
+ ('loppi', u"Loppi"),
+ ('loviisa', u"Loviisa"),
+ ('luhanka', u"Luhanka"),
+ ('lumijoki', u"Lumijoki"),
+ ('lumparland', u"Lumparland"),
+ ('luoto', u"Luoto"),
+ ('luumaki', u"Luumäki"),
+ ('luvia', u"Luvia"),
+ ('maalahti', u"Maalahti"),
+ ('maaninka', u"Maaninka"),
+ ('maarianhamina', u"Maarianhamina"),
+ ('marttila', u"Marttila"),
+ ('masku', u"Masku"),
+ ('mellila', u"Mellilä"),
+ ('merijarvi', u"Merijärvi"),
+ ('merikarvia', u"Merikarvia"),
+ ('merimasku', u"Merimasku"),
+ ('miehikkala', u"Miehikkälä"),
+ ('mikkeli', u"Mikkeli"),
+ ('mouhijarvi', u"Mouhijärvi"),
+ ('muhos', u"Muhos"),
+ ('multia', u"Multia"),
+ ('muonio', u"Muonio"),
+ ('mustasaari', u"Mustasaari"),
+ ('muurame', u"Muurame"),
+ ('muurla', u"Muurla"),
+ ('mynamaki', u"Mynämäki"),
+ ('myrskyla', u"Myrskylä"),
+ ('mantsala', u"Mäntsälä"),
+ ('mantta', u"Mänttä"),
+ ('mantyharju', u"Mäntyharju"),
+ ('naantali', u"Naantali"),
+ ('nakkila', u"Nakkila"),
+ ('nastola', u"Nastola"),
+ ('nauvo', u"Nauvo"),
+ ('nilsia', u"Nilsiä"),
+ ('nivala', u"Nivala"),
+ ('nokia', u"Nokia"),
+ ('noormarkku', u"Noormarkku"),
+ ('nousiainen', u"Nousiainen"),
+ ('nummi-pusula', u"Nummi-Pusula"),
+ ('nurmes', u"Nurmes"),
+ ('nurmijarvi', u"Nurmijärvi"),
+ ('nurmo', u"Nurmo"),
+ ('narpio', u"Närpiö"),
+ ('oravainen', u"Oravainen"),
+ ('orimattila', u"Orimattila"),
+ ('oripaa', u"Oripää"),
+ ('orivesi', u"Orivesi"),
+ ('oulainen', u"Oulainen"),
+ ('oulu', u"Oulu"),
+ ('oulunsalo', u"Oulunsalo"),
+ ('outokumpu', u"Outokumpu"),
+ ('padasjoki', u"Padasjoki"),
+ ('paimio', u"Paimio"),
+ ('paltamo', u"Paltamo"),
+ ('parainen', u"Parainen"),
+ ('parikkala', u"Parikkala"),
+ ('parkano', u"Parkano"),
+ ('pedersore', u"Pedersöre"),
+ ('pelkosenniemi', u"Pelkosenniemi"),
+ ('pello', u"Pello"),
+ ('perho', u"Perho"),
+ ('pernaja', u"Pernaja"),
+ ('pernio', u"Perniö"),
+ ('pertteli', u"Pertteli"),
+ ('pertunmaa', u"Pertunmaa"),
+ ('petajavesi', u"Petäjävesi"),
+ ('pieksamaki', u"Pieksämäki"),
+ ('pielavesi', u"Pielavesi"),
+ ('pietarsaari', u"Pietarsaari"),
+ ('pihtipudas', u"Pihtipudas"),
+ ('piikkio', u"Piikkiö"),
+ ('piippola', u"Piippola"),
+ ('pirkkala', u"Pirkkala"),
+ ('pohja', u"Pohja"),
+ ('polvijarvi', u"Polvijärvi"),
+ ('pomarkku', u"Pomarkku"),
+ ('pori', u"Pori"),
+ ('pornainen', u"Pornainen"),
+ ('porvoo', u"Porvoo"),
+ ('posio', u"Posio"),
+ ('pudasjarvi', u"Pudasjärvi"),
+ ('pukkila', u"Pukkila"),
+ ('pulkkila', u"Pulkkila"),
+ ('punkaharju', u"Punkaharju"),
+ ('punkalaidun', u"Punkalaidun"),
+ ('puolanka', u"Puolanka"),
+ ('puumala', u"Puumala"),
+ ('pyhtaa', u"Pyhtää"),
+ ('pyhajoki', u"Pyhäjoki"),
+ ('pyhajarvi', u"Pyhäjärvi"),
+ ('pyhanta', u"Pyhäntä"),
+ ('pyharanta', u"Pyhäranta"),
+ ('pyhaselka', u"Pyhäselkä"),
+ ('pylkonmaki', u"Pylkönmäki"),
+ ('palkane', u"Pälkäne"),
+ ('poytya', u"Pöytyä"),
+ ('raahe', u"Raahe"),
+ ('raisio', u"Raisio"),
+ ('rantasalmi', u"Rantasalmi"),
+ ('rantsila', u"Rantsila"),
+ ('ranua', u"Ranua"),
+ ('rauma', u"Rauma"),
+ ('rautalampi', u"Rautalampi"),
+ ('rautavaara', u"Rautavaara"),
+ ('rautjarvi', u"Rautjärvi"),
+ ('reisjarvi', u"Reisjärvi"),
+ ('renko', u"Renko"),
+ ('riihimaki', u"Riihimäki"),
+ ('ristiina', u"Ristiina"),
+ ('ristijarvi', u"Ristijärvi"),
+ ('rovaniemi', u"Rovaniemi"),
+ ('ruokolahti', u"Ruokolahti"),
+ ('ruotsinpyhtaa', u"Ruotsinpyhtää"),
+ ('ruovesi', u"Ruovesi"),
+ ('rusko', u"Rusko"),
+ ('rymattyla', u"Rymättylä"),
+ ('raakkyla', u"Rääkkylä"),
+ ('saarijarvi', u"Saarijärvi"),
+ ('salla', u"Salla"),
+ ('salo', u"Salo"),
+ ('saltvik', u"Saltvik"),
+ ('sammatti', u"Sammatti"),
+ ('sauvo', u"Sauvo"),
+ ('savitaipale', u"Savitaipale"),
+ ('savonlinna', u"Savonlinna"),
+ ('savonranta', u"Savonranta"),
+ ('savukoski', u"Savukoski"),
+ ('seinajoki', u"Seinäjoki"),
+ ('sievi', u"Sievi"),
+ ('siikainen', u"Siikainen"),
+ ('siikajoki', u"Siikajoki"),
+ ('siilinjarvi', u"Siilinjärvi"),
+ ('simo', u"Simo"),
+ ('sipoo', u"Sipoo"),
+ ('siuntio', u"Siuntio"),
+ ('sodankyla', u"Sodankylä"),
+ ('soini', u"Soini"),
+ ('somero', u"Somero"),
+ ('sonkajarvi', u"Sonkajärvi"),
+ ('sotkamo', u"Sotkamo"),
+ ('sottunga', u"Sottunga"),
+ ('sulkava', u"Sulkava"),
+ ('sund', u"Sund"),
+ ('suomenniemi', u"Suomenniemi"),
+ ('suomusjarvi', u"Suomusjärvi"),
+ ('suomussalmi', u"Suomussalmi"),
+ ('suonenjoki', u"Suonenjoki"),
+ ('sysma', u"Sysmä"),
+ ('sakyla', u"Säkylä"),
+ ('sarkisalo', u"Särkisalo"),
+ ('taipalsaari', u"Taipalsaari"),
+ ('taivalkoski', u"Taivalkoski"),
+ ('taivassalo', u"Taivassalo"),
+ ('tammela', u"Tammela"),
+ ('tammisaari', u"Tammisaari"),
+ ('tampere', u"Tampere"),
+ ('tarvasjoki', u"Tarvasjoki"),
+ ('tervo', u"Tervo"),
+ ('tervola', u"Tervola"),
+ ('teuva', u"Teuva"),
+ ('tohmajarvi', u"Tohmajärvi"),
+ ('toholampi', u"Toholampi"),
+ ('toivakka', u"Toivakka"),
+ ('tornio', u"Tornio"),
+ ('turku', u"Turku"),
+ ('tuulos', u"Tuulos"),
+ ('tuusniemi', u"Tuusniemi"),
+ ('tuusula', u"Tuusula"),
+ ('tyrnava', u"Tyrnävä"),
+ ('toysa', u"Töysä"),
+ ('ullava', u"Ullava"),
+ ('ulvila', u"Ulvila"),
+ ('urjala', u"Urjala"),
+ ('utajarvi', u"Utajärvi"),
+ ('utsjoki', u"Utsjoki"),
+ ('uurainen', u"Uurainen"),
+ ('uusikaarlepyy', u"Uusikaarlepyy"),
+ ('uusikaupunki', u"Uusikaupunki"),
+ ('vaala', u"Vaala"),
+ ('vaasa', u"Vaasa"),
+ ('vahto', u"Vahto"),
+ ('valkeakoski', u"Valkeakoski"),
+ ('valkeala', u"Valkeala"),
+ ('valtimo', u"Valtimo"),
+ ('vammala', u"Vammala"),
+ ('vampula', u"Vampula"),
+ ('vantaa', u"Vantaa"),
+ ('varkaus', u"Varkaus"),
+ ('varpaisjarvi', u"Varpaisjärvi"),
+ ('vehmaa', u"Vehmaa"),
+ ('velkua', u"Velkua"),
+ ('vesanto', u"Vesanto"),
+ ('vesilahti', u"Vesilahti"),
+ ('veteli', u"Veteli"),
+ ('vierema', u"Vieremä"),
+ ('vihanti', u"Vihanti"),
+ ('vihti', u"Vihti"),
+ ('viitasaari', u"Viitasaari"),
+ ('vilppula', u"Vilppula"),
+ ('vimpeli', u"Vimpeli"),
+ ('virolahti', u"Virolahti"),
+ ('virrat', u"Virrat"),
+ ('vardo', u"Vårdö"),
+ ('vahakyro', u"Vähäkyrö"),
+ ('vastanfjard', u"Västanfjärd"),
+ ('voyri-maksamaa', u"Vöyri-Maksamaa"),
+ ('yliharma', u"Ylihärmä"),
+ ('yli-ii', u"Yli-Ii"),
+ ('ylikiiminki', u"Ylikiiminki"),
+ ('ylistaro', u"Ylistaro"),
+ ('ylitornio', u"Ylitornio"),
+ ('ylivieska', u"Ylivieska"),
+ ('ylamaa', u"Ylämaa"),
+ ('ylane', u"Yläne"),
+ ('ylojarvi', u"Ylöjärvi"),
+ ('ypaja', u"Ypäjä"),
+ ('aetsa', u"Äetsä"),
+ ('ahtari', u"Ähtäri"),
+ ('aanekoski', u"Äänekoski")
+)
\ No newline at end of file
diff --git a/django/contrib/localflavor/fi/forms.py b/django/contrib/localflavor/fi/forms.py
new file mode 100644
index 0000000000..29d01b9de2
--- /dev/null
+++ b/django/contrib/localflavor/fi/forms.py
@@ -0,0 +1,22 @@
+"""
+FI-specific Form helpers
+"""
+
+from django.newforms import ValidationError
+from django.newforms.fields import RegexField, Select
+from django.utils.translation import gettext
+
+class FIZipCodeField(RegexField):
+ def __init__(self, *args, **kwargs):
+ super(FIZipCodeField, self).__init__(r'^\d{5}$',
+ max_length=None, min_length=None,
+ error_message=gettext(u'Enter a zip code in the format XXXXX.'),
+ *args, **kwargs)
+
+class FIMunicipalitySelect(Select):
+ """
+ A Select widget that uses a list of Finnish municipalities as its choices.
+ """
+ def __init__(self, attrs=None):
+ from fi_municipalities import MUNICIPALITY_CHOICES # relative import
+ super(FIMunicipalitySelect, self).__init__(attrs, choices=MUNICIPALITY_CHOICES)
diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
index f805a221aa..95453e7eeb 100644
--- a/tests/regressiontests/forms/tests.py
+++ b/tests/regressiontests/forms/tests.py
@@ -3878,6 +3878,57 @@ A Select widget that uses a list of Japanese prefectures as its choices.
+# FIZipCodeField #############################################################
+
+FIZipCodeField validates that the data is a valid FI zipcode.
+>>> from django.contrib.localflavor.fi.forms import FIZipCodeField
+>>> f = FIZipCodeField()
+>>> f.clean('20540')
+u'20540'
+>>> f.clean('20101')
+u'20101'
+>>> f.clean('20s40')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a zip code in the format XXXXX.']
+>>> f.clean('205401')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a zip code in the format XXXXX.']
+>>> 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 = FIZipCodeField(required=False)
+>>> f.clean('20540')
+u'20540'
+>>> f.clean('20101')
+u'20101'
+>>> f.clean('20s40')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a zip code in the format XXXXX.']
+>>> f.clean('205401')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a zip code in the format XXXXX.']
+>>> f.clean(None)
+u''
+>>> f.clean('')
+u''
+
+# FIMunicipalitySelect ###############################################################
+
+A Select widget that uses a list of Finnish municipalities as its choices.
+>>> from django.contrib.localflavor.fi.forms import FIMunicipalitySelect
+>>> w = FIMunicipalitySelect()
+>>> unicode(w.render('municipalities', 'turku'))
+u''
#################################
# Tests of underlying functions #