web/lib/django/views/i18n.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
       
     1 import os
       
     2 import gettext as gettext_module
       
     3 
     1 from django import http
     4 from django import http
     2 from django.conf import settings
     5 from django.conf import settings
     3 from django.utils import importlib
     6 from django.utils import importlib
     4 from django.utils.translation import check_for_language, activate, to_locale, get_language
     7 from django.utils.translation import check_for_language, activate, to_locale, get_language
     5 from django.utils.text import javascript_quote
     8 from django.utils.text import javascript_quote
     6 import os
     9 from django.utils.encoding import smart_unicode
     7 import gettext as gettext_module
    10 from django.utils.formats import get_format_modules
     8 
    11 
     9 def set_language(request):
    12 def set_language(request):
    10     """
    13     """
    11     Redirect to a given url while setting the chosen language in the
    14     Redirect to a given url while setting the chosen language in the
    12     session or cookie. The url and the language code need to be
    15     session or cookie. The url and the language code need to be
    30                 request.session['django_language'] = lang_code
    33                 request.session['django_language'] = lang_code
    31             else:
    34             else:
    32                 response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
    35                 response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
    33     return response
    36     return response
    34 
    37 
       
    38 def get_formats():
       
    39     """
       
    40     Returns all formats strings required for i18n to work
       
    41     """
       
    42     FORMAT_SETTINGS = (
       
    43         'DATE_FORMAT', 'DATETIME_FORMAT', 'TIME_FORMAT',
       
    44         'YEAR_MONTH_FORMAT', 'MONTH_DAY_FORMAT', 'SHORT_DATE_FORMAT',
       
    45         'SHORT_DATETIME_FORMAT', 'FIRST_DAY_OF_WEEK', 'DECIMAL_SEPARATOR',
       
    46         'THOUSAND_SEPARATOR', 'NUMBER_GROUPING',
       
    47         'DATE_INPUT_FORMATS', 'TIME_INPUT_FORMATS', 'DATETIME_INPUT_FORMATS'
       
    48     )
       
    49     result = {}
       
    50     for module in [settings] + get_format_modules(reverse=True):
       
    51         for attr in FORMAT_SETTINGS:
       
    52             try:
       
    53                 result[attr] = getattr(module, attr)
       
    54             except AttributeError:
       
    55                 pass
       
    56     src = []
       
    57     for k, v in result.items():
       
    58         if isinstance(v, (basestring, int)):
       
    59             src.append("formats['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(smart_unicode(v))))
       
    60         elif isinstance(v, (tuple, list)):
       
    61             v = [javascript_quote(smart_unicode(value)) for value in v]
       
    62             src.append("formats['%s'] = ['%s'];\n" % (javascript_quote(k), "', '".join(v)))
       
    63     return ''.join(src)
       
    64 
    35 NullSource = """
    65 NullSource = """
    36 /* gettext identity library */
    66 /* gettext identity library */
    37 
    67 
    38 function gettext(msgid) { return msgid; }
    68 function gettext(msgid) { return msgid; }
    39 function ngettext(singular, plural, count) { return (count == 1) ? singular : plural; }
    69 function ngettext(singular, plural, count) { return (count == 1) ? singular : plural; }
    65     return value[pluralidx(count)];
    95     return value[pluralidx(count)];
    66   }
    96   }
    67 }
    97 }
    68 
    98 
    69 function gettext_noop(msgid) { return msgid; }
    99 function gettext_noop(msgid) { return msgid; }
       
   100 
       
   101 """
       
   102 
       
   103 LibFormatHead = """
       
   104 /* formatting library */
       
   105 
       
   106 var formats = new Array();
       
   107 
       
   108 """
       
   109 
       
   110 LibFormatFoot = """
       
   111 function get_format(format_type) {
       
   112     var value = formats[format_type];
       
   113     if (typeof(value) == 'undefined') {
       
   114       return msgid;
       
   115     } else {
       
   116       return value;
       
   117     }
       
   118 }
    70 """
   119 """
    71 
   120 
    72 SimplePlural = """
   121 SimplePlural = """
    73 function pluralidx(count) { return (count == 1) ? 0 : 1; }
   122 function pluralidx(count) { return (count == 1) ? 0 : 1; }
    74 """
   123 """
    97 def null_javascript_catalog(request, domain=None, packages=None):
   146 def null_javascript_catalog(request, domain=None, packages=None):
    98     """
   147     """
    99     Returns "identity" versions of the JavaScript i18n functions -- i.e.,
   148     Returns "identity" versions of the JavaScript i18n functions -- i.e.,
   100     versions that don't actually do anything.
   149     versions that don't actually do anything.
   101     """
   150     """
   102     return http.HttpResponse(NullSource + InterPolate, 'text/javascript')
   151     src = [NullSource, InterPolate, LibFormatHead, get_formats(), LibFormatFoot]
       
   152     return http.HttpResponse(''.join(src), 'text/javascript')
   103 
   153 
   104 def javascript_catalog(request, domain='djangojs', packages=None):
   154 def javascript_catalog(request, domain='djangojs', packages=None):
   105     """
   155     """
   106     Returns the selected language catalog as a javascript library.
   156     Returns the selected language catalog as a javascript library.
   107 
   157 
   118         if 'language' in request.GET:
   168         if 'language' in request.GET:
   119             if check_for_language(request.GET['language']):
   169             if check_for_language(request.GET['language']):
   120                 activate(request.GET['language'])
   170                 activate(request.GET['language'])
   121     if packages is None:
   171     if packages is None:
   122         packages = ['django.conf']
   172         packages = ['django.conf']
   123     if type(packages) in (str, unicode):
   173     if isinstance(packages, basestring):
   124         packages = packages.split('+')
   174         packages = packages.split('+')
   125     packages = [p for p in packages if p == 'django.conf' or p in settings.INSTALLED_APPS]
   175     packages = [p for p in packages if p == 'django.conf' or p in settings.INSTALLED_APPS]
   126     default_locale = to_locale(settings.LANGUAGE_CODE)
   176     default_locale = to_locale(settings.LANGUAGE_CODE)
   127     locale = to_locale(get_language())
   177     locale = to_locale(get_language())
   128     t = {}
   178     t = {}
   129     paths = []
   179     paths = []
       
   180     en_catalog_missing = False
   130     # first load all english languages files for defaults
   181     # first load all english languages files for defaults
   131     for package in packages:
   182     for package in packages:
   132         p = importlib.import_module(package)
   183         p = importlib.import_module(package)
   133         path = os.path.join(os.path.dirname(p.__file__), 'locale')
   184         path = os.path.join(os.path.dirname(p.__file__), 'locale')
   134         paths.append(path)
   185         paths.append(path)
   135         try:
   186         try:
   136             catalog = gettext_module.translation(domain, path, ['en'])
   187             catalog = gettext_module.translation(domain, path, ['en'])
   137             t.update(catalog._catalog)
   188             t.update(catalog._catalog)
   138         except IOError:
   189         except IOError:
   139             # 'en' catalog was missing. This is harmless.
   190             # 'en' catalog was missing.
       
   191             if locale.startswith('en'):
       
   192                 # If 'en' is the selected language this would cause issues
       
   193                 # later on if default_locale is something other than 'en'.
       
   194                 en_catalog_missing = True
       
   195             # Otherwise it is harmless.
   140             pass
   196             pass
   141     # next load the settings.LANGUAGE_CODE translations if it isn't english
   197     # next load the settings.LANGUAGE_CODE translations if it isn't english
   142     if default_locale != 'en':
   198     if default_locale != 'en':
   143         for path in paths:
   199         for path in paths:
   144             try:
   200             try:
   147                 catalog = None
   203                 catalog = None
   148             if catalog is not None:
   204             if catalog is not None:
   149                 t.update(catalog._catalog)
   205                 t.update(catalog._catalog)
   150     # last load the currently selected language, if it isn't identical to the default.
   206     # last load the currently selected language, if it isn't identical to the default.
   151     if locale != default_locale:
   207     if locale != default_locale:
   152         for path in paths:
   208         # If the flag en_catalog_missing has been set, the currently
   153             try:
   209         # selected language is English but it doesn't have a translation
   154                 catalog = gettext_module.translation(domain, path, [locale])
   210         # catalog (presumably due to being the language translated from).
   155             except IOError:
   211         # If that is the case, a wrong language catalog might have been
   156                 catalog = None
   212         # loaded in the previous step. It needs to be discarded.
   157             if catalog is not None:
   213         if en_catalog_missing:
   158                 t.update(catalog._catalog)
   214             t = {}
       
   215         else:
       
   216             for path in paths:
       
   217                 try:
       
   218                     catalog = gettext_module.translation(domain, path, [locale])
       
   219                 except IOError:
       
   220                     catalog = None
       
   221                 if catalog is not None:
       
   222                     t = catalog._catalog
   159     src = [LibHead]
   223     src = [LibHead]
   160     plural = None
   224     plural = None
   161     if '' in t:
   225     if '' in t:
   162         for l in t[''].split('\n'):
   226         for l in t[''].split('\n'):
   163             if l.startswith('Plural-Forms:'):
   227             if l.startswith('Plural-Forms:'):
   172     csrc = []
   236     csrc = []
   173     pdict = {}
   237     pdict = {}
   174     for k, v in t.items():
   238     for k, v in t.items():
   175         if k == '':
   239         if k == '':
   176             continue
   240             continue
   177         if type(k) in (str, unicode):
   241         if isinstance(k, basestring):
   178             csrc.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(v)))
   242             csrc.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(v)))
   179         elif type(k) == tuple:
   243         elif isinstance(k, tuple):
   180             if k[0] not in pdict:
   244             if k[0] not in pdict:
   181                 pdict[k[0]] = k[1]
   245                 pdict[k[0]] = k[1]
   182             else:
   246             else:
   183                 pdict[k[0]] = max(k[1], pdict[k[0]])
   247                 pdict[k[0]] = max(k[1], pdict[k[0]])
   184             csrc.append("catalog['%s'][%d] = '%s';\n" % (javascript_quote(k[0]), k[1], javascript_quote(v)))
   248             csrc.append("catalog['%s'][%d] = '%s';\n" % (javascript_quote(k[0]), k[1], javascript_quote(v)))
   185         else:
   249         else:
   186             raise TypeError, k
   250             raise TypeError(k)
   187     csrc.sort()
   251     csrc.sort()
   188     for k,v in pdict.items():
   252     for k, v in pdict.items():
   189         src.append("catalog['%s'] = [%s];\n" % (javascript_quote(k), ','.join(["''"]*(v+1))))
   253         src.append("catalog['%s'] = [%s];\n" % (javascript_quote(k), ','.join(["''"]*(v+1))))
   190     src.extend(csrc)
   254     src.extend(csrc)
   191     src.append(LibFoot)
   255     src.append(LibFoot)
   192     src.append(InterPolate)
   256     src.append(InterPolate)
       
   257     src.append(LibFormatHead)
       
   258     src.append(get_formats())
       
   259     src.append(LibFormatFoot)
   193     src = ''.join(src)
   260     src = ''.join(src)
   194     return http.HttpResponse(src, 'text/javascript')
   261     return http.HttpResponse(src, 'text/javascript')
       
   262