Django

Code

Ticket #4030: 4030_language_info_v2.diff

File 4030_language_info_v2.diff, 20.8 kB (added by akaihola, 2 months ago)

removed fallback for missing language_info.py, improved make-language-info.py

  • django/conf/language_info.py

    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'Arabic'}, 
     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 Argentino'}, 
     55 'eu': {'bidi': False, 
     56        'language_code': 'eu', 
     57        'name': 'Basque', 
     58        'name_local': u'Basque'}, 
     59 'fa': {'bidi': True, 
     60        'language_code': 'fa', 
     61        'name': 'Persian', 
     62        'name_local': u'Persian'}, 
     63 'fi': {'bidi': False, 
     64        'language_code': 'fi', 
     65        'name': 'Finnish', 
     66        'name_local': u'suomi'}, 
     67 'fr': {'bidi': False, 
     68        'language_code': 'fr', 
     69        'name': 'French', 
     70        'name_local': u'Fran\xe7ais'}, 
     71 'ga': {'bidi': False, 
     72        'language_code': 'ga', 
     73        'name': 'Irish', 
     74        'name_local': u'Irish'}, 
     75 'gl': {'bidi': False, 
     76        'language_code': 'gl', 
     77        'name': 'Galician', 
     78        'name_local': u'galego'}, 
     79 'he': {'bidi': True, 
     80        'language_code': 'he', 
     81        'name': 'Hebrew', 
     82        'name_local': u'\u05e2\u05d1\u05e8\u05d9\u05ea - Hebrew'}, 
     83 'hr': {'bidi': False, 
     84        'language_code': 'hr', 
     85        'name': 'Croatian', 
     86        'name_local': u'Hrvatski'}, 
     87 'hu': {'bidi': False, 
     88        'language_code': 'hu', 
     89        'name': 'Hungarian', 
     90        'name_local': u'Magyar'}, 
     91 'is': {'bidi': False, 
     92        'language_code': 'is', 
     93        'name': 'Icelandic', 
     94        'name_local': u'\xcdslenska'}, 
     95 'it': {'bidi': False, 
     96        'language_code': 'it', 
     97        'name': 'Italian', 
     98        'name_local': u'Italiano'}, 
     99 'ja': {'bidi': False, 
     100        'language_code': 'ja', 
     101        'name': 'Japanese', 
     102        'name_local': u'\u65e5\u672c\u8a9e'}, 
     103 'ka': {'bidi': False, 
     104        'language_code': 'ka', 
     105        'name': 'Georgian', 
     106        'name_local': u'\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8'}, 
     107 'km': {'bidi': False, 
     108        'language_code': 'km', 
     109        'name': 'Khmer', 
     110        'name_local': u'Khmer'}, 
     111 'kn': {'bidi': False, 
     112        'language_code': 'kn', 
     113        'name': 'Kannada', 
     114        'name_local': u'Kannada'}, 
     115 'ko': {'bidi': False, 
     116        'language_code': 'ko', 
     117        'name': 'Korean', 
     118        'name_local': u'\ud55c\uad6d\uc5b4'}, 
     119 'lv': {'bidi': False, 
     120        'language_code': 'lv', 
     121        'name': 'Latvian', 
     122        'name_local': u'Latvie\u0161u'}, 
     123 'mk': {'bidi': False, 
     124        'language_code': 'mk', 
     125        'name': 'Macedonian', 
     126        'name_local': u'\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438'}, 
     127 'nl': {'bidi': False, 
     128        'language_code': 'nl', 
     129        'name': 'Dutch', 
     130        'name_local': u'Nederlands'}, 
     131 'no': {'bidi': False, 
     132        'language_code': 'no', 
     133        'name': 'Norwegian', 
     134        'name_local': u'Norsk'}, 
     135 'pl': {'bidi': False, 
     136        'language_code': 'pl', 
     137        'name': 'Polish', 
     138        'name_local': u'Polski'}, 
     139 'pt': {'bidi': False, 
     140        'language_code': 'pt', 
     141        'name': 'Portugese', 
     142        'name_local': u'Portugese'}, 
     143 'pt-br': {'bidi': False, 
     144           'language_code': 'pt-br', 
     145           'name': 'Brazilian Portuguese', 
     146           'name_local': u'Portugu\xeas Brasileiro'}, 
     147 'ro': {'bidi': False, 
     148        'language_code': 'ro', 
     149        'name': 'Romanian', 
     150        'name_local': u'Romana'}, 
     151 'ru': {'bidi': False, 
     152        'language_code': 'ru', 
     153        'name': 'Russian', 
     154        'name_local': u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439'}, 
     155 'sk': {'bidi': False, 
     156        'language_code': 'sk', 
     157        'name': 'Slovak', 
     158        'name_local': u'Slovensky'}, 
     159 'sl': {'bidi': False, 
     160        'language_code': 'sl', 
     161        'name': 'Slovenian', 
     162        'name_local': u'Slovenski'}, 
     163 'sr': {'bidi': False, 
     164        'language_code': 'sr', 
     165        'name': 'Serbian', 
     166        'name_local': u'Srpski'}, 
     167 'sv': {'bidi': False, 
     168        'language_code': 'sv', 
     169        'name': 'Swedish', 
     170        'name_local': u'Svenska'}, 
     171 'ta': {'bidi': False, 
     172        'language_code': 'ta', 
     173        'name': 'Tamil', 
     174        'name_local': u'\u0ba4\u0bae\u0bbf\u0bb4\u0bcd'}, 
     175 'te': {'bidi': False, 
     176        'language_code': 'te', 
     177        'name': 'Telugu', 
     178        'name_local': u'Telugu'}, 
     179 'tr': {'bidi': False, 
     180        'language_code': 'tr', 
     181        'name': 'Turkish', 
     182        'name_local': u'T\xfcrk\xe7e'}, 
     183 'uk': {'bidi': False, 
     184        'language_code': 'uk', 
     185        'name': 'Ukrainian', 
     186        'name_local': u'Ukrainian'}, 
     187 'zh-cn': {'bidi': False, 
     188           'language_code': 'zh-cn', 
     189           'name': 'Simplified Chinese', 
     190           'name_local': u'\u7b80\u4f53\u4e2d\u6587'}, 
     191 'zh-tw': {'bidi': False, 
     192           'language_code': 'zh-tw', 
     193           'name': 'Traditional Chinese', 
     194           'name_local': u'\u7e41\u9ad4\u4e2d\u6587'} 
     195} 
  • 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) 
  • 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) 
  • django/bin/make-language-info.py

    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) 
  • 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} 
  • tests/regressiontests/templates/tests.py

    old new  
    755755            'i18n17': ('{% load i18n %}{% blocktrans with anton|escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'), 
    756756            'i18n18': ('{% load i18n %}{% blocktrans with anton|force_escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'), 
    757757 
     758            # retrieving language information 
     759            'i18n19': ('{% 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'), 
     760            'i18n20': ('{% 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'), 
     761            'i18n21': ('{% 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']}, 'it: Italian/Italiano bidi=False; no: Norwegian/Norsk bidi=False; '), 
     762            'i18n22': ('{% 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'))}, 'sl: Slovenian/Slovenski bidi=False; fa: Persian/Persian bidi=True; '), 
     763            'i18n23': ('{% load i18n %}{{ "hu"|language_name }} {{ "hu"|language_name_local }} {{ "hu"|language_bidi }}', {}, 'Hungarian Magyar False'), 
     764            'i18n24': ('{% load i18n %}{{ langcode|language_name }} {{ langcode|language_name_local }} {{ langcode|language_bidi }}', {'langcode': 'nl'}, 'Dutch Nederlands False'), 
     765 
    758766            ### HANDLING OF TEMPLATE_STRING_IF_INVALID ################################### 
    759767 
    760768            'invalidstr01': ('{{ var|default:"Foo" }}', {}, ('Foo','INVALID')), 
  • docs/i18n.txt

    old new  
    266266Each ``RequestContext`` has access to three translation-specific variables: 
    267267 
    268268    * ``LANGUAGES`` is a list of tuples in which the first element is the 
    269       language code and the second is the language name (in that language). 
     269      language code and the second is the language name (in English). 
    270270    * ``LANGUAGE_CODE`` is the current user's preferred language, as a string. 
    271271      Example: ``en-us``. (See "How language preference is discovered", below.) 
    272272    * ``LANGUAGE_BIDI`` is the current language's direction. If True, it's a 
     
    640640.. _session: ../sessions/ 
    641641.. _request object: ../request_response/#httprequest-objects 
    642642 
     643Local names of languages 
     644======================== 
     645 
     646The ``get_language_info()`` function provides detailed information about 
     647languages:: 
     648 
     649    >>> form django.utils.translation import get_language_info 
     650    >>> l = get_language_info('de') 
     651    >>> print l['name'], l['name_local'], l['bidi'] 
     652    German Deutsch False 
     653 
     654The ``name`` and ``name_local`` attributes of the dictionary contain the name 
     655of the language in English and the language itself, respectively.  The ``bidi`` 
     656attribute is True only for bi-directional languages. 
     657 
     658In templates, you can use special template tags or filters to retrieve the same 
     659information. To get information about a single language, use the  
     660``{% get_language_info %}`` tag:: 
     661 
     662    {% get_language_info for LANGUAGE_CODE as lang %} 
     663    {% get_language_info for "pl" as lang %} 
     664 
     665You can then access the information:: 
     666 
     667    Language code: {{ lang.language_code }}<br /> 
     668    Name of language: {{ lang.name_local }}<br /> 
     669    Name in English: {{ lang.name }}<br /> 
     670    Bi-directional: {{ lang.bidi }} 
     671 
     672You can also use the ``{% get_language_info_list %}`` template tag to retrieve 
     673information for a list of languages (e.g. active languages as specified in 
     674``settings.LANGUAGES``).  See `The set_language redirect view`_ for an example 
     675of how to display a language selector using ``{% get_language_info_list %}``. 
     676 
     677In addition to ``settings.LANGUAGES`` style nested tuples, 
     678``{% get_language_info_list %}`` supports simple lists of language codes.  If 
     679you do this in your view:: 
     680 
     681  return render_to_response('mytemplate.html',  
     682                            {'available_languages': ['en', 'es', 'fr']},  
     683                            RequestContext(request)) 
     684 
     685you can iterate those languages in the template:: 
     686 
     687  {% get_language_info_list available_languages %} 
     688  {% for l in available_languages %} ... {% endfor %} 
     689 
     690There are also simple filters available for convenience: 
     691 
     692    * ``{{ LANGUAGE_CODE|language_name }}``  ("German") 
     693    * ``{{ LANGUAGE_CODE|language_name_local }}`` ("Deutsch") 
     694    * ``{{ LANGUAGE_CODE|bidi }}`` (False)      
     695 
     696The source of the language information is the ``django.conf.language_info`` 
     697module.  If you add a new translation, you should run the 
     698``django/bin/make-language-info.py`` script to insert the information for the 
     699added language. 
     700 
    643701Using translations in your own projects 
    644702======================================= 
    645703 
     
    732790    * If that's empty -- say, if a user's browser suppresses that header -- 
    733791      then the user will be redirected to ``/`` (the site root) as a fallback. 
    734792 
    735 Here's example HTML template code:: 
     793Here's example HTML template code (see `Local names of languages`_ for more 
     794information):: 
    736795 
     796    {% get_language_info_list for LANGUAGES as available_languages %} 
    737797    <form action="/i18n/setlang/" method="post"> 
    738     <input name="next" type="hidden" value="/next/page/" /> 
    739     <select name="language"> 
    740     {% for lang in LANGUAGES %} 
    741     <option value="{{ lang.0 }}">{{ lang.1 }}</option> 
    742     {% endfor %} 
    743     </select> 
    744     <input type="submit" value="Go" /> 
     798      <input name="next" type="hidden" value="/next/page/" /> 
     799      <select name="language"> 
     800        {% for lang in available_languages %} 
     801        <option value="{{ lang.language_code }}" {% ifequal lang.language_code LANGUAGE_CODE %}selected{% endifequal %}> 
     802          {{ lang.name_local }} 
     803        </option> 
     804        {% endfor %} 
     805      </select> 
     806      <input type="submit" value="Go" /> 
    745807    </form> 
    746808 
    747809Translations and JavaScript