Ticket #9289: django_localflavor_se.diff

File django_localflavor_se.diff, 51.4 KB (added by peritus, 7 years ago)

Swedish localflavor patch against current trunk

  • AUTHORS

    diff --git a/AUTHORS b/AUTHORS
    index 7bbec38..558f0ff 100644
    a b answer newbie questions, and generally made Django that much better: 
    297297    Carlos Eduardo de Paula <carlosedp@gmail.com>
    298298    pavithran s <pavithran.s@gmail.com>
    299299    Barry Pederson <bp@barryp.org>
     300    Andreas Pelme <andreas@pelme.se>
    300301    permonik@mesias.brnonet.cz
    301302    peter@mymart.com
    302303    pgross@thoughtworks.com
  • django/conf/locale/sv/LC_MESSAGES/django.po

    diff --git a/django/conf/locale/sv/LC_MESSAGES/django.mo b/django/conf/locale/sv/LC_MESSAGES/django.mo
    index f2ae006..ea2dc58 100644
    Binary files a/django/conf/locale/sv/LC_MESSAGES/django.mo and b/django/conf/locale/sv/LC_MESSAGES/django.mo differ
    diff --git a/django/conf/locale/sv/LC_MESSAGES/django.po b/django/conf/locale/sv/LC_MESSAGES/django.po
    index d279647..5a75119 100644
    a b msgid "" 
    66msgstr ""
    77"Project-Id-Version: Django\n"
    88"Report-Msgid-Bugs-To: \n"
    9 "POT-Creation-Date: 2008-09-03 04:36+0200\n"
     9"POT-Creation-Date: 2008-10-03 11:01-0500\n"
    1010"PO-Revision-Date: 2008-05-26 11:15+0200\n"
    1111"Last-Translator: Ludvig Ericson <ludvig.ericson@gmail.com>\n"
    1212"Language-Team: Django I18N <Django-I18N@googlegroups.com>\n"
    msgid "" 
    347347msgstr ""
    348348"%(name)s \"%(obj)s\" lades till. Du kan redigera objektet igen nedanför."
    349349
    350 #: contrib/admin/options.py:536
     350#: contrib/admin/options.py:528
    351351#, python-format
    352352msgid "Add %s"
    353353msgstr "Lägg till %s"
    354354
    355 #: contrib/admin/options.py:614
     355#: contrib/admin/options.py:605
    356356#, python-format
    357357msgid "Change %s"
    358358msgstr "Ändra %s"
    359359
    360 #: contrib/admin/options.py:646
     360#: contrib/admin/options.py:637
    361361msgid "Database error"
    362362msgstr "Databasfel"
    363363
    364 #: contrib/admin/options.py:696
     364#: contrib/admin/options.py:687
    365365#, python-format
    366366msgid "The %(name)s \"%(obj)s\" was deleted successfully."
    367367msgstr "%(name)s \"%(obj)s\" togs bort."
    368368
    369 #: contrib/admin/options.py:703
     369#: contrib/admin/options.py:694
    370370msgid "Are you sure?"
    371371msgstr "Är du säker?"
    372372
    373 #: contrib/admin/options.py:732
     373#: contrib/admin/options.py:723
    374374#, python-format
    375375msgid "Change history: %s"
    376376msgstr "Ändringshistorik: %s"
    msgstr "" 
    384384"Var god ange ett korrekt användarnamn och lösenord. Tänk på att skilja "
    385385"mellan gemener och versaler."
    386386
    387 #: contrib/admin/sites.py:227 contrib/admin/views/decorators.py:40
     387#: contrib/admin/sites.py:226 contrib/admin/views/decorators.py:40
    388388msgid "Please log in again, because your session has expired."
    389389msgstr "Var god logga in igen, eftersom din session har förfallit."
    390390
    391 #: contrib/admin/sites.py:234 contrib/admin/views/decorators.py:47
     391#: contrib/admin/sites.py:233 contrib/admin/views/decorators.py:47
    392392msgid ""
    393393"Looks like your browser isn't configured to accept cookies. Please enable "
    394394"cookies, reload this page, and try again."
    msgstr "" 
    396396"Det verkar som att din webläsare inte är konfigurerad att acceptera cookies. "
    397397"Aktivera cookies, ladda om denna sida och försök igen."
    398398
    399 #: contrib/admin/sites.py:250 contrib/admin/sites.py:256
     399#: contrib/admin/sites.py:249 contrib/admin/sites.py:255
    400400#: contrib/admin/views/decorators.py:66
    401401msgid "Usernames cannot contain the '@' character."
    402402msgstr "Användarnamn får inte innehålla '@'-tecknet."
    403403
    404 #: contrib/admin/sites.py:253 contrib/admin/views/decorators.py:62
     404#: contrib/admin/sites.py:252 contrib/admin/views/decorators.py:62
    405405#, python-format
    406406msgid "Your e-mail address is not your username. Try '%s' instead."
    407407msgstr "Din e-postadress är inte ditt användarnamn. Försök med '%s' istället."
    408408
    409 #: contrib/admin/sites.py:313
     409#: contrib/admin/sites.py:312
    410410msgid "Site administration"
    411411msgstr "Webbplatsadministration"
    412412
    413 #: contrib/admin/sites.py:326 contrib/admin/templates/admin/login.html:26
     413#: contrib/admin/sites.py:325 contrib/admin/templates/admin/login.html:26
    414414#: contrib/admin/templates/registration/password_reset_complete.html:14
    415415#: contrib/admin/views/decorators.py:20
    416416msgid "Log in"
    417417msgstr "Logga in"
    418418
    419 #: contrib/admin/sites.py:373
     419#: contrib/admin/sites.py:372
    420420#, python-format
    421421msgid "%s administration"
    422422msgstr "Administration av %s"
    msgstr "Aktuell:" 
    447447msgid "Change:"
    448448msgstr "Ändra:"
    449449
    450 #: contrib/admin/widgets.py:121
     450#: contrib/admin/widgets.py:123
    451451msgid "Lookup"
    452452msgstr "Uppslag"
    453453
    454 #: contrib/admin/widgets.py:228
     454#: contrib/admin/widgets.py:230
    455455msgid "Add Another"
    456456msgstr "Lägg till ytterligare"
    457457
    msgstr "E-postadress:" 
    904904msgid "Reset my password"
    905905msgstr "Nollställ mitt lösenord"
    906906
    907 #: contrib/admin/templatetags/admin_list.py:288
     907#: contrib/admin/templatetags/admin_list.py:284
    908908msgid "All dates"
    909909msgstr "Alla datum"
    910910
    msgstr "Telefonnummer måste vara i formatet XXXX-XXXXXX." 
    28022802msgid "Enter a valid postal code in the format XXXXXX"
    28032803msgstr "Fyll i ett postnummer med formatet XXX XXX."
    28042804
     2805#: contrib/localflavor/se/forms.py:35
     2806msgid "Enter a valid Swedish organisation number."
     2807msgstr "Fyll i ett giltigt svenskt organisationsnummer."
     2808
     2809#: contrib/localflavor/se/forms.py:69
     2810msgid "Enter a valid Swedish personal identity number."
     2811msgstr "Fyll i ett giltigt svenskt personnummer."
     2812
     2813#: contrib/localflavor/se/forms.py:70
     2814msgid "Enter a Swedish personal identity number with 10 digits (YYMMDD-NNNN)."
     2815msgstr "Fyll i ett svenskt personnummer med 10 siffror (YYMMDD-NNNN)."
     2816
     2817#: contrib/localflavor/se/forms.py:71
     2818msgid "Co-ordination numbers are not allowed."
     2819msgstr "Samordningsnummer är inte tillåtna."
     2820
     2821#: contrib/localflavor/se/forms.py:110
     2822msgid "Enter a Swedish postal code in the format XXXXX."
     2823msgstr "Fyll i ett svenskt postnummer med formatet XXXXX."
     2824
     2825#: contrib/localflavor/se/se_counties.py:16
     2826msgid "Stockholm County"
     2827msgstr "Stockholms län"
     2828
     2829#: contrib/localflavor/se/se_counties.py:17
     2830msgid "Västerbotten County"
     2831msgstr "Västerbottens län"
     2832
     2833#: contrib/localflavor/se/se_counties.py:18
     2834msgid "Norrbotten County"
     2835msgstr "Norrbottens län"
     2836
     2837#: contrib/localflavor/se/se_counties.py:19
     2838msgid "Uppsala County"
     2839msgstr "Uppsala län"
     2840
     2841#: contrib/localflavor/se/se_counties.py:20
     2842msgid "Södermanland County"
     2843msgstr "Södermanlands län"
     2844
     2845#: contrib/localflavor/se/se_counties.py:21
     2846msgid "Östergötland County"
     2847msgstr "Östergötlands län"
     2848
     2849#: contrib/localflavor/se/se_counties.py:22
     2850msgid "Jönköping County"
     2851msgstr "Jönköpings län"
     2852
     2853#: contrib/localflavor/se/se_counties.py:23
     2854msgid "Kronoberg County"
     2855msgstr "Kronobergs län"
     2856
     2857#: contrib/localflavor/se/se_counties.py:24
     2858msgid "Kalmar County"
     2859msgstr "Kalmar län"
     2860
     2861#: contrib/localflavor/se/se_counties.py:25
     2862msgid "Gotland County"
     2863msgstr "Gotlands län"
     2864
     2865#: contrib/localflavor/se/se_counties.py:26
     2866msgid "Blekinge County"
     2867msgstr "Blekinge län"
     2868
     2869#: contrib/localflavor/se/se_counties.py:27
     2870msgid "Skåne County"
     2871msgstr "Skåne län"
     2872
     2873#: contrib/localflavor/se/se_counties.py:28
     2874msgid "Halland County"
     2875msgstr "Hallands län"
     2876
     2877#: contrib/localflavor/se/se_counties.py:29
     2878msgid "Västra Götaland County"
     2879msgstr "Västa Götalands län"
     2880
     2881#: contrib/localflavor/se/se_counties.py:30
     2882msgid "Värmland County"
     2883msgstr "Värmlands län"
     2884
     2885#: contrib/localflavor/se/se_counties.py:31
     2886msgid "Örebro County"
     2887msgstr "Örebro län"
     2888
     2889#: contrib/localflavor/se/se_counties.py:32
     2890msgid "Västmanland County"
     2891msgstr "Västmanlands län"
     2892
     2893#: contrib/localflavor/se/se_counties.py:33
     2894msgid "Dalarna County"
     2895msgstr "Dalarnas län"
     2896
     2897#: contrib/localflavor/se/se_counties.py:34
     2898msgid "Gävleborg County"
     2899msgstr "Gävleborgs län"
     2900
     2901#: contrib/localflavor/se/se_counties.py:35
     2902msgid "Västernorrland County"
     2903msgstr "Västernorrlands län"
     2904
     2905#: contrib/localflavor/se/se_counties.py:36
     2906msgid "Jämtland County"
     2907msgstr "Jämtlands län"
     2908
    28052909#: contrib/localflavor/sk/forms.py:30
    28062910msgid "Enter a postal code in the format XXXXX or XXX XX."
    28072911msgstr "Fyll i ett postnummer med formatet XXXXX eller XXX XX."
    msgstr "" 
    37113815"Välj ett giltigt alternativ. %(value)s finns inte bland tillgängliga "
    37123816"alternativ."
    37133817
    3714 #: forms/fields.py:697 forms/fields.py:758 forms/models.py:654
     3818#: forms/fields.py:697 forms/fields.py:758 forms/models.py:661
    37153819msgid "Enter a list of values."
    37163820msgstr "Fyll i en lista med värden."
    37173821
    msgstr "Sortering" 
    37353839msgid "%(model_name)s with this %(field_label)s already exists."
    37363840msgstr "%(model_name)s med detta %(field_label)s finns redan."
    37373841
    3738 #: forms/models.py:584
     3842#: forms/models.py:591
    37393843msgid "Select a valid choice. That choice is not one of the available choices."
    37403844msgstr ""
    37413845"Välj ett giltigt alternativ. Det valet finns inte bland tillgängliga "
    37423846"alternativ."
    37433847
    3744 #: forms/models.py:655
     3848#: forms/models.py:662
    37453849#, python-format
    37463850msgid "Select a valid choice. %s is not one of the available choices."
    37473851msgstr ""
    msgstr "%(verbose_name)s togs bort." 
    43174421#~ msgid "This field must be given if %(field)s is not %(value)s"
    43184422#~ msgstr "Detta fält måste anges om %(field)s inte är %(value)s"
    43194423
    4320 #~ msgid "Duplicate values are not allowed."
    4321 #~ msgstr "Dubbletter är inte tillåtna."
    4322 
    43234424#~ msgid "This value must be between %(lower)s and %(upper)s."
    43244425#~ msgstr "Detta värde måste vara mellan %(lower)s och %(upper)s."
    43254426
  • new file django/contrib/localflavor/se/forms.py

    diff --git a/django/contrib/localflavor/se/__init__.py b/django/contrib/localflavor/se/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/django/contrib/localflavor/se/forms.py b/django/contrib/localflavor/se/forms.py
    new file mode 100644
    index 0000000..4f26cc8
    - +  
     1"""
     2Swedish specific Form helpers
     3"""
     4
     5from django import forms
     6from django.utils.translation import ugettext_lazy as _
     7from django.forms.fields import EMPTY_VALUES
     8
     9from utils import *
     10
     11__all__ = ('SECountySelect', 'SEMunicipalitySelect', 'SEOrganisationNumberField', 'SEPersonalIdentityNumberField', 'SEPostalCodeField')
     12
     13
     14class SECountySelect(forms.Select):
     15    """
     16    A Select form widget that uses a list of the Swedish counties (län)
     17    as its choices.
     18
     19    The cleaned value is the official county code -- see
     20    http://en.wikipedia.org/wiki/Counties_of_Sweden for a list.
     21    """
     22
     23    def __init__(self, attrs=None):
     24        from se_counties import COUNTY_CHOICES
     25        super(SECountySelect, self).__init__(attrs=attrs, choices=COUNTY_CHOICES)
     26
     27
     28class SEMunicipalitySelect(forms.Select):
     29    """
     30    A Select form widget that uses a list of the Swedish municipalities
     31    (kommuner) as its choices.
     32
     33    Returns the official municipality code.
     34    """
     35
     36    def __init__(self, attrs=None):
     37        from se_municipalities import MUNICIPALITY_CHOICES
     38        super(SEMunicipalitySelect, self).__init__(attrs, choices=MUNICIPALITY_CHOICES)
     39
     40
     41class SEOrganisationNumberField(forms.CharField):
     42    """
     43    A form field that validates input as a Swedish organisation number
     44    (organisationsnummer).
     45
     46    This fields accepts the same data as SEPersonalIdentityField (for
     47    sole proprietorships (enskild firma)), with the exception of
     48    co-ordination numbers.
     49   
     50    It also accepts ordinary Swedish organisation numbers.
     51
     52    The correct formats are YYMMDD-XXXX and YYMMDDXXXX. YYMMDDXXXX will be
     53    corrected to YYMMDD-XXXX.
     54   
     55    The YYMMDD+XXXX format has the same meaning as for SEPersonalIdentifyNumber
     56    and can only be used if the organisation is a sole proprietorship
     57    (enskildfirma).
     58    """
     59
     60    default_error_messages = {
     61        'invalid': _('Enter a valid Swedish organisation number.'),
     62    }
     63
     64    def clean(self, value):
     65        value = super(SEOrganisationNumberField, self).clean(value)
     66       
     67        if value in EMPTY_VALUES:
     68            return u''
     69       
     70        match = SWEDISH_ID_NUMBER.match(value)
     71        if not match:
     72            raise forms.ValidationError(self.error_messages['invalid'])
     73
     74        gd = match.groupdict()
     75       
     76        # compare the calculated value with the checksum
     77        if id_number_checksum(gd) != int(gd['checksum']):
     78            raise forms.ValidationError(self.error_messages['invalid'])
     79
     80        if not (valid_organisation(gd) or valid_id_birthday(gd, False)):
     81            raise forms.ValidationError(self.error_messages['invalid'])
     82
     83        return format_id_number(gd)
     84
     85
     86class SEPersonalIdentityNumberField(forms.CharField):
     87    """
     88    A form field that validates input as a Swedish personal identity number
     89    (personnummer).
     90
     91    The correct formats are YYMMDD-XXXX, YYMMDD+XXXX and YYMMDDXXXX.
     92    YYMMDDXXXX will be corrected to YYMMDD-XXXX.
     93
     94    \+ indicates that the person is more than 100 years old, which will be
     95    taken into consideration when the date is validated.
     96   
     97    The checksum will be calculated and checked. The birth date is checked
     98    to be a valid date.
     99
     100    By default, co-ordination numbers (samordningsnummer) will be accepted.
     101    To only allow real personal identity numbers, pass the keyword argument
     102    coordination_number=False to the constructor.
     103    """
     104
     105    def __init__(self, *args, **kwargs):
     106        self.coordination_number = kwargs.pop('coordination_number', True)
     107        super(SEPersonalIdentityNumberField, self).__init__(*args, **kwargs)
     108
     109    default_error_messages = {
     110        'invalid': _('Enter a valid Swedish personal identity number.'),
     111        'invalid_length': _('Enter a Swedish personal identity number with 10 digits (YYMMDD-NNNN).'),
     112        'coordination_number': _('Co-ordination numbers are not allowed.'),
     113    }
     114
     115    def clean(self, value):
     116        value = super(SEPersonalIdentityNumberField, self).clean(value)
     117       
     118        if value in EMPTY_VALUES:
     119            return u''
     120       
     121        if LONG_SWEDISH_ID_NUMBER.match(value):
     122            raise forms.ValidationError(self.error_messages['invalid_length'])
     123       
     124        match = SWEDISH_ID_NUMBER.match(value)
     125        if not match:
     126            raise forms.ValidationError(self.error_messages['invalid'])
     127
     128        gd = match.groupdict()
     129       
     130        # compare the calculated value with the checksum
     131        if id_number_checksum(gd) != int(gd['checksum']):
     132            raise forms.ValidationError(self.error_messages['invalid'])
     133
     134        # check for valid birthday   
     135        if not valid_id_birthday(gd):
     136            raise forms.ValidationError(self.error_messages['invalid'])
     137
     138        # make sure that co-ordination numbers do not pass if not allowed
     139        if not self.coordination_number and int(gd['day']) > 60:
     140            raise forms.ValidationError(self.error_messages['coordination_number'])
     141 
     142        return format_id_number(gd)
     143
     144
     145class SEPostalCodeField(forms.RegexField):
     146    """
     147    A form field that validates input as a Swedish postal code (postnummer).
     148    Valid codes consist of five digits (XXXXX). The number can optionally be
     149    formatted with a space after the third digit (XXX XX).
     150
     151    The cleaned value will never contain the space.
     152    """
     153
     154    default_error_messages = {
     155        'invalid': _('Enter a Swedish postal code in the format XXXXX.'),
     156    }
     157
     158    def __init__(self, *args, **kwargs):
     159        super(SEPostalCodeField, self).__init__(SE_POSTAL_CODE, *args, **kwargs)
     160
     161    def clean(self, value):
     162        return super(SEPostalCodeField, self).clean(value).replace(' ', '')
     163
     164
  • new file django/contrib/localflavor/se/se_counties.py

    diff --git a/django/contrib/localflavor/se/se_counties.py b/django/contrib/localflavor/se/se_counties.py
    new file mode 100644
    index 0000000..0944064
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3A alphabetical list of Swedish counties, sorted by county codes.
     4
     5
     6http://en.wikipedia.org/wiki/Counties_of_Sweden
     7
     8This exists in this standalone file so that it's only imported into memory
     9when explicitly needed.
     10
     11"""
     12
     13from django.utils.translation import ugettext_lazy as _
     14
     15COUNTY_CHOICES = (
     16    ('AB', _(u'Stockholm County')),
     17    ('AC', _(u'Västerbotten County')),
     18    ('BD', _(u'Norrbotten County')),
     19    ('C', _(u'Uppsala County')),
     20    ('D', _(u'Södermanland County')),
     21    ('E', _(u'Östergötland County')),
     22    ('F', _(u'Jönköping County')),
     23    ('G', _(u'Kronoberg County')),
     24    ('H', _(u'Kalmar County')),
     25    ('I', _(u'Gotland County')),
     26    ('K', _(u'Blekinge County')),
     27    ('M', _(u'Skåne County')),
     28    ('N', _(u'Halland County')),
     29    ('O', _(u'Västra Götaland County')),
     30    ('S', _(u'Värmland County')),
     31    ('T', _(u'Örebro County')),
     32    ('U', _(u'Västmanland County')),
     33    ('W', _(u'Dalarna County')),
     34    ('X', _(u'Gävleborg County')),
     35    ('Y', _(u'Västernorrland County')),
     36    ('Z', _(u'Jämtland County')),
     37)
  • new file django/contrib/localflavor/se/se_municipalities.py

    diff --git a/django/contrib/localflavor/se/se_municipalities.py b/django/contrib/localflavor/se/se_municipalities.py
    new file mode 100644
    index 0000000..2035dda
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3An alphabetical list of Swedish municipalities for use as `choices` in a
     4formfield.
     5
     6This exists in this standalone file so that it's only imported into memory
     7when explicitly needed.
     8
     9This list was fetched 2008-10-03 from:
     10http://www.ssd.scb.se/databaser/makro/visavar.asp?yp=duwird&xu=c5587001&lang=2&langdb=2&Fromwhere=S&omradekod=BE&huvudtabell=BefArealTathetKon&innehall=Areal&prodid=BE0101&deltabell=K1&fromSok=&preskat=O
     11
     12"""
     13
     14MUNICIPALITY_CHOICES = (
     15    ('1440', u'Ale'),
     16    ('1489', u'Alingsås'),
     17    ('0764', u'Alvesta'),
     18    ('0604', u'Aneby'),
     19    ('1984', u'Arboga'),
     20    ('2506', u'Arjeplog'),
     21    ('2505', u'Arvidsjaur'),
     22    ('1784', u'Arvika'),
     23    ('1882', u'Askersund'),
     24    ('2084', u'Avesta'),
     25    ('1460', u'Bengtsfors'),
     26    ('2326', u'Berg'),
     27    ('2403', u'Bjurholm'),
     28    ('1260', u'Bjuv'),
     29    ('2582', u'Boden'),
     30    ('1443', u'Bollebygd'),
     31    ('2183', u'Bollnäs'),
     32    ('0885', u'Borgholm'),
     33    ('2081', u'Borlänge'),
     34    ('1490', u'Borås'),
     35    ('0127', u'Botkyrka'),
     36    ('0560', u'Boxholm'),
     37    ('1272', u'Bromölla'),
     38    ('2305', u'Bräcke'),
     39    ('1231', u'Burlöv'),
     40    ('1278', u'Båstad'),
     41    ('1438', u'Dals-Ed'),
     42    ('0162', u'Danderyd'),
     43    ('1862', u'Degerfors'),
     44    ('2425', u'Dorotea'),
     45    ('1730', u'Eda'),
     46    ('0125', u'Ekerö'),
     47    ('0686', u'Eksjö'),
     48    ('0862', u'Emmaboda'),
     49    ('0381', u'Enköping'),
     50    ('0484', u'Eskilstuna'),
     51    ('1285', u'Eslöv'),
     52    ('1445', u'Essunga'),
     53    ('1982', u'Fagersta'),
     54    ('1382', u'Falkenberg'),
     55    ('1499', u'Falköping'),
     56    ('2080', u'Falun'),
     57    ('1782', u'Filipstad'),
     58    ('0562', u'Finspång'),
     59    ('0482', u'Flen'),
     60    ('1763', u'Forshaga'),
     61    ('1439', u'Färgelanda'),
     62    ('2026', u'Gagnef'),
     63    ('0662', u'Gislaved'),
     64    ('0461', u'Gnesta'),
     65    ('0617', u'Gnosjö'),
     66    ('0980', u'Gotland'),
     67    ('1764', u'Grums'),
     68    ('1444', u'Grästorp'),
     69    ('1447', u'Gullspång'),
     70    ('2523', u'Gällivare'),
     71    ('2180', u'Gävle'),
     72    ('1480', u'Göteborg'),
     73    ('1471', u'Götene'),
     74    ('0643', u'Habo'),
     75    ('1783', u'Hagfors'),
     76    ('1861', u'Hallsberg'),
     77    ('1961', u'Hallstahammar'),
     78    ('1380', u'Halmstad'),
     79    ('1761', u'Hammarö'),
     80    ('0136', u'Haninge'),
     81    ('2583', u'Haparanda'),
     82    ('0331', u'Heby'),
     83    ('2083', u'Hedemora'),
     84    ('1283', u'Helsingborg'),
     85    ('1466', u'Herrljunga'),
     86    ('1497', u'Hjo'),
     87    ('2104', u'Hofors'),
     88    ('0126', u'Huddinge'),
     89    ('2184', u'Hudiksvall'),
     90    ('0860', u'Hultsfred'),
     91    ('1315', u'Hylte'),
     92    ('1863', u'Hällefors'),
     93    ('2361', u'Härjedalen'),
     94    ('2280', u'Härnösand'),
     95    ('1401', u'Härryda'),
     96    ('1293', u'Hässleholm'),
     97    ('0305', u'Håbo'),
     98    ('1284', u'Höganäs'),
     99    ('0821', u'Högsby'),
     100    ('1266', u'Hörby'),
     101    ('1267', u'Höör'),
     102    ('2510', u'Jokkmokk'),
     103    ('0123', u'Järfälla'),
     104    ('0680', u'Jönköping'),
     105    ('2514', u'Kalix'),
     106    ('0880', u'Kalmar'),
     107    ('1446', u'Karlsborg'),
     108    ('1082', u'Karlshamn'),
     109    ('1883', u'Karlskoga'),
     110    ('1080', u'Karlskrona'),
     111    ('1780', u'Karlstad'),
     112    ('0483', u'Katrineholm'),
     113    ('1715', u'Kil'),
     114    ('0513', u'Kinda'),
     115    ('2584', u'Kiruna'),
     116    ('1276', u'Klippan'),
     117    ('0330', u'Knivsta'),
     118    ('2282', u'Kramfors'),
     119    ('1290', u'Kristianstad'),
     120    ('1781', u'Kristinehamn'),
     121    ('2309', u'Krokom'),
     122    ('1881', u'Kumla'),
     123    ('1384', u'Kungsbacka'),
     124    ('1960', u'Kungsör'),
     125    ('1482', u'Kungälv'),
     126    ('1261', u'Kävlinge'),
     127    ('1983', u'Köping'),
     128    ('1381', u'Laholm'),
     129    ('1282', u'Landskrona'),
     130    ('1860', u'Laxå'),
     131    ('1814', u'Lekeberg'),
     132    ('2029', u'Leksand'),
     133    ('1441', u'Lerum'),
     134    ('0761', u'Lessebo'),
     135    ('0186', u'Lidingö'),
     136    ('1494', u'Lidköping'),
     137    ('1462', u'Lilla Edet'),
     138    ('1885', u'Lindesberg'),
     139    ('0580', u'Linköping'),
     140    ('0781', u'Ljungby'),
     141    ('2161', u'Ljusdal'),
     142    ('1864', u'Ljusnarsberg'),
     143    ('1262', u'Lomma'),
     144    ('2085', u'Ludvika'),
     145    ('2580', u'Luleå'),
     146    ('1281', u'Lund'),
     147    ('2481', u'Lycksele'),
     148    ('1484', u'Lysekil'),
     149    ('1280', u'Malmö'),
     150    ('2023', u'Malung-Sälen'),
     151    ('2418', u'Malå'),
     152    ('1493', u'Mariestad'),
     153    ('1463', u'Mark'),
     154    ('0767', u'Markaryd'),
     155    ('1461', u'Mellerud'),
     156    ('0586', u'Mjölby'),
     157    ('2062', u'Mora'),
     158    ('0583', u'Motala'),
     159    ('0642', u'Mullsjö'),
     160    ('1430', u'Munkedal'),
     161    ('1762', u'Munkfors'),
     162    ('1481', u'Mölndal'),
     163    ('0861', u'Mönsterås'),
     164    ('0840', u'Mörbylånga'),
     165    ('0182', u'Nacka'),
     166    ('1884', u'Nora'),
     167    ('1962', u'Norberg'),
     168    ('2132', u'Nordanstig'),
     169    ('2401', u'Nordmaling'),
     170    ('0581', u'Norrköping'),
     171    ('0188', u'Norrtälje'),
     172    ('2417', u'Norsjö'),
     173    ('0881', u'Nybro'),
     174    ('0140', u'Nykvarn'),
     175    ('0480', u'Nyköping'),
     176    ('0192', u'Nynäshamn'),
     177    ('0682', u'Nässjö'),
     178    ('2101', u'Ockelbo'),
     179    ('1060', u'Olofström'),
     180    ('2034', u'Orsa'),
     181    ('1421', u'Orust'),
     182    ('1273', u'Osby'),
     183    ('0882', u'Oskarshamn'),
     184    ('2121', u'Ovanåker'),
     185    ('0481', u'Oxelösund'),
     186    ('2521', u'Pajala'),
     187    ('1402', u'Partille'),
     188    ('1275', u'Perstorp'),
     189    ('2581', u'Piteå'),
     190    ('2303', u'Ragunda'),
     191    ('2409', u'Robertsfors'),
     192    ('1081', u'Ronneby'),
     193    ('2031', u'Rättvik'),
     194    ('1981', u'Sala'),
     195    ('0128', u'Salem'),
     196    ('2181', u'Sandviken'),
     197    ('0191', u'Sigtuna'),
     198    ('1291', u'Simrishamn'),
     199    ('1265', u'Sjöbo'),
     200    ('1495', u'Skara'),
     201    ('2482', u'Skellefteå'),
     202    ('1904', u'Skinnskatteberg'),
     203    ('1264', u'Skurup'),
     204    ('1496', u'Skövde'),
     205    ('2061', u'Smedjebacken'),
     206    ('2283', u'Sollefteå'),
     207    ('0163', u'Sollentuna'),
     208    ('0184', u'Solna'),
     209    ('2422', u'Sorsele'),
     210    ('1427', u'Sotenäs'),
     211    ('1230', u'Staffanstorp'),
     212    ('1415', u'Stenungsund'),
     213    ('0180', u'Stockholm'),
     214    ('1760', u'Storfors'),
     215    ('2421', u'Storuman'),
     216    ('0486', u'Strängnäs'),
     217    ('1486', u'Strömstad'),
     218    ('2313', u'Strömsund'),
     219    ('0183', u'Sundbyberg'),
     220    ('2281', u'Sundsvall'),
     221    ('1766', u'Sunne'),
     222    ('1907', u'Surahammar'),
     223    ('1214', u'Svalöv'),
     224    ('1263', u'Svedala'),
     225    ('1465', u'Svenljunga'),
     226    ('1785', u'Säffle'),
     227    ('2082', u'Säter'),
     228    ('0684', u'Sävsjö'),
     229    ('2182', u'Söderhamn'),
     230    ('0582', u'Söderköping'),
     231    ('0181', u'Södertälje'),
     232    ('1083', u'Sölvesborg'),
     233    ('1435', u'Tanum'),
     234    ('1472', u'Tibro'),
     235    ('1498', u'Tidaholm'),
     236    ('0360', u'Tierp'),
     237    ('2262', u'Timrå'),
     238    ('0763', u'Tingsryd'),
     239    ('1419', u'Tjörn'),
     240    ('1270', u'Tomelilla'),
     241    ('1737', u'Torsby'),
     242    ('0834', u'Torsås'),
     243    ('1452', u'Tranemo'),
     244    ('0687', u'Tranås'),
     245    ('1287', u'Trelleborg'),
     246    ('1488', u'Trollhättan'),
     247    ('0488', u'Trosa'),
     248    ('0138', u'Tyresö'),
     249    ('0160', u'Täby'),
     250    ('1473', u'Töreboda'),
     251    ('1485', u'Uddevalla'),
     252    ('1491', u'Ulricehamn'),
     253    ('2480', u'Umeå'),
     254    ('0114', u'Upplands Väsby'),
     255    ('0139', u'Upplands-Bro'),
     256    ('0380', u'Uppsala'),
     257    ('0760', u'Uppvidinge'),
     258    ('0584', u'Vadstena'),
     259    ('0665', u'Vaggeryd'),
     260    ('0563', u'Valdemarsvik'),
     261    ('0115', u'Vallentuna'),
     262    ('2021', u'Vansbro'),
     263    ('1470', u'Vara'),
     264    ('1383', u'Varberg'),
     265    ('0187', u'Vaxholm'),
     266    ('1233', u'Vellinge'),
     267    ('0685', u'Vetlanda'),
     268    ('2462', u'Vilhelmina'),
     269    ('0884', u'Vimmerby'),
     270    ('2404', u'Vindeln'),
     271    ('0428', u'Vingåker'),
     272    ('1487', u'Vänersborg'),
     273    ('2460', u'Vännäs'),
     274    ('0120', u'Värmdö'),
     275    ('0683', u'Värnamo'),
     276    ('0883', u'Västervik'),
     277    ('1980', u'Västerås'),
     278    ('0780', u'Växjö'),
     279    ('1442', u'Vårgårda'),
     280    ('0512', u'Ydre'),
     281    ('1286', u'Ystad'),
     282    ('0765', u'Älmhult'),
     283    ('2039', u'Älvdalen'),
     284    ('0319', u'Älvkarleby'),
     285    ('2560', u'Älvsbyn'),
     286    ('1292', u'Ängelholm'),
     287    ('1492', u'Åmål'),
     288    ('2260', u'Ånge'),
     289    ('2321', u'Åre'),
     290    ('1765', u'Årjäng'),
     291    ('2463', u'Åsele'),
     292    ('1277', u'Åstorp'),
     293    ('0561', u'Åtvidaberg'),
     294    ('1407', u'Öckerö'),
     295    ('0509', u'Ödeshög'),
     296    ('1880', u'Örebro'),
     297    ('1257', u'Örkelljunga'),
     298    ('2284', u'Örnsköldsvik'),
     299    ('2380', u'Östersund'),
     300    ('0117', u'Österåker'),
     301    ('0382', u'Östhammar'),
     302    ('1256', u'Östra Göinge'),
     303    ('2513', u'Överkalix'),
     304    ('2518', u'Övertorneå'),
     305)
  • new file django/contrib/localflavor/se/utils.py

    diff --git a/django/contrib/localflavor/se/utils.py b/django/contrib/localflavor/se/utils.py
    new file mode 100644
    index 0000000..f9b3cc6
    - +  
     1import re
     2import time
     3import datetime
     4
     5SWEDISH_ID_NUMBER = re.compile(r'^(?P<year>\d{2})(?P<month>\d{2})(?P<day>\d{2})(?P<sign>[\-+]?)(?P<serial>\d{3})(?P<checksum>\d)$')
     6LONG_SWEDISH_ID_NUMBER = re.compile(r'^\d{8}[\-+]?\d{4}$')
     7SE_POSTAL_CODE = re.compile(r'^[1-9]\d{2} ?\d{2}$')
     8
     9def id_number_checksum(gd):
     10    """
     11    Calculates a Swedish id number checksum 
     12    """
     13
     14    n = s = 0
     15    for c in (gd['year'] + gd['month'] + gd['day'] + gd['serial']):
     16        tmp = ((n % 2) and 1 or 2) * int(c)
     17        if tmp > 9:
     18            tmp = sum([int(i) for i in str(tmp)])
     19 
     20        s += tmp
     21        n += 1
     22 
     23    return (((s / 10) + 1) * 10) - s
     24
     25def valid_id_birthday(gd, fix_coordination_number_day=True):
     26
     27    day = int(gd['day'])
     28    if fix_coordination_number_day and day > 60:
     29        day -= 60
     30
     31    current_year = datetime.date.today().year
     32    year = int(time.strftime('%Y')) - int(time.strftime('%y')) + int(gd['year'])
     33   
     34    if ('%s%s%02d' % (gd['year'], gd['month'], day)) > time.strftime('%y%m%d'):
     35        year -= 100
     36
     37    # if the person is older than 100 years
     38    if gd['sign'] == '+':
     39        year -= 100
     40
     41    # Make sure it is a valid date
     42    try:
     43        datetime.date(year, int(gd['month']), day)
     44        return True
     45    except ValueError:
     46        return False
     47
     48def format_id_number(gd):
     49    if not gd['sign']:
     50        gd['sign'] = '-'
     51
     52    return unicode(gd['year'] + gd['month'] + gd['day'] + gd['sign'] + gd['serial'] + gd['checksum'])
     53
     54def valid_organisation(gd):
     55    return int(gd['month']) >= 20 and gd['sign'] in ('-', '')
     56
  • docs/ref/contrib/localflavor.txt

    diff --git a/docs/ref/contrib/localflavor.txt b/docs/ref/contrib/localflavor.txt
    index 6771efc..a6b6525 100644
    a b Countries currently supported by :mod:`~django.contrib.localflavor` are: 
    6060    * Slovakia_
    6161    * `South Africa`_
    6262    * Spain_
     63    * Sweden_
    6364    * Switzerland_
    6465    * `United Kingdom`_
    6566    * `United States of America`_
    Here's an example of how to use them:: 
    99100.. _Slovakia: `Slovakia (sk)`_
    100101.. _South Africa: `South Africa (za)`_
    101102.. _Spain: `Spain (es)`_
     103.. _Sweden: `Sweden (se)`_
    102104.. _Switzerland: `Switzerland (ch)`_
    103105.. _United Kingdom: `United Kingdom (uk)`_
    104106.. _United States of America: `United States of America (us)`_
    Spain (``es``) 
    573575
    574576    A ``Select`` widget that uses a list of Spanish regions as its choices.
    575577
     578Sweden (``se``)
     579===============
     580
     581.. class:: se.forms.SECountySelect
     582
     583    A Select form widget that uses a list of the Swedish counties (län)
     584    as its choices.
     585
     586    The cleaned value is the official county code -- see
     587    http://en.wikipedia.org/wiki/Counties_of_Sweden for a list.
     588
     589.. class:: se.forms.SEMunicipalitySelect
     590
     591    A Select form widget that uses a list of the Swedish municipalities
     592    (kommuner) as its choices.
     593
     594    Returns the official municipality code.
     595
     596.. class:: se.forms.SEOrganisationNumber
     597
     598    A form field that validates input as a Swedish organisation number
     599    (organisationsnummer).
     600
     601    This fields accepts the same data as SEPersonalIdentityField (for
     602    sole proprietorships (enskild firma)), with the exception of
     603    co-ordination numbers.
     604   
     605    It also accepts ordinary Swedish organisation numbers.
     606
     607    The correct formats are YYMMDD-XXXX and YYMMDDXXXX. YYMMDDXXXX will be
     608    corrected to YYMMDD-XXXX.
     609   
     610    The YYMMDD+XXXX format has the same meaning as for SEPersonalIdentifyNumber
     611    and can only be used if the organisation is a sole proprietorship
     612    (enskildfirma).
     613
     614.. class:: se.forms.SEPersonalIdentityNumber
     615
     616    A form field that validates input as a Swedish personal identity number
     617    (personnummer).
     618
     619    The correct formats are YYMMDD-XXXX, YYMMDD+XXXX and YYMMDDXXXX.
     620    YYMMDDXXXX will be corrected to YYMMDD-XXXX.
     621
     622    \+ indicates that the person is more than 100 years old, which will be
     623    taken into consideration when the date is validated.
     624   
     625    The checksum will be calculated and checked. The birth date is checked
     626    to be a valid date.
     627
     628    By default, co-ordination numbers (samordningsnummer) will be accepted.
     629    To only allow real personal identity numbers, pass the keyword argument
     630    coordination_number=False to the constructor.
     631
     632.. class:: se.forms.SEPostalCodeField
     633
     634    A form field that validates input as a Swedish postal code (postnummer).
     635    Valid codes consist of five digits (XXXXX). The number can optionally be
     636    formatted with a space after the third digit (XXX XX).
     637
     638    The cleaned value will never contain the space.
     639
    576640Switzerland (``ch``)
    577641====================
    578642
  • new file tests/regressiontests/forms/localflavor/se.py

    diff --git a/tests/regressiontests/forms/localflavor/se.py b/tests/regressiontests/forms/localflavor/se.py
    new file mode 100644
    index 0000000..99553c7
    - +  
     1# -*- coding: utf-8 -*-
     2# Tests for the contrib/localflavor/se form fields.
     3
     4tests = r"""
     5
     6# SECountySelect #####################################################
     7>>> from django.contrib.localflavor.se.forms import SECountySelect
     8
     9>>> w = SECountySelect()
     10>>> w.render('swedish_county', 'E')
     11u'<select name="swedish_county">\n<option value="AB">Stockholm County</option>\n<option value="AC">V\xe4sterbotten County</option>\n<option value="BD">Norrbotten County</option>\n<option value="C">Uppsala County</option>\n<option value="D">S\xf6dermanland County</option>\n<option value="E" selected="selected">\xd6sterg\xf6tland County</option>\n<option value="F">J\xf6nk\xf6ping County</option>\n<option value="G">Kronoberg County</option>\n<option value="H">Kalmar County</option>\n<option value="I">Gotland County</option>\n<option value="K">Blekinge County</option>\n<option value="M">Sk\xe5ne County</option>\n<option value="N">Halland County</option>\n<option value="O">V\xe4stra G\xf6taland County</option>\n<option value="S">V\xe4rmland County</option>\n<option value="T">\xd6rebro County</option>\n<option value="U">V\xe4stmanland County</option>\n<option value="W">Dalarna County</option>\n<option value="X">G\xe4vleborg County</option>\n<option value="Y">V\xe4sternorrland County</option>\n<option value="Z">J\xe4mtland County</option>\n</select>'
     12
     13>>> from django.contrib.localflavor.se.forms import SEMunicipalitySelect
     14>>> w = SEMunicipalitySelect()
     15>>> w.render('swedish_municipalities', '0580')
     16u'<select name="swedish_municipalities">\n<option value="1440">Ale</option>\n<option value="1489">Alings\xe5s</option>\n<option value="0764">Alvesta</option>\n<option value="0604">Aneby</option>\n<option value="1984">Arboga</option>\n<option value="2506">Arjeplog</option>\n<option value="2505">Arvidsjaur</option>\n<option value="1784">Arvika</option>\n<option value="1882">Askersund</option>\n<option value="2084">Avesta</option>\n<option value="1460">Bengtsfors</option>\n<option value="2326">Berg</option>\n<option value="2403">Bjurholm</option>\n<option value="1260">Bjuv</option>\n<option value="2582">Boden</option>\n<option value="1443">Bollebygd</option>\n<option value="2183">Bolln\xe4s</option>\n<option value="0885">Borgholm</option>\n<option value="2081">Borl\xe4nge</option>\n<option value="1490">Bor\xe5s</option>\n<option value="0127">Botkyrka</option>\n<option value="0560">Boxholm</option>\n<option value="1272">Brom\xf6lla</option>\n<option value="2305">Br\xe4cke</option>\n<option value="1231">Burl\xf6v</option>\n<option value="1278">B\xe5stad</option>\n<option value="1438">Dals-Ed</option>\n<option value="0162">Danderyd</option>\n<option value="1862">Degerfors</option>\n<option value="2425">Dorotea</option>\n<option value="1730">Eda</option>\n<option value="0125">Eker\xf6</option>\n<option value="0686">Eksj\xf6</option>\n<option value="0862">Emmaboda</option>\n<option value="0381">Enk\xf6ping</option>\n<option value="0484">Eskilstuna</option>\n<option value="1285">Esl\xf6v</option>\n<option value="1445">Essunga</option>\n<option value="1982">Fagersta</option>\n<option value="1382">Falkenberg</option>\n<option value="1499">Falk\xf6ping</option>\n<option value="2080">Falun</option>\n<option value="1782">Filipstad</option>\n<option value="0562">Finsp\xe5ng</option>\n<option value="0482">Flen</option>\n<option value="1763">Forshaga</option>\n<option value="1439">F\xe4rgelanda</option>\n<option value="2026">Gagnef</option>\n<option value="0662">Gislaved</option>\n<option value="0461">Gnesta</option>\n<option value="0617">Gnosj\xf6</option>\n<option value="0980">Gotland</option>\n<option value="1764">Grums</option>\n<option value="1444">Gr\xe4storp</option>\n<option value="1447">Gullsp\xe5ng</option>\n<option value="2523">G\xe4llivare</option>\n<option value="2180">G\xe4vle</option>\n<option value="1480">G\xf6teborg</option>\n<option value="1471">G\xf6tene</option>\n<option value="0643">Habo</option>\n<option value="1783">Hagfors</option>\n<option value="1861">Hallsberg</option>\n<option value="1961">Hallstahammar</option>\n<option value="1380">Halmstad</option>\n<option value="1761">Hammar\xf6</option>\n<option value="0136">Haninge</option>\n<option value="2583">Haparanda</option>\n<option value="0331">Heby</option>\n<option value="2083">Hedemora</option>\n<option value="1283">Helsingborg</option>\n<option value="1466">Herrljunga</option>\n<option value="1497">Hjo</option>\n<option value="2104">Hofors</option>\n<option value="0126">Huddinge</option>\n<option value="2184">Hudiksvall</option>\n<option value="0860">Hultsfred</option>\n<option value="1315">Hylte</option>\n<option value="1863">H\xe4llefors</option>\n<option value="2361">H\xe4rjedalen</option>\n<option value="2280">H\xe4rn\xf6sand</option>\n<option value="1401">H\xe4rryda</option>\n<option value="1293">H\xe4ssleholm</option>\n<option value="0305">H\xe5bo</option>\n<option value="1284">H\xf6gan\xe4s</option>\n<option value="0821">H\xf6gsby</option>\n<option value="1266">H\xf6rby</option>\n<option value="1267">H\xf6\xf6r</option>\n<option value="2510">Jokkmokk</option>\n<option value="0123">J\xe4rf\xe4lla</option>\n<option value="0680">J\xf6nk\xf6ping</option>\n<option value="2514">Kalix</option>\n<option value="0880">Kalmar</option>\n<option value="1446">Karlsborg</option>\n<option value="1082">Karlshamn</option>\n<option value="1883">Karlskoga</option>\n<option value="1080">Karlskrona</option>\n<option value="1780">Karlstad</option>\n<option value="0483">Katrineholm</option>\n<option value="1715">Kil</option>\n<option value="0513">Kinda</option>\n<option value="2584">Kiruna</option>\n<option value="1276">Klippan</option>\n<option value="0330">Knivsta</option>\n<option value="2282">Kramfors</option>\n<option value="1290">Kristianstad</option>\n<option value="1781">Kristinehamn</option>\n<option value="2309">Krokom</option>\n<option value="1881">Kumla</option>\n<option value="1384">Kungsbacka</option>\n<option value="1960">Kungs\xf6r</option>\n<option value="1482">Kung\xe4lv</option>\n<option value="1261">K\xe4vlinge</option>\n<option value="1983">K\xf6ping</option>\n<option value="1381">Laholm</option>\n<option value="1282">Landskrona</option>\n<option value="1860">Lax\xe5</option>\n<option value="1814">Lekeberg</option>\n<option value="2029">Leksand</option>\n<option value="1441">Lerum</option>\n<option value="0761">Lessebo</option>\n<option value="0186">Liding\xf6</option>\n<option value="1494">Lidk\xf6ping</option>\n<option value="1462">Lilla Edet</option>\n<option value="1885">Lindesberg</option>\n<option value="0580" selected="selected">Link\xf6ping</option>\n<option value="0781">Ljungby</option>\n<option value="2161">Ljusdal</option>\n<option value="1864">Ljusnarsberg</option>\n<option value="1262">Lomma</option>\n<option value="2085">Ludvika</option>\n<option value="2580">Lule\xe5</option>\n<option value="1281">Lund</option>\n<option value="2481">Lycksele</option>\n<option value="1484">Lysekil</option>\n<option value="1280">Malm\xf6</option>\n<option value="2023">Malung-S\xe4len</option>\n<option value="2418">Mal\xe5</option>\n<option value="1493">Mariestad</option>\n<option value="1463">Mark</option>\n<option value="0767">Markaryd</option>\n<option value="1461">Mellerud</option>\n<option value="0586">Mj\xf6lby</option>\n<option value="2062">Mora</option>\n<option value="0583">Motala</option>\n<option value="0642">Mullsj\xf6</option>\n<option value="1430">Munkedal</option>\n<option value="1762">Munkfors</option>\n<option value="1481">M\xf6lndal</option>\n<option value="0861">M\xf6nster\xe5s</option>\n<option value="0840">M\xf6rbyl\xe5nga</option>\n<option value="0182">Nacka</option>\n<option value="1884">Nora</option>\n<option value="1962">Norberg</option>\n<option value="2132">Nordanstig</option>\n<option value="2401">Nordmaling</option>\n<option value="0581">Norrk\xf6ping</option>\n<option value="0188">Norrt\xe4lje</option>\n<option value="2417">Norsj\xf6</option>\n<option value="0881">Nybro</option>\n<option value="0140">Nykvarn</option>\n<option value="0480">Nyk\xf6ping</option>\n<option value="0192">Nyn\xe4shamn</option>\n<option value="0682">N\xe4ssj\xf6</option>\n<option value="2101">Ockelbo</option>\n<option value="1060">Olofstr\xf6m</option>\n<option value="2034">Orsa</option>\n<option value="1421">Orust</option>\n<option value="1273">Osby</option>\n<option value="0882">Oskarshamn</option>\n<option value="2121">Ovan\xe5ker</option>\n<option value="0481">Oxel\xf6sund</option>\n<option value="2521">Pajala</option>\n<option value="1402">Partille</option>\n<option value="1275">Perstorp</option>\n<option value="2581">Pite\xe5</option>\n<option value="2303">Ragunda</option>\n<option value="2409">Robertsfors</option>\n<option value="1081">Ronneby</option>\n<option value="2031">R\xe4ttvik</option>\n<option value="1981">Sala</option>\n<option value="0128">Salem</option>\n<option value="2181">Sandviken</option>\n<option value="0191">Sigtuna</option>\n<option value="1291">Simrishamn</option>\n<option value="1265">Sj\xf6bo</option>\n<option value="1495">Skara</option>\n<option value="2482">Skellefte\xe5</option>\n<option value="1904">Skinnskatteberg</option>\n<option value="1264">Skurup</option>\n<option value="1496">Sk\xf6vde</option>\n<option value="2061">Smedjebacken</option>\n<option value="2283">Sollefte\xe5</option>\n<option value="0163">Sollentuna</option>\n<option value="0184">Solna</option>\n<option value="2422">Sorsele</option>\n<option value="1427">Soten\xe4s</option>\n<option value="1230">Staffanstorp</option>\n<option value="1415">Stenungsund</option>\n<option value="0180">Stockholm</option>\n<option value="1760">Storfors</option>\n<option value="2421">Storuman</option>\n<option value="0486">Str\xe4ngn\xe4s</option>\n<option value="1486">Str\xf6mstad</option>\n<option value="2313">Str\xf6msund</option>\n<option value="0183">Sundbyberg</option>\n<option value="2281">Sundsvall</option>\n<option value="1766">Sunne</option>\n<option value="1907">Surahammar</option>\n<option value="1214">Sval\xf6v</option>\n<option value="1263">Svedala</option>\n<option value="1465">Svenljunga</option>\n<option value="1785">S\xe4ffle</option>\n<option value="2082">S\xe4ter</option>\n<option value="0684">S\xe4vsj\xf6</option>\n<option value="2182">S\xf6derhamn</option>\n<option value="0582">S\xf6derk\xf6ping</option>\n<option value="0181">S\xf6dert\xe4lje</option>\n<option value="1083">S\xf6lvesborg</option>\n<option value="1435">Tanum</option>\n<option value="1472">Tibro</option>\n<option value="1498">Tidaholm</option>\n<option value="0360">Tierp</option>\n<option value="2262">Timr\xe5</option>\n<option value="0763">Tingsryd</option>\n<option value="1419">Tj\xf6rn</option>\n<option value="1270">Tomelilla</option>\n<option value="1737">Torsby</option>\n<option value="0834">Tors\xe5s</option>\n<option value="1452">Tranemo</option>\n<option value="0687">Tran\xe5s</option>\n<option value="1287">Trelleborg</option>\n<option value="1488">Trollh\xe4ttan</option>\n<option value="0488">Trosa</option>\n<option value="0138">Tyres\xf6</option>\n<option value="0160">T\xe4by</option>\n<option value="1473">T\xf6reboda</option>\n<option value="1485">Uddevalla</option>\n<option value="1491">Ulricehamn</option>\n<option value="2480">Ume\xe5</option>\n<option value="0114">Upplands V\xe4sby</option>\n<option value="0139">Upplands-Bro</option>\n<option value="0380">Uppsala</option>\n<option value="0760">Uppvidinge</option>\n<option value="0584">Vadstena</option>\n<option value="0665">Vaggeryd</option>\n<option value="0563">Valdemarsvik</option>\n<option value="0115">Vallentuna</option>\n<option value="2021">Vansbro</option>\n<option value="1470">Vara</option>\n<option value="1383">Varberg</option>\n<option value="0187">Vaxholm</option>\n<option value="1233">Vellinge</option>\n<option value="0685">Vetlanda</option>\n<option value="2462">Vilhelmina</option>\n<option value="0884">Vimmerby</option>\n<option value="2404">Vindeln</option>\n<option value="0428">Ving\xe5ker</option>\n<option value="1487">V\xe4nersborg</option>\n<option value="2460">V\xe4nn\xe4s</option>\n<option value="0120">V\xe4rmd\xf6</option>\n<option value="0683">V\xe4rnamo</option>\n<option value="0883">V\xe4stervik</option>\n<option value="1980">V\xe4ster\xe5s</option>\n<option value="0780">V\xe4xj\xf6</option>\n<option value="1442">V\xe5rg\xe5rda</option>\n<option value="0512">Ydre</option>\n<option value="1286">Ystad</option>\n<option value="0765">\xc4lmhult</option>\n<option value="2039">\xc4lvdalen</option>\n<option value="0319">\xc4lvkarleby</option>\n<option value="2560">\xc4lvsbyn</option>\n<option value="1292">\xc4ngelholm</option>\n<option value="1492">\xc5m\xe5l</option>\n<option value="2260">\xc5nge</option>\n<option value="2321">\xc5re</option>\n<option value="1765">\xc5rj\xe4ng</option>\n<option value="2463">\xc5sele</option>\n<option value="1277">\xc5storp</option>\n<option value="0561">\xc5tvidaberg</option>\n<option value="1407">\xd6cker\xf6</option>\n<option value="0509">\xd6desh\xf6g</option>\n<option value="1880">\xd6rebro</option>\n<option value="1257">\xd6rkelljunga</option>\n<option value="2284">\xd6rnsk\xf6ldsvik</option>\n<option value="2380">\xd6stersund</option>\n<option value="0117">\xd6ster\xe5ker</option>\n<option value="0382">\xd6sthammar</option>\n<option value="1256">\xd6stra G\xf6inge</option>\n<option value="2513">\xd6verkalix</option>\n<option value="2518">\xd6vertorne\xe5</option>\n</select>'
     17
     18
     19
     20
     21# SEOrganisationNumberField #######################################
     22
     23>>> from django.contrib.localflavor.se.forms import SEOrganisationNumberField
     24
     25>>> f = SEOrganisationNumberField()
     26
     27# Check ordinary personal identity numbers first
     28>>> f.clean('870512-1989')
     29u'870512-1989'
     30>>> f.clean('870512-2128')
     31u'870512-2128'
     32>>> f.clean('081015-6315')
     33u'081015-6315'
     34>>> f.clean('081015+6315')
     35u'081015+6315'
     36>>> f.clean('0810156315')
     37u'081015-6315'
     38>>> f.clean('081015 6315')
     39Traceback (most recent call last):
     40...
     41ValidationError: [u'Enter a valid Swedish organisation number.']
     42
     43>>> f.clean('950231-4496')
     44Traceback (most recent call last):
     45...
     46ValidationError: [u'Enter a valid Swedish organisation number.']
     47
     48Invalid date - month 14
     49>>> f.clean('6914104499')
     50Traceback (most recent call last):
     51...
     52ValidationError: [u'Enter a valid Swedish organisation number.']
     53
     54No special treatment for 12 (four year digits) digits
     55>>> f.clean('19870512-1989')
     56Traceback (most recent call last):
     57...
     58ValidationError: [u'Enter a valid Swedish organisation number.']
     59
     60# Invalid value
     61>>> f.clean('950d314496')
     62Traceback (most recent call last):
     63...
     64ValidationError: [u'Enter a valid Swedish organisation number.']
     65
     66>>> f.clean('invalid!!!')
     67Traceback (most recent call last):
     68...
     69ValidationError: [u'Enter a valid Swedish organisation number.']
     70
     71# Invalid checksum
     72>>> f.clean('870514-1111')
     73Traceback (most recent call last):
     74...
     75ValidationError: [u'Enter a valid Swedish organisation number.']
     76
     77# Empty values
     78>>> f.clean('')
     79Traceback (most recent call last):
     80...
     81ValidationError: [u'This field is required.']
     82
     83>>> f.clean(None)
     84Traceback (most recent call last):
     85...
     86ValidationError: [u'This field is required.']
     87
     88# Co-ordination number checking
     89# Co-ordination numbers are not valid organisation numbers
     90
     91>>> f.clean('870574-1315')
     92Traceback (most recent call last):
     93...
     94ValidationError: [u'Enter a valid Swedish organisation number.']
     95
     96>>> f.clean('870573-1311')
     97Traceback (most recent call last):
     98...
     99ValidationError: [u'Enter a valid Swedish organisation number.']
     100
     101# Test some different organisation numbers
     102>>> f.clean('556074-7569') # IKEA Linköping
     103u'556074-7569'
     104
     105>>> f.clean('556074-3089') # Volvo Personvagnar
     106u'556074-3089'
     107
     108>>> f.clean('822001-5476') # LJS (organisation)
     109u'822001-5476'
     110
     111>>> f.clean('8220015476') # LJS (organisation)
     112u'822001-5476'
     113
     114>>> f.clean('212000-0449') # Katedralskolan Linköping (school)
     115u'212000-0449'
     116
     117>>> f.clean('556074+3089') # Volvo Personvagnar, bad formatting
     118Traceback (most recent call last):
     119...
     120ValidationError: [u'Enter a valid Swedish organisation number.']
     121
     122
     123# Empty values with required=False
     124>>> f = SEOrganisationNumberField(required=False)
     125
     126>>> f.clean(None)
     127u''
     128
     129>>> f.clean('')
     130u''
     131
     132
     133
     134# SEPersonalIdentityNumberField #######################################
     135
     136>>> from django.contrib.localflavor.se.forms import SEPersonalIdentityNumberField
     137
     138>>> f = SEPersonalIdentityNumberField()
     139>>> f.clean('870512-1989')
     140u'870512-1989'
     141
     142>>> f.clean('870512-2128')
     143u'870512-2128'
     144
     145The date and the extra numbers can be separated by - or +
     146>>> f.clean('081015-6315')
     147u'081015-6315'
     148
     149>>> f.clean('081015+6315')
     150u'081015+6315'
     151
     152>>> f.clean('0810156315')
     153u'081015-6315'
     154
     155Separation by space are not allowed
     156>>> f.clean('081015 6315')
     157Traceback (most recent call last):
     158...
     159ValidationError: [u'Enter a valid Swedish personal identity number.']
     160
     161February 31st does not exist
     162>>> f.clean('950231-4496')
     163Traceback (most recent call last):
     164...
     165ValidationError: [u'Enter a valid Swedish personal identity number.']
     166
     167Invalid date - month 14
     168>>> f.clean('6914104499')
     169Traceback (most recent call last):
     170...
     171ValidationError: [u'Enter a valid Swedish personal identity number.']
     172
     17312 (four year digits) digit numbers are not allowed
     174>>> f.clean('19870512-1989')
     175Traceback (most recent call last):
     176...
     177ValidationError: [u'Enter a Swedish personal identity number with 10 digits (YYMMDD-NNNN).']
     178
     179# Invalid value
     180>>> f.clean('950d314496')
     181Traceback (most recent call last):
     182...
     183ValidationError: [u'Enter a valid Swedish personal identity number.']
     184
     185>>> f.clean('invalid!!!')
     186Traceback (most recent call last):
     187...
     188ValidationError: [u'Enter a valid Swedish personal identity number.']
     189
     190# Invalid checksum
     191>>> f.clean('870514-1111')
     192Traceback (most recent call last):
     193...
     194ValidationError: [u'Enter a valid Swedish personal identity number.']
     195
     196# Empty values
     197>>> f.clean('')
     198Traceback (most recent call last):
     199...
     200ValidationError: [u'This field is required.']
     201
     202>>> f.clean(None)
     203Traceback (most recent call last):
     204...
     205ValidationError: [u'This field is required.']
     206
     207# Co-ordination number checking
     208>>> f.clean('870574-1315')
     209u'870574-1315'
     210
     211>>> f.clean('870574+1315')
     212u'870574+1315'
     213
     214>>> f.clean('870573-1311')
     215Traceback (most recent call last):
     216...
     217ValidationError: [u'Enter a valid Swedish personal identity number.']
     218
     219# Check valid co-ordination numbers, that should not be accepted
     220# because of coordination_number=False
     221>>> f = SEPersonalIdentityNumberField(coordination_number=False)
     222
     223>>> f.clean('870574-1315')
     224Traceback (most recent call last):
     225...
     226ValidationError: [u'Co-ordination numbers are not allowed.']
     227
     228>>> f.clean('870574+1315')
     229Traceback (most recent call last):
     230...
     231ValidationError: [u'Co-ordination numbers are not allowed.']
     232
     233>>> f.clean('8705741315')
     234Traceback (most recent call last):
     235...
     236ValidationError: [u'Co-ordination numbers are not allowed.']
     237
     238# Invalid co-ordination numbers should be treated as invalid, and not
     239# as co-ordination numbers
     240>>> f.clean('870573-1311')
     241Traceback (most recent call last):
     242...
     243ValidationError: [u'Enter a valid Swedish personal identity number.']
     244
     245# Empty values with required=False
     246>>> f = SEPersonalIdentityNumberField(required=False)
     247
     248>>> f.clean(None)
     249u''
     250
     251>>> f.clean('')
     252u''
     253
     254# SEPostalCodeField ###############################################
     255>>> from django.contrib.localflavor.se.forms import SEPostalCodeField
     256>>> f = SEPostalCodeField()
     257>>>
     258Postal codes can have spaces
     259>>> f.clean('589 37')
     260u'58937'
     261
     262... but the dont have to
     263>>> f.clean('58937')
     264u'58937'
     265>>> f.clean('abcasfassadf')
     266Traceback (most recent call last):
     267...
     268ValidationError: [u'Enter a Swedish postal code in the format XXXXX.']
     269
     270# Only one space is allowed for separation
     271>>> f.clean('589  37')
     272Traceback (most recent call last):
     273...
     274ValidationError: [u'Enter a Swedish postal code in the format XXXXX.']
     275
     276# The postal code must not start with 0
     277>>> f.clean('01234')
     278Traceback (most recent call last):
     279...
     280ValidationError: [u'Enter a Swedish postal code in the format XXXXX.']
     281
     282# Empty values
     283>>> f.clean('')
     284Traceback (most recent call last):
     285...
     286ValidationError: [u'This field is required.']
     287
     288>>> f.clean(None)
     289Traceback (most recent call last):
     290...
     291ValidationError: [u'This field is required.']
     292
     293# Empty values, required=False
     294>>> f = SEPostalCodeField(required=False)
     295>>> f.clean('')
     296u''
     297>>> f.clean(None)
     298u''
     299
     300"""
  • tests/regressiontests/forms/tests.py

    diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
    index 6a8b017..f930003 100644
    a b from localflavor.jp import tests as localflavor_jp_tests 
    2121from localflavor.nl import tests as localflavor_nl_tests
    2222from localflavor.pl import tests as localflavor_pl_tests
    2323from localflavor.ro import tests as localflavor_ro_tests
     24from localflavor.se import tests as localflavor_se_tests
    2425from localflavor.sk import tests as localflavor_sk_tests
    2526from localflavor.uk import tests as localflavor_uk_tests
    2627from localflavor.us import tests as localflavor_us_tests
    __test__ = { 
    5455    'localflavor_nl_tests': localflavor_nl_tests,
    5556    'localflavor_pl_tests': localflavor_pl_tests,
    5657    'localflavor_ro_tests': localflavor_ro_tests,
     58    'localflavor_se_tests': localflavor_se_tests,
    5759    'localflavor_sk_tests': localflavor_sk_tests,
    5860    'localflavor_uk_tests': localflavor_uk_tests,
    5961    'localflavor_us_tests': localflavor_us_tests,
Back to Top