web/lib/django/utils/translation/trans_real.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     2 
     2 
     3 import locale
     3 import locale
     4 import os
     4 import os
     5 import re
     5 import re
     6 import sys
     6 import sys
       
     7 import warnings
     7 import gettext as gettext_module
     8 import gettext as gettext_module
     8 from cStringIO import StringIO
     9 from cStringIO import StringIO
     9 
    10 
    10 from django.utils.importlib import import_module
    11 from django.utils.importlib import import_module
    11 from django.utils.safestring import mark_safe, SafeData
    12 from django.utils.safestring import mark_safe, SafeData
    38     p = language.find('-')
    39     p = language.find('-')
    39     if p >= 0:
    40     if p >= 0:
    40         if to_lower:
    41         if to_lower:
    41             return language[:p].lower()+'_'+language[p+1:].lower()
    42             return language[:p].lower()+'_'+language[p+1:].lower()
    42         else:
    43         else:
       
    44             # Get correct locale for sr-latn
       
    45             if len(language[p+1:]) > 2:
       
    46                 return language[:p].lower()+'_'+language[p+1].upper()+language[p+2:].lower()
    43             return language[:p].lower()+'_'+language[p+1:].upper()
    47             return language[:p].lower()+'_'+language[p+1:].upper()
    44     else:
    48     else:
    45         return language.lower()
    49         return language.lower()
    46 
    50 
    47 def to_language(locale):
    51 def to_language(locale):
    54 
    58 
    55 class DjangoTranslation(gettext_module.GNUTranslations):
    59 class DjangoTranslation(gettext_module.GNUTranslations):
    56     """
    60     """
    57     This class sets up the GNUTranslations context with regard to output
    61     This class sets up the GNUTranslations context with regard to output
    58     charset. Django uses a defined DEFAULT_CHARSET as the output charset on
    62     charset. Django uses a defined DEFAULT_CHARSET as the output charset on
    59     Python 2.4. With Python 2.3, use DjangoTranslation23.
    63     Python 2.4.
    60     """
    64     """
    61     def __init__(self, *args, **kw):
    65     def __init__(self, *args, **kw):
    62         from django.conf import settings
    66         from django.conf import settings
    63         gettext_module.GNUTranslations.__init__(self, *args, **kw)
    67         gettext_module.GNUTranslations.__init__(self, *args, **kw)
    64         # Starting with Python 2.4, there's a function to define
    68         # Starting with Python 2.4, there's a function to define
    81         return self.__language
    85         return self.__language
    82 
    86 
    83     def __repr__(self):
    87     def __repr__(self):
    84         return "<DjangoTranslation lang:%s>" % self.__language
    88         return "<DjangoTranslation lang:%s>" % self.__language
    85 
    89 
    86 class DjangoTranslation23(DjangoTranslation):
       
    87     """
       
    88     Compatibility class that is only used with Python 2.3.
       
    89     Python 2.3 doesn't support set_output_charset on translation objects and
       
    90     needs this wrapper class to make sure input charsets from translation files
       
    91     are correctly translated to output charsets.
       
    92 
       
    93     With a full switch to Python 2.4, this can be removed from the source.
       
    94     """
       
    95     def gettext(self, msgid):
       
    96         res = self.ugettext(msgid)
       
    97         return res.encode(self.django_output_charset)
       
    98 
       
    99     def ngettext(self, msgid1, msgid2, n):
       
   100         res = self.ungettext(msgid1, msgid2, n)
       
   101         return res.encode(self.django_output_charset)
       
   102 
       
   103 def translation(language):
    90 def translation(language):
   104     """
    91     """
   105     Returns a translation object.
    92     Returns a translation object.
   106 
    93 
   107     This translation object will be constructed out of multiple GNUTranslations
    94     This translation object will be constructed out of multiple GNUTranslations
   114     t = _translations.get(language, None)
   101     t = _translations.get(language, None)
   115     if t is not None:
   102     if t is not None:
   116         return t
   103         return t
   117 
   104 
   118     from django.conf import settings
   105     from django.conf import settings
   119 
       
   120     # set up the right translation class
       
   121     klass = DjangoTranslation
       
   122     if sys.version_info < (2, 4):
       
   123         klass = DjangoTranslation23
       
   124 
   106 
   125     globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
   107     globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
   126 
   108 
   127     if settings.SETTINGS_MODULE is not None:
   109     if settings.SETTINGS_MODULE is not None:
   128         parts = settings.SETTINGS_MODULE.split('.')
   110         parts = settings.SETTINGS_MODULE.split('.')
   141         if res is not None:
   123         if res is not None:
   142             return res
   124             return res
   143 
   125 
   144         def _translation(path):
   126         def _translation(path):
   145             try:
   127             try:
   146                 t = gettext_module.translation('django', path, [loc], klass)
   128                 t = gettext_module.translation('django', path, [loc], DjangoTranslation)
   147                 t.set_language(lang)
   129                 t.set_language(lang)
   148                 return t
   130                 return t
   149             except IOError, e:
   131             except IOError, e:
   150                 return None
   132                 return None
   151 
   133 
   171 
   153 
   172         for localepath in settings.LOCALE_PATHS:
   154         for localepath in settings.LOCALE_PATHS:
   173             if os.path.isdir(localepath):
   155             if os.path.isdir(localepath):
   174                 res = _merge(localepath)
   156                 res = _merge(localepath)
   175 
   157 
   176         if projectpath and os.path.isdir(projectpath):
       
   177             res = _merge(projectpath)
       
   178 
       
   179         for appname in settings.INSTALLED_APPS:
   158         for appname in settings.INSTALLED_APPS:
   180             app = import_module(appname)
   159             app = import_module(appname)
   181             apppath = os.path.join(os.path.dirname(app.__file__), 'locale')
   160             apppath = os.path.join(os.path.dirname(app.__file__), 'locale')
   182 
   161 
   183             if os.path.isdir(apppath):
   162             if os.path.isdir(apppath):
   184                 res = _merge(apppath)
   163                 res = _merge(apppath)
       
   164 
       
   165         if projectpath and os.path.isdir(projectpath):
       
   166             res = _merge(projectpath)
   185 
   167 
   186         if res is None:
   168         if res is None:
   187             if fallback is not None:
   169             if fallback is not None:
   188                 res = fallback
   170                 res = fallback
   189             else:
   171             else:
   200     """
   182     """
   201     Fetches the translation object for a given tuple of application name and
   183     Fetches the translation object for a given tuple of application name and
   202     language and installs it as the current translation object for the current
   184     language and installs it as the current translation object for the current
   203     thread.
   185     thread.
   204     """
   186     """
       
   187     if isinstance(language, basestring) and language == 'no':
       
   188         warnings.warn(
       
   189             "The use of the language code 'no' is deprecated. "
       
   190             "Please use the 'nb' translation instead.",
       
   191             PendingDeprecationWarning
       
   192         )
   205     _active[currentThread()] = translation(language)
   193     _active[currentThread()] = translation(language)
   206 
   194 
   207 def deactivate():
   195 def deactivate():
   208     """
   196     """
   209     Deinstalls the currently active translation object so that further _ calls
   197     Deinstalls the currently active translation object so that further _ calls
   264     Translates 'message' using the given 'translation_function' name -- which
   252     Translates 'message' using the given 'translation_function' name -- which
   265     will be either gettext or ugettext. It uses the current thread to find the
   253     will be either gettext or ugettext. It uses the current thread to find the
   266     translation object to use. If no current translation is activated, the
   254     translation object to use. If no current translation is activated, the
   267     message will be run through the default translation object.
   255     message will be run through the default translation object.
   268     """
   256     """
       
   257     eol_message = message.replace('\r\n', '\n').replace('\r', '\n')
   269     global _default, _active
   258     global _default, _active
   270     t = _active.get(currentThread(), None)
   259     t = _active.get(currentThread(), None)
   271     if t is not None:
   260     if t is not None:
   272         result = getattr(t, translation_function)(message)
   261         result = getattr(t, translation_function)(eol_message)
   273     else:
   262     else:
   274         if _default is None:
   263         if _default is None:
   275             from django.conf import settings
   264             from django.conf import settings
   276             _default = translation(settings.LANGUAGE_CODE)
   265             _default = translation(settings.LANGUAGE_CODE)
   277         result = getattr(_default, translation_function)(message)
   266         result = getattr(_default, translation_function)(eol_message)
   278     if isinstance(message, SafeData):
   267     if isinstance(message, SafeData):
   279         return mark_safe(result)
   268         return mark_safe(result)
   280     return result
   269     return result
   281 
   270 
   282 def gettext(message):
   271 def gettext(message):
   349         lang_code = request.session.get('django_language', None)
   338         lang_code = request.session.get('django_language', None)
   350         if lang_code in supported and lang_code is not None and check_for_language(lang_code):
   339         if lang_code in supported and lang_code is not None and check_for_language(lang_code):
   351             return lang_code
   340             return lang_code
   352 
   341 
   353     lang_code = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME)
   342     lang_code = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME)
       
   343 
       
   344     if lang_code and lang_code not in supported:
       
   345         lang_code = lang_code.split('-')[0] # e.g. if fr-ca is not supported fallback to fr
       
   346 
   354     if lang_code and lang_code in supported and check_for_language(lang_code):
   347     if lang_code and lang_code in supported and check_for_language(lang_code):
   355         return lang_code
   348         return lang_code
   356 
   349 
   357     accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
   350     accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
   358     for accept_lang, unused in parse_accept_lang_header(accept):
   351     for accept_lang, unused in parse_accept_lang_header(accept):
   386             if os.path.exists(langfile):
   379             if os.path.exists(langfile):
   387                 _accepted[normalized] = lang
   380                 _accepted[normalized] = lang
   388                 return lang
   381                 return lang
   389 
   382 
   390     return settings.LANGUAGE_CODE
   383     return settings.LANGUAGE_CODE
   391 
       
   392 def get_date_formats():
       
   393     """
       
   394     Checks whether translation files provide a translation for some technical
       
   395     message ID to store date and time formats. If it doesn't contain one, the
       
   396     formats provided in the settings will be used.
       
   397     """
       
   398     from django.conf import settings
       
   399     date_format = ugettext('DATE_FORMAT')
       
   400     datetime_format = ugettext('DATETIME_FORMAT')
       
   401     time_format = ugettext('TIME_FORMAT')
       
   402     if date_format == 'DATE_FORMAT':
       
   403         date_format = settings.DATE_FORMAT
       
   404     if datetime_format == 'DATETIME_FORMAT':
       
   405         datetime_format = settings.DATETIME_FORMAT
       
   406     if time_format == 'TIME_FORMAT':
       
   407         time_format = settings.TIME_FORMAT
       
   408     return date_format, datetime_format, time_format
       
   409 
       
   410 def get_partial_date_formats():
       
   411     """
       
   412     Checks whether translation files provide a translation for some technical
       
   413     message ID to store partial date formats. If it doesn't contain one, the
       
   414     formats provided in the settings will be used.
       
   415     """
       
   416     from django.conf import settings
       
   417     year_month_format = ugettext('YEAR_MONTH_FORMAT')
       
   418     month_day_format = ugettext('MONTH_DAY_FORMAT')
       
   419     if year_month_format == 'YEAR_MONTH_FORMAT':
       
   420         year_month_format = settings.YEAR_MONTH_FORMAT
       
   421     if month_day_format == 'MONTH_DAY_FORMAT':
       
   422         month_day_format = settings.MONTH_DAY_FORMAT
       
   423     return year_month_format, month_day_format
       
   424 
   384 
   425 dot_re = re.compile(r'\S')
   385 dot_re = re.compile(r'\S')
   426 def blankout(src, char):
   386 def blankout(src, char):
   427     """
   387     """
   428     Changes every non-whitespace character to the given char.
   388     Changes every non-whitespace character to the given char.
   535             return []
   495             return []
   536         priority = priority and float(priority) or 1.0
   496         priority = priority and float(priority) or 1.0
   537         result.append((lang, priority))
   497         result.append((lang, priority))
   538     result.sort(lambda x, y: -cmp(x[1], y[1]))
   498     result.sort(lambda x, y: -cmp(x[1], y[1]))
   539     return result
   499     return result
       
   500 
       
   501 # get_date_formats and get_partial_date_formats aren't used anymore by Django
       
   502 # and are kept for backward compatibility.
       
   503 # Note, it's also important to keep format names marked for translation.
       
   504 # For compatibility we still want to have formats on translation catalogs.
       
   505 # That makes template code like {{ my_date|date:_('DATE_FORMAT') }} still work
       
   506 def get_date_formats():
       
   507     """
       
   508     Checks whether translation files provide a translation for some technical
       
   509     message ID to store date and time formats. If it doesn't contain one, the
       
   510     formats provided in the settings will be used.
       
   511     """
       
   512     warnings.warn(
       
   513         "'django.utils.translation.get_date_formats' is deprecated. "
       
   514         "Please update your code to use the new i18n aware formatting.",
       
   515         PendingDeprecationWarning
       
   516     )
       
   517     from django.conf import settings
       
   518     date_format = ugettext('DATE_FORMAT')
       
   519     datetime_format = ugettext('DATETIME_FORMAT')
       
   520     time_format = ugettext('TIME_FORMAT')
       
   521     if date_format == 'DATE_FORMAT':
       
   522         date_format = settings.DATE_FORMAT
       
   523     if datetime_format == 'DATETIME_FORMAT':
       
   524         datetime_format = settings.DATETIME_FORMAT
       
   525     if time_format == 'TIME_FORMAT':
       
   526         time_format = settings.TIME_FORMAT
       
   527     return date_format, datetime_format, time_format
       
   528 
       
   529 def get_partial_date_formats():
       
   530     """
       
   531     Checks whether translation files provide a translation for some technical
       
   532     message ID to store partial date formats. If it doesn't contain one, the
       
   533     formats provided in the settings will be used.
       
   534     """
       
   535     warnings.warn(
       
   536         "'django.utils.translation.get_partial_date_formats' is deprecated. "
       
   537         "Please update your code to use the new i18n aware formatting.",
       
   538         PendingDeprecationWarning
       
   539     )
       
   540     from django.conf import settings
       
   541     year_month_format = ugettext('YEAR_MONTH_FORMAT')
       
   542     month_day_format = ugettext('MONTH_DAY_FORMAT')
       
   543     if year_month_format == 'YEAR_MONTH_FORMAT':
       
   544         year_month_format = settings.YEAR_MONTH_FORMAT
       
   545     if month_day_format == 'MONTH_DAY_FORMAT':
       
   546         month_day_format = settings.MONTH_DAY_FORMAT
       
   547     return year_month_format, month_day_format
       
   548