app/django/views/i18n.py
changeset 54 03e267d67478
equal deleted inserted replaced
53:57b4279d8c4e 54:03e267d67478
       
     1 from django import http
       
     2 from django.utils.translation import check_for_language, activate, to_locale, get_language
       
     3 from django.utils.text import javascript_quote
       
     4 from django.conf import settings
       
     5 import os
       
     6 import gettext as gettext_module
       
     7 
       
     8 def set_language(request):
       
     9     """
       
    10     Redirect to a given url while setting the chosen language in the
       
    11     session or cookie. The url and the language code need to be
       
    12     specified in the request parameters.
       
    13 
       
    14     Since this view changes how the user will see the rest of the site, it must
       
    15     only be accessed as a POST request. If called as a GET request, it will
       
    16     redirect to the page in the request (the 'next' parameter) without changing
       
    17     any state.
       
    18     """
       
    19     next = request.REQUEST.get('next', None)
       
    20     if not next:
       
    21         next = request.META.get('HTTP_REFERER', None)
       
    22     if not next:
       
    23         next = '/'
       
    24     response = http.HttpResponseRedirect(next)
       
    25     if request.method == 'POST':
       
    26         lang_code = request.POST.get('language', None)
       
    27         if lang_code and check_for_language(lang_code):
       
    28             if hasattr(request, 'session'):
       
    29                 request.session['django_language'] = lang_code
       
    30             else:
       
    31                 response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
       
    32     return response
       
    33 
       
    34 NullSource = """
       
    35 /* gettext identity library */
       
    36 
       
    37 function gettext(msgid) { return msgid; }
       
    38 function ngettext(singular, plural, count) { return (count == 1) ? singular : plural; }
       
    39 function gettext_noop(msgid) { return msgid; }
       
    40 """
       
    41 
       
    42 LibHead = """
       
    43 /* gettext library */
       
    44 
       
    45 var catalog = new Array();
       
    46 """
       
    47 
       
    48 LibFoot = """
       
    49 
       
    50 function gettext(msgid) {
       
    51   var value = catalog[msgid];
       
    52   if (typeof(value) == 'undefined') {
       
    53     return msgid;
       
    54   } else {
       
    55     return (typeof(value) == 'string') ? value : value[0];
       
    56   }
       
    57 }
       
    58 
       
    59 function ngettext(singular, plural, count) {
       
    60   value = catalog[singular];
       
    61   if (typeof(value) == 'undefined') {
       
    62     return (count == 1) ? singular : plural;
       
    63   } else {
       
    64     return value[pluralidx(count)];
       
    65   }
       
    66 }
       
    67 
       
    68 function gettext_noop(msgid) { return msgid; }
       
    69 """
       
    70 
       
    71 SimplePlural = """
       
    72 function pluralidx(count) { return (count == 1) ? 0 : 1; }
       
    73 """
       
    74 
       
    75 InterPolate = r"""
       
    76 function interpolate(fmt, obj, named) {
       
    77   if (named) {
       
    78     return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])});
       
    79   } else {
       
    80     return fmt.replace(/%s/g, function(match){return String(obj.shift())});
       
    81   }
       
    82 }
       
    83 """
       
    84 
       
    85 PluralIdx = r"""
       
    86 function pluralidx(n) {
       
    87   var v=%s;
       
    88   if (typeof(v) == 'boolean') {
       
    89     return v ? 1 : 0;
       
    90   } else {
       
    91     return v;
       
    92   }
       
    93 }
       
    94 """
       
    95 
       
    96 def null_javascript_catalog(request, domain=None, packages=None):
       
    97     """
       
    98     Returns "identity" versions of the JavaScript i18n functions -- i.e.,
       
    99     versions that don't actually do anything.
       
   100     """
       
   101     return http.HttpResponse(NullSource + InterPolate, 'text/javascript')
       
   102 
       
   103 def javascript_catalog(request, domain='djangojs', packages=None):
       
   104     """
       
   105     Returns the selected language catalog as a javascript library.
       
   106 
       
   107     Receives the list of packages to check for translations in the
       
   108     packages parameter either from an infodict or as a +-delimited
       
   109     string from the request. Default is 'django.conf'.
       
   110 
       
   111     Additionally you can override the gettext domain for this view,
       
   112     but usually you don't want to do that, as JavaScript messages
       
   113     go to the djangojs domain. But this might be needed if you
       
   114     deliver your JavaScript source from Django templates.
       
   115     """
       
   116     if request.GET:
       
   117         if 'language' in request.GET:
       
   118             if check_for_language(request.GET['language']):
       
   119                 activate(request.GET['language'])
       
   120     if packages is None:
       
   121         packages = ['django.conf']
       
   122     if type(packages) in (str, unicode):
       
   123         packages = packages.split('+')
       
   124     packages = [p for p in packages if p == 'django.conf' or p in settings.INSTALLED_APPS]
       
   125     default_locale = to_locale(settings.LANGUAGE_CODE)
       
   126     locale = to_locale(get_language())
       
   127     t = {}
       
   128     paths = []
       
   129     # first load all english languages files for defaults
       
   130     for package in packages:
       
   131         p = __import__(package, {}, {}, [''])
       
   132         path = os.path.join(os.path.dirname(p.__file__), 'locale')
       
   133         paths.append(path)
       
   134         try:
       
   135             catalog = gettext_module.translation(domain, path, ['en'])
       
   136             t.update(catalog._catalog)
       
   137         except IOError:
       
   138             # 'en' catalog was missing. This is harmless.
       
   139             pass
       
   140     # next load the settings.LANGUAGE_CODE translations if it isn't english
       
   141     if default_locale != 'en':
       
   142         for path in paths:
       
   143             try:
       
   144                 catalog = gettext_module.translation(domain, path, [default_locale])
       
   145             except IOError:
       
   146                 catalog = None
       
   147             if catalog is not None:
       
   148                 t.update(catalog._catalog)
       
   149     # last load the currently selected language, if it isn't identical to the default.
       
   150     if locale != default_locale:
       
   151         for path in paths:
       
   152             try:
       
   153                 catalog = gettext_module.translation(domain, path, [locale])
       
   154             except IOError:
       
   155                 catalog = None
       
   156             if catalog is not None:
       
   157                 t.update(catalog._catalog)
       
   158     src = [LibHead]
       
   159     plural = None
       
   160     if '' in t:
       
   161         for l in t[''].split('\n'):
       
   162             if l.startswith('Plural-Forms:'):
       
   163                 plural = l.split(':',1)[1].strip()
       
   164     if plural is not None:
       
   165         # this should actually be a compiled function of a typical plural-form:
       
   166         # Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
       
   167         plural = [el.strip() for el in plural.split(';') if el.strip().startswith('plural=')][0].split('=',1)[1]
       
   168         src.append(PluralIdx % plural)
       
   169     else:
       
   170         src.append(SimplePlural)
       
   171     csrc = []
       
   172     pdict = {}
       
   173     for k, v in t.items():
       
   174         if k == '':
       
   175             continue
       
   176         if type(k) in (str, unicode):
       
   177             csrc.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(v)))
       
   178         elif type(k) == tuple:
       
   179             if k[0] not in pdict:
       
   180                 pdict[k[0]] = k[1]
       
   181             else:
       
   182                 pdict[k[0]] = max(k[1], pdict[k[0]])
       
   183             csrc.append("catalog['%s'][%d] = '%s';\n" % (javascript_quote(k[0]), k[1], javascript_quote(v)))
       
   184         else:
       
   185             raise TypeError, k
       
   186     csrc.sort()
       
   187     for k,v in pdict.items():
       
   188         src.append("catalog['%s'] = [%s];\n" % (javascript_quote(k), ','.join(["''"]*(v+1))))
       
   189     src.extend(csrc)
       
   190     src.append(LibFoot)
       
   191     src.append(InterPolate)
       
   192     src = ''.join(src)
       
   193     return http.HttpResponse(src, 'text/javascript')