Commit ae7213b5 authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

Fixed #14563 -- Added Turkish localflavor. Thanks to serkank for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14794 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 34a38637
Loading
Loading
Loading
Loading
+0 −0

Empty file added.

+91 −0
Original line number Diff line number Diff line
"""
TR-specific Form helpers
"""

from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select, CharField
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext_lazy as _
import re

phone_digits_re = re.compile(r'^(\+90|0)? ?(([1-9]\d{2})|\([1-9]\d{2}\)) ?([2-9]\d{2} ?\d{2} ?\d{2})$')

class TRPostalCodeField(RegexField):
    default_error_messages = {
        'invalid': _(u'Enter a postal code in the format XXXXX.'),
    }

    def __init__(self, *args, **kwargs):
        super(TRPostalCodeField, self).__init__(r'^\d{5}$',
            max_length=5, min_length=5, *args, **kwargs)

    def clean(self, value):
        value = super(TRPostalCodeField, self).clean(value)
        if value in EMPTY_VALUES:
            return u''
        if len(value) != 5:
            raise ValidationError(self.error_messages['invalid'])
        province_code = int(value[:2])
        if province_code == 0 or province_code > 81:
            raise ValidationError(self.error_messages['invalid'])
        return value


class TRPhoneNumberField(CharField):
    default_error_messages = {
        'invalid': _(u'Phone numbers must be in 0XXX XXX XXXX format.'),
    }

    def clean(self, value):
        super(TRPhoneNumberField, 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' % (m.group(2), m.group(4))
        raise ValidationError(self.error_messages['invalid'])

class TRIdentificationNumberField(Field):
    """
    A Turkey Identification Number number.
	See: http://tr.wikipedia.org/wiki/T%C3%BCrkiye_Cumhuriyeti_Kimlik_Numaras%C4%B1

    Checks the following rules to determine whether the number is valid:

        * The number is 11-digits.
        * First digit is not 0.
        * Conforms to the following two formula:
          (sum(1st, 3rd, 5th, 7th, 9th)*7 - sum(2nd,4th,6th,8th)) % 10 = 10th digit
          sum(1st to 10th) % 10 = 11th digit
    """
    default_error_messages = {
        'invalid': _(u'Enter a valid Turkish Identification number.'),
        'not_11': _(u'Turkish Identification number must be 11 digits.'),
    }

    def clean(self, value):
        super(TRIdentificationNumberField, self).clean(value)
        if value in EMPTY_VALUES:
            return u''
        if len(value) != 11:
            raise ValidationError(self.error_messages['not_11'])
        if not re.match(r'^\d{11}$', value):
            raise ValidationError(self.error_messages['invalid'])
        if int(value[0]) == 0:
            raise ValidationError(self.error_messages['invalid'])
        chksum = (sum([int(value[i]) for i in xrange(0,9,2)])*7-
				          sum([int(value[i]) for i in xrange(1,9,2)])) % 10
        if chksum != int(value[9]) or \
           (sum([int(value[i]) for i in xrange(10)]) % 10) != int(value[10]):
            raise ValidationError(self.error_messages['invalid'])
        return value

class TRProvinceSelect(Select):
    """
    A Select widget that uses a list of provinces in Turkey as its choices.
    """
    def __init__(self, attrs=None):
        from tr_provinces import PROVINCE_CHOICES
        super(TRProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
+89 −0
Original line number Diff line number Diff line
# -*- coding: utf-8 -*-
"""
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""

PROVINCE_CHOICES = (
    ('01', ('Adana')),
    ('02', ('Adıyaman')),
    ('03', ('Afyonkarahisar')),
    ('04', ('Ağrı')),
    ('68', ('Aksaray')),
    ('05', ('Amasya')),
    ('06', ('Ankara')),
    ('07', ('Antalya')),
    ('75', ('Ardahan')),
    ('08', ('Artvin')),
    ('09', ('Aydın')),
    ('10', ('Balıkesir')),
    ('74', ('Bartın')),
    ('72', ('Batman')),
    ('69', ('Bayburt')),
    ('11', ('Bilecik')),
    ('12', ('Bingöl')),
    ('13', ('Bitlis')),
    ('14', ('Bolu')),
    ('15', ('Burdur')),
    ('16', ('Bursa')),
    ('17', ('Çanakkale')),
    ('18', ('Çankırı')),
    ('19', ('Çorum')),
    ('20', ('Denizli')),
    ('21', ('Diyarbakır')),
    ('81', ('Düzce')),
    ('22', ('Edirne')),
    ('23', ('Elazığ')),
    ('24', ('Erzincan')),
    ('25', ('Erzurum')),
    ('26', ('Eskişehir')),
    ('27', ('Gaziantep')),
    ('28', ('Giresun')),
    ('29', ('Gümüşhane')),
    ('30', ('Hakkari')),
    ('31', ('Hatay')),
    ('76', ('Iğdır')),
    ('32', ('Isparta')),
    ('33', ('Mersin')),
    ('34', ('İstanbul')),
    ('35', ('İzmir')),
    ('78', ('Karabük')),
    ('36', ('Kars')),
    ('37', ('Kastamonu')),
    ('38', ('Kayseri')),
    ('39', ('Kırklareli')),
    ('40', ('Kırşehir')),
    ('41', ('Kocaeli')),
    ('42', ('Konya')),
    ('43', ('Kütahya')),
    ('44', ('Malatya')),
    ('45', ('Manisa')),
    ('46', ('Kahramanmaraş')),
    ('70', ('Karaman')),
    ('71', ('Kırıkkale')),
    ('79', ('Kilis')),
    ('47', ('Mardin')),
    ('48', ('Muğla')),
    ('49', ('Muş')),
    ('50', ('Nevşehir')),
    ('51', ('Niğde')),
    ('52', ('Ordu')),
    ('80', ('Osmaniye')),
    ('53', ('Rize')),
    ('54', ('Sakarya')),
    ('55', ('Samsun')),
    ('56', ('Siirt')),
    ('57', ('Sinop')),
    ('58', ('Sivas')),
    ('73', ('Şırnak')),
    ('59', ('Tekirdağ')),
    ('60', ('Tokat')),
    ('61', ('Trabzon')),
    ('62', ('Tunceli')),
    ('63', ('Şanlıurfa')),
    ('64', ('Uşak')),
    ('65', ('Van')),
    ('77', ('Yalova')),
    ('66', ('Yozgat')),
    ('67', ('Zonguldak')),
)
+31 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ Countries currently supported by :mod:`~django.contrib.localflavor` are:
    * Spain_
    * Sweden_
    * Switzerland_
    * Turkey_
    * `United Kingdom`_
    * `United States of America`_
    * Uruguay_
@@ -115,6 +116,7 @@ Here's an example of how to use them::
.. _Spain: `Spain (es)`_
.. _Sweden: `Sweden (se)`_
.. _Switzerland: `Switzerland (ch)`_
.. _Turkey: `Turkey (tr)`_
.. _United Kingdom: `United Kingdom (uk)`_
.. _United States of America: `United States of America (us)`_
.. _Uruguay: `Uruguay (uy)`_
@@ -853,6 +855,35 @@ Switzerland (``ch``)

    A ``Select`` widget that uses a list of Swiss states as its choices.

Turkey (``tr``)
===============

.. class:: tr.forms.TRZipCodeField

    A form field that validates input as a Turkish zip code. Valid codes
    consist of five digits.

.. class:: tr.forms.TRPhoneNumberField

    A form field that validates input as a Turkish phone number. The correct
    format is 0xxx xxx xxxx. +90xxx xxx xxxx and inputs without spaces also
    validates. The result is normalized to xxx xxx xxxx format.

.. class:: tr.forms.TRIdentificationNumberField

    A form field that validates input as a TR identification number. A valid
    number must satisfy the following:

    * The number consist of 11 digits.
    * The first digit cannot be 0.
    * (sum(1st, 3rd, 5th, 7th, 9th)*7 - sum(2nd,4th,6th,8th)) % 10) must be
    equal to the 10th digit.
    * (sum(1st to 10th) % 10) must be equal to the 11th digit.

.. class:: tr.forms.TRProvinceSelect

    A ``select`` widget that uses a list of Turkish provinces as its choices.

United Kingdom (``uk``)
=======================

+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ from django.forms import *
from django.contrib.localflavor.be.forms import (BEPostalCodeField,
    BEPhoneNumberField, BERegionSelect, BEProvinceSelect)

class BETests(TestCase):
class BELocalFlavorTests(TestCase):
    """
    Test case to validate BE localflavor
    """
Loading