From 9233d0426537615e06b78d28010d17d5a66adf44 Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Tue, 22 Dec 2009 17:58:49 +0000 Subject: [PATCH] Fixed #7980 - Improved i18n framework to support locale aware formatting (dates and numbers) and form processing. Thanks to Marc Garcia for working on this during his Google Summer of Code 2009! Additionally fixes #1061, #2203, #3940, #5526, #6449, #6231, #6693, #6783, #9366 and #10891. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11964 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/conf/global_settings.py | 74 +++ django/conf/locale/__init__.py | 0 django/conf/locale/ar/__init__.py | 0 django/conf/locale/ar/formats.py | 18 + django/conf/locale/bg/__init__.py | 0 django/conf/locale/bg/formats.py | 18 + django/conf/locale/bn/__init__.py | 0 django/conf/locale/bn/formats.py | 18 + django/conf/locale/ca/__init__.py | 0 django/conf/locale/ca/formats.py | 30 ++ django/conf/locale/cs/__init__.py | 0 django/conf/locale/cs/formats.py | 18 + django/conf/locale/cy/__init__.py | 0 django/conf/locale/cy/formats.py | 18 + django/conf/locale/da/__init__.py | 0 django/conf/locale/da/formats.py | 26 ++ django/conf/locale/de/__init__.py | 0 django/conf/locale/de/formats.py | 32 ++ django/conf/locale/el/__init__.py | 0 django/conf/locale/el/formats.py | 18 + django/conf/locale/en/__init__.py | 0 django/conf/locale/en/formats.py | 38 ++ django/conf/locale/es/__init__.py | 0 django/conf/locale/es/formats.py | 30 ++ django/conf/locale/es_AR/__init__.py | 0 django/conf/locale/es_AR/formats.py | 18 + django/conf/locale/et/__init__.py | 0 django/conf/locale/et/formats.py | 18 + django/conf/locale/eu/__init__.py | 0 django/conf/locale/eu/formats.py | 18 + django/conf/locale/fa/__init__.py | 0 django/conf/locale/fa/formats.py | 18 + django/conf/locale/fi/__init__.py | 0 django/conf/locale/fi/formats.py | 18 + django/conf/locale/fr/__init__.py | 0 django/conf/locale/fr/formats.py | 18 + django/conf/locale/ga/__init__.py | 0 django/conf/locale/ga/formats.py | 18 + django/conf/locale/gl/__init__.py | 0 django/conf/locale/gl/formats.py | 18 + django/conf/locale/he/__init__.py | 0 django/conf/locale/he/formats.py | 18 + django/conf/locale/hi/__init__.py | 0 django/conf/locale/hi/formats.py | 18 + django/conf/locale/hr/__init__.py | 0 django/conf/locale/hr/formats.py | 18 + django/conf/locale/hu/__init__.py | 0 django/conf/locale/hu/formats.py | 18 + django/conf/locale/is/__init__.py | 0 django/conf/locale/is/formats.py | 18 + django/conf/locale/it/__init__.py | 0 django/conf/locale/it/formats.py | 18 + django/conf/locale/ja/__init__.py | 0 django/conf/locale/ja/formats.py | 18 + django/conf/locale/ka/__init__.py | 0 django/conf/locale/ka/formats.py | 42 ++ django/conf/locale/km/__init__.py | 0 django/conf/locale/km/formats.py | 18 + django/conf/locale/kn/__init__.py | 0 django/conf/locale/kn/formats.py | 18 + django/conf/locale/ko/__init__.py | 0 django/conf/locale/ko/formats.py | 44 ++ django/conf/locale/lt/__init__.py | 0 django/conf/locale/lt/formats.py | 18 + django/conf/locale/lv/__init__.py | 0 django/conf/locale/lv/formats.py | 18 + django/conf/locale/mk/__init__.py | 0 django/conf/locale/mk/formats.py | 18 + django/conf/locale/nl/__init__.py | 0 django/conf/locale/nl/formats.py | 48 ++ django/conf/locale/no/__init__.py | 0 django/conf/locale/no/formats.py | 34 ++ django/conf/locale/pl/__init__.py | 0 django/conf/locale/pl/formats.py | 18 + django/conf/locale/pt/__init__.py | 0 django/conf/locale/pt/formats.py | 18 + django/conf/locale/pt_BR/__init__.py | 0 django/conf/locale/pt_BR/formats.py | 35 ++ django/conf/locale/ro/__init__.py | 0 django/conf/locale/ro/formats.py | 18 + django/conf/locale/ru/__init__.py | 0 django/conf/locale/ru/formats.py | 18 + django/conf/locale/sk/__init__.py | 0 django/conf/locale/sk/formats.py | 18 + django/conf/locale/sl/__init__.py | 0 django/conf/locale/sl/formats.py | 18 + django/conf/locale/sr/__init__.py | 0 django/conf/locale/sr/formats.py | 44 ++ django/conf/locale/sr_Latn/__init__.py | 0 django/conf/locale/sr_Latn/formats.py | 44 ++ django/conf/locale/sv/__init__.py | 0 django/conf/locale/sv/formats.py | 18 + django/conf/locale/ta/__init__.py | 0 django/conf/locale/ta/formats.py | 18 + django/conf/locale/te/__init__.py | 0 django/conf/locale/te/formats.py | 18 + django/conf/locale/th/__init__.py | 0 django/conf/locale/th/formats.py | 18 + django/conf/locale/tr/__init__.py | 0 django/conf/locale/tr/formats.py | 18 + django/conf/locale/uk/__init__.py | 0 django/conf/locale/uk/formats.py | 18 + django/conf/locale/zh_CN/__init__.py | 0 django/conf/locale/zh_CN/formats.py | 18 + django/conf/locale/zh_TW/__init__.py | 0 django/conf/locale/zh_TW/formats.py | 18 + django/contrib/admin/media/js/calendar.js | 5 +- .../admin/templates/admin/object_history.html | 2 +- .../contrib/admin/templatetags/admin_list.py | 38 +- django/contrib/databrowse/datastructures.py | 10 +- django/forms/extras/widgets.py | 77 ++-- django/forms/fields.py | 61 ++- django/forms/widgets.py | 3 +- django/template/__init__.py | 2 + django/template/debug.py | 5 +- django/template/defaultfilters.py | 19 +- django/utils/formats.py | 97 ++++ django/utils/numberformat.py | 42 ++ django/utils/translation/trans_null.py | 23 +- django/utils/translation/trans_real.py | 88 ++-- django/views/i18n.py | 29 +- docs/internals/deprecation.txt | 12 + docs/ref/settings.txt | 221 ++++++++- docs/ref/templates/builtins.txt | 17 +- docs/releases/1.2.txt | 45 ++ docs/topics/i18n.txt | 72 ++- tests/regressiontests/i18n/misc.py | 114 ----- tests/regressiontests/i18n/tests.py | 427 +++++++++++++++--- 128 files changed, 2304 insertions(+), 346 deletions(-) create mode 100644 django/conf/locale/__init__.py create mode 100644 django/conf/locale/ar/__init__.py create mode 100644 django/conf/locale/ar/formats.py create mode 100644 django/conf/locale/bg/__init__.py create mode 100644 django/conf/locale/bg/formats.py create mode 100644 django/conf/locale/bn/__init__.py create mode 100644 django/conf/locale/bn/formats.py create mode 100644 django/conf/locale/ca/__init__.py create mode 100644 django/conf/locale/ca/formats.py create mode 100644 django/conf/locale/cs/__init__.py create mode 100644 django/conf/locale/cs/formats.py create mode 100644 django/conf/locale/cy/__init__.py create mode 100644 django/conf/locale/cy/formats.py create mode 100644 django/conf/locale/da/__init__.py create mode 100644 django/conf/locale/da/formats.py create mode 100644 django/conf/locale/de/__init__.py create mode 100644 django/conf/locale/de/formats.py create mode 100644 django/conf/locale/el/__init__.py create mode 100644 django/conf/locale/el/formats.py create mode 100644 django/conf/locale/en/__init__.py create mode 100644 django/conf/locale/en/formats.py create mode 100644 django/conf/locale/es/__init__.py create mode 100644 django/conf/locale/es/formats.py create mode 100644 django/conf/locale/es_AR/__init__.py create mode 100644 django/conf/locale/es_AR/formats.py create mode 100644 django/conf/locale/et/__init__.py create mode 100644 django/conf/locale/et/formats.py create mode 100644 django/conf/locale/eu/__init__.py create mode 100644 django/conf/locale/eu/formats.py create mode 100644 django/conf/locale/fa/__init__.py create mode 100644 django/conf/locale/fa/formats.py create mode 100644 django/conf/locale/fi/__init__.py create mode 100644 django/conf/locale/fi/formats.py create mode 100644 django/conf/locale/fr/__init__.py create mode 100644 django/conf/locale/fr/formats.py create mode 100644 django/conf/locale/ga/__init__.py create mode 100644 django/conf/locale/ga/formats.py create mode 100644 django/conf/locale/gl/__init__.py create mode 100644 django/conf/locale/gl/formats.py create mode 100644 django/conf/locale/he/__init__.py create mode 100644 django/conf/locale/he/formats.py create mode 100644 django/conf/locale/hi/__init__.py create mode 100644 django/conf/locale/hi/formats.py create mode 100644 django/conf/locale/hr/__init__.py create mode 100644 django/conf/locale/hr/formats.py create mode 100644 django/conf/locale/hu/__init__.py create mode 100644 django/conf/locale/hu/formats.py create mode 100644 django/conf/locale/is/__init__.py create mode 100644 django/conf/locale/is/formats.py create mode 100644 django/conf/locale/it/__init__.py create mode 100644 django/conf/locale/it/formats.py create mode 100644 django/conf/locale/ja/__init__.py create mode 100644 django/conf/locale/ja/formats.py create mode 100644 django/conf/locale/ka/__init__.py create mode 100644 django/conf/locale/ka/formats.py create mode 100644 django/conf/locale/km/__init__.py create mode 100644 django/conf/locale/km/formats.py create mode 100644 django/conf/locale/kn/__init__.py create mode 100644 django/conf/locale/kn/formats.py create mode 100644 django/conf/locale/ko/__init__.py create mode 100644 django/conf/locale/ko/formats.py create mode 100644 django/conf/locale/lt/__init__.py create mode 100644 django/conf/locale/lt/formats.py create mode 100644 django/conf/locale/lv/__init__.py create mode 100644 django/conf/locale/lv/formats.py create mode 100644 django/conf/locale/mk/__init__.py create mode 100644 django/conf/locale/mk/formats.py create mode 100644 django/conf/locale/nl/__init__.py create mode 100644 django/conf/locale/nl/formats.py create mode 100644 django/conf/locale/no/__init__.py create mode 100644 django/conf/locale/no/formats.py create mode 100644 django/conf/locale/pl/__init__.py create mode 100644 django/conf/locale/pl/formats.py create mode 100644 django/conf/locale/pt/__init__.py create mode 100644 django/conf/locale/pt/formats.py create mode 100644 django/conf/locale/pt_BR/__init__.py create mode 100644 django/conf/locale/pt_BR/formats.py create mode 100644 django/conf/locale/ro/__init__.py create mode 100644 django/conf/locale/ro/formats.py create mode 100644 django/conf/locale/ru/__init__.py create mode 100644 django/conf/locale/ru/formats.py create mode 100644 django/conf/locale/sk/__init__.py create mode 100644 django/conf/locale/sk/formats.py create mode 100644 django/conf/locale/sl/__init__.py create mode 100644 django/conf/locale/sl/formats.py create mode 100644 django/conf/locale/sr/__init__.py create mode 100644 django/conf/locale/sr/formats.py create mode 100644 django/conf/locale/sr_Latn/__init__.py create mode 100644 django/conf/locale/sr_Latn/formats.py create mode 100644 django/conf/locale/sv/__init__.py create mode 100644 django/conf/locale/sv/formats.py create mode 100644 django/conf/locale/ta/__init__.py create mode 100644 django/conf/locale/ta/formats.py create mode 100644 django/conf/locale/te/__init__.py create mode 100644 django/conf/locale/te/formats.py create mode 100644 django/conf/locale/th/__init__.py create mode 100644 django/conf/locale/th/formats.py create mode 100644 django/conf/locale/tr/__init__.py create mode 100644 django/conf/locale/tr/formats.py create mode 100644 django/conf/locale/uk/__init__.py create mode 100644 django/conf/locale/uk/formats.py create mode 100644 django/conf/locale/zh_CN/__init__.py create mode 100644 django/conf/locale/zh_CN/formats.py create mode 100644 django/conf/locale/zh_TW/__init__.py create mode 100644 django/conf/locale/zh_TW/formats.py create mode 100644 django/utils/formats.py create mode 100644 django/utils/numberformat.py delete mode 100644 tests/regressiontests/i18n/misc.py diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 950b5547db..e970c12792 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -103,6 +103,10 @@ USE_I18N = True LOCALE_PATHS = () LANGUAGE_COOKIE_NAME = 'django_language' +# If you set this to True, Django will format dates, numbers and calendars +# according to user current locale +USE_L10N = False + # Not-necessarily-technical managers of the site. They get broken link # notifications and other various e-mails. MANAGERS = ADMINS @@ -265,6 +269,12 @@ FILE_UPLOAD_TEMP_DIR = None # you'd pass directly to os.chmod; see http://docs.python.org/lib/os-file-dir.html. FILE_UPLOAD_PERMISSIONS = None +# Python module path where user will place custom format definition. +# The directory where this setting is pointing should contain subdirectories +# named as the locales, containing a formats.py file +# (i.e. "myproject.locale" for myproject/locale/en/formats.py etc. use) +FORMAT_MODULE_PATH = None + # Default formatting for date objects. See all available format strings here: # http://docs.djangoproject.com/en/dev/ref/templates/builtins/#now DATE_FORMAT = 'N j, Y' @@ -287,6 +297,70 @@ YEAR_MONTH_FORMAT = 'F Y' # http://docs.djangoproject.com/en/dev/ref/templates/builtins/#now MONTH_DAY_FORMAT = 'F j' +# Default shortformatting for date objects. See all available format strings here: +# http://docs.djangoproject.com/en/dev/ref/templates/builtins/#now +SHORT_DATE_FORMAT = 'm/d/Y' + +# Default short formatting for datetime objects. +# See all available format strings here: +# http://docs.djangoproject.com/en/dev/ref/templates/builtins/#now +SHORT_DATETIME_FORMAT = 'm/d/Y P' + +# Default formats to be used when parsing dates from input boxes, in order +# See all available format string here: +# http://docs.python.org/library/datetime.html#strftime-behavior +# * Note that these format strings are different from the ones to display dates +DATE_INPUT_FORMATS = ( + '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' + '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' + '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' + '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' + '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' +) + +# Default formats to be used when parsing times from input boxes, in order +# See all available format string here: +# http://docs.python.org/library/datetime.html#strftime-behavior +# * Note that these format strings are different from the ones to display dates +TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' +) + +# Default formats to be used when parsing dates and times from input boxes, +# in order +# See all available format string here: +# http://docs.python.org/library/datetime.html#strftime-behavior +# * Note that these format strings are different from the ones to display dates +DATETIME_INPUT_FORMATS = ( + '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%M', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' + '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59' + '%m/%d/%Y %H:%M', # '10/25/2006 14:30' + '%m/%d/%Y', # '10/25/2006' + '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59' + '%m/%d/%y %H:%M', # '10/25/06 14:30' + '%m/%d/%y', # '10/25/06' +) + +# First day of week, to be used on calendars +# 0 means Sunday, 1 means Monday... +FIRST_DAY_OF_WEEK = 0 + +# Decimal separator symbol +DECIMAL_SEPARATOR = '.' + +# Boolean that sets whether to add thousand separator when formatting numbers +USE_THOUSAND_SEPARATOR = False + +# Number of digits that will be togheter, when spliting them by THOUSAND_SEPARATOR +# 0 means no grouping, 3 means splitting by thousands... +NUMBER_GROUPING = 0 + +# Thousand separator symbol +THOUSAND_SEPARATOR = ',' + # Do you want to manage transactions manually? # Hint: you really don't! TRANSACTIONS_MANAGED = False diff --git a/django/conf/locale/__init__.py b/django/conf/locale/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/ar/__init__.py b/django/conf/locale/ar/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/ar/formats.py b/django/conf/locale/ar/formats.py new file mode 100644 index 0000000000..d8d627f820 --- /dev/null +++ b/django/conf/locale/ar/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F، Y' +TIME_FORMAT = 'g:i:s A' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'd‏/m‏/Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/bg/__init__.py b/django/conf/locale/bg/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/bg/formats.py b/django/conf/locale/bg/formats.py new file mode 100644 index 0000000000..045543a7ac --- /dev/null +++ b/django/conf/locale/bg/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'd F Y' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'd.m.Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/bn/__init__.py b/django/conf/locale/bn/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/bn/formats.py b/django/conf/locale/bn/formats.py new file mode 100644 index 0000000000..46e5da9392 --- /dev/null +++ b/django/conf/locale/bn/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F, Y' +TIME_FORMAT = 'g:i:s A' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M, Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = ',' +# NUMBER_GROUPING = diff --git a/django/conf/locale/ca/__init__.py b/django/conf/locale/ca/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/ca/formats.py b/django/conf/locale/ca/formats.py new file mode 100644 index 0000000000..aebaea3d07 --- /dev/null +++ b/django/conf/locale/ca/formats.py @@ -0,0 +1,30 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j \de F \de Y' +TIME_FORMAT = 'G:i:s' +DATETIME_FORMAT = 'j \de F \de Y \\a \le\s G:i' +YEAR_MONTH_FORMAT = 'F \de\l Y' +MONTH_DAY_FORMAT = 'j \de F' +SHORT_DATE_FORMAT = 'd/m/Y' +SHORT_DATETIME_FORMAT = 'd/m/Y G:i' +FIRST_DAY_OF_WEEK = 1 # Monday +DATE_INPUT_FORMATS = ( + # '31/12/2009', '31/12/09' + '%d/%m/%Y', '%d/%m/%y' +) +TIME_INPUT_FORMATS = ( + # '14:30:59', '14:30' + '%H:%M:%S', '%H:%M' +) +DATETIME_INPUT_FORMATS = ( + '%d/%m/%Y %H:%M:%S', + '%d/%m/%Y %H:%M', + '%d/%m/%y %H:%M:%S', + '%d/%m/%y %H:%M', +) +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +NUMBER_GROUPING = 3 + diff --git a/django/conf/locale/cs/__init__.py b/django/conf/locale/cs/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/cs/formats.py b/django/conf/locale/cs/formats.py new file mode 100644 index 0000000000..327e77e868 --- /dev/null +++ b/django/conf/locale/cs/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j. F Y' +TIME_FORMAT = 'G:i:s' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'j.n.Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/cy/__init__.py b/django/conf/locale/cy/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/cy/formats.py b/django/conf/locale/cy/formats.py new file mode 100644 index 0000000000..a58d81f479 --- /dev/null +++ b/django/conf/locale/cy/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'd F Y' +TIME_FORMAT = 'g:i:s A' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +# MONTH_DAY_FORMAT = +SHORT_DATE_FORMAT = 'j M Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/django/conf/locale/da/__init__.py b/django/conf/locale/da/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/da/formats.py b/django/conf/locale/da/formats.py new file mode 100644 index 0000000000..9982014cba --- /dev/null +++ b/django/conf/locale/da/formats.py @@ -0,0 +1,26 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j. F Y' +TIME_FORMAT = 'H:i' +DATETIME_FORMAT = 'j. F Y H:i' +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'd.m.Y' +SHORT_DATETIME_FORMAT = 'd.m.Y H:i' +FIRST_DAY_OF_WEEK = 1 +DATE_INPUT_FORMATS = ( + '%d.%m.%Y', # '25.10.2006' +) +TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' +) +DATETIME_INPUT_FORMATS = ( + '%d.%m.%Y %H:%M:%S', # '25.10.2006 14:30:59' + '%d.%m.%Y %H:%M', # '25.10.2006 14:30' +) +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +NUMBER_GROUPING = 3 diff --git a/django/conf/locale/de/__init__.py b/django/conf/locale/de/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/de/formats.py b/django/conf/locale/de/formats.py new file mode 100644 index 0000000000..89b57846b6 --- /dev/null +++ b/django/conf/locale/de/formats.py @@ -0,0 +1,32 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j. F Y' +TIME_FORMAT = 'H:i:s' +DATETIME_FORMAT = 'j. F Y H:i:s' +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'd.m.Y' +SHORT_DATETIME_FORMAT = 'd.m.Y H:i:s' +FIRST_DAY_OF_WEEK = 1 # Monday +DATE_INPUT_FORMATS = ( + '%d.%m.%Y', '%d.%m.%y', # '25.10.2006', '25.10.06' + '%Y-%m-%d', '%y-%m-%d', # '2006-10-25', '06-10-25' + '%d. %B %Y', '%d. %b. %Y', # '25. October 2006', '25. Oct. 2006' +) +TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' +) +DATETIME_INPUT_FORMATS = ( + '%d.%m.%Y %H:%M:%S', # '25.10.2006 14:30:59' + '%d.%m.%Y %H:%M', # '25.10.2006 14:30' + '%d.%m.%Y', # '25.10.2006' + '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%M', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' +) +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +NUMBER_GROUPING = 3 diff --git a/django/conf/locale/el/__init__.py b/django/conf/locale/el/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/el/formats.py b/django/conf/locale/el/formats.py new file mode 100644 index 0000000000..d476ab3885 --- /dev/null +++ b/django/conf/locale/el/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'd F Y' +TIME_FORMAT = 'g:i:s A' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'd M Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/en/__init__.py b/django/conf/locale/en/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/en/formats.py b/django/conf/locale/en/formats.py new file mode 100644 index 0000000000..3a507cd27e --- /dev/null +++ b/django/conf/locale/en/formats.py @@ -0,0 +1,38 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'N j, Y' +TIME_FORMAT = 'P' +DATETIME_FORMAT = 'N j, Y, P' +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'F j' +SHORT_DATE_FORMAT = 'm/d/Y' +SHORT_DATETIME_FORMAT = 'm/d/Y P' +FIRST_DAY_OF_WEEK = 0 # Sunday +DATE_INPUT_FORMATS = ( + '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' + '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' + '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' + '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' + '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' +) +TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' +) +DATETIME_INPUT_FORMATS = ( + '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%M', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' + '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59' + '%m/%d/%Y %H:%M', # '10/25/2006 14:30' + '%m/%d/%Y', # '10/25/2006' + '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59' + '%m/%d/%y %H:%M', # '10/25/06 14:30' + '%m/%d/%y', # '10/25/06' +) +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = ',' +NUMBER_GROUPING = 3 + diff --git a/django/conf/locale/es/__init__.py b/django/conf/locale/es/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/es/formats.py b/django/conf/locale/es/formats.py new file mode 100644 index 0000000000..349810f0fe --- /dev/null +++ b/django/conf/locale/es/formats.py @@ -0,0 +1,30 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j \de F \de Y' +TIME_FORMAT = 'H:i:s' +DATETIME_FORMAT = 'j \de F \de Y \a \l\a\s H:i' +YEAR_MONTH_FORMAT = 'F \de Y' +MONTH_DAY_FORMAT = 'j \de F' +SHORT_DATE_FORMAT = 'd/m/Y' +SHORT_DATETIME_FORMAT = 'd/m/Y H:i' +FIRST_DAY_OF_WEEK = 1 # Monday +DATE_INPUT_FORMATS = ( + # '31/12/2009', '31/12/09' + '%d/%m/%Y', '%d/%m/%y' +) +TIME_INPUT_FORMATS = ( + # '14:30:59', '14:30' + '%H:%M:%S', '%H:%M' +) +DATETIME_INPUT_FORMATS = ( + '%d/%m/%Y %H:%M:%S', + '%d/%m/%Y %H:%M', + '%d/%m/%y %H:%M:%S', + '%d/%m/%y %H:%M', +) +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +NUMBER_GROUPING = 3 + diff --git a/django/conf/locale/es_AR/__init__.py b/django/conf/locale/es_AR/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/es_AR/formats.py b/django/conf/locale/es_AR/formats.py new file mode 100644 index 0000000000..6d71786415 --- /dev/null +++ b/django/conf/locale/es_AR/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +# DATE_FORMAT = +# TIME_FORMAT = +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +# MONTH_DAY_FORMAT = +# SHORT_DATE_FORMAT = +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/django/conf/locale/et/__init__.py b/django/conf/locale/et/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/et/formats.py b/django/conf/locale/et/formats.py new file mode 100644 index 0000000000..b96420c0c1 --- /dev/null +++ b/django/conf/locale/et/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'G:i:s' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'd.m.Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/eu/__init__.py b/django/conf/locale/eu/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/eu/formats.py b/django/conf/locale/eu/formats.py new file mode 100644 index 0000000000..475f924fe8 --- /dev/null +++ b/django/conf/locale/eu/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'Yeko M\re\n d\a' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +# MONTH_DAY_FORMAT = +SHORT_DATE_FORMAT = 'Y M j' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/fa/__init__.py b/django/conf/locale/fa/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/fa/formats.py b/django/conf/locale/fa/formats.py new file mode 100644 index 0000000000..dc11281790 --- /dev/null +++ b/django/conf/locale/fa/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'G:i:s' +DATETIME_FORMAT = 'j F Y، ساعت G:i:s' +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'Y/n/j' +SHORT_DATETIME_FORMAT = 'Y/n/j،‏ G:i:s' +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/fi/__init__.py b/django/conf/locale/fi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/fi/formats.py b/django/conf/locale/fi/formats.py new file mode 100644 index 0000000000..670e26841a --- /dev/null +++ b/django/conf/locale/fi/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j. F Y' +TIME_FORMAT = 'G.i.s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'j.n.Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/fr/__init__.py b/django/conf/locale/fr/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/fr/formats.py b/django/conf/locale/fr/formats.py new file mode 100644 index 0000000000..1d670d7f6a --- /dev/null +++ b/django/conf/locale/fr/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'H:i:s' +DATETIME_FORMAT = 'j F Y H:i:s' +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M Y' +SHORT_DATETIME_FORMAT = 'j M Y H:i:s' +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/ga/__init__.py b/django/conf/locale/ga/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/ga/formats.py b/django/conf/locale/ga/formats.py new file mode 100644 index 0000000000..f177bb28d4 --- /dev/null +++ b/django/conf/locale/ga/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = ',' +# NUMBER_GROUPING = diff --git a/django/conf/locale/gl/__init__.py b/django/conf/locale/gl/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/gl/formats.py b/django/conf/locale/gl/formats.py new file mode 100644 index 0000000000..e0a95d5106 --- /dev/null +++ b/django/conf/locale/gl/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'd F Y' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M, Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/he/__init__.py b/django/conf/locale/he/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/he/formats.py b/django/conf/locale/he/formats.py new file mode 100644 index 0000000000..8d7c7f2a4a --- /dev/null +++ b/django/conf/locale/he/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j בF Y' +TIME_FORMAT = 'H:i:s' +DATETIME_FORMAT = 'j בF Y H:i:s' +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j בF' +SHORT_DATE_FORMAT = 'd/m/Y' +SHORT_DATETIME_FORMAT = 'd/m/Y H:i:s' +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = ',' +# NUMBER_GROUPING = diff --git a/django/conf/locale/hi/__init__.py b/django/conf/locale/hi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/hi/formats.py b/django/conf/locale/hi/formats.py new file mode 100644 index 0000000000..6afa2581b9 --- /dev/null +++ b/django/conf/locale/hi/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'g:i:s A' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'd-m-Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = ',' +# NUMBER_GROUPING = diff --git a/django/conf/locale/hr/__init__.py b/django/conf/locale/hr/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/hr/formats.py b/django/conf/locale/hr/formats.py new file mode 100644 index 0000000000..62d1a7edf5 --- /dev/null +++ b/django/conf/locale/hr/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j. F Y.' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y.' +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'j.n.Y.' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/hu/__init__.py b/django/conf/locale/hu/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/hu/formats.py b/django/conf/locale/hu/formats.py new file mode 100644 index 0000000000..6ee2db0cd5 --- /dev/null +++ b/django/conf/locale/hu/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'Y. F j.' +TIME_FORMAT = 'G:i:s' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'F j.' +SHORT_DATE_FORMAT = 'Y.m.d.' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/is/__init__.py b/django/conf/locale/is/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/is/formats.py b/django/conf/locale/is/formats.py new file mode 100644 index 0000000000..b6377db40b --- /dev/null +++ b/django/conf/locale/is/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j. F Y' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'j.n.Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/it/__init__.py b/django/conf/locale/it/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/it/formats.py b/django/conf/locale/it/formats.py new file mode 100644 index 0000000000..fe86b5bd70 --- /dev/null +++ b/django/conf/locale/it/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'd F Y' +TIME_FORMAT = 'H.i.s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'd/M/Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/ja/__init__.py b/django/conf/locale/ja/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/ja/formats.py b/django/conf/locale/ja/formats.py new file mode 100644 index 0000000000..853056d8da --- /dev/null +++ b/django/conf/locale/ja/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'Y年n月j日' +TIME_FORMAT = 'G:i:s' +DATETIME_FORMAT = 'Y年n月j日G:i:s' +YEAR_MONTH_FORMAT = 'Y年n月' +MONTH_DAY_FORMAT = 'n月j日' +SHORT_DATE_FORMAT = 'Y/m/d' +SHORT_DATETIME_FORMAT = 'Y/m/d G:i:s' +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = ',' +# NUMBER_GROUPING = diff --git a/django/conf/locale/ka/__init__.py b/django/conf/locale/ka/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/ka/formats.py b/django/conf/locale/ka/formats.py new file mode 100644 index 0000000000..665a73fcfc --- /dev/null +++ b/django/conf/locale/ka/formats.py @@ -0,0 +1,42 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'l, j F, Y' +TIME_FORMAT = 'h:i:s a' +DATETIME_FORMAT = 'j F, Y h:i:s a' +YEAR_MONTH_FORMAT = 'F, Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j.M.Y' +SHORT_DATETIME_FORMAT = 'j.M.Y H:i:s' +FIRST_DAY_OF_WEEK = 1 # (Monday) +DATE_INPUT_FORMATS = ( + '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' + '%d %b %Y', '%d %b, %Y', '%d %b. %Y', # '25 Oct 2006', '25 Oct, 2006', '25 Oct. 2006' + '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' + '%d.%m.%Y', '%d.%m.%y', # '25.10.2006', '25.10.06' +) +TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' +) +DATETIME_INPUT_FORMATS = ( + '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%M', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' + '%d.%m.%Y %H:%M:%S', # '25.10.2006 14:30:59' + '%d.%m.%Y %H:%M', # '25.10.2006 14:30' + '%d.%m.%Y', # '25.10.2006' + '%d.%m.%y %H:%M:%S', # '25.10.06 14:30:59' + '%d.%m.%y %H:%M', # '25.10.06 14:30' + '%d.%m.%y', # '25.10.06' + '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59' + '%m/%d/%Y %H:%M', # '10/25/2006 14:30' + '%m/%d/%Y', # '10/25/2006' + '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59' + '%m/%d/%y %H:%M', # '10/25/06 14:30' + '%m/%d/%y', # '10/25/06' +) +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = " " +NUMBER_GROUPING = 3 diff --git a/django/conf/locale/km/__init__.py b/django/conf/locale/km/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/km/formats.py b/django/conf/locale/km/formats.py new file mode 100644 index 0000000000..3736d574fb --- /dev/null +++ b/django/conf/locale/km/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j ខែ F ឆ្នាំ Y' +TIME_FORMAT = 'G:i:s' +DATETIME_FORMAT = 'j ខែ F ឆ្នាំ Y, G:i:s' +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M Y' +SHORT_DATETIME_FORMAT = 'j M Y, G:i:s' +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/kn/__init__.py b/django/conf/locale/kn/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/kn/formats.py b/django/conf/locale/kn/formats.py new file mode 100644 index 0000000000..fa7a7b9546 --- /dev/null +++ b/django/conf/locale/kn/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'h:i:s A' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/django/conf/locale/ko/__init__.py b/django/conf/locale/ko/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/ko/formats.py b/django/conf/locale/ko/formats.py new file mode 100644 index 0000000000..619047dae0 --- /dev/null +++ b/django/conf/locale/ko/formats.py @@ -0,0 +1,44 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'Y년 n월 j일' +TIME_FORMAT = 'A g:i:s' +DATETIME_FORMAT = 'Y년 n월 j일 g:i:s A' +YEAR_MONTH_FORMAT = 'Y년 F월' +MONTH_DAY_FORMAT = 'F월 j일' +SHORT_DATE_FORMAT = 'Y-n-j.' +SHORT_DATETIME_FORMAT = 'Y-n-j H:i' +# FIRST_DAY_OF_WEEK = +DATE_INPUT_FORMATS = ( + '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' + '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' + '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' + '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' + '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' + '%Y년 %m월 %d일', # '2006년 10월 25일', with localized suffix. +) +TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' + '%H시 %M분 %S초', # '14시 30분 59초' + '%H시 %M분', # '14시 30분' +) +DATETIME_INPUT_FORMATS = ( + '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%M', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' + '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59' + '%m/%d/%Y %H:%M', # '10/25/2006 14:30' + '%m/%d/%Y', # '10/25/2006' + '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59' + '%m/%d/%y %H:%M', # '10/25/06 14:30' + '%m/%d/%y', # '10/25/06' + + '%Y년 %m월 %d일 %H시 %M분 %S초', # '2006년 10월 25일 14시 30분 59초' + '%Y년 %m월 %d일 %H시 %M분', # '2006년 10월 25일 14시 30분' +) + +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = ',' +NUMBER_GROUPING = 3 diff --git a/django/conf/locale/lt/__init__.py b/django/conf/locale/lt/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/lt/formats.py b/django/conf/locale/lt/formats.py new file mode 100644 index 0000000000..d9fb0c86f7 --- /dev/null +++ b/django/conf/locale/lt/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'Y \m. F j \d.' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +# MONTH_DAY_FORMAT = +SHORT_DATE_FORMAT = 'Y.m.d' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/lv/__init__.py b/django/conf/locale/lv/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/lv/formats.py b/django/conf/locale/lv/formats.py new file mode 100644 index 0000000000..5dc211cfc0 --- /dev/null +++ b/django/conf/locale/lv/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'Y. \g\a\d\a j. F' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'Y. \g. F' +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'Y. \g\a\d\a j. M' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/mk/__init__.py b/django/conf/locale/mk/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/mk/formats.py b/django/conf/locale/mk/formats.py new file mode 100644 index 0000000000..746ac0ea9f --- /dev/null +++ b/django/conf/locale/mk/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'd F Y' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +# MONTH_DAY_FORMAT = +SHORT_DATE_FORMAT = 'd.n.Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/nl/__init__.py b/django/conf/locale/nl/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/nl/formats.py b/django/conf/locale/nl/formats.py new file mode 100644 index 0000000000..dcef8c1eb7 --- /dev/null +++ b/django/conf/locale/nl/formats.py @@ -0,0 +1,48 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' # '20 januari 2009' +TIME_FORMAT = 'H:i' # '15:23' +DATETIME_FORMAT = 'j F Y H:i' # '20 januari 2009 15:23' +YEAR_MONTH_FORMAT = 'F Y' # 'januari 2009' +MONTH_DAY_FORMAT = 'j F' # '20 januari' +SHORT_DATE_FORMAT = 'j-n-Y' # '20-1-2009' +SHORT_DATETIME_FORMAT = 'j-n-Y H:i' # '20-1-2009 15:23' +FIRST_DAY_OF_WEEK = 1 # Monday (in Dutch 'maandag') +DATE_INPUT_FORMATS = ( + '%d-%m-%Y', '%d-%m-%y', '%Y-%m-%d', # '20-01-2009', '20-01-09', '2009-01-20' + '%d %b %Y', '%d %b %y', # '20 jan 2009', '20 jan 09' + '%d %B %Y', '%d %B %y', # '20 januari 2009', '20 januari 09' +) +TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '15:23:35' + '%H.%M:%S', # '15.23:35' + '%H.%M', # '15.23' + '%H:%M', # '15:23' +) +DATETIME_INPUT_FORMATS = ( + # With time in %H:%M:%S : + '%d-%m-%Y %H:%M:%S', '%d-%m-%y %H:%M:%S', '%Y-%m-%d %H:%M:%S', # '20-01-2009 15:23:35', '20-01-09 15:23:35', '2009-01-20 15:23:35' + '%d %b %Y %H:%M:%S', '%d %b %y %H:%M:%S', # '20 jan 2009 15:23:35', '20 jan 09 15:23:35' + '%d %B %Y %H:%M:%S', '%d %B %y %H:%M:%S', # '20 januari 2009 15:23:35', '20 januari 2009 15:23:35' + # With time in %H.%M:%S : + '%d-%m-%Y %H.%M:%S', '%d-%m-%y %H.%M:%S', # '20-01-2009 15.23:35', '20-01-09 15.23:35' + '%d %b %Y %H.%M:%S', '%d %b %y %H.%M:%S', # '20 jan 2009 15.23:35', '20 jan 09 15.23:35' + '%d %B %Y %H.%M:%S', '%d %B %y %H.%M:%S', # '20 januari 2009 15.23:35', '20 januari 2009 15.23:35' + # With time in %H:%M : + '%d-%m-%Y %H:%M', '%d-%m-%y %H:%M', '%Y-%m-%d %H:%M', # '20-01-2009 15:23', '20-01-09 15:23', '2009-01-20 15:23' + '%d %b %Y %H:%M', '%d %b %y %H:%M', # '20 jan 2009 15:23', '20 jan 09 15:23' + '%d %B %Y %H:%M', '%d %B %y %H:%M', # '20 januari 2009 15:23', '20 januari 2009 15:23' + # With time in %H.%M : + '%d-%m-%Y %H.%M', '%d-%m-%y %H.%M', # '20-01-2009 15.23', '20-01-09 15.23' + '%d %b %Y %H.%M', '%d %b %y %H.%M', # '20 jan 2009 15.23', '20 jan 09 15.23' + '%d %B %Y %H.%M', '%d %B %y %H.%M', # '20 januari 2009 15.23', '20 januari 2009 15.23' + # Without time : + '%d-%m-%Y', '%d-%m-%y', '%Y-%m-%d', # '20-01-2009', '20-01-09', '2009-01-20' + '%d %b %Y', '%d %b %y', # '20 jan 2009', '20 jan 09' + '%d %B %Y', '%d %B %y', # '20 januari 2009', '20 januari 2009' +) +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +NUMBER_GROUPING = 3 diff --git a/django/conf/locale/no/__init__.py b/django/conf/locale/no/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/no/formats.py b/django/conf/locale/no/formats.py new file mode 100644 index 0000000000..62ee886f11 --- /dev/null +++ b/django/conf/locale/no/formats.py @@ -0,0 +1,34 @@ +DATE_FORMAT = 'j. F Y' +TIME_FORMAT = 'H:i' +DATETIME_FORMAT = 'j. F Y H:i' +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'd.m.Y' +SHORT_DATETIME_FORMAT = 'd.m.Y H:i' +FIRST_DAY_OF_WEEK = 1 # Monday +DATE_INPUT_FORMATS = ( + '%Y-%m-%d', '%j.%m.%Y', '%j.%m.%y', # '2006-10-25', '25.10.2006', '25.10.06' + '%Y-%m-%j', # '2006-10-25', + '%j. %b %Y', '%j %b %Y', # '25. okt 2006', '25 okt 2006' + '%j. %b. %Y', '%j %b. %Y', # '25. okt. 2006', '25 okt. 2006' + '%j. %B %Y', '%j %B %Y', # '25. oktober 2006', '25 oktober 2006' +) +TIME_INPUT_FORMATS = ( + '%H:%i:%S', # '14:30:59' + '%H:%i', # '14:30' +) +DATETIME_INPUT_FORMATS = ( + '%Y-%m-%d %H:%i:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%i', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' + '%Y-%m-%j', # '2006-10-25' + '%j.%m.%Y %H:%i:%S', # '25.10.2006 14:30:59' + '%j.%m.%Y %H:%i', # '25.10.2006 14:30' + '%j.%m.%Y', # '25.10.2006' + '%j.%m.%y %H:%i:%S', # '25.10.06 14:30:59' + '%j.%m.%y %H:%i', # '25.10.06 14:30' + '%j.%m.%y', # '25.10.06' +) +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +NUMBER_GROUPING = 3 diff --git a/django/conf/locale/pl/__init__.py b/django/conf/locale/pl/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/pl/formats.py b/django/conf/locale/pl/formats.py new file mode 100644 index 0000000000..860a4a88ca --- /dev/null +++ b/django/conf/locale/pl/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'd-m-Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/pt/__init__.py b/django/conf/locale/pt/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/pt/formats.py b/django/conf/locale/pt/formats.py new file mode 100644 index 0000000000..053a48af53 --- /dev/null +++ b/django/conf/locale/pt/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j \de F \de Y' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F \de Y' +MONTH_DAY_FORMAT = 'j \de F' +SHORT_DATE_FORMAT = 'd/m/Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/pt_BR/__init__.py b/django/conf/locale/pt_BR/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/pt_BR/formats.py b/django/conf/locale/pt_BR/formats.py new file mode 100644 index 0000000000..f30d5c4dfc --- /dev/null +++ b/django/conf/locale/pt_BR/formats.py @@ -0,0 +1,35 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j \\de N \\de Y' +TIME_FORMAT = 'H:i' +DATETIME_FORMAT = 'j \\de N \\de Y à\\s H:i' +YEAR_MONTH_FORMAT = 'F \\de Y' +MONTH_DAY_FORMAT = 'j \\de F' +SHORT_DATE_FORMAT = 'd/m/Y' +SHORT_DATETIME_FORMAT = 'd/m/Y H:i' +FIRST_DAY_OF_WEEK = 0 # Sunday +DATE_INPUT_FORMATS = ( + '%Y-%m-%d', '%d/%m/%Y', '%d/%m/%y', # '2006-10-25', '25/10/2006', '25/10/06' + '%d de %b de %Y', '%d de %b, %Y', # '25 de Out de 2006', '25 Out, 2006' + '%d de %B de %Y', '%d de %B, %Y', # '25 de Outubro de 2006', '25 de Outubro, 2006' +) +TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' +) +DATETIME_INPUT_FORMATS = ( + '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%M', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' + '%d/%m/%Y %H:%M:%S', # '25/10/2006 14:30:59' + '%d/%m/%Y %H:%M', # '25/10/2006 14:30' + '%d/%m/%Y', # '25/10/2006' + '%d/%m/%y %H:%M:%S', # '25/10/06 14:30:59' + '%d/%m/%y %H:%M', # '25/10/06 14:30' + '%d/%m/%y', # '25/10/06' +) +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +NUMBER_GROUPING = 3 diff --git a/django/conf/locale/ro/__init__.py b/django/conf/locale/ro/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/ro/formats.py b/django/conf/locale/ro/formats.py new file mode 100644 index 0000000000..6d6e800467 --- /dev/null +++ b/django/conf/locale/ro/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'H:i:s' +DATETIME_FORMAT = 'j F Y, H:i:s' +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'd.m.Y' +SHORT_DATETIME_FORMAT = 'd.m.Y, H:i:s' +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/ru/__init__.py b/django/conf/locale/ru/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/ru/formats.py b/django/conf/locale/ru/formats.py new file mode 100644 index 0000000000..9a9ee96561 --- /dev/null +++ b/django/conf/locale/ru/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y г.' +TIME_FORMAT = 'G:i:s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'd.m.Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/sk/__init__.py b/django/conf/locale/sk/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/sk/formats.py b/django/conf/locale/sk/formats.py new file mode 100644 index 0000000000..1bc3549dcf --- /dev/null +++ b/django/conf/locale/sk/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j. F Y' +TIME_FORMAT = 'G:i:s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'j.n.Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/sl/__init__.py b/django/conf/locale/sl/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/sl/formats.py b/django/conf/locale/sl/formats.py new file mode 100644 index 0000000000..4007f10707 --- /dev/null +++ b/django/conf/locale/sl/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'd. F Y' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'j. M. Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/sr/__init__.py b/django/conf/locale/sr/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/sr/formats.py b/django/conf/locale/sr/formats.py new file mode 100644 index 0000000000..6dc19cf788 --- /dev/null +++ b/django/conf/locale/sr/formats.py @@ -0,0 +1,44 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j. F Y.' +TIME_FORMAT = 'H:i' +DATETIME_FORMAT = 'j. F Y. H:i' +YEAR_MONTH_FORMAT = 'F Y.' +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'j.m.Y.' +SHORT_DATETIME_FORMAT = 'j.m.Y. H:i' +FIRST_DAY_OF_WEEK = 1 +DATE_INPUT_FORMATS = ( + '%Y-%m-%d', # '2006-10-25' + '%d.%m.%Y.', '%d.%m.%y.', # '25.10.2006.', '25.10.06.' + '%d. %m. %Y.', '%d. %m. %y.', # '25. 10. 2006.', '25. 10. 06.' + '%d. %b %y.', '%d. %B %y.', # '25. Oct 06.', '25. October 06.' + '%d. %b \'%y.', '%d. %B \'%y.', # '25. Oct '06.', '25. October '06.' + '%d. %b %Y.', '%d. %B %Y.', # '25. Oct 2006.', '25. October 2006.' +) +TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' +) +DATETIME_INPUT_FORMATS = ( + '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%M', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' + '%d.%m.%Y. %H:%M:%S', # '25.10.2006. 14:30:59' + '%d.%m.%Y. %H:%M', # '25.10.2006. 14:30' + '%d.%m.%Y.', # '25.10.2006.' + '%d.%m.%y. %H:%M:%S', # '25.10.06. 14:30:59' + '%d.%m.%y. %H:%M', # '25.10.06. 14:30' + '%d.%m.%y.', # '25.10.06.' + '%d. %m. %Y. %H:%M:%S', # '25. 10. 2006. 14:30:59' + '%d. %m. %Y. %H:%M', # '25. 10. 2006. 14:30' + '%d. %m. %Y.', # '25. 10. 2006.' + '%d. %m. %y. %H:%M:%S', # '25. 10. 06. 14:30:59' + '%d. %m. %y. %H:%M', # '25. 10. 06. 14:30' + '%d. %m. %y.', # '25. 10. 06.' +) +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = ',' +NUMBER_GROUPING = 3 diff --git a/django/conf/locale/sr_Latn/__init__.py b/django/conf/locale/sr_Latn/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/sr_Latn/formats.py b/django/conf/locale/sr_Latn/formats.py new file mode 100644 index 0000000000..6dc19cf788 --- /dev/null +++ b/django/conf/locale/sr_Latn/formats.py @@ -0,0 +1,44 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j. F Y.' +TIME_FORMAT = 'H:i' +DATETIME_FORMAT = 'j. F Y. H:i' +YEAR_MONTH_FORMAT = 'F Y.' +MONTH_DAY_FORMAT = 'j. F' +SHORT_DATE_FORMAT = 'j.m.Y.' +SHORT_DATETIME_FORMAT = 'j.m.Y. H:i' +FIRST_DAY_OF_WEEK = 1 +DATE_INPUT_FORMATS = ( + '%Y-%m-%d', # '2006-10-25' + '%d.%m.%Y.', '%d.%m.%y.', # '25.10.2006.', '25.10.06.' + '%d. %m. %Y.', '%d. %m. %y.', # '25. 10. 2006.', '25. 10. 06.' + '%d. %b %y.', '%d. %B %y.', # '25. Oct 06.', '25. October 06.' + '%d. %b \'%y.', '%d. %B \'%y.', # '25. Oct '06.', '25. October '06.' + '%d. %b %Y.', '%d. %B %Y.', # '25. Oct 2006.', '25. October 2006.' +) +TIME_INPUT_FORMATS = ( + '%H:%M:%S', # '14:30:59' + '%H:%M', # '14:30' +) +DATETIME_INPUT_FORMATS = ( + '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' + '%Y-%m-%d %H:%M', # '2006-10-25 14:30' + '%Y-%m-%d', # '2006-10-25' + '%d.%m.%Y. %H:%M:%S', # '25.10.2006. 14:30:59' + '%d.%m.%Y. %H:%M', # '25.10.2006. 14:30' + '%d.%m.%Y.', # '25.10.2006.' + '%d.%m.%y. %H:%M:%S', # '25.10.06. 14:30:59' + '%d.%m.%y. %H:%M', # '25.10.06. 14:30' + '%d.%m.%y.', # '25.10.06.' + '%d. %m. %Y. %H:%M:%S', # '25. 10. 2006. 14:30:59' + '%d. %m. %Y. %H:%M', # '25. 10. 2006. 14:30' + '%d. %m. %Y.', # '25. 10. 2006.' + '%d. %m. %y. %H:%M:%S', # '25. 10. 06. 14:30:59' + '%d. %m. %y. %H:%M', # '25. 10. 06. 14:30' + '%d. %m. %y.', # '25. 10. 06.' +) +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = ',' +NUMBER_GROUPING = 3 diff --git a/django/conf/locale/sv/__init__.py b/django/conf/locale/sv/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/sv/formats.py b/django/conf/locale/sv/formats.py new file mode 100644 index 0000000000..df4e633562 --- /dev/null +++ b/django/conf/locale/sv/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'H.i.s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'Y F' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/ta/__init__.py b/django/conf/locale/ta/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/ta/formats.py b/django/conf/locale/ta/formats.py new file mode 100644 index 0000000000..69fa17df33 --- /dev/null +++ b/django/conf/locale/ta/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F, Y' +TIME_FORMAT = 'g:i:s A' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M, Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/django/conf/locale/te/__init__.py b/django/conf/locale/te/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/te/formats.py b/django/conf/locale/te/formats.py new file mode 100644 index 0000000000..e805872d52 --- /dev/null +++ b/django/conf/locale/te/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'g:i:s A' +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/django/conf/locale/th/__init__.py b/django/conf/locale/th/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/th/formats.py b/django/conf/locale/th/formats.py new file mode 100644 index 0000000000..7091dc6b98 --- /dev/null +++ b/django/conf/locale/th/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y' +TIME_FORMAT = 'G:i:s' +DATETIME_FORMAT = 'j F Y, G:i:s' +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M Y' +SHORT_DATETIME_FORMAT = 'j M Y, G:i:s' +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = '.' +THOUSAND_SEPARATOR = ',' +# NUMBER_GROUPING = diff --git a/django/conf/locale/tr/__init__.py b/django/conf/locale/tr/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/tr/formats.py b/django/conf/locale/tr/formats.py new file mode 100644 index 0000000000..b97878865b --- /dev/null +++ b/django/conf/locale/tr/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'd F Y' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'd F' +SHORT_DATE_FORMAT = 'd M Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = '.' +# NUMBER_GROUPING = diff --git a/django/conf/locale/uk/__init__.py b/django/conf/locale/uk/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/uk/formats.py b/django/conf/locale/uk/formats.py new file mode 100644 index 0000000000..8e41bf020d --- /dev/null +++ b/django/conf/locale/uk/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +DATE_FORMAT = 'j F Y р.' +TIME_FORMAT = 'H:i:s' +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = 'F Y' +MONTH_DAY_FORMAT = 'j F' +SHORT_DATE_FORMAT = 'j M Y' +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = ',' +THOUSAND_SEPARATOR = ' ' +# NUMBER_GROUPING = diff --git a/django/conf/locale/zh_CN/__init__.py b/django/conf/locale/zh_CN/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/zh_CN/formats.py b/django/conf/locale/zh_CN/formats.py new file mode 100644 index 0000000000..6d71786415 --- /dev/null +++ b/django/conf/locale/zh_CN/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +# DATE_FORMAT = +# TIME_FORMAT = +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +# MONTH_DAY_FORMAT = +# SHORT_DATE_FORMAT = +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/django/conf/locale/zh_TW/__init__.py b/django/conf/locale/zh_TW/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/locale/zh_TW/formats.py b/django/conf/locale/zh_TW/formats.py new file mode 100644 index 0000000000..6d71786415 --- /dev/null +++ b/django/conf/locale/zh_TW/formats.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +# This file is distributed under the same license as the Django package. +# + +# DATE_FORMAT = +# TIME_FORMAT = +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +# MONTH_DAY_FORMAT = +# SHORT_DATE_FORMAT = +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/django/contrib/admin/media/js/calendar.js b/django/contrib/admin/media/js/calendar.js index 90351763a7..3f57145041 100644 --- a/django/contrib/admin/media/js/calendar.js +++ b/django/contrib/admin/media/js/calendar.js @@ -25,6 +25,7 @@ function quickElement() { var CalendarNamespace = { monthsOfYear: gettext('January February March April May June July August September October November December').split(' '), daysOfWeek: gettext('S M T W T F S').split(' '), + firstDayOfWeek: parseInt(gettext('FIRST_DAY_OF_WEEK')), isLeapYear: function(year) { return (((year % 4)==0) && ((year % 100)!=0) || ((year % 400)==0)); }, @@ -56,10 +57,10 @@ var CalendarNamespace = { // Draw days-of-week header var tableRow = quickElement('tr', tableBody); for (var i = 0; i < 7; i++) { - quickElement('th', tableRow, CalendarNamespace.daysOfWeek[i]); + quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]); } - var startingPos = new Date(year, month-1, 1).getDay(); + var startingPos = new Date(year, month-1, 1 - CalendarNamespace.firstDayOfWeek).getDay(); var days = CalendarNamespace.getDaysInMonth(month, year); // Draw blanks before first of month diff --git a/django/contrib/admin/templates/admin/object_history.html b/django/contrib/admin/templates/admin/object_history.html index 38b1c34ac8..9e6223acb9 100644 --- a/django/contrib/admin/templates/admin/object_history.html +++ b/django/contrib/admin/templates/admin/object_history.html @@ -27,7 +27,7 @@ {% for action in action_list %} - {{ action.action_time|date:_("DATETIME_FORMAT") }} + {{ action.action_time|date }} {{ action.user.username }}{% if action.user.get_full_name %} ({{ action.user.get_full_name }}){% endif %} {{ action.change_message }} diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index 5a02ab01be..cd05957197 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -3,11 +3,11 @@ from django.contrib.admin.views.main import ALL_VAR, EMPTY_CHANGELIST_VALUE from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR from django.core.exceptions import ObjectDoesNotExist from django.db import models -from django.utils import dateformat +from django.utils import formats from django.utils.html import escape, conditional_escape from django.utils.text import capfirst from django.utils.safestring import mark_safe -from django.utils.translation import get_date_formats, get_partial_date_formats, ugettext as _ +from django.utils.translation import ugettext as _ from django.utils.encoding import smart_unicode, smart_str, force_unicode from django.template import Library import datetime @@ -189,25 +189,24 @@ def items_for_result(cl, result, form): # Dates and times are special: They're formatted in a certain way. elif isinstance(f, models.DateField) or isinstance(f, models.TimeField): if field_val: - (date_format, datetime_format, time_format) = get_date_formats() - if isinstance(f, models.DateTimeField): - result_repr = capfirst(dateformat.format(field_val, datetime_format)) - elif isinstance(f, models.TimeField): - result_repr = capfirst(dateformat.time_format(field_val, time_format)) - else: - result_repr = capfirst(dateformat.format(field_val, date_format)) + result_repr = formats.localize(field_val) + else: + result_repr = EMPTY_CHANGELIST_VALUE + elif isinstance(f, models.DecimalField): + if field_val: + result_repr = formats.number_format(field_val, f.decimal_places) + else: + result_repr = EMPTY_CHANGELIST_VALUE + row_class = ' class="nowrap"' + elif isinstance(f, models.FloatField): + if field_val: + result_repr = formats.number_format(field_val) else: result_repr = EMPTY_CHANGELIST_VALUE row_class = ' class="nowrap"' # Booleans are special: We use images. elif isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField): result_repr = _boolean_icon(field_val) - # DecimalFields are special: Zero-pad the decimals. - elif isinstance(f, models.DecimalField): - if field_val is not None: - result_repr = ('%%.%sf' % f.decimal_places) % field_val - else: - result_repr = EMPTY_CHANGELIST_VALUE # Fields with choices are special: Use the representation # of the choice. elif f.flatchoices: @@ -268,7 +267,6 @@ def date_hierarchy(cl): year_lookup = cl.params.get(year_field) month_lookup = cl.params.get(month_field) day_lookup = cl.params.get(day_field) - year_month_format, month_day_format = get_partial_date_formats() link = lambda d: cl.get_query_string(d, [field_generic]) @@ -278,9 +276,9 @@ def date_hierarchy(cl): 'show': True, 'back': { 'link': link({year_field: year_lookup, month_field: month_lookup}), - 'title': dateformat.format(day, year_month_format) + 'title': capfirst(formats.date_format(day, 'YEAR_MONTH_FORMAT')) }, - 'choices': [{'title': dateformat.format(day, month_day_format)}] + 'choices': [{'title': capfirst(formats.date_format(day, 'MONTH_DAY_FORMAT'))}] } elif year_lookup and month_lookup: days = cl.query_set.filter(**{year_field: year_lookup, month_field: month_lookup}).dates(field_name, 'day') @@ -292,7 +290,7 @@ def date_hierarchy(cl): }, 'choices': [{ 'link': link({year_field: year_lookup, month_field: month_lookup, day_field: day.day}), - 'title': dateformat.format(day, month_day_format) + 'title': capfirst(formats.date_format(day, 'MONTH_DAY_FORMAT')) } for day in days] } elif year_lookup: @@ -305,7 +303,7 @@ def date_hierarchy(cl): }, 'choices': [{ 'link': link({year_field: year_lookup, month_field: month.month}), - 'title': dateformat.format(month, year_month_format) + 'title': capfirst(formats.date_format(month, 'YEAR_MONTH_FORMAT')) } for month in months] } else: diff --git a/django/contrib/databrowse/datastructures.py b/django/contrib/databrowse/datastructures.py index 5fdbdbe134..369f825f0e 100644 --- a/django/contrib/databrowse/datastructures.py +++ b/django/contrib/databrowse/datastructures.py @@ -4,9 +4,8 @@ convenience functionality and permalink functions for the databrowse app. """ from django.db import models -from django.utils import dateformat +from django.utils import formats from django.utils.text import capfirst -from django.utils.translation import get_date_formats from django.utils.encoding import smart_unicode, smart_str, iri_to_uri from django.utils.safestring import mark_safe from django.db.models.query import QuerySet @@ -156,13 +155,12 @@ class EasyInstanceField(object): objs = dict(self.field.choices).get(self.raw_value, EMPTY_VALUE) elif isinstance(self.field, models.DateField) or isinstance(self.field, models.TimeField): if self.raw_value: - date_format, datetime_format, time_format = get_date_formats() if isinstance(self.field, models.DateTimeField): - objs = capfirst(dateformat.format(self.raw_value, datetime_format)) + objs = capfirst(formats.date_format(self.raw_value, 'DATETIME_FORMAT')) elif isinstance(self.field, models.TimeField): - objs = capfirst(dateformat.time_format(self.raw_value, time_format)) + objs = capfirst(formats.date_format(self.raw_value, 'TIME_FORMAT')) else: - objs = capfirst(dateformat.format(self.raw_value, date_format)) + objs = capfirst(formats.date_format(self.raw_value, 'DATE_FORMAT')) else: objs = EMPTY_VALUE elif isinstance(self.field, models.BooleanField) or isinstance(self.field, models.NullBooleanField): diff --git a/django/forms/extras/widgets.py b/django/forms/extras/widgets.py index e36b8a1d67..173ef2e1de 100644 --- a/django/forms/extras/widgets.py +++ b/django/forms/extras/widgets.py @@ -8,6 +8,8 @@ import re from django.forms.widgets import Widget, Select from django.utils.dates import MONTHS from django.utils.safestring import mark_safe +from django.utils.formats import get_format +from django.conf import settings __all__ = ('SelectDateWidget',) @@ -45,38 +47,27 @@ class SelectDateWidget(Widget): if match: year_val, month_val, day_val = [int(v) for v in match.groups()] + choices = [(i, i) for i in self.years] + year_html = self.create_select(name, self.year_field, value, year_val, choices) + choices = MONTHS.items() + month_html = self.create_select(name, self.month_field, value, month_val, choices) + choices = [(i, i) for i in range(1, 32)] + day_html = self.create_select(name, self.day_field, value, day_val, choices) + + format = get_format('DATE_FORMAT') + escaped = False output = [] - - if 'id' in self.attrs: - id_ = self.attrs['id'] - else: - id_ = 'id_%s' % name - - month_choices = MONTHS.items() - if not (self.required and value): - month_choices.append(self.none_value) - month_choices.sort() - local_attrs = self.build_attrs(id=self.month_field % id_) - s = Select(choices=month_choices) - select_html = s.render(self.month_field % name, month_val, local_attrs) - output.append(select_html) - - day_choices = [(i, i) for i in range(1, 32)] - if not (self.required and value): - day_choices.insert(0, self.none_value) - local_attrs['id'] = self.day_field % id_ - s = Select(choices=day_choices) - select_html = s.render(self.day_field % name, day_val, local_attrs) - output.append(select_html) - - year_choices = [(i, i) for i in self.years] - if not (self.required and value): - year_choices.insert(0, self.none_value) - local_attrs['id'] = self.year_field % id_ - s = Select(choices=year_choices) - select_html = s.render(self.year_field % name, year_val, local_attrs) - output.append(select_html) - + for char in format: + if escaped: + escaped = False + elif char == '\\': + escaped = True + elif char in 'Yy': + output.append(year_html) + elif char in 'bFMmNn': + output.append(month_html) + elif char in 'dj': + output.append(day_html) return mark_safe(u'\n'.join(output)) def id_for_label(self, id_): @@ -90,5 +81,27 @@ class SelectDateWidget(Widget): if y == m == d == "0": return None if y and m and d: - return '%s-%s-%s' % (y, m, d) + if settings.USE_L10N: + input_format = get_format('DATE_INPUT_FORMATS')[0] + try: + date_value = datetime.date(int(y), int(m), int(d)) + except ValueError: + pass + else: + return date_value.strftime(input_format) + else: + return '%s-%s-%s' % (y, m, d) return data.get(name, None) + + def create_select(self, name, field, value, val, choices): + if 'id' in self.attrs: + id_ = self.attrs['id'] + else: + id_ = 'id_%s' % name + if not (self.required and value): + choices.insert(0, self.none_value) + local_attrs = self.build_attrs(id=field % id_) + s = Select(choices=choices) + select_html = s.render(field % name, val, local_attrs) + return select_html + diff --git a/django/forms/fields.py b/django/forms/fields.py index c0ee2f0955..a4904d452d 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -7,6 +7,7 @@ import os import re import time import urlparse +import warnings from decimal import Decimal, DecimalException try: from cStringIO import StringIO @@ -17,6 +18,7 @@ import django.core.exceptions import django.utils.copycompat as copy from django.utils.translation import ugettext_lazy as _ from django.utils.encoding import smart_unicode, smart_str +from django.utils.formats import get_format from util import ErrorList, ValidationError from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget @@ -36,6 +38,20 @@ __all__ = ( # These values, if given to to_python(), will trigger the self.required check. EMPTY_VALUES = (None, '') +def en_format(name): + """ + Helper function to stay backward compatible. + """ + from django.conf.locale.en import formats + warnings.warn( + "`django.forms.fields.DEFAULT_%s` is deprecated; use `django.utils.formats.get_format('%s')` instead." % (name, name), + PendingDeprecationWarning + ) + return getattr(formats, name) + +DEFAULT_DATE_INPUT_FORMATS = en_format('DATE_INPUT_FORMATS') +DEFAULT_TIME_INPUT_FORMATS = en_format('TIME_INPUT_FORMATS') +DEFAULT_DATETIME_INPUT_FORMATS = en_format('DATETIME_INPUT_FORMATS') class Field(object): widget = TextInput # Default widget to use when rendering this type of Field. @@ -200,7 +216,9 @@ class FloatField(Field): if not self.required and value in EMPTY_VALUES: return None try: - value = float(value) + # We always accept dot as decimal separator + if isinstance(value, str) or isinstance(value, unicode): + value = float(value.replace(get_format('DECIMAL_SEPARATOR'), '.')) except (ValueError, TypeError): raise ValidationError(self.error_messages['invalid']) if self.max_value is not None and value > self.max_value: @@ -236,7 +254,9 @@ class DecimalField(Field): return None value = smart_str(value).strip() try: - value = Decimal(value) + # We always accept dot as decimal separator + if isinstance(value, str) or isinstance(value, unicode): + value = Decimal(value.replace(get_format('DECIMAL_SEPARATOR'), '.')) except DecimalException: raise ValidationError(self.error_messages['invalid']) @@ -264,14 +284,6 @@ class DecimalField(Field): raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places)) return value -DEFAULT_DATE_INPUT_FORMATS = ( - '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' - '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' - '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' - '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' - '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' -) - class DateField(Field): widget = DateInput default_error_messages = { @@ -280,7 +292,7 @@ class DateField(Field): def __init__(self, input_formats=None, *args, **kwargs): super(DateField, self).__init__(*args, **kwargs) - self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS + self.input_formats = input_formats def clean(self, value): """ @@ -294,18 +306,13 @@ class DateField(Field): return value.date() if isinstance(value, datetime.date): return value - for format in self.input_formats: + for format in self.input_formats or get_format('DATE_INPUT_FORMATS'): try: return datetime.date(*time.strptime(value, format)[:3]) except ValueError: continue raise ValidationError(self.error_messages['invalid']) -DEFAULT_TIME_INPUT_FORMATS = ( - '%H:%M:%S', # '14:30:59' - '%H:%M', # '14:30' -) - class TimeField(Field): widget = TimeInput default_error_messages = { @@ -314,7 +321,7 @@ class TimeField(Field): def __init__(self, input_formats=None, *args, **kwargs): super(TimeField, self).__init__(*args, **kwargs) - self.input_formats = input_formats or DEFAULT_TIME_INPUT_FORMATS + self.input_formats = input_formats def clean(self, value): """ @@ -326,25 +333,13 @@ class TimeField(Field): return None if isinstance(value, datetime.time): return value - for format in self.input_formats: + for format in self.input_formats or get_format('TIME_INPUT_FORMATS'): try: return datetime.time(*time.strptime(value, format)[3:6]) except ValueError: continue raise ValidationError(self.error_messages['invalid']) -DEFAULT_DATETIME_INPUT_FORMATS = ( - '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' - '%Y-%m-%d %H:%M', # '2006-10-25 14:30' - '%Y-%m-%d', # '2006-10-25' - '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59' - '%m/%d/%Y %H:%M', # '10/25/2006 14:30' - '%m/%d/%Y', # '10/25/2006' - '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59' - '%m/%d/%y %H:%M', # '10/25/06 14:30' - '%m/%d/%y', # '10/25/06' -) - class DateTimeField(Field): widget = DateTimeInput default_error_messages = { @@ -353,7 +348,7 @@ class DateTimeField(Field): def __init__(self, input_formats=None, *args, **kwargs): super(DateTimeField, self).__init__(*args, **kwargs) - self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS + self.input_formats = input_formats def clean(self, value): """ @@ -373,7 +368,7 @@ class DateTimeField(Field): if len(value) != 2: raise ValidationError(self.error_messages['invalid']) value = '%s %s' % tuple(value) - for format in self.input_formats: + for format in self.input_formats or get_format('DATETIME_INPUT_FORMATS'): try: return datetime.datetime(*time.strptime(value, format)[:6]) except ValueError: diff --git a/django/forms/widgets.py b/django/forms/widgets.py index d59e6343e5..aabd1b017d 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -10,6 +10,7 @@ from django.utils.html import escape, conditional_escape from django.utils.translation import ugettext from django.utils.encoding import StrAndUnicode, force_unicode from django.utils.safestring import mark_safe +from django.utils.formats import localize from django.utils import datetime_safe from datetime import time from util import flatatt @@ -208,7 +209,7 @@ class Input(Widget): final_attrs = self.build_attrs(attrs, type=self.input_type, name=name) if value != '': # Only add the 'value' attribute if a value is non-empty. - final_attrs['value'] = force_unicode(value) + final_attrs['value'] = force_unicode(localize(value, is_input=True)) return mark_safe(u'' % flatatt(final_attrs)) class TextInput(Input): diff --git a/django/template/__init__.py b/django/template/__init__.py index 8764bfada4..4c386bea30 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -60,6 +60,7 @@ from django.utils.text import smart_split, unescape_string_literal from django.utils.encoding import smart_unicode, force_unicode, smart_str from django.utils.translation import ugettext as _ from django.utils.safestring import SafeData, EscapeData, mark_safe, mark_for_escaping +from django.utils.formats import localize from django.utils.html import escape __all__ = ('Template', 'Context', 'RequestContext', 'compile_string') @@ -815,6 +816,7 @@ def _render_value_in_context(value, context): means escaping, if required, and conversion to a unicode object. If value is a string, it is expected to have already been translated. """ + value = localize(value) value = force_unicode(value) if (context.autoescape and not isinstance(value, SafeData)) or isinstance(value, EscapeData): return escape(value) diff --git a/django/template/debug.py b/django/template/debug.py index c58c854858..382fb75ebd 100644 --- a/django/template/debug.py +++ b/django/template/debug.py @@ -2,6 +2,7 @@ from django.template import Lexer, Parser, tag_re, NodeList, VariableNode, Templ from django.utils.encoding import force_unicode from django.utils.html import escape from django.utils.safestring import SafeData, EscapeData +from django.utils.formats import localize class DebugLexer(Lexer): def __init__(self, template_string, origin): @@ -84,7 +85,9 @@ class DebugNodeList(NodeList): class DebugVariableNode(VariableNode): def render(self, context): try: - output = force_unicode(self.filter_expression.resolve(context)) + output = self.filter_expression.resolve(context) + output = localize(output) + output = force_unicode(output) except TemplateSyntaxError, e: if not hasattr(e, 'source'): e.source = self.source diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py index a8c25670f6..26b6b5ec4e 100644 --- a/django/template/defaultfilters.py +++ b/django/template/defaultfilters.py @@ -18,6 +18,7 @@ from django.conf import settings from django.utils.translation import ugettext, ungettext from django.utils.encoding import force_unicode, iri_to_uri from django.utils.safestring import mark_safe, SafeData +from django.utils.formats import date_format, number_format register = Library() @@ -166,14 +167,14 @@ def floatformat(text, arg=-1): return input_val if not m and p < 0: - return mark_safe(u'%d' % (int(d))) + return mark_safe(number_format(u'%d' % (int(d)), 0)) if p == 0: exp = Decimal(1) else: exp = Decimal('1.0') / (Decimal(10) ** abs(p)) try: - return mark_safe(u'%s' % str(d.quantize(exp, ROUND_HALF_UP))) + return mark_safe(number_format(u'%s' % str(d.quantize(exp, ROUND_HALF_UP)), abs(p))) except InvalidOperation: return input_val floatformat.is_safe = True @@ -685,9 +686,12 @@ def date(value, arg=None): if arg is None: arg = settings.DATE_FORMAT try: - return format(value, arg) + return date_format(value, arg) except AttributeError: - return '' + try: + return format(value, arg) + except AttributeError: + return '' date.is_safe = False def time(value, arg=None): @@ -698,9 +702,12 @@ def time(value, arg=None): if arg is None: arg = settings.TIME_FORMAT try: - return time_format(value, arg) + return date_format(value, arg) except AttributeError: - return '' + try: + return time_format(value, arg) + except AttributeError: + return '' time.is_safe = False def timesince(value, arg=None): diff --git a/django/utils/formats.py b/django/utils/formats.py new file mode 100644 index 0000000000..e18e120b36 --- /dev/null +++ b/django/utils/formats.py @@ -0,0 +1,97 @@ +import decimal +import datetime + +from django.conf import settings +from django.utils.translation import get_language, to_locale, check_for_language +from django.utils.importlib import import_module +from django.utils import dateformat +from django.utils import numberformat + +def get_format_modules(): + """ + Returns an iterator over the format modules found in the project and Django + """ + modules = [] + if not check_for_language(get_language()): + return modules + locale = to_locale(get_language()) + if settings.FORMAT_MODULE_PATH: + format_locations = [settings.FORMAT_MODULE_PATH + '.%s'] + else: + format_locations = [] + format_locations.append('django.conf.locale.%s') + for location in format_locations: + for l in (locale, locale.split('_')[0]): + try: + mod = import_module('.formats', location % l) + except ImportError: + pass + else: + # Don't return duplicates + if mod not in modules: + modules.append(mod) + return modules + +def get_format(format_type): + """ + For a specific format type, returns the format for the current + language (locale), defaults to the format in the settings. + format_type is the name of the format, e.g. 'DATE_FORMAT' + """ + if settings.USE_L10N: + for module in get_format_modules(): + try: + return getattr(module, format_type) + except AttributeError: + pass + return getattr(settings, format_type) + +def date_format(value, format=None): + """ + Formats a datetime.date or datetime.datetime object using a + localizable format + """ + return dateformat.format(value, get_format(format or 'DATE_FORMAT')) + +def number_format(value, decimal_pos=None): + """ + Formats a numeric value using localization settings + """ + return numberformat.format( + value, + get_format('DECIMAL_SEPARATOR'), + decimal_pos, + get_format('NUMBER_GROUPING'), + get_format('THOUSAND_SEPARATOR'), + ) + +def localize(value, is_input=False): + """ + Checks value, and if it has a localizable type (date, + number...) it returns the value as a string using + current locale format + """ + if settings.USE_L10N: + if isinstance(value, decimal.Decimal): + return number_format(value) + elif isinstance(value, float): + return number_format(value) + elif isinstance(value, int): + return number_format(value) + elif isinstance(value, datetime.datetime): + if not is_input: + return date_format(value, 'DATETIME_FORMAT') + else: + return value.strftime(get_format('DATETIME_INPUT_FORMATS')[0]) + elif isinstance(value, datetime.date): + if not is_input: + return date_format(value) + else: + return value.strftime(get_format('DATE_INPUT_FORMATS')[0]) + elif isinstance(value, datetime.time): + if not is_input: + return date_format(value, 'TIME_FORMAT') + else: + return value.strftime(get_format('TIME_INPUT_FORMATS')[0]) + return value + diff --git a/django/utils/numberformat.py b/django/utils/numberformat.py new file mode 100644 index 0000000000..78ecb2fbdb --- /dev/null +++ b/django/utils/numberformat.py @@ -0,0 +1,42 @@ +from django.conf import settings + +def format(number, decimal_sep, decimal_pos, grouping=0, thousand_sep=''): + """ + Gets a number (as a number or string), and returns it as a string, + using formats definied as arguments: + + * decimal_sep: Decimal separator symbol (for example ".") + * decimal_pos: Number of decimal positions + * grouping: Number of digits in every group limited by thousand separator + * thousand_sep: Thousand separator symbol (for example ",") + + """ + # sign + if float(number) < 0: + sign = '-' + else: + sign = '' + # decimal part + str_number = unicode(number) + if str_number[0] == '-': + str_number = str_number[1:] + if '.' in str_number: + int_part, dec_part = str_number.split('.') + if decimal_pos: + dec_part = dec_part[:decimal_pos] + else: + int_part, dec_part = str_number, '' + if decimal_pos: + dec_part = dec_part + ('0' * (decimal_pos - len(dec_part))) + if dec_part: dec_part = decimal_sep + dec_part + # grouping + if settings.USE_THOUSAND_SEPARATOR and grouping: + int_part_gd = '' + for cnt, digit in enumerate(int_part[::-1]): + if cnt and not cnt % grouping: + int_part_gd += thousand_sep + int_part_gd += digit + int_part = int_part_gd[::-1] + + return sign + int_part + dec_part + diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py index 98c6de6197..50f41a2c23 100644 --- a/django/utils/translation/trans_null.py +++ b/django/utils/translation/trans_null.py @@ -2,6 +2,7 @@ # that don't actually do anything. This is purely for performance, so that # settings.USE_I18N = False can use this module rather than trans_real.py. +import warnings from django.conf import settings from django.utils.encoding import force_unicode from django.utils.safestring import mark_safe, SafeData @@ -18,10 +19,10 @@ activate = lambda x: None deactivate = deactivate_all = lambda: None get_language = lambda: settings.LANGUAGE_CODE get_language_bidi = lambda: settings.LANGUAGE_CODE in settings.LANGUAGES_BIDI -get_date_formats = lambda: (settings.DATE_FORMAT, settings.DATETIME_FORMAT, settings.TIME_FORMAT) -get_partial_date_formats = lambda: (settings.YEAR_MONTH_FORMAT, settings.MONTH_DAY_FORMAT) check_for_language = lambda x: True +# date formats shouldn't be used using gettext anymore. This +# is kept for backward compatibility TECHNICAL_ID_MAP = { "DATE_WITH_TIME_FULL": settings.DATETIME_FORMAT, "DATE_FORMAT": settings.DATE_FORMAT, @@ -51,3 +52,21 @@ def to_locale(language): def get_language_from_request(request): return settings.LANGUAGE_CODE + +# get_date_formats and get_partial_date_formats aren't used anymore by Django +# but are kept for backward compatibility. +def get_date_formats(): + warnings.warn( + '`django.utils.translation.get_date_formats` is deprecated. ' + 'Please update your code to use the new i18n aware formatting.', + PendingDeprecationWarning + ) + return settings.DATE_FORMAT, settings.DATETIME_FORMAT, settings.TIME_FORMAT + +def get_partial_date_formats(): + warnings.warn( + '`django.utils.translation.get_partial_date_formats` is deprecated. ' + 'Please update your code to use the new i18n aware formatting.', + PendingDeprecationWarning + ) + return settings.YEAR_MONTH_FORMAT, settings.MONTH_DAY_FORMAT diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index 48ed7cc885..8b7db0f123 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -4,6 +4,7 @@ import locale import os import re import sys +import warnings import gettext as gettext_module from cStringIO import StringIO @@ -266,15 +267,16 @@ def do_translate(message, translation_function): translation object to use. If no current translation is activated, the message will be run through the default translation object. """ + eol_message = message.replace('\r\n', '\n').replace('\r', '\n') global _default, _active t = _active.get(currentThread(), None) if t is not None: - result = getattr(t, translation_function)(message) + result = getattr(t, translation_function)(eol_message) else: if _default is None: from django.conf import settings _default = translation(settings.LANGUAGE_CODE) - result = getattr(_default, translation_function)(message) + result = getattr(_default, translation_function)(eol_message) if isinstance(message, SafeData): return mark_safe(result) return result @@ -389,39 +391,6 @@ def get_language_from_request(request): return settings.LANGUAGE_CODE -def get_date_formats(): - """ - Checks whether translation files provide a translation for some technical - message ID to store date and time formats. If it doesn't contain one, the - formats provided in the settings will be used. - """ - from django.conf import settings - date_format = ugettext('DATE_FORMAT') - datetime_format = ugettext('DATETIME_FORMAT') - time_format = ugettext('TIME_FORMAT') - if date_format == 'DATE_FORMAT': - date_format = settings.DATE_FORMAT - if datetime_format == 'DATETIME_FORMAT': - datetime_format = settings.DATETIME_FORMAT - if time_format == 'TIME_FORMAT': - time_format = settings.TIME_FORMAT - return date_format, datetime_format, time_format - -def get_partial_date_formats(): - """ - Checks whether translation files provide a translation for some technical - message ID to store partial date formats. If it doesn't contain one, the - formats provided in the settings will be used. - """ - from django.conf import settings - year_month_format = ugettext('YEAR_MONTH_FORMAT') - month_day_format = ugettext('MONTH_DAY_FORMAT') - if year_month_format == 'YEAR_MONTH_FORMAT': - year_month_format = settings.YEAR_MONTH_FORMAT - if month_day_format == 'MONTH_DAY_FORMAT': - month_day_format = settings.MONTH_DAY_FORMAT - return year_month_format, month_day_format - dot_re = re.compile(r'\S') def blankout(src, char): """ @@ -537,3 +506,52 @@ def parse_accept_lang_header(lang_string): result.append((lang, priority)) result.sort(lambda x, y: -cmp(x[1], y[1])) return result + +# get_date_formats and get_partial_date_formats aren't used anymore by Django +# and are kept for backward compatibility. +# Note, it's also important to keep format names marked for translation. +# For compatibility we still want to have formats on translation catalogs. +# That makes template code like {{ my_date|date:_('DATE_FORMAT') }} still work +def get_date_formats(): + """ + Checks whether translation files provide a translation for some technical + message ID to store date and time formats. If it doesn't contain one, the + formats provided in the settings will be used. + """ + warnings.warn( + '`django.utils.translation.get_date_formats` is deprecated. ' + 'Please update your code to use the new i18n aware formatting.', + PendingDeprecationWarning + ) + from django.conf import settings + date_format = ugettext('DATE_FORMAT') + datetime_format = ugettext('DATETIME_FORMAT') + time_format = ugettext('TIME_FORMAT') + if date_format == 'DATE_FORMAT': + date_format = settings.DATE_FORMAT + if datetime_format == 'DATETIME_FORMAT': + datetime_format = settings.DATETIME_FORMAT + if time_format == 'TIME_FORMAT': + time_format = settings.TIME_FORMAT + return date_format, datetime_format, time_format + +def get_partial_date_formats(): + """ + Checks whether translation files provide a translation for some technical + message ID to store partial date formats. If it doesn't contain one, the + formats provided in the settings will be used. + """ + warnings.warn( + '`django.utils.translation.get_partial_date_formats` is deprecated. ' + 'Please update your code to use the new i18n aware formatting.', + PendingDeprecationWarning + ) + from django.conf import settings + year_month_format = ugettext('YEAR_MONTH_FORMAT') + month_day_format = ugettext('MONTH_DAY_FORMAT') + if year_month_format == 'YEAR_MONTH_FORMAT': + year_month_format = settings.YEAR_MONTH_FORMAT + if month_day_format == 'MONTH_DAY_FORMAT': + month_day_format = settings.MONTH_DAY_FORMAT + return year_month_format, month_day_format + diff --git a/django/views/i18n.py b/django/views/i18n.py index 0280698aae..ddd75203a7 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -1,10 +1,12 @@ +import os +import gettext as gettext_module + from django import http from django.conf import settings from django.utils import importlib from django.utils.translation import check_for_language, activate, to_locale, get_language from django.utils.text import javascript_quote -import os -import gettext as gettext_module +from django.utils.formats import get_format_modules def set_language(request): """ @@ -32,6 +34,24 @@ def set_language(request): response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code) return response +def get_formats(): + """ + Returns an iterator over all formats in formats file + """ + FORMAT_SETTINGS = ('DATE_FORMAT', 'DATETIME_FORMAT', 'TIME_FORMAT', + 'YEAR_MONTH_FORMAT', 'MONTH_DAY_FORMAT', 'SHORT_DATE_FORMAT', + 'SHORT_DATETIME_FORMAT', 'FIRST_DAY_OF_WEEK', 'DECIMAL_SEPARATOR', + 'THOUSAND_SEPARATOR', 'NUMBER_GROUPING') + + result = {} + for module in [settings] + get_format_modules(): + for attr in FORMAT_SETTINGS: + try: + result[attr] = getattr(module, attr) + except AttributeError: + pass + return result + NullSource = """ /* gettext identity library */ @@ -185,10 +205,13 @@ def javascript_catalog(request, domain='djangojs', packages=None): else: raise TypeError, k csrc.sort() - for k,v in pdict.items(): + for k, v in pdict.items(): src.append("catalog['%s'] = [%s];\n" % (javascript_quote(k), ','.join(["''"]*(v+1)))) + for k, v in get_formats().items(): + src.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(unicode(v)))) src.extend(csrc) src.append(LibFoot) src.append(InterPolate) src = ''.join(src) return http.HttpResponse(src, 'text/javascript') + diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 2e44e418bc..1bd58ec0b3 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -62,6 +62,18 @@ their deprecation, as per the :ref:`Django deprecation policy backwards compatibility. These have been deprecated since the 1.2 release. + * ``django.utils.translation.get_date_formats()`` and + ``django.utils.translation.get_partial_date_formats()``. These + functions are replaced by the new locale aware formatting; use + ``django.utils.formats.get_format()`` to get the appropriate + formats. + + * In ``django.forms.fields``: ``DEFAULT_DATE_INPUT_FORMATS``, + ``DEFAULT_TIME_INPUT_FORMATS`` and + ``DEFAULT_DATETIME_INPUT_FORMATS``. Use + ``django.utils.formats.get_format()`` to get the appropriate + formats. + * 2.0 * ``django.views.defaults.shortcut()``. This function has been moved to ``django.contrib.contenttypes.views.shortcut()`` as part of the diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 1feb34a90b..bd8be27e5f 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -372,12 +372,32 @@ DATE_FORMAT Default: ``'N j, Y'`` (e.g. ``Feb. 4, 2003``) -The default formatting to use for date fields on Django admin change-list -pages -- and, possibly, by other parts of the system. See -:ttag:`allowed date format strings `. +The default formatting to use for date fields in any part of the system. +Note that if ``USE_L10N`` is set to ``True``, then locale format will +be applied. See :ttag:`allowed date format strings `. -See also ``DATETIME_FORMAT``, ``TIME_FORMAT``, ``YEAR_MONTH_FORMAT`` -and ``MONTH_DAY_FORMAT``. +See also ``DATETIME_FORMAT``, ``TIME_FORMAT`` and ``SHORT_DATE_FORMAT``. + +.. setting:: DATE_INPUT_FORMATS + +DATE_INPUT_FORMATS +------------------ + +Default:: + + ('%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', '%b %d %Y', + '%b %d, %Y', '%d %b %Y', '%d %b, %Y', '%B %d %Y', + '%B %d, %Y', '%d %B %Y', '%d %B, %Y') + +A tuple of formats that will be accepted when inputting data on a date +field. Formats will be tried in order, using the first valid. +Note that these format strings are specified in Python's datetime_ module +syntax, that is different from the one used by Django for formatting dates +to be displayed. + +See also ``DATETIME_INPUT_FORMATS`` and ``TIME_INPUT_FORMATS``. + +.. _datetime: http://docs.python.org/library/datetime.html#strftime-behavior .. setting:: DATETIME_FORMAT @@ -386,12 +406,32 @@ DATETIME_FORMAT Default: ``'N j, Y, P'`` (e.g. ``Feb. 4, 2003, 4 p.m.``) -The default formatting to use for datetime fields on Django admin change-list -pages -- and, possibly, by other parts of the system. See -:ttag:`allowed date format strings `. +The default formatting to use for datetime fields in any part of the system. +Note that if ``USE_L10N`` is set to ``True``, then locale format will +be applied. See :ttag:`allowed date format strings `. -See also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT``, -``YEAR_MONTH_FORMAT`` and ``MONTH_DAY_FORMAT``. +See also ``DATE_FORMAT``, ``TIME_FORMAT`` and ``SHORT_DATETIME_FORMAT``. + +.. setting:: DATETIME_INPUT_FORMATS + +DATETIME_INPUT_FORMATS +---------------------- + +Default:: + + ('%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M', '%Y-%m-%d', + '%m/%d/%Y %H:%M:%S', '%m/%d/%Y %H:%M', '%m/%d/%Y', + '%m/%d/%y %H:%M:%S', '%m/%d/%y %H:%M', '%m/%d/%y') + +A tuple of formats that will be accepted when inputting data on a datetime +field. Formats will be tried in order, using the first valid. +Note that these format strings are specified in Python's datetime_ module +syntax, that is different from the one used by Django for formatting dates +to be displayed. + +See also ``DATE_INPUT_FORMATS`` and ``TIME_INPUT_FORMATS``. + +.. _datetime: http://docs.python.org/library/datetime.html#strftime-behavior .. setting:: DEBUG @@ -431,6 +471,14 @@ will be suppressed, and exceptions will propagate upwards. This can be useful for some test setups, and should never be used on a live site. +.. setting:: DECIMAL_SEPARATOR + +DECIMAL_SEPARATOR +----------------- + +Default: ``'.'`` (Dot) + +Default decimal separator used when formatting decimal numbers. .. setting:: DEFAULT_CHARSET @@ -680,6 +728,21 @@ system's standard umask. .. _documentation for os.chmod: http://docs.python.org/lib/os-file-dir.html +.. setting:: FIRST_DAY_OF_WEEK + +FIRST_DAY_OF_WEEK +----------------- + +Default: ``0`` (Sunday) + +Number representing the first day of the week. This is especially useful +when displaying a calendar. This value is only used when not using +format internationalization, or when a format cannot be found for the +current locale. + +The value must be an integer from 0 to 6, where 0 means Sunday, 1 means +Monday and so on. + .. setting:: FIXTURE_DIRS FIXTURE_DIRS @@ -701,6 +764,34 @@ environment variable in any HTTP request. This setting can be used to override the server-provided value of ``SCRIPT_NAME``, which may be a rewritten version of the preferred value or not supplied at all. +.. setting:: FORMAT_MODULE_PATH + +FORMAT_MODULE_PATH +------------------ + +Default: ``None`` + +A full Python path to a Python package that contains format definitions for +project locales. If not ``None``, Django will check for a ``formats.py`` +file, under the directory named as the current locale, and will use the +formats defined on this file. + +For example, if ``FORMAT_MODULE_PATH`` is set to ``mysite.formats``, and +current language is ``en`` (English), Django will expect a directory tree +like:: + + mysite/ + formats/ + __init__.py + en/ + __init__.py + formats.py + +Available formats are ``DATE_FORMAT``, ``TIME_FORMAT``, ``DATETIME_FORMAT``, +``YEAR_MONTH_FORMAT``, ``MONTH_DAY_FORMAT``, ``SHORT_DATE_FORMAT``, +``SHORT_DATETIME_FORMAT``, ``FIRST_DAY_OF_WEEK``, ``DECIMAL_SEPARATOR``, +``THOUSAND_SEPARATOR`` and ``NUMBER_GROUPING``. + .. setting:: IGNORABLE_404_ENDS IGNORABLE_404_ENDS @@ -845,7 +936,7 @@ LOGIN_URL Default: ``'/accounts/login/'`` -The URL where requests are redirected for login, specially when using the +The URL where requests are redirected for login, especially when using the :func:`~django.contrib.auth.decorators.login_required` decorator. .. setting:: LOGOUT_URL @@ -970,6 +1061,21 @@ locales have different formats. For example, U.S. English would say See :ttag:`allowed date format strings `. See also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT`` and ``YEAR_MONTH_FORMAT``. +.. setting:: NUMBER_GROUPING + +NUMBER_GROUPING +---------------- + +Default: ``0`` + +Number of digits grouped together on the integer part of a number. Common use +is to display a thousand separator. If this setting is ``0``, then, no grouping +will be applied to the number. If this setting is greater than ``0`` then the +setting ``THOUSAND_SEPARATOR`` will be used as the separator between those +groups. + +See also ``THOUSAND_SEPARATOR`` + .. setting:: PREPEND_WWW PREPEND_WWW @@ -1173,6 +1279,32 @@ Default: ``False`` Whether to save the session data on every request. See :ref:`topics-http-sessions`. +.. setting:: SHORT_DATE_FORMAT + +SHORT_DATE_FORMAT +----------------- + +Default: ``m/d/Y`` (e.g. ``12/31/2003``) + +An available formatting that can be used for date fields on templates. +Note that if ``USE_L10N`` is set to ``True``, then locale format will +be applied. See :ttag:`allowed date format strings `. + +See also ``DATE_FORMAT`` and ``SHORT_DATETIME_FORMAT``. + +.. setting:: SHORT_DATETIME_FORMAT + +SHORT_DATETIME_FORMAT +--------------------- + +Default: ``m/d/Y P`` (e.g. ``12/31/2003 4 p.m.``) + +An available formatting that can be used for datetime fields on templates. +Note that if ``USE_L10N`` is set to ``True``, then locale format will +be applied. See :ttag:`allowed date format strings `. + +See also ``DATE_FORMAT`` and ``SHORT_DATETIME_FORMAT``. + .. setting:: SITE_ID SITE_ID @@ -1277,6 +1409,18 @@ The name of the method to use for starting the test suite. See .. _Testing Django Applications: ../testing/ +.. setting:: THOUSAND_SEPARATOR + +THOUSAND_SEPARATOR +------------------ + +Default ``,`` (Comma) + +Default thousand separator used when formatting numbers. This setting is +used only when ``NUMBER_GROUPPING`` is set. + +See also ``NUMBER_GROUPPING``, ``DECIMAL_SEPARATOR`` + .. setting:: TIME_FORMAT TIME_FORMAT @@ -1284,12 +1428,28 @@ TIME_FORMAT Default: ``'P'`` (e.g. ``4 p.m.``) -The default formatting to use for time fields on Django admin change-list -pages -- and, possibly, by other parts of the system. See -:ttag:`allowed date format strings `. +The default formatting to use for time fields in any part of the system. +Note that if ``USE_L10N`` is set to ``True``, then locale format will +be applied. See :ttag:`allowed date format strings `. -See also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT``, -``YEAR_MONTH_FORMAT`` and ``MONTH_DAY_FORMAT``. +See also ``DATE_FORMAT`` and ``DATETIME_FORMAT``. + +.. setting:: TIME_INPUT_FORMATS + +TIME_INPUT_FORMATS +------------------ + +Default: ``('%H:%M:%S', '%H:%M')`` + +A tuple of formats that will be accepted when inputting data on a time +field. Formats will be tried in order, using the first valid. +Note that these format strings are specified in Python's datetime_ module +syntax, that is different from the one used by Django for formatting dates +to be displayed. + +See also ``DATE_INPUT_FORMATS`` and ``DATETIME_INPUT_FORMATS``. + +.. _datetime: http://docs.python.org/library/datetime.html#strftime-behavior .. setting:: TIME_ZONE @@ -1344,6 +1504,19 @@ A boolean that specifies whether to output the "Etag" header. This saves bandwidth but slows down performance. This is only used if ``CommonMiddleware`` is installed (see :ref:`topics-http-middleware`). +.. setting:: USE_L10N + +USE_L10N +-------- + +Default ``False`` + +A boolean that specifies if data will be localized by default or not. If this +is set to ``True``, e.g. Django will display numbers and dates using the +format of the current locale. + +See also ``USE_I18N`` and ``LANGUAGE_CODE`` + .. setting:: USE_I18N USE_I18N @@ -1356,6 +1529,22 @@ enabled. This provides an easy way to turn it off, for performance. If this is set to ``False``, Django will make some optimizations so as not to load the internationalization machinery. +See also ``USE_L10N`` + +.. setting:: USE_THOUSAND_SEPARATOR + +USE_THOUSAND_SEPARATOR +---------------------- + +Default ``False`` + +A boolean that specifies wheter to display numbers using a thousand separator. +If this is set to ``True``, Django will use values from ``THOUSAND_SEPARATOR`` +and ``NUMBER_GROUPING`` from current locale, to format the number. +``USE_L10N`` must be set to ``True``, in order to format numbers. + +See also ``THOUSAND_SEPARATOR`` and ``NUMBER_GROUPING``. + .. setting:: YEAR_MONTH_FORMAT YEAR_MONTH_FORMAT diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index bf2d9e899c..b7afa15f7f 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -1047,7 +1047,12 @@ If ``value`` is ``"String with spaces"``, the output will be ``"Stringwithspaces date ~~~~ -Formats a date according to the given format (same as the `now`_ tag). +Formats a date according to the given format. + +Given format can be one of the predefined ones ``DATE_FORMAT``, +``DATETIME_FORMAT``, ``SHORT_DATE_FORMAT`` or ``SHORT_DATETIME_FORMAT``, +or a custom format, same as the `now`_ tag. Note that predefined formats may +vary depending on the current locale. For example:: @@ -1062,7 +1067,7 @@ When used without a format string:: {{ value|date }} ...the formatting string defined in the :setting:`DATE_FORMAT` setting will be -used. +used, without applying any localization. .. templatefilter:: default @@ -1610,7 +1615,11 @@ output will be ``"Joel is a slug"``. time ~~~~ -Formats a time according to the given format (same as the `now`_ tag). +Formats a time according to the given format. + +Given format can be the predefined one ``TIME_FORMAT``, or a custom format, +same as the `now`_ tag. Note that the predefined format is locale depending. + The time filter will only accept parameters in the format string that relate to the time of day, not the date (for obvious reasons). If you need to format a date, use the `date`_ filter. @@ -1627,7 +1636,7 @@ When used without a format string:: {{ value|time }} ...the formatting string defined in the :setting:`TIME_FORMAT` setting will be -used. +used, without aplying any localization. .. templatefilter:: timesince diff --git a/docs/releases/1.2.txt b/docs/releases/1.2.txt index 2111212054..200fb4a5b6 100644 --- a/docs/releases/1.2.txt +++ b/docs/releases/1.2.txt @@ -318,6 +318,41 @@ For more information, see the full :ref:`messages documentation `. You should begin to update your code to use the new API immediately. +Date format helper functions +---------------------------- + +``django.utils.translation.get_date_formats()`` and +``django.utils.translation.get_partial_date_formats()`` have been deprecated +in favor of the appropriate calls to ``django.utils.formats.get_format()`` +which is locale aware when :setting:`USE_L10N` is set to ``True``, and falls +back to default settings if set to ``False``. + +To get the different date formats, instead of writing:: + + from django.utils.translation import get_date_formats + date_format, datetime_format, time_format = get_date_formats() + +use:: + + from django.utils import formats + + date_format = formats.get_format('DATE_FORMAT') + datetime_format = formats.get_format('DATETIME_FORMAT') + time_format = formats.get_format('TIME_FORMAT') + +or, when directly formatting a date value:: + + from django.utils import formats + value_formatted = formats.date_format(value, 'DATETIME_FORMAT') + +The same applies to the globals found in ``django.forms.fields``: + + * ``DEFAULT_DATE_INPUT_FORMATS`` + * ``DEFAULT_TIME_INPUT_FORMATS`` + * ``DEFAULT_DATETIME_INPUT_FORMATS`` + +Use ``django.utils.formats.get_format()`` to get the appropriate formats. + What's new in Django 1.2 ======================== @@ -440,3 +475,13 @@ The ``test`` subcommand of ``django-admin.py``, and the ``runtests.py`` script used to run Django's own test suite, support a new ``--failfast`` option. When specified, this option causes the test runner to exit after encountering a failure instead of continuing with the test run. + +Improved localization +--------------------- + +Django's :ref:`internationalization framework ` has been +expanded by locale aware formatting and form processing. That means, if +enabled, dates and numbers on templates will be displayed using the format +specified for the current locale. Django will also use localized formats +when parsing data in forms. +See :ref:`Format localization ` for more details. diff --git a/docs/topics/i18n.txt b/docs/topics/i18n.txt index c5f4ab6481..993c7b5285 100644 --- a/docs/topics/i18n.txt +++ b/docs/topics/i18n.txt @@ -4,20 +4,20 @@ Internationalization ==================== -Django has full support for internationalization of text in code and templates. -Here's how it works. +Django has full support for internationalization of text in code and +templates, and format localization of dates and numbers. Here's how it works. Overview ======== The goal of internationalization is to allow a single Web application to offer -its content and functionality in multiple languages. +its content and functionality in multiple languages and locales. -You, the Django developer, can accomplish this goal by adding a minimal amount -of hooks to your Python code and templates. These hooks are called -**translation strings**. They tell Django: "This text should be translated into -the end user's language, if a translation for this text is available in that -language." +For text translation, you, the Django developer, can accomplish this goal by +adding a minimal amount of hooks to your Python code and templates. These hooks +are called **translation strings**. They tell Django: "This text should be +translated into the end user's language, if a translation for this text is +available in that language." Django takes care of using these hooks to translate Web apps, on the fly, according to users' language preferences. @@ -29,6 +29,12 @@ Essentially, Django does two things: * It uses these hooks to translate Web apps for particular users according to their language preferences. +For format localization, it's just necessary to set +:setting:`USE_L10N = True ` in your settings file. If +:setting:`USE_L10N` is set to ``True``, Django will display +numbers and dates in the format of the current locale. That includes field +representation on templates, and allowed input formats on the admin. + If you don't need internationalization in your app ================================================== @@ -1074,3 +1080,53 @@ have been found to not support this command. Do not attempt to use Django translation utilities with a ``gettext`` package if the command ``xgettext --version`` entered at a Windows command prompt causes a popup window saying "xgettext.exe has generated errors and will be closed by Windows". + +.. _format-localization: + +Format localization +=================== + +Django's formatting system is disabled by default. To enable it, it's necessay +to set :setting:`USE_L10N = True ` in your settings file. + +When using Django's formatting system, dates and numbers on templates will be +displayed using the format specified for the current locale. Two users +accessing the same content, but in different language, will see date and +number fields formatted in different ways, depending on the format for their +current locale. + +Django will also use localized formats when parsing data in forms. That means +Django uses different formats for different locales when guessing the format +used by the user when inputting data on forms. Note that Django uses different +formats for displaying data, and for parsing it. + +Creating custom format files +---------------------------- + +Django provides format definitions for many locales, but sometimes you might +want to create your own, because a format files doesn't exist for your locale, +or because you want to overwrite some of the values. + +To use custom formats, first thing to do, is to specify the path where you'll +place format files. To do that, just set your :setting:`FORMAT_MODULE_PATH` +setting to the the path (in the format ``'foo.bar.baz``) where format files +will exists. + +Files are not placed directly in this directory, but in a directory named as +the locale, and must be named ``formats.py``. + +To customize the English formats, a structure like this would be needed:: + + mysite/ + formats/ + __init__.py + en/ + __init__.py + formats.py + +where :file:`formats.py` contains custom format definitions. For example:: + + THOUSAND_SEPARATOR = ' ' + +to use a space as a thousand separator, instead of the default for English, +a comma. diff --git a/tests/regressiontests/i18n/misc.py b/tests/regressiontests/i18n/misc.py deleted file mode 100644 index f8f35ad4e4..0000000000 --- a/tests/regressiontests/i18n/misc.py +++ /dev/null @@ -1,114 +0,0 @@ -import sys - -tests = """ ->>> from django.utils.translation.trans_real import parse_accept_lang_header ->>> p = parse_accept_lang_header - -# -# Testing HTTP header parsing. First, we test that we can parse the values -# according to the spec (and that we extract all the pieces in the right order). -# - -Good headers. ->>> p('de') -[('de', 1.0)] ->>> p('en-AU') -[('en-AU', 1.0)] ->>> p('*;q=1.00') -[('*', 1.0)] ->>> p('en-AU;q=0.123') -[('en-AU', 0.123)] ->>> p('en-au;q=0.1') -[('en-au', 0.10000000000000001)] ->>> p('en-au;q=1.0') -[('en-au', 1.0)] ->>> p('da, en-gb;q=0.25, en;q=0.5') -[('da', 1.0), ('en', 0.5), ('en-gb', 0.25)] ->>> p('en-au-xx') -[('en-au-xx', 1.0)] ->>> p('de,en-au;q=0.75,en-us;q=0.5,en;q=0.25,es;q=0.125,fa;q=0.125') -[('de', 1.0), ('en-au', 0.75), ('en-us', 0.5), ('en', 0.25), ('es', 0.125), ('fa', 0.125)] ->>> p('*') -[('*', 1.0)] ->>> p('de;q=0.') -[('de', 1.0)] ->>> p('') -[] - -Bad headers; should always return []. ->>> p('en-gb;q=1.0000') -[] ->>> p('en;q=0.1234') -[] ->>> p('en;q=.2') -[] ->>> p('abcdefghi-au') -[] ->>> p('**') -[] ->>> p('en,,gb') -[] ->>> p('en-au;q=0.1.0') -[] ->>> p('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXZ,en') -[] ->>> p('da, en-gb;q=0.8, en;q=0.7,#') -[] ->>> p('de;q=2.0') -[] ->>> p('de;q=0.a') -[] ->>> p('') -[] - -# -# Now test that we parse a literal HTTP header correctly. -# - ->>> from django.utils.translation.trans_real import get_language_from_request ->>> g = get_language_from_request ->>> from django.http import HttpRequest ->>> r = HttpRequest ->>> r.COOKIES = {} - -These tests assumes the es, es_AR, pt and pt_BR translations exit in the Django -source tree. ->>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'pt-br'} ->>> g(r) -'pt-br' ->>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'pt'} ->>> g(r) -'pt' ->>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es,de'} ->>> g(r) -'es' ->>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-ar,de'} ->>> g(r) -'es-ar' -""" - -# Python 2.3 and 2.4 return slightly different results for completely bogus -# locales, so we omit this test for that anything below 2.4. It's relatively -# harmless in any cases (GIGO). This also means this won't be executed on -# Jython currently, but life's like that sometimes. (On those platforms, -# passing in a truly bogus locale will get you the default locale back.) -if sys.version_info >= (2, 5): - tests += """ -This test assumes there won't be a Django translation to a US variation -of the Spanish language, a safe assumption. When the user sets it -as the preferred language, the main 'es' translation should be selected -instead. ->>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-us'} ->>> g(r) -'es' -""" - -tests += """ -This tests the following scenario: there isn't a main language (zh) -translation of Django but there is a translation to variation (zh_CN) -the user sets zh-cn as the preferred language, it should be selected by -Django without falling back nor ignoring it. ->>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'zh-cn,de'} ->>> g(r) -'zh-cn' -""" diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py index 94e792cf54..c356970166 100644 --- a/tests/regressiontests/i18n/tests.py +++ b/tests/regressiontests/i18n/tests.py @@ -1,72 +1,375 @@ -# coding: utf-8 -import misc +import sys +from django.test import TestCase, client +from django.utils.translation import ugettext, ugettext_lazy, activate, deactivate, gettext_lazy -regressions = ur""" -Format string interpolation should work with *_lazy objects. +class TranslationTests(TestCase): ->>> from django.utils.translation import ugettext, ugettext_lazy, activate, deactivate, gettext_lazy ->>> s = ugettext_lazy('Add %(name)s') ->>> d = {'name': 'Ringo'} ->>> s % d -u'Add Ringo' ->>> activate('de') ->>> s % d -u'Ringo hinzuf\xfcgen' ->>> activate('pl') ->>> s % d -u'Dodaj Ringo' ->>> deactivate() + def test_lazy_objects(self): + """ + Format string interpolation should work with *_lazy objects. + """ + s = ugettext_lazy('Add %(name)s') + d = {'name': 'Ringo'} + self.assertEqual(u'Add Ringo', s % d) + activate('de') + self.assertEqual(u'Ringo hinzuf\xfcgen', s % d) + activate('pl') + self.assertEqual(u'Dodaj Ringo', s % d) + deactivate() -It should be possible to compare *_lazy objects. + # It should be possible to compare *_lazy objects. + s1 = ugettext_lazy('Add %(name)s') + self.assertEqual(True, s == s1) + s2 = gettext_lazy('Add %(name)s') + s3 = gettext_lazy('Add %(name)s') + self.assertEqual(True, s2 == s3) + self.assertEqual(True, s == s2) + s4 = ugettext_lazy('Some other string') + self.assertEqual(False, s == s4) ->>> s1 = ugettext_lazy('Add %(name)s') ->>> s == s1 -True ->>> s2 = gettext_lazy('Add %(name)s') ->>> s3 = gettext_lazy('Add %(name)s') ->>> s2 == s3 -True ->>> s == s2 -True ->>> s4 = ugettext_lazy('Some other string') ->>> s == s4 -False + def test_string_concat(self): + """ + unicode(string_concat(...)) should not raise a TypeError - #4796 + """ + import django.utils.translation + self.assertEqual(django.utils.translation, reload(django.utils.translation)) + self.assertEqual(u'django', unicode(django.utils.translation.string_concat("dja", "ngo"))) -unicode(string_concat(...)) should not raise a TypeError - #4796 + def test_safe_status(self): + """ + Translating a string requiring no auto-escaping shouldn't change the "safe" status. + """ + from django.utils.safestring import mark_safe, SafeString, SafeUnicode + s = mark_safe('Password') + self.assertEqual(SafeString, type(s)) + activate('de') + self.assertEqual(SafeUnicode, type(ugettext(s))) + deactivate() + self.assertEqual('aPassword', SafeString('a') + s) + self.assertEqual('Passworda', s + SafeString('a')) + self.assertEqual('Passworda', s + mark_safe('a')) + self.assertEqual('aPassword', mark_safe('a') + s) + self.assertEqual('as', mark_safe('a') + mark_safe('s')) + #self.assertEqual(Password, print s) ->>> import django.utils.translation ->>> reload(django.utils.translation) - ->>> unicode(django.utils.translation.string_concat("dja", "ngo")) -u'django' + def test_maclines(self): + """ + Translations on files with mac or dos end of lines will be converted + to unix eof in .po catalogs, and they have to match when retrieved + """ + from django.utils.translation.trans_real import translation + ca_translation = translation('ca') + ca_translation._catalog[u'Mac\nEOF\n'] = u'Catalan Mac\nEOF\n' + ca_translation._catalog[u'Win\nEOF\n'] = u'Catalan Win\nEOF\n' + activate('ca') + self.assertEqual(u'Catalan Mac\nEOF\n', ugettext(u'Mac\rEOF\r')) + self.assertEqual(u'Catalan Win\nEOF\n', ugettext(u'Win\r\nEOF\r\n')) + deactivate() -Translating a string requiring no auto-escaping shouldn't change the "safe" -status. + def test_dates_and_numbers(self): + """ + Localization of dates and numbers + """ + import datetime + import decimal + from django.conf import settings + from django.utils.formats import get_format, date_format, number_format, localize + from django.utils.numberformat import format + from django import template, forms + from django.forms.extras import SelectDateWidget ->>> from django.utils.safestring import mark_safe, SafeString ->>> s = mark_safe('Password') ->>> type(s) - ->>> activate('de') ->>> type(ugettext(s)) - ->>> deactivate() + old_use_i18n = settings.USE_I18N + old_use_l10n = settings.USE_L10N + old_use_thousand_separator = settings.USE_THOUSAND_SEPARATOR ->>> SafeString('a') + s -'aPassword' ->>> s + SafeString('a') -'Passworda' ->>> s + mark_safe('a') -'Passworda' ->>> mark_safe('a') + s -'aPassword' ->>> mark_safe('a') + mark_safe('s') -'as' ->>> print s -Password -""" + n = decimal.Decimal('66666.666') + f = 99999.999 + d = datetime.date(2009, 12, 31) + dt = datetime.datetime(2009, 12, 31, 20, 50) + ctxt = template.Context({'n': n, 'd': d, 'dt': dt, 'f': f}) -__test__ = { - 'regressions': regressions, - 'misc': misc.tests, -} + # Locale independent + + class I18nForm(forms.Form): + decimal_field = forms.DecimalField() + float_field = forms.FloatField() + date_field = forms.DateField() + datetime_field = forms.DateTimeField() + time_field = forms.TimeField() + + class SelectDateForm(forms.Form): + date_field = forms.DateField(widget=SelectDateWidget) + + settings.USE_L10N = True + settings.USE_THOUSAND_SEPARATOR = False + self.assertEqual(u'66666.66', format(n, decimal_sep='.', decimal_pos=2, grouping=3, thousand_sep=',')) + self.assertEqual(u'66666A6', format(n, decimal_sep='A', decimal_pos=1, grouping=1, thousand_sep='B')) + + settings.USE_THOUSAND_SEPARATOR = True + self.assertEqual(u'66,666.66', format(n, decimal_sep='.', decimal_pos=2, grouping=3, thousand_sep=',')) + self.assertEqual(u'6B6B6B6B6A6', format(n, decimal_sep='A', decimal_pos=1, grouping=1, thousand_sep='B')) + self.assertEqual(u'-66666.6', format(-66666.666, decimal_sep='.', decimal_pos=1)) + self.assertEqual(u'-66666.0', format(int('-66666'), decimal_sep='.', decimal_pos=1)) + + # Catalan locale with format i18n disabled translations will be used, but not formats + + settings.USE_L10N = False + activate('ca') + self.assertEqual('N j, Y', get_format('DATE_FORMAT')) + self.assertEqual(0, get_format('FIRST_DAY_OF_WEEK')) + self.assertEqual('.', get_format('DECIMAL_SEPARATOR')) + self.assertEqual(u'des. 31, 2009', date_format(d)) + self.assertEqual(u'desembre 2009', date_format(d, 'YEAR_MONTH_FORMAT')) + self.assertEqual(u'12/31/2009 8:50 p.m.', date_format(dt, 'SHORT_DATETIME_FORMAT')) + self.assertEqual('No localizable', localize('No localizable')) + self.assertEqual(decimal.Decimal('66666.666'), localize(n)) + self.assertEqual(99999.999, localize(f)) + self.assertEqual(datetime.date(2009, 12, 31), localize(d)) + self.assertEqual(datetime.datetime(2009, 12, 31, 20, 50), localize(dt)) + self.assertEqual(u'66666.666', template.Template('{{ n }}').render(ctxt)) + self.assertEqual(u'99999.999', template.Template('{{ f }}').render(ctxt)) + self.assertEqual(u'2009-12-31', template.Template('{{ d }}').render(ctxt)) + self.assertEqual(u'2009-12-31 20:50:00', template.Template('{{ dt }}').render(ctxt)) + self.assertEqual(u'66666.67', template.Template('{{ n|floatformat:2 }}').render(ctxt)) + self.assertEqual(u'100000.0', template.Template('{{ f|floatformat }}').render(ctxt)) + self.assertEqual(u'12/31/2009', template.Template('{{ d|date:"SHORT_DATE_FORMAT" }}').render(ctxt)) + self.assertEqual(u'12/31/2009 8:50 p.m.', template.Template('{{ dt|date:"SHORT_DATETIME_FORMAT" }}').render(ctxt)) + + form = I18nForm({ + 'decimal_field': u'66666,666', + 'float_field': u'99999,999', + 'date_field': u'31/12/2009', + 'datetime_field': u'31/12/2009 20:50', + 'time_field': u'20:50' + }) + self.assertEqual(False, form.is_valid()) + self.assertEqual([u'Introdu\xefu un n\xfamero.'], form.errors['float_field']) + self.assertEqual([u'Introdu\xefu un n\xfamero.'], form.errors['decimal_field']) + self.assertEqual([u'Introdu\xefu una data v\xe0lida.'], form.errors['date_field']) + self.assertEqual([u'Introdu\xefu una data/hora v\xe0lides.'], form.errors['datetime_field']) + + form2 = SelectDateForm({ + 'date_field_month': u'12', + 'date_field_day': u'31', + 'date_field_year': u'2009' + }) + self.assertEqual(True, form2.is_valid()) + self.assertEqual(datetime.date(2009, 12, 31), form2.cleaned_data['date_field']) + self.assertEqual(u'\n\n', SelectDateWidget().render('mydate', datetime.date(2009, 12, 31))) + deactivate() + + # Catalan locale + + settings.USE_L10N = True + activate('ca') + self.assertEqual('j \de F \de Y', get_format('DATE_FORMAT')) + self.assertEqual(1, get_format('FIRST_DAY_OF_WEEK')) + self.assertEqual(',', get_format('DECIMAL_SEPARATOR')) + self.assertEqual(u'31 de desembre de 2009', date_format(d)) + self.assertEqual(u'desembre del 2009', date_format(d, 'YEAR_MONTH_FORMAT')) + self.assertEqual(u'31/12/2009 20:50', date_format(dt, 'SHORT_DATETIME_FORMAT')) + self.assertEqual('No localizable', localize('No localizable')) + + settings.USE_THOUSAND_SEPARATOR = True + self.assertEqual(u'66.666,666', localize(n)) + self.assertEqual(u'99.999,999', localize(f)) + + settings.USE_THOUSAND_SEPARATOR = False + self.assertEqual(u'66666,666', localize(n)) + self.assertEqual(u'99999,999', localize(f)) + self.assertEqual(u'31 de desembre de 2009', localize(d)) + self.assertEqual(u'31 de desembre de 2009 a les 20:50', localize(dt)) + + settings.USE_THOUSAND_SEPARATOR = True + self.assertEqual(u'66.666,666', template.Template('{{ n }}').render(ctxt)) + self.assertEqual(u'99.999,999', template.Template('{{ f }}').render(ctxt)) + + settings.USE_THOUSAND_SEPARATOR = False + self.assertEqual(u'66666,666', template.Template('{{ n }}').render(ctxt)) + self.assertEqual(u'99999,999', template.Template('{{ f }}').render(ctxt)) + self.assertEqual(u'31 de desembre de 2009', template.Template('{{ d }}').render(ctxt)) + self.assertEqual(u'31 de desembre de 2009 a les 20:50', template.Template('{{ dt }}').render(ctxt)) + self.assertEqual(u'66666,67', template.Template('{{ n|floatformat:2 }}').render(ctxt)) + self.assertEqual(u'100000,0', template.Template('{{ f|floatformat }}').render(ctxt)) + self.assertEqual(u'31/12/2009', template.Template('{{ d|date:"SHORT_DATE_FORMAT" }}').render(ctxt)) + self.assertEqual(u'31/12/2009 20:50', template.Template('{{ dt|date:"SHORT_DATETIME_FORMAT" }}').render(ctxt)) + + form3 = I18nForm({ + 'decimal_field': u'66666,666', + 'float_field': u'99999,999', + 'date_field': u'31/12/2009', + 'datetime_field': u'31/12/2009 20:50', + 'time_field': u'20:50' + }) + self.assertEqual(True, form3.is_valid()) + self.assertEqual(decimal.Decimal('66666.666'), form3.cleaned_data['decimal_field']) + self.assertEqual(99999.999, form3.cleaned_data['float_field']) + self.assertEqual(datetime.date(2009, 12, 31), form3.cleaned_data['date_field']) + self.assertEqual(datetime.datetime(2009, 12, 31, 20, 50), form3.cleaned_data['datetime_field']) + self.assertEqual(datetime.time(20, 50), form3.cleaned_data['time_field']) + + form4 = SelectDateForm({ + 'date_field_month': u'12', + 'date_field_day': u'31', + 'date_field_year': u'2009' + }) + self.assertEqual(True, form4.is_valid()) + self.assertEqual(datetime.date(2009, 12, 31), form4.cleaned_data['date_field']) + self.assertEqual(u'\n\n', SelectDateWidget().render('mydate', datetime.date(2009, 12, 31))) + deactivate() + + # English locale + + settings.USE_L10N = True + activate('en') + self.assertEqual('N j, Y', get_format('DATE_FORMAT')) + self.assertEqual(0, get_format('FIRST_DAY_OF_WEEK')) + self.assertEqual('.', get_format('DECIMAL_SEPARATOR')) + self.assertEqual(u'Dec. 31, 2009', date_format(d)) + self.assertEqual(u'December 2009', date_format(d, 'YEAR_MONTH_FORMAT')) + self.assertEqual(u'12/31/2009 8:50 p.m.', date_format(dt, 'SHORT_DATETIME_FORMAT')) + self.assertEqual('No localizable', localize('No localizable')) + + settings.USE_THOUSAND_SEPARATOR = True + self.assertEqual(u'66,666.666', localize(n)) + self.assertEqual(u'99,999.999', localize(f)) + + settings.USE_THOUSAND_SEPARATOR = False + self.assertEqual(u'66666.666', localize(n)) + self.assertEqual(u'99999.999', localize(f)) + self.assertEqual(u'Dec. 31, 2009', localize(d)) + self.assertEqual(u'Dec. 31, 2009, 8:50 p.m.', localize(dt)) + + settings.USE_THOUSAND_SEPARATOR = True + self.assertEqual(u'66,666.666', template.Template('{{ n }}').render(ctxt)) + self.assertEqual(u'99,999.999', template.Template('{{ f }}').render(ctxt)) + + settings.USE_THOUSAND_SEPARATOR = False + self.assertEqual(u'66666.666', template.Template('{{ n }}').render(ctxt)) + self.assertEqual(u'99999.999', template.Template('{{ f }}').render(ctxt)) + self.assertEqual(u'Dec. 31, 2009', template.Template('{{ d }}').render(ctxt)) + self.assertEqual(u'Dec. 31, 2009, 8:50 p.m.', template.Template('{{ dt }}').render(ctxt)) + self.assertEqual(u'66666.67', template.Template('{{ n|floatformat:2 }}').render(ctxt)) + self.assertEqual(u'100000.0', template.Template('{{ f|floatformat }}').render(ctxt)) + self.assertEqual(u'12/31/2009', template.Template('{{ d|date:"SHORT_DATE_FORMAT" }}').render(ctxt)) + self.assertEqual(u'12/31/2009 8:50 p.m.', template.Template('{{ dt|date:"SHORT_DATETIME_FORMAT" }}').render(ctxt)) + + form5 = I18nForm({ + 'decimal_field': u'66666.666', + 'float_field': u'99999.999', + 'date_field': u'12/31/2009', + 'datetime_field': u'12/31/2009 20:50', + 'time_field': u'20:50' + }) + self.assertEqual(True, form5.is_valid()) + self.assertEqual(decimal.Decimal('66666.666'), form5.cleaned_data['decimal_field']) + self.assertEqual(99999.999, form5.cleaned_data['float_field']) + self.assertEqual(datetime.date(2009, 12, 31), form5.cleaned_data['date_field']) + self.assertEqual(datetime.datetime(2009, 12, 31, 20, 50), form5.cleaned_data['datetime_field']) + self.assertEqual(datetime.time(20, 50), form5.cleaned_data['time_field']) + + form6 = SelectDateForm({ + 'date_field_month': u'12', + 'date_field_day': u'31', + 'date_field_year': u'2009' + }) + self.assertEqual(True, form6.is_valid()) + self.assertEqual(datetime.date(2009, 12, 31), form6.cleaned_data['date_field']) + self.assertEqual(u'\n\n', SelectDateWidget().render('mydate', datetime.date(2009, 12, 31))) + deactivate() + + # Check if sublocales fall back to the main locale + activate('de-at') + settings.USE_THOUSAND_SEPARATOR = True + self.assertEqual(u'66.666,666', template.Template('{{ n }}').render(ctxt)) + deactivate() + + activate('es-ar') + self.assertEqual(u'31 de Diciembre de 2009', date_format(d)) + deactivate() + + # Restore defaults + settings.USE_I18N = old_use_i18n + settings.USE_L10N = old_use_l10n + settings.USE_THOUSAND_SEPARATOR = old_use_thousand_separator + + +class MiscTests(TestCase): + + def test_parse_spec_http_header(self): + """ + Testing HTTP header parsing. First, we test that we can parse the + values according to the spec (and that we extract all the pieces in + the right order). + """ + from django.utils.translation.trans_real import parse_accept_lang_header + p = parse_accept_lang_header + # Good headers. + self.assertEqual([('de', 1.0)], p('de')) + self.assertEqual([('en-AU', 1.0)], p('en-AU')) + self.assertEqual([('*', 1.0)], p('*;q=1.00')) + self.assertEqual([('en-AU', 0.123)], p('en-AU;q=0.123')) + self.assertEqual([('en-au', 0.10000000000000001)], p('en-au;q=0.1')) + self.assertEqual([('en-au', 1.0)], p('en-au;q=1.0')) + self.assertEqual([('da', 1.0), ('en', 0.5), ('en-gb', 0.25)], p('da, en-gb;q=0.25, en;q=0.5')) + self.assertEqual([('en-au-xx', 1.0)], p('en-au-xx')) + self.assertEqual([('de', 1.0), ('en-au', 0.75), ('en-us', 0.5), ('en', 0.25), ('es', 0.125), ('fa', 0.125)], p('de,en-au;q=0.75,en-us;q=0.5,en;q=0.25,es;q=0.125,fa;q=0.125')) + self.assertEqual([('*', 1.0)], p('*')) + self.assertEqual([('de', 1.0)], p('de;q=0.')) + self.assertEqual([], p('')) + + # Bad headers; should always return []. + self.assertEqual([], p('en-gb;q=1.0000')) + self.assertEqual([], p('en;q=0.1234')) + self.assertEqual([], p('en;q=.2')) + self.assertEqual([], p('abcdefghi-au')) + self.assertEqual([], p('**')) + self.assertEqual([], p('en,,gb')) + self.assertEqual([], p('en-au;q=0.1.0')) + self.assertEqual([], p('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXZ,en')) + self.assertEqual([], p('da, en-gb;q=0.8, en;q=0.7,#')) + self.assertEqual([], p('de;q=2.0')) + self.assertEqual([], p('de;q=0.a')) + self.assertEqual([], p('')) + + def test_parse_literal_http_header(self): + """ + Now test that we parse a literal HTTP header correctly. + """ + from django.utils.translation.trans_real import get_language_from_request + g = get_language_from_request + from django.http import HttpRequest + r = HttpRequest + r.COOKIES = {} + r.META = {'HTTP_ACCEPT_LANGUAGE': 'pt-br'} + self.assertEqual('pt-br', g(r)) + + r.META = {'HTTP_ACCEPT_LANGUAGE': 'pt'} + self.assertEqual('pt', g(r)) + + r.META = {'HTTP_ACCEPT_LANGUAGE': 'es,de'} + self.assertEqual('es', g(r)) + + r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-ar,de'} + self.assertEqual('es-ar', g(r)) + + # Python 2.3 and 2.4 return slightly different results for completely + # bogus locales, so we omit this test for that anything below 2.4. + # It's relatively harmless in any cases (GIGO). This also means this + # won't be executed on Jython currently, but life's like that + # sometimes. (On those platforms, passing in a truly bogus locale + # will get you the default locale back.) + if sys.version_info >= (2, 5): + # This test assumes there won't be a Django translation to a US + # variation of the Spanish language, a safe assumption. When the + # user sets it as the preferred language, the main 'es' + # translation should be selected instead. + r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-us'} + self.assertEqual(g(r), 'es') + + # This tests the following scenario: there isn't a main language (zh) + # translation of Django but there is a translation to variation (zh_CN) + # the user sets zh-cn as the preferred language, it should be selected + # by Django without falling back nor ignoring it. + r.META = {'HTTP_ACCEPT_LANGUAGE': 'zh-cn,de'} + self.assertEqual(g(r), 'zh-cn')