Author: garcia_marc Date: 2009-07-07 19:52:25 -0500 (Tue, 07 Jul 2009) New Revision: 11204
Modified: django/branches/soc2009/i18n-improvements/django/conf/global_settings.py django/branches/soc2009/i18n-improvements/django/conf/locale/ca/formats.py django/branches/soc2009/i18n-improvements/django/contrib/admin/templatetags/admin_list.py django/branches/soc2009/i18n-improvements/django/template/defaultfilters.py django/branches/soc2009/i18n-improvements/django/utils/formats.py django/branches/soc2009/i18n-improvements/django/utils/numberformat.py django/branches/soc2009/i18n-improvements/docs/ref/settings.txt django/branches/soc2009/i18n-improvements/tests/regressiontests/i18n/tests.py Log: [soc2009/i18n] formatting system in development Modified: django/branches/soc2009/i18n-improvements/django/conf/global_settings.py =================================================================== --- django/branches/soc2009/i18n-improvements/django/conf/global_settings.py 2009-07-07 13:31:57 UTC (rev 11203) +++ django/branches/soc2009/i18n-improvements/django/conf/global_settings.py 2009-07-08 00:52:25 UTC (rev 11204) @@ -259,6 +259,12 @@ # 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' @@ -283,21 +289,28 @@ # Default shortformatting for date objects. See all available format strings here: # http://docs.djangoproject.com/en/dev/ref/templates/builtins/#now -SHORT_DATE_FORMAT = 'N j, Y' +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 = 'N j, Y, P' +SHORT_DATETIME_FORMAT = 'm/d/Y P' -# Default first day of week, to be used on calendars -# 0 means Sunday +# First day of week, to be used on calendars +# 0 means Sunday, 1 means Monday... FIRST_DAY_OF_WEEK = 0 -# Default decimal separator symbol +# Decimal separator symbol DECIMAL_SEPARATOR = '.' -# Default thousand separator symbol +# 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? Modified: django/branches/soc2009/i18n-improvements/django/conf/locale/ca/formats.py =================================================================== --- django/branches/soc2009/i18n-improvements/django/conf/locale/ca/formats.py 2009-07-07 13:31:57 UTC (rev 11203) +++ django/branches/soc2009/i18n-improvements/django/conf/locale/ca/formats.py 2009-07-08 00:52:25 UTC (rev 11204) @@ -3,7 +3,7 @@ DATE_FORMAT = 'j \de F \de Y' DATETIME_FORMAT = 'j \de F \de Y \\a \le\s H:i' -TIME_FORMAT = 'P' +TIME_FORMAT = 'H:i' YEAR_MONTH_FORMAT = 'F \de Y' MONTH_DAY_FORMAT = 'j \de F' @@ -14,5 +14,5 @@ DECIMAL_SEPARATOR = ',' THOUSAND_SEPARATOR = '.' +NUMBER_GROUPING = 3 - Modified: django/branches/soc2009/i18n-improvements/django/contrib/admin/templatetags/admin_list.py =================================================================== --- django/branches/soc2009/i18n-improvements/django/contrib/admin/templatetags/admin_list.py 2009-07-07 13:31:57 UTC (rev 11203) +++ django/branches/soc2009/i18n-improvements/django/contrib/admin/templatetags/admin_list.py 2009-07-08 00:52:25 UTC (rev 11204) @@ -8,7 +8,6 @@ from django.utils.text import capfirst from django.utils.safestring import mark_safe from django.utils.translation import ugettext as _ -from django.utils.formats import localize from django.utils.encoding import smart_unicode, smart_str, force_unicode from django.template import Library import datetime @@ -183,14 +182,17 @@ else: result_repr = EMPTY_CHANGELIST_VALUE # Dates and times are special: They're formatted in a certain way. - elif isinstance(f, models.DateField) or isinstance(f, models.TimeField) or isinstance(f, models.DecimalField): + elif isinstance(f, models.DateField) or isinstance(f, models.TimeField): if field_val: - result_repr = localize(field_val) - # result_repr = ('%%.%sf' % f.decimal_places) % field_val + result_repr = formats.localize(field_val) else: result_repr = EMPTY_CHANGELIST_VALUE - if not isinstance(f, models.DecimalField): - row_class = ' class="nowrap"' + 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"' # Booleans are special: We use images. elif isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField): result_repr = _boolean_icon(field_val) Modified: django/branches/soc2009/i18n-improvements/django/template/defaultfilters.py =================================================================== --- django/branches/soc2009/i18n-improvements/django/template/defaultfilters.py 2009-07-07 13:31:57 UTC (rev 11203) +++ django/branches/soc2009/i18n-improvements/django/template/defaultfilters.py 2009-07-08 00:52:25 UTC (rev 11204) @@ -18,6 +18,7 @@ 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 number_format register = Library() @@ -166,14 +167,14 @@ 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 Modified: django/branches/soc2009/i18n-improvements/django/utils/formats.py =================================================================== --- django/branches/soc2009/i18n-improvements/django/utils/formats.py 2009-07-07 13:31:57 UTC (rev 11203) +++ django/branches/soc2009/i18n-improvements/django/utils/formats.py 2009-07-08 00:52:25 UTC (rev 11204) @@ -1,6 +1,8 @@ import decimal import datetime +from django.conf import settings +from django.utils.translation import get_language from django.utils.importlib import import_module from django.utils import dateformat from django.utils import numberformat @@ -11,7 +13,6 @@ set on the settings. format_type is the name of the format, for example 'DATE_FORMAT' """ - from django.conf import settings return getattr(settings, format_type) def getformat_real(format_type): @@ -20,16 +21,22 @@ current language (locale) defaulting to the format on settings. format_type is the name of the format, for example 'DATE_FORMAT' """ - from django.utils.translation import get_language import_formats = lambda s: import_module('.formats', 'django.conf.locale.%s' % s) - tmp = import_formats('ca') - format = None - try: - module = import_formats(get_language()) - except ImportError: - pass - else: + module = format = None + if settings.FORMAT_MODULE_PATH: try: + module = import_module('.formats', '%s.%s' % (settings.FORMAT_MODULE_PATH, get_language())) + except ImportError: + pass + + if not module: + try: + module = import_module('.formats', 'django.conf.locale.%s' % get_language()) + except ImportError: + pass + + if module: + try: format = getattr(module, format_type) except AttributeError: pass @@ -37,28 +44,43 @@ # getformat will just return the value on setings if # we don't use i18n in our project -from django.conf import settings if settings.USE_I18N and settings.USE_FORMAT_I18N: getformat = getformat_real else: getformat = getformat_null def date_format(value, format=None): + """ + Formats a datetime.date or datetime.datetime object using a + localizable format + """ return dateformat.format(value, getformat(format or 'DATE_FORMAT')) -def number_format(value): +def number_format(value, decimal_pos=None): + """ + Formats a numeric value using localization settings + """ return numberformat.format( value, getformat('DECIMAL_SEPARATOR'), - 2, # TODO: decide how to set decimal positions later - 3, # TODO: get it from formats + decimal_pos, + getformat('NUMBER_GROUPING'), getformat('THOUSAND_SEPARATOR'), ) def localize(value): + """ + 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_I18N and settings.USE_FORMAT_I18N: 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): return date_format(value, 'DATETIME_FORMAT') elif isinstance(value, datetime.date): Modified: django/branches/soc2009/i18n-improvements/django/utils/numberformat.py =================================================================== --- django/branches/soc2009/i18n-improvements/django/utils/numberformat.py 2009-07-07 13:31:57 UTC (rev 11203) +++ django/branches/soc2009/i18n-improvements/django/utils/numberformat.py 2009-07-08 00:52:25 UTC (rev 11204) @@ -1,5 +1,13 @@ -def format(number, decimal_sep, decimal_pos, groupping=0, thousand_sep=''): +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 number < 0: @@ -7,28 +15,26 @@ else: sign = '' # decimal part - str_number = str(abs(number)) + str_number = unicode(number) + if str_number[0] == '-': + str_number = str_number[1:] if '.' in str_number: int_part, dec_part = str_number.split('.') - dec_part = dec_part[:decimal_pos] + if decimal_pos: + dec_part = dec_part[:decimal_pos] else: int_part, dec_part = str_number, '' - dec_part = dec_part + ('0' * (decimal_pos - len(dec_part))) + if decimal_pos: + dec_part = dec_part + ('0' * (decimal_pos - len(dec_part))) if dec_part: dec_part = decimal_sep + dec_part - # groupping - if groupping: + # grouping + if settings.USE_THOUSAND_SEPARATOR and grouping: int_part_gd = '' for cnt, digit in enumerate(int_part[::-1]): - if cnt and not cnt % groupping: + 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 -if __name__ == '__main__': - import decimal - print format_number(-1000000, ',', 4, 3, '.') - print format_number(-100.100, ',', 4, 3, '.') - print format_number(decimal.Decimal('1000.100'), ',', 4) Modified: django/branches/soc2009/i18n-improvements/docs/ref/settings.txt =================================================================== --- django/branches/soc2009/i18n-improvements/docs/ref/settings.txt 2009-07-07 13:31:57 UTC (rev 11203) +++ django/branches/soc2009/i18n-improvements/docs/ref/settings.txt 2009-07-08 00:52:25 UTC (rev 11204) @@ -302,7 +302,6 @@ be useful for some test setups, and should never be used on a live site. - .. setting:: DECIMAL_SEPARATOR DECIMAL_SEPARATOR @@ -310,7 +309,7 @@ Default: ``'.'`` (Dot) -The default decimal separator used when formatting decimal numbers. +Default decimal separator used when formatting decimal numbers. .. setting:: DEFAULT_CHARSET @@ -537,6 +536,21 @@ .. _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 specially 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 @@ -783,6 +797,21 @@ See :ttag:`allowed date format strings <now>`. 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 @@ -1119,6 +1148,18 @@ .. _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 @@ -1186,6 +1227,20 @@ bandwidth but slows down performance. This is only used if ``CommonMiddleware`` is installed (see :ref:`topics-http-middleware`). +.. setting:: USE_FORMAT_I18N + +USE_FORMAT_I18N +--------------- + +Default ``False`` + +A boolean that specifies if data will be localized by default or not. If this is +set to ``True``, Django will display numbers and dates using the format of the +current locale. It is required to set ``USE_I18N`` to ``True`` to allow data +format localization. + +See also ``USE_I18N`` + .. setting:: USE_I18N USE_I18N @@ -1198,6 +1253,8 @@ set to ``False``, Django will make some optimizations so as not to load the internationalization machinery. +See also ``USE_FORMAT_I18N`` + .. setting:: YEAR_MONTH_FORMAT YEAR_MONTH_FORMAT Modified: django/branches/soc2009/i18n-improvements/tests/regressiontests/i18n/tests.py =================================================================== --- django/branches/soc2009/i18n-improvements/tests/regressiontests/i18n/tests.py 2009-07-07 13:31:57 UTC (rev 11203) +++ django/branches/soc2009/i18n-improvements/tests/regressiontests/i18n/tests.py 2009-07-08 00:52:25 UTC (rev 11204) @@ -65,13 +65,70 @@ >>> print s Password ->>> from django.utils.formats import getformat +Localization of dates and numbers + +>>> import datetime +>>> import decimal +>>> from django.utils.formats import getformat, date_format, number_format, localize + +>>> n = decimal.Decimal('66666.666') +>>> d = datetime.date(2009, 7, 6) +>>> dt = datetime.datetime(2009, 7, 6, 20, 50) + +Locale independent + +>>> number_format(n, decimal_sep='.', decimal_pos=2, grouping=3, thousand_sep=',') +'66,666.66' +>>> number_format(n, decimal_sep='A', decimal_pos=1, grouping=1, thousand_sep='B') +'6B6B6B6B6BA6' + +English locale + >>> activate('en') >>> getformat('DATE_FORMAT') 'N j, Y' +>>> getformat('FIRST_DAY_OF_WEEK') +0 +>>> getformat('DECIMAL_SEPARATOR') +'.' +>>> date_format(d) +'July 6, 2009' +>>> date_format(d, 'YEAR_MONTH_FORMAT') +'July 2009' +>>> date_format(d, 'SHORT_DATETIME_FORMAT') +'07/06/2009 8:50 p.m.' +>>> localize('No localizable') +'No localizable' +>>> localize(n) +'66666.666' +>>> localize(d) +'July 6, 2009' +>>> localize(dt) +'July 6, 2009, 8:50 p.m.' + +Catalan locale + >>> activate('ca') >>> getformat('DATE_FORMAT') 'j \de N \de Y' +>>> getformat('FIRST_DAY_OF_WEEK') +1 +>>> getformat('DECIMAL_SEPARATOR') +',' +>>> date_format(d) +'6 de juliol de 2009' +>>> date_format(d, 'YEAR_MONTH_FORMAT') +'juliol de 2009' +>>> date_format(d, 'SHORT_DATETIME_FORMAT') +'06/07/2009 20:50' +>>> localize('No localizable') +'No localizable' +>>> localize(n) +'66.666,666' +>>> localize(d) +'6 de juliol de 2009' +>>> localize(dt) +'6 de juliol de 2009 a les 20:50' """ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/django-updates?hl=en -~----------~----~----~----~------~----~------~--~---
