Ticket #945: jsi18n.diff

File jsi18n.diff, 5.7 KB (added by hugo, 18 years ago)

first take at gettext functionality for JavaScript

  • utils/translation.py

     
    212212    from django.conf.settings import LANGUAGE_CODE
    213213    return LANGUAGE_CODE
    214214
     215def catalog():
     216    """
     217    This function returns the current active catalog for further processing.
     218    This can be used if you need to modify the catalog or want to access the
     219    whole message catalog instead of just translating one string.
     220    """
     221    global _default, _active
     222    t = _active.get(currentThread(), None)
     223    if t is not None:
     224        return t
     225    if _default is None:
     226        from django.conf import settings
     227        _default = translation(settings.LANGUAGE_CODE)
     228    return _default
     229
    215230def gettext(message):
    216231    """
    217232    This function will be patched into the builtins module to provide the _
  • utils/text.py

     
    11import re
    22
     3from django.conf.settings import DEFAULT_CHARSET
     4
    35# Capitalizes the first letter of a string.
    46capfirst = lambda x: x and x[0].upper() + x[1:]
    57
     
    9092    zfile.write(s)
    9193    zfile.close()
    9294    return zbuf.getvalue()
     95
     96ustring_re = re.compile(u"([\u0080-\uffff])")
     97def javascript_quote(s):
     98
     99    def fix(match):
     100        return r"\u%04x" % ord(match.group(1))
     101
     102    if type(s) == str:
     103        s = s.decode(DEFAULT_ENCODING)
     104    elif type(s) != unicode:
     105        raise TypeError, s
     106    s = s.replace('\\', '\\\\')
     107    s = s.replace('\n', '\\n')
     108    s = s.replace('\t', '\\t')
     109    s = s.replace("'", "\\'")
     110    return str(ustring_re.sub(fix, s))
     111
  • views/i18n.py

     
     1import re
     2
    13from django.utils import httpwrappers
    2 from django.utils.translation import check_for_language
     4from django.utils.translation import check_for_language, catalog, DjangoTranslation, activate
     5from django.utils.text import javascript_quote
    36
    47def set_language(request):
    58    """
     
    2023        else:
    2124            response.set_cookie('django_language', lang_code)
    2225    return response
     26
     27NullSource = """
     28/* gettext identity library */
     29
     30function gettext(msgid) {
     31    return msgid;
     32}
     33
     34function ngettext(singular, plural, count) {
     35    if (count == 1) {
     36        return singular;
     37    } else {
     38        return plural;
     39    }
     40}
     41
     42function gettext_noop(msgid) {
     43    return msgid;
     44}
     45"""
     46
     47LibHead = """
     48/* gettext library */
     49
     50var catalog = new Array();
     51"""
     52
     53LibFoot = """
     54
     55function gettext(msgid) {
     56    var value = catalog[msgid];
     57    if (typeof(value) == 'undefined') {
     58        return msgid;
     59    } else {
     60        if (typeof(value) == 'string') {
     61            return value;
     62        } else {
     63            return value[0];
     64        }
     65    }
     66}
     67
     68function ngettext(singular, plural, count) {
     69    value = catalog[singular];
     70    if (typeof(value) == 'undefined') {
     71        if (count == 1) {
     72            return singular;
     73        } else {
     74            return plural;
     75        }
     76    } else {
     77        return value[pluralidx(count)];
     78    }
     79}
     80
     81function gettext_noop(msgid) {
     82    return msgid;
     83}
     84"""
     85
     86SimplePlural = """
     87function pluralidx(count) {
     88    if (count == 1) {
     89        return 0;
     90    } else {
     91        return 1;
     92    }
     93}
     94"""
     95
     96InterPolate = r"""
     97function interpolate(fmt, obj, named) {
     98    if (named) {
     99        return fmt.replace(/%\(\w+\)s/, function(match){return String(obj[match.slice(2,-2)])});
     100    } else {
     101        return fmt.replace(/%s/, function(match){return String(obj.shift())});
     102    }
     103}
     104"""
     105
     106def javascript_catalog(request):
     107    """
     108    Returns the selected language catalog as a javascript library.
     109    """
     110    if request.GET:
     111        if request.GET.has_key('language'):
     112            activate(request.GET['language'])
     113    t = catalog()
     114    if isinstance(t, DjangoTranslation):
     115        src = [LibHead]
     116        plural = None
     117        for l in t._catalog[''].split('\n'):
     118            if l.startswith('Plural-Forms:'):
     119                plural = l.split(':',1)[1].strip()
     120        if plural is not None:
     121            # this should actually be a compiled function of a typical plural-form:
     122            # 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;
     123            plural = [el.strip() for el in plural.split(';') if el.strip().startswith('plural=')][0].split('=',1)[1]
     124            src.append('function pluralidx(n) {\n    return %s;\n}\n' % plural)
     125        else:
     126            src.append(SimplePlural)
     127        csrc = []
     128        pdict = {}
     129        for k, v in t._catalog.items():
     130            if k == '':
     131                continue
     132            if type(k) in (str, unicode):
     133                csrc.append("catalog['%s'] = '%s';\n" % (javascript_quote(k), javascript_quote(v)))
     134            elif type(k) == tuple:
     135                if not pdict.has_key(k[0]):
     136                    pdict[k[0]] = k[1]
     137                else:
     138                    pdict[k[0]] = max(k[1], pdict[k[0]])
     139                csrc.append("catalog['%s'][%d] = '%s';\n" % (javascript_quote(k[0]), k[1], javascript_quote(v)))
     140            else:
     141                raise TypeError, k
     142        csrc.sort()
     143        for k,v in pdict.items():
     144            src.append("catalog['%s'] = [%s];\n" % (javascript_quote(k), ','.join(["''"]*(v+1))))
     145        src.extend(csrc)
     146        src.append(LibFoot)
     147        src.append(InterPolate)
     148        src = ''.join(src)
     149    else:
     150        src = [NullSource, InterPolate]
     151    return httpwrappers.HttpResponse(src, 'text/javascript')
     152
Back to Top