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