Django

Code

Ticket #4030: 4030_language_info_v2_r10639.diff

File 4030_language_info_v2_r10639.diff, 21.3 kB (added by akaihola, 11 months ago)

updated patch for revision 10639 (1.1beta1+)

  • /dev/null

    old new  
     1#!/usr/bin/env python 
     2 
     3LANGUAGE_INFO_PY_FILE = 'django/conf/language_info.py' 
     4 
     5# Need to ensure that the i18n framework is enabled 
     6from django.conf import settings 
     7settings.configure(USE_I18N = True) 
     8 
     9TEMPLATE = """\ 
     10# This file was generated with django/bin/make-language-info.py and it is not 
     11# recommended to edit it by hand.  For new translations, compile the new .po 
     12# files and edit the LANGUAGES setting, and finally re-run 
     13# django/bin/make-language-info.py to generate this file. 
     14 
     15language_info = { 
     16 %s 
     17} 
     18""" 
     19 
     20def make_language_info(target_path): 
     21    print 'Writing language information to\n%s' % target_path 
     22    # Create a dummy language_info.py file to make sure we can import the 
     23    # translation module. 
     24    file(target_path, 'w').write(TEMPLATE % '') 
     25    from django.utils import translation 
     26    from pprint import pformat 
     27    language_info = {} 
     28    for code, name in settings.LANGUAGES: 
     29        translation.activate(code) 
     30        language_info[code] = {"language_code": code, 
     31                               "name": name, 
     32                               "name_local": translation.ugettext(name), 
     33                               "bidi": code in settings.LANGUAGES_BIDI} 
     34    file(target_path, 'w').write(TEMPLATE % pformat(language_info)[1:-1]) 
     35    # Because the timestamps of the dummy .pyc and real .py may fall on the 
     36    # same second, we must enforce compilation. 
     37    import py_compile 
     38    py_compile.compile(target_path) 
     39    print 'Done.' 
     40 
     41 
     42if __name__ == "__main__": 
     43    from os.path import join, dirname, abspath 
     44    path = abspath(join(dirname(__file__), '..', '..', LANGUAGE_INFO_PY_FILE)) 
     45    make_language_info(path) 
  • /dev/null

    old new  
     1# This file was generated with django/bin/make-language-info.py and it is not 
     2# recommended to edit it by hand.  For new translations, compile the new .po 
     3# files and edit the LANGUAGES setting, and finally re-run 
     4# django/bin/make-language-info.py to generate this file. 
     5 
     6language_info = { 
     7 'ar': {'bidi': True, 
     8        'language_code': 'ar', 
     9        'name': 'Arabic', 
     10        'name_local': u'\u0627\u0644\u0639\u0631\u0628\u064a\u0651\u0629'}, 
     11 'bg': {'bidi': False, 
     12        'language_code': 'bg', 
     13        'name': 'Bulgarian', 
     14        'name_local': u'\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438'}, 
     15 'bn': {'bidi': False, 
     16        'language_code': 'bn', 
     17        'name': 'Bengali', 
     18        'name_local': u'\u09ac\u09be\u0982\u09b2\u09be'}, 
     19 'ca': {'bidi': False, 
     20        'language_code': 'ca', 
     21        'name': 'Catalan', 
     22        'name_local': u'catal\xe0'}, 
     23 'cs': {'bidi': False, 
     24        'language_code': 'cs', 
     25        'name': 'Czech', 
     26        'name_local': u'\u010desky'}, 
     27 'cy': {'bidi': False, 
     28        'language_code': 'cy', 
     29        'name': 'Welsh', 
     30        'name_local': u'Cymraeg'}, 
     31 'da': {'bidi': False, 
     32        'language_code': 'da', 
     33        'name': 'Danish', 
     34        'name_local': u'Dansk'}, 
     35 'de': {'bidi': False, 
     36        'language_code': 'de', 
     37        'name': 'German', 
     38        'name_local': u'Deutsch'}, 
     39 'el': {'bidi': False, 
     40        'language_code': 'el', 
     41        'name': 'Greek', 
     42        'name_local': u'\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac'}, 
     43 'en': {'bidi': False, 
     44        'language_code': 'en', 
     45        'name': 'English', 
     46        'name_local': u'English'}, 
     47 'es': {'bidi': False, 
     48        'language_code': 'es', 
     49        'name': 'Spanish', 
     50        'name_local': u'espa\xf1ol'}, 
     51 'es-ar': {'bidi': False, 
     52           'language_code': 'es-ar', 
     53           'name': 'Argentinean Spanish', 
     54           'name_local': u'espa\xf1ol de Argentina'}, 
     55 'et': {'bidi': False, 
     56        'language_code': 'et', 
     57        'name': 'Estonian', 
     58        'name_local': u'eesti'}, 
     59 'eu': {'bidi': False, 
     60        'language_code': 'eu', 
     61        'name': 'Basque', 
     62        'name_local': u'Basque'}, 
     63 'fa': {'bidi': True, 
     64        'language_code': 'fa', 
     65        'name': 'Persian', 
     66        'name_local': u'\u0641\u0627\u0631\u0633\u06cc'}, 
     67 'fi': {'bidi': False, 
     68        'language_code': 'fi', 
     69        'name': 'Finnish', 
     70        'name_local': u'suomi'}, 
     71 'fr': {'bidi': False, 
     72        'language_code': 'fr', 
     73        'name': 'French', 
     74        'name_local': u'Fran\xe7ais'}, 
     75 'ga': {'bidi': False, 
     76        'language_code': 'ga', 
     77        'name': 'Irish', 
     78        'name_local': u'Gaeilge'}, 
     79 'gl': {'bidi': False, 
     80        'language_code': 'gl', 
     81        'name': 'Galician', 
     82        'name_local': u'galego'}, 
     83 'he': {'bidi': True, 
     84        'language_code': 'he', 
     85        'name': 'Hebrew', 
     86        'name_local': u'\u05e2\u05d1\u05e8\u05d9\u05ea'}, 
     87 'hi': {'bidi': False, 
     88        'language_code': 'hi', 
     89        'name': 'Hindi', 
     90        'name_local': u'Hindi'}, 
     91 'hr': {'bidi': False, 
     92        'language_code': 'hr', 
     93        'name': 'Croatian', 
     94        'name_local': u'Hrvatski'}, 
     95 'hu': {'bidi': False, 
     96        'language_code': 'hu', 
     97        'name': 'Hungarian', 
     98        'name_local': u'Magyar'}, 
     99 'is': {'bidi': False, 
     100        'language_code': 'is', 
     101        'name': 'Icelandic', 
     102        'name_local': u'\xcdslenska'}, 
     103 'it': {'bidi': False, 
     104        'language_code': 'it', 
     105        'name': 'Italian', 
     106        'name_local': u'italiano'}, 
     107 'ja': {'bidi': False, 
     108        'language_code': 'ja', 
     109        'name': 'Japanese', 
     110        'name_local': u'\u65e5\u672c\u8a9e'}, 
     111 'ka': {'bidi': False, 
     112        'language_code': 'ka', 
     113        'name': 'Georgian', 
     114        'name_local': u'\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8'}, 
     115 'km': {'bidi': False, 
     116        'language_code': 'km', 
     117        'name': 'Khmer', 
     118        'name_local': u'Khmer'}, 
     119 'kn': {'bidi': False, 
     120        'language_code': 'kn', 
     121        'name': 'Kannada', 
     122        'name_local': u'Kannada'}, 
     123 'ko': {'bidi': False, 
     124        'language_code': 'ko', 
     125        'name': 'Korean', 
     126        'name_local': u'\ud55c\uad6d\uc5b4'}, 
     127 'lt': {'bidi': False, 
     128        'language_code': 'lt', 
     129        'name': 'Lithuanian', 
     130        'name_local': u'Lithuanian'}, 
     131 'lv': {'bidi': False, 
     132        'language_code': 'lv', 
     133        'name': 'Latvian', 
     134        'name_local': u'Latvie\u0161u'}, 
     135 'mk': {'bidi': False, 
     136        'language_code': 'mk', 
     137        'name': 'Macedonian', 
     138        'name_local': u'\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438'}, 
     139 'nl': {'bidi': False, 
     140        'language_code': 'nl', 
     141        'name': 'Dutch', 
     142        'name_local': u'Nederlands'}, 
     143 'no': {'bidi': False, 
     144        'language_code': 'no', 
     145        'name': 'Norwegian', 
     146        'name_local': u'Norsk'}, 
     147 'pl': {'bidi': False, 
     148        'language_code': 'pl', 
     149        'name': 'Polish', 
     150        'name_local': u'polski'}, 
     151 'pt': {'bidi': False, 
     152        'language_code': 'pt', 
     153        'name': 'Portuguese', 
     154        'name_local': u'Portuguese'}, 
     155 'pt-br': {'bidi': False, 
     156           'language_code': 'pt-br', 
     157           'name': 'Brazilian Portuguese', 
     158           'name_local': u'Portugu\xeas Brasileiro'}, 
     159 'ro': {'bidi': False, 
     160        'language_code': 'ro', 
     161        'name': 'Romanian', 
     162        'name_local': u'Romana'}, 
     163 'ru': {'bidi': False, 
     164        'language_code': 'ru', 
     165        'name': 'Russian', 
     166        'name_local': u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439'}, 
     167 'sk': {'bidi': False, 
     168        'language_code': 'sk', 
     169        'name': 'Slovak', 
     170        'name_local': u'slovensk\xfd'}, 
     171 'sl': {'bidi': False, 
     172        'language_code': 'sl', 
     173        'name': 'Slovenian', 
     174        'name_local': u'Sloven\u0161\u010dina'}, 
     175 'sr': {'bidi': False, 
     176        'language_code': 'sr', 
     177        'name': 'Serbian', 
     178        'name_local': u'\u0421\u0440\u043f\u0441\u043a\u0438'}, 
     179 'sv': {'bidi': False, 
     180        'language_code': 'sv', 
     181        'name': 'Swedish', 
     182        'name_local': u'Svenska'}, 
     183 'ta': {'bidi': False, 
     184        'language_code': 'ta', 
     185        'name': 'Tamil', 
     186        'name_local': u'\u0ba4\u0bae\u0bbf\u0bb4\u0bcd'}, 
     187 'te': {'bidi': False, 
     188        'language_code': 'te', 
     189        'name': 'Telugu', 
     190        'name_local': u'\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41'}, 
     191 'th': {'bidi': False, 
     192        'language_code': 'th', 
     193        'name': 'Thai', 
     194        'name_local': u'Thai'}, 
     195 'tr': {'bidi': False, 
     196        'language_code': 'tr', 
     197        'name': 'Turkish', 
     198        'name_local': u'T\xfcrk\xe7e'}, 
     199 'uk': {'bidi': False, 
     200        'language_code': 'uk', 
     201        'name': 'Ukrainian', 
     202        'name_local': u'\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430'}, 
     203 'zh-cn': {'bidi': False, 
     204           'language_code': 'zh-cn', 
     205           'name': 'Simplified Chinese', 
     206           'name_local': u'\u7b80\u4f53\u4e2d\u6587'}, 
     207 'zh-tw': {'bidi': False, 
     208           'language_code': 'zh-tw', 
     209           'name': 'Traditional Chinese', 
     210           'name_local': u'\u7e41\u9ad4\u4e2d\u6587'} 
     211} 
  • a/django/templatetags/i18n.py

    old new  
    1717        context[self.variable] = [(k, translation.ugettext(v)) for k, v in settings.LANGUAGES] 
    1818        return '' 
    1919 
     20class GetLanguageInfoNode(Node): 
     21    def __init__(self, lang_code, variable): 
     22        self.lang_code = Variable(lang_code) 
     23        self.variable = variable 
     24 
     25    def render(self, context): 
     26        lang_code = self.lang_code.resolve(context) 
     27        context[self.variable] = translation.get_language_info(lang_code) 
     28        return '' 
     29 
     30class GetLanguageInfoListNode(Node): 
     31    def __init__(self, languages, variable): 
     32        self.languages = Variable(languages) 
     33        self.variable = variable 
     34 
     35    def get_language_info(self, language): 
     36        # ``language`` is either a language code string or a sequence with the 
     37        # language code as its first item 
     38        if len(language[0]) > 1: 
     39            return translation.get_language_info(language[0]) 
     40        else: 
     41            return translation.get_language_info(str(language)) 
     42 
     43    def render(self, context): 
     44        languages = self.languages.resolve(context) 
     45        context[self.variable] = [self.get_language_info(l) for l in languages] 
     46        return '' 
     47 
    2048class GetCurrentLanguageNode(Node): 
    2149    def __init__(self, variable): 
    2250        self.variable = variable 
     
    107135        raise TemplateSyntaxError, "'get_available_languages' requires 'as variable' (got %r)" % args 
    108136    return GetAvailableLanguagesNode(args[2]) 
    109137 
     138def do_get_language_info(parser, token): 
     139    """ 
     140    This will store the language information dictionary for the given language 
     141    code in a context variable. 
     142 
     143    Usage:: 
     144 
     145        {% get_language_info for language_code as l %} 
     146        {{ l.language_code }} 
     147        {{ l.name }} 
     148        {{ l.name_local }} 
     149        {{ l.bidi|yesno:"bi-directional,uni-directional" }} 
     150    """ 
     151    args = token.contents.split() 
     152    if len(args) != 5 or args[1] != 'for' or args[3] != 'as': 
     153        raise TemplateSyntaxError, "'%s' requires 'for string as variable' (got %r)" % (args[0], args[1:]) 
     154    return GetLanguageInfoNode(args[2], args[4]) 
     155 
     156def do_get_language_info_list(parser, token): 
     157    """ 
     158    This will store a list of language information dictionaries for the given 
     159    language codes in a context variable.  The language codes can be specified 
     160    ither as a list of strings or a settings.LANGUAGES style tuple (or any 
     161    sequence of sequences whose first items are language codes). 
     162 
     163    Usage:: 
     164 
     165        {% get_language_info_list for LANGUAGES as langs %} 
     166        {% for l in langs %} 
     167          {{ l.language_code }} 
     168          {{ l.name }} 
     169          {{ l.name_local }} 
     170          {{ l.bidi|yesno:"bi-directional,uni-directional" }} 
     171        {% endfor %} 
     172    """ 
     173    args = token.contents.split() 
     174    if len(args) != 5 or args[1] != 'for' or args[3] != 'as': 
     175        raise TemplateSyntaxError, "'%s' requires 'for sequence as variable' (got %r)" % (args[0], args[1:]) 
     176    return GetLanguageInfoListNode(args[2], args[4]) 
     177 
     178def language_name(lang_code): 
     179    return translation.get_language_info(lang_code)['name'] 
     180 
     181def language_name_local(lang_code): 
     182    return translation.get_language_info(lang_code)['name_local'] 
     183 
     184def language_bidi(lang_code): 
     185    return translation.get_language_info(lang_code)['bidi'] 
     186 
    110187def do_get_current_language(parser, token): 
    111188    """ 
    112189    This will store the current language in the context. 
     
    253330            counter) 
    254331 
    255332register.tag('get_available_languages', do_get_available_languages) 
     333register.tag('get_language_info', do_get_language_info) 
     334register.tag('get_language_info_list', do_get_language_info_list) 
    256335register.tag('get_current_language', do_get_current_language) 
    257336register.tag('get_current_language_bidi', do_get_current_language_bidi) 
    258337register.tag('trans', do_translate) 
    259338register.tag('blocktrans', do_block_translate) 
     339 
     340register.filter(language_name) 
     341register.filter(language_name_local) 
     342register.filter(language_bidi) 
  • a/django/utils/translation/__init__.py

    old new  
    33""" 
    44from django.utils.functional import lazy 
    55from django.utils.encoding import force_unicode 
     6try: 
     7    from django.conf.language_info import language_info 
     8except ImportError: 
     9    raise ImportError("Module django.conf.language_info not found. Run django/bin/make-language-info.py to generate it.") 
    610 
    711__all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext', 
    812        'ngettext_lazy', 'string_concat', 'activate', 'deactivate', 
     
    109113    """ 
    110114    return u''.join([force_unicode(s) for s in strings]) 
    111115string_concat = lazy(string_concat, unicode) 
     116 
     117def get_language_info(lang_code): 
     118    try: 
     119        return language_info[lang_code] 
     120    except KeyError: 
     121        raise KeyError("Unknown language code %r.  If you have added a new translation, remember to add the language to the LANGUAGES setting and update the django/conf/language_info.py file by running django/bin/make-language-info.py." % lang_code) 
  • a/docs/topics/i18n.txt

    old new  
    726726 
    727727.. _translations-in-your-own-projects: 
    728728 
     729Local names of languages 
     730======================== 
     731 
     732The ``get_language_info()`` function provides detailed information about 
     733languages:: 
     734 
     735    >>> form django.utils.translation import get_language_info 
     736    >>> l = get_language_info('de') 
     737    >>> print l['name'], l['name_local'], l['bidi'] 
     738    German Deutsch False 
     739 
     740The ``name`` and ``name_local`` attributes of the dictionary contain the name 
     741of the language in English and the language itself, respectively.  The ``bidi`` 
     742attribute is True only for bi-directional languages. 
     743 
     744In templates, you can use special template tags or filters to retrieve the same 
     745information. To get information about a single language, use the 
     746``{% get_language_info %}`` tag:: 
     747 
     748    {% get_language_info for LANGUAGE_CODE as lang %} 
     749    {% get_language_info for "pl" as lang %} 
     750 
     751You can then access the information:: 
     752 
     753    Language code: {{ lang.language_code }}<br /> 
     754    Name of language: {{ lang.name_local }}<br /> 
     755    Name in English: {{ lang.name }}<br /> 
     756    Bi-directional: {{ lang.bidi }} 
     757 
     758You can also use the ``{% get_language_info_list %}`` template tag to retrieve 
     759information for a list of languages (e.g. active languages as specified in 
     760``settings.LANGUAGES``).  See `The set_language redirect view`_ for an example 
     761of how to display a language selector using ``{% get_language_info_list %}``. 
     762 
     763In addition to ``settings.LANGUAGES`` style nested tuples, 
     764``{% get_language_info_list %}`` supports simple lists of language codes.  If 
     765you do this in your view:: 
     766 
     767  return render_to_response('mytemplate.html', 
     768                            {'available_languages': ['en', 'es', 'fr']}, 
     769                            RequestContext(request)) 
     770 
     771you can iterate those languages in the template:: 
     772 
     773  {% get_language_info_list available_languages %} 
     774  {% for l in available_languages %} ... {% endfor %} 
     775 
     776There are also simple filters available for convenience: 
     777 
     778    * ``{{ LANGUAGE_CODE|language_name }}``  ("German") 
     779    * ``{{ LANGUAGE_CODE|language_name_local }}`` ("Deutsch") 
     780    * ``{{ LANGUAGE_CODE|bidi }}`` (False) 
     781 
     782The source of the language information is the ``django.conf.language_info`` 
     783module.  If you add a new translation, you should run the 
     784``django/bin/make-language-info.py`` script to insert the information for the 
     785added language. 
     786 
    729787Using translations in your own projects 
    730788======================================= 
    731789 
     
    817875    * If that's empty -- say, if a user's browser suppresses that header -- 
    818876      then the user will be redirected to ``/`` (the site root) as a fallback. 
    819877 
    820 Here's example HTML template code: 
     878Here's example HTML template code (see `Local names of languages`_ for more 
     879information):: 
    821880 
    822881.. code-block:: html+django 
    823882 
     883    {% get_language_info_list for LANGUAGES as available_languages %} 
    824884    <form action="/i18n/setlang/" method="post"> 
    825     <input name="next" type="hidden" value="/next/page/" /> 
    826     <select name="language"> 
    827     {% for lang in LANGUAGES %} 
    828     <option value="{{ lang.0 }}">{{ lang.1 }}</option> 
    829     {% endfor %} 
    830     </select> 
    831     <input type="submit" value="Go" /> 
     885      <input name="next" type="hidden" value="/next/page/" /> 
     886      <select name="language"> 
     887        {% for lang in available_languages %} 
     888        <option value="{{ lang.language_code }}" {% ifequal lang.language_code LANGUAGE_CODE %}selected{% endifequal %}> 
     889          {{ lang.name_local }} 
     890        </option> 
     891        {% endfor %} 
     892      </select> 
     893      <input type="submit" value="Go" /> 
    832894    </form> 
    833895 
    834896Translations and JavaScript 
  • /dev/null

    old new  
     1tests = """ 
     2>>> from django.utils.translation import get_language_info 
     3>>> from pprint import pprint 
     4>>> pprint(get_language_info('de')) 
     5{'bidi': False, 
     6 'language_code': 'de', 
     7 'name': 'German', 
     8 'name_local': u'Deutsch'} 
     9""" 
     10tests = """ 
     11>>> from django.utils.translation import get_language_info 
     12>>> from pprint import pprint 
     13>>> pprint(get_language_info('de')) 
     14{'bidi': False, 
     15 'language_code': 'de', 
     16 'name': 'German', 
     17 'name_local': u'Deutsch'} 
     18""" 
  • a/tests/regressiontests/i18n/tests.py

    old new  
    11# coding: utf-8 
    2 import misc 
     2import misc, language_info 
    33 
    44regressions = ur""" 
    55Format string interpolation should work with *_lazy objects. 
     
    6868 
    6969__test__ = { 
    7070    'regressions': regressions, 
     71    'language_info': language_info.tests, 
    7172    'misc': misc.tests, 
    7273} 
  • a/tests/regressiontests/templates/tests.py

    old new  
    869869            'i18n21': ('{% load i18n %}{% blocktrans %}{{ andrew }}{% endblocktrans %}', {'andrew': mark_safe('a & b')}, u'a & b'), 
    870870            'i18n22': ('{% load i18n %}{% trans andrew %}', {'andrew': mark_safe('a & b')}, u'a & b'), 
    871871 
     872            # retrieving language information 
     873            'i18n23': ('{% load i18n %}{% get_language_info for "de" as l %}{{ l.language_code }}: {{ l.name }}/{{ l.name_local }} bidi={{ l.bidi }}', {}, 'de: German/Deutsch bidi=False'), 
     874            'i18n24': ('{% load i18n %}{% get_language_info for LANGUAGE_CODE as l %}{{ l.language_code }}: {{ l.name }}/{{ l.name_local }} bidi={{ l.bidi }}', {'LANGUAGE_CODE': 'fi'}, 'fi: Finnish/suomi bidi=False'), 
     875            'i18n25': ('{% load i18n %}{% get_language_info_list for langcodes as langs %}{% for l in langs %}{{ l.language_code }}: {{ l.name }}/{{ l.name_local }} bidi={{ l.bidi }}; {% endfor %}', {'langcodes': ['it', 'no']}, u'it: Italian/italiano bidi=False; no: Norwegian/Norsk bidi=False; '), 
     876            'i18n26': ('{% load i18n %}{% get_language_info_list for langcodes as langs %}{% for l in langs %}{{ l.language_code }}: {{ l.name }}/{{ l.name_local }} bidi={{ l.bidi }}; {% endfor %}', {'langcodes': (('sl', 'Slovenian'), ('fa', 'Persian'))}, u'sl: Slovenian/Sloven\u0161\u010dina bidi=False; fa: Persian/\u0641\u0627\u0631\u0633\u06cc bidi=True; '), 
     877            'i18n27': ('{% load i18n %}{{ "hu"|language_name }} {{ "hu"|language_name_local }} {{ "hu"|language_bidi }}', {}, u'Hungarian Magyar False'), 
     878            'i18n28': ('{% load i18n %}{{ langcode|language_name }} {{ langcode|language_name_local }} {{ langcode|language_bidi }}', {'langcode': 'nl'}, u'Dutch Nederlands False'), 
     879 
    872880            ### HANDLING OF TEMPLATE_STRING_IF_INVALID ################################### 
    873881 
    874882            'invalidstr01': ('{{ var|default:"Foo" }}', {}, ('Foo','INVALID')),