Ticket #4030: 4030-rc0.diff

File 4030-rc0.diff, 28.0 KB (added by ramiro, 5 years ago)

First release cadidate patch for this ticket. Entirely based on work by akaihola.

  • new file django/conf/locale/language_info.py

    diff -r f700b623b8db -r 07ed5e4869c0 django/conf/locale/language_info.py
    - +  
     1# This file was generated with the makelanginfo Django management command and
     2# is not meant to be edited by hand. For new translations, add them following
     3# the steps described in the internals/contributing.txt document ('Submitting
     4# and maintaining translations' section) and finally re-run
     5# 'django-admin.py makelanginfo' to generate this file.
     6
     7lang_info = {
     8'ar': {'bidi': True,
     9        'language_code': 'ar',
     10        'name': 'Arabic',
     11        'name_local': u'\u0627\u0644\u0639\u0631\u0628\u064a\u0651\u0629'},
     12 'bg': {'bidi': False,
     13        'language_code': 'bg',
     14        'name': 'Bulgarian',
     15        'name_local': u'\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438'},
     16 'bn': {'bidi': False,
     17        'language_code': 'bn',
     18        'name': 'Bengali',
     19        'name_local': u'\u09ac\u09be\u0982\u09b2\u09be'},
     20 'bs': {'bidi': False,
     21        'language_code': 'bs',
     22        'name': 'Bosnian',
     23        'name_local': u'bosanski'},
     24 'ca': {'bidi': False,
     25        'language_code': 'ca',
     26        'name': 'Catalan',
     27        'name_local': u'catal\xe0'},
     28 'cs': {'bidi': False,
     29        'language_code': 'cs',
     30        'name': 'Czech',
     31        'name_local': u'\u010desky'},
     32 'cy': {'bidi': False,
     33        'language_code': 'cy',
     34        'name': 'Welsh',
     35        'name_local': u'Cymraeg'},
     36 'da': {'bidi': False,
     37        'language_code': 'da',
     38        'name': 'Danish',
     39        'name_local': u'Dansk'},
     40 'de': {'bidi': False,
     41        'language_code': 'de',
     42        'name': 'German',
     43        'name_local': u'Deutsch'},
     44 'el': {'bidi': False,
     45        'language_code': 'el',
     46        'name': 'Greek',
     47        'name_local': u'\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac'},
     48 'en': {'bidi': False,
     49        'language_code': 'en',
     50        'name': 'English',
     51        'name_local': u'English'},
     52 'en-gb': {'bidi': False,
     53           'language_code': 'en-gb',
     54           'name': 'British English',
     55           'name_local': u'British English'},
     56 'es': {'bidi': False,
     57        'language_code': 'es',
     58        'name': 'Spanish',
     59        'name_local': u'espa\xf1ol'},
     60 'es-ar': {'bidi': False,
     61           'language_code': 'es-ar',
     62           'name': 'Argentinian Spanish',
     63           'name_local': u'espa\xf1ol de Argentina'},
     64 'et': {'bidi': False,
     65        'language_code': 'et',
     66        'name': 'Estonian',
     67        'name_local': u'eesti'},
     68 'eu': {'bidi': False,
     69        'language_code': 'eu',
     70        'name': 'Basque',
     71        'name_local': u'Basque'},
     72 'fa': {'bidi': True,
     73        'language_code': 'fa',
     74        'name': 'Persian',
     75        'name_local': u'\u0641\u0627\u0631\u0633\u06cc'},
     76 'fi': {'bidi': False,
     77        'language_code': 'fi',
     78        'name': 'Finnish',
     79        'name_local': u'suomi'},
     80 'fr': {'bidi': False,
     81        'language_code': 'fr',
     82        'name': 'French',
     83        'name_local': u'Fran\xe7ais'},
     84 'fy-nl': {'bidi': False,
     85           'language_code': 'fy-nl',
     86           'name': 'Frisian',
     87           'name_local': u'Frisian'},
     88 'ga': {'bidi': False,
     89        'language_code': 'ga',
     90        'name': 'Irish',
     91        'name_local': u'Gaeilge'},
     92 'gl': {'bidi': False,
     93        'language_code': 'gl',
     94        'name': 'Galician',
     95        'name_local': u'galego'},
     96 'he': {'bidi': True,
     97        'language_code': 'he',
     98        'name': 'Hebrew',
     99        'name_local': u'\u05e2\u05d1\u05e8\u05d9\u05ea'},
     100 'hi': {'bidi': False,
     101        'language_code': 'hi',
     102        'name': 'Hindi',
     103        'name_local': u'Hindi'},
     104 'hr': {'bidi': False,
     105        'language_code': 'hr',
     106        'name': 'Croatian',
     107        'name_local': u'Hrvatski'},
     108 'hu': {'bidi': False,
     109        'language_code': 'hu',
     110        'name': 'Hungarian',
     111        'name_local': u'Magyar'},
     112 'id': {'bidi': False,
     113        'language_code': 'id',
     114        'name': 'Indonesian',
     115        'name_local': u'Bahasa Indonesia'},
     116 'is': {'bidi': False,
     117        'language_code': 'is',
     118        'name': 'Icelandic',
     119        'name_local': u'\xcdslenska'},
     120 'it': {'bidi': False,
     121        'language_code': 'it',
     122        'name': 'Italian',
     123        'name_local': u'italiano'},
     124 'ja': {'bidi': False,
     125        'language_code': 'ja',
     126        'name': 'Japanese',
     127        'name_local': u'\u65e5\u672c\u8a9e'},
     128 'ka': {'bidi': False,
     129        'language_code': 'ka',
     130        'name': 'Georgian',
     131        'name_local': u'\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8'},
     132 'km': {'bidi': False,
     133        'language_code': 'km',
     134        'name': 'Khmer',
     135        'name_local': u'Khmer'},
     136 'kn': {'bidi': False,
     137        'language_code': 'kn',
     138        'name': 'Kannada',
     139        'name_local': u'Kannada'},
     140 'ko': {'bidi': False,
     141        'language_code': 'ko',
     142        'name': 'Korean',
     143        'name_local': u'\ud55c\uad6d\uc5b4'},
     144 'lt': {'bidi': False,
     145        'language_code': 'lt',
     146        'name': 'Lithuanian',
     147        'name_local': u'Lithuanian'},
     148 'lv': {'bidi': False,
     149        'language_code': 'lv',
     150        'name': 'Latvian',
     151        'name_local': u'latvie\u0161u'},
     152 'mk': {'bidi': False,
     153        'language_code': 'mk',
     154        'name': 'Macedonian',
     155        'name_local': u'\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438'},
     156 'ml': {'bidi': False,
     157        'language_code': 'ml',
     158        'name': 'Malayalam',
     159        'name_local': u'Malayalam'},
     160 'mn': {'bidi': False,
     161        'language_code': 'mn',
     162        'name': 'Mongolian',
     163        'name_local': u'Mongolian'},
     164 'nb': {'bidi': False,
     165        'language_code': 'nb',
     166        'name': 'Norwegian Bokmal',
     167        'name_local': u'Norsk (bokm\xe5l)'},
     168 'nl': {'bidi': False,
     169        'language_code': 'nl',
     170        'name': 'Dutch',
     171        'name_local': u'Nederlands'},
     172 'nn': {'bidi': False,
     173        'language_code': 'nn',
     174        'name': 'Norwegian Nynorsk',
     175        'name_local': u'Norsk (nynorsk)'},
     176 'no': {'bidi': False,
     177        'language_code': 'no',
     178        'name': 'Norwegian',
     179        'name_local': u'Norsk'},
     180 'pa': {'bidi': False,
     181        'language_code': 'pa',
     182        'name': 'Punjabi',
     183        'name_local': u'Punjabi'},
     184 'pl': {'bidi': False,
     185        'language_code': 'pl',
     186        'name': 'Polish',
     187        'name_local': u'polski'},
     188 'pt': {'bidi': False,
     189        'language_code': 'pt',
     190        'name': 'Portuguese',
     191        'name_local': u'Portugu\xeas'},
     192 'pt-br': {'bidi': False,
     193           'language_code': 'pt-br',
     194           'name': 'Brazilian Portuguese',
     195           'name_local': u'Portugu\xeas Brasileiro'},
     196 'ro': {'bidi': False,
     197        'language_code': 'ro',
     198        'name': 'Romanian',
     199        'name_local': u'Rom\xe2n\u0103'},
     200 'ru': {'bidi': False,
     201        'language_code': 'ru',
     202        'name': 'Russian',
     203        'name_local': u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439'},
     204 'sk': {'bidi': False,
     205        'language_code': 'sk',
     206        'name': 'Slovak',
     207        'name_local': u'slovensk\xfd'},
     208 'sl': {'bidi': False,
     209        'language_code': 'sl',
     210        'name': 'Slovenian',
     211        'name_local': u'Sloven\u0161\u010dina'},
     212 'sq': {'bidi': False,
     213        'language_code': 'sq',
     214        'name': 'Albanian',
     215        'name_local': u'Albanian'},
     216 'sr': {'bidi': False,
     217        'language_code': 'sr',
     218        'name': 'Serbian',
     219        'name_local': u'\u0441\u0440\u043f\u0441\u043a\u0438'},
     220 'sr-latn': {'bidi': False,
     221             'language_code': 'sr-latn',
     222             'name': 'Serbian Latin',
     223             'name_local': u'srpski (latinica)'},
     224 'sv': {'bidi': False,
     225        'language_code': 'sv',
     226        'name': 'Swedish',
     227        'name_local': u'Svenska'},
     228 'ta': {'bidi': False,
     229        'language_code': 'ta',
     230        'name': 'Tamil',
     231        'name_local': u'\u0ba4\u0bae\u0bbf\u0bb4\u0bcd'},
     232 'te': {'bidi': False,
     233        'language_code': 'te',
     234        'name': 'Telugu',
     235        'name_local': u'\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41'},
     236 'th': {'bidi': False,
     237        'language_code': 'th',
     238        'name': 'Thai',
     239        'name_local': u'Thai'},
     240 'tr': {'bidi': False,
     241        'language_code': 'tr',
     242        'name': 'Turkish',
     243        'name_local': u'T\xfcrk\xe7e'},
     244 'uk': {'bidi': False,
     245        'language_code': 'uk',
     246        'name': 'Ukrainian',
     247        'name_local': u'\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430'},
     248 'vi': {'bidi': False,
     249        'language_code': 'vi',
     250        'name': 'Vietnamese',
     251        'name_local': u'Vietnamese'},
     252 'zh-cn': {'bidi': False,
     253           'language_code': 'zh-cn',
     254           'name': 'Simplified Chinese',
     255           'name_local': u'\u7b80\u4f53\u4e2d\u6587'},
     256 'zh-tw': {'bidi': False,
     257           'language_code': 'zh-tw',
     258           'name': 'Traditional Chinese',
     259           'name_local': u'\u7e41\u9ad4\u4e2d\u6587'}
     260}
  • new file django/core/management/commands/makelanginfo.py

    diff -r f700b623b8db -r 07ed5e4869c0 django/core/management/commands/makelanginfo.py
    - +  
     1import os
     2from pprint import pformat
     3import sys
     4
     5from django.core.management.base import CommandError, NoArgsCommand
     6from django.utils import translation
     7
     8LANGUAGE_INFO_PY_FILE = 'language_info.py'
     9
     10TEMPLATE = """\
     11# This file was generated with the makelanginfo Django management command and
     12# is not meant to be edited by hand. For new translations, add them following
     13# the steps described in the internals/contributing.txt document ('Submitting
     14# and maintaining translations' section) and finally re-run
     15# 'django-admin.py makelanginfo' to generate this file.
     16
     17lang_info = {
     18%s
     19}
     20"""
     21
     22def make_language_info(verbosity='1'):
     23    # Need to ensure that the i18n framework is enabled
     24    from django.conf import settings
     25    if settings.configured:
     26        settings.USE_I18N = True
     27    else:
     28        settings.configure(USE_I18N = True)
     29
     30    invoked_for_django = False
     31    if os.path.isdir(os.path.join('conf', 'locale')):
     32        localedir = os.path.abspath(os.path.join('conf', 'locale'))
     33        invoked_for_django = True
     34    elif os.path.isdir('locale'):
     35        localedir = os.path.abspath('locale')
     36    else:
     37        raise CommandError("This command should be run from the django/ directory of the Django source code tree. If you did indeed run it from there, maybe you are just missing the conf/locale?")
     38
     39    target_path = os.path.join(localedir, LANGUAGE_INFO_PY_FILE)
     40
     41    write_ok = True
     42    # On Jython there is no os.access()
     43    if not sys.platform.startswith('java'):
     44        if os.access(target_path, os.F_OK) and not os.access(target_path, os.W_OK):
     45            write_ok = False
     46    if write_ok:
     47        try:
     48            f = open(target_path, 'w')
     49        except IOError:
     50            write_ok = False
     51
     52    if not write_ok:
     53        raise CommandError("Can't open the %s file for writing, make sure you have the permissions to create or replace that file. Aborting the operation." % target_path)
     54
     55    if verbosity >= 1:
     56        print 'Writing language information to %s' % target_path
     57
     58    lang_info = {}
     59    for code, name in settings.LANGUAGES:
     60        translation.activate(code)
     61        lang_info[code] = {
     62            "language_code": code,
     63            "name": name,
     64            "name_local": translation.ugettext(name),
     65            "bidi": code in settings.LANGUAGES_BIDI
     66        }
     67    f.write(TEMPLATE % pformat(lang_info)[1:-1])
     68    f.close()
     69
     70
     71class Command(NoArgsCommand):
     72    help = "Generates the data structures containing metadata about the available languages needed by some Django I18N runtime tools. This is a Django internal maintenance command."
     73
     74    requires_model_validation = False
     75    can_import_settings = False
     76
     77    def handle_noargs(self, **options):
     78        verbosity = int(options.get('verbosity'))
     79        make_language_info(verbosity)
  • django/templatetags/i18n.py

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

    diff -r f700b623b8db -r 07ed5e4869c0 django/utils/translation/__init__.py
    a b  
    1111        'get_partial_date_formats', 'check_for_language', 'to_locale',
    1212        'get_language_from_request', 'templatize', 'ugettext', 'ugettext_lazy',
    1313        'ungettext', 'ungettext_lazy', 'pgettext', 'pgettext_lazy',
    14         'npgettext', 'npgettext_lazy', 'deactivate_all']
     14        'npgettext', 'npgettext_lazy', 'deactivate_all', 'get_language_info']
    1515
    1616# Here be dragons, so a short explanation of the logic won't hurt:
    1717# We are trying to solve two problems: (1) access settings, in particular
     
    117117    """
    118118    return u''.join([force_unicode(s) for s in strings])
    119119string_concat = lazy(_string_concat, unicode)
     120
     121def get_language_info(lang_code):
     122    try:
     123        from django.conf.locale.language_info import lang_info
     124    except ImportError:
     125        raise ImportError("Module django.conf.locale.language_info not found. Run django-admin.py makelanginfo to generate it.")
     126    try:
     127        return lang_info[lang_code]
     128    except KeyError:
     129        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/locale/language_info.py file by running django-admin.py makelanginfo." % lang_code)
  • docs/man/django-admin.1

    diff -r f700b623b8db -r 07ed5e4869c0 docs/man/django-admin.1
    a b  
    6060.B sqlall
    6161for the given app(s) in the current database.
    6262.TP
     63.BI "makelanginfo
     64Extracts metadata about the languages that have translations available in
     65Django by reading their PO message files and stores that information on disk.
     66This command is used by the Django developers to make sure this information is
     67up to date before a release.
     68.TP
    6369.BI "makemessages [" "\-\-locale=LOCALE" "] [" "\-\-domain=DOMAIN" "] [" "\-\-extension=EXTENSION" "] [" "\-\-all" "] [" "\-\-symlinks" "] [" "\-\-ignore=PATTERN" "] [" "\-\-no\-default\-ignore" "] [" "\-\-no\-wrap" "]"
    6470Runs over the entire source tree of the current directory and pulls out all
    6571strings marked for translation. It creates (or updates) a message file in the
     
    99105Prints the custom SQL statements for the given app name(s).
    100106.TP
    101107.BI "sqlflush [" "appname ..." "]"
    102 Prints the SQL statements that would be executed for the "flush" 
     108Prints the SQL statements that would be executed for the "flush"
    103109command.
    104110.TP
    105111.BI "sqlindexes [" "appname ..." "]"
     
    144150Show program's version number and exit.
    145151.TP
    146152.I \-h, \-\-help
    147 Show this help message and exit.
     153Show an usage help message and exit.
    148154.TP
    149155.I \-\-settings=SETTINGS
    150156Python path to settings module, e.g. "myproject.settings.main". If
     
    210216.TP
    211217.I \-a, \-\-all
    212218Process all available locales when using makemessages..SH "ENVIRONMENT"
    213 .TP
    214 .I DJANGO_SETTINGS_MODULE
     219.SH "ENVIRONMENT VARIABLES"
     220
     221.IP DJANGO_SETTINGS_MODULE
    215222In the absence of the
    216223.BI \-\-settings
    217224option, this environment variable defines the settings module to be read.
     
    219226.I \-\-database=DB
    220227Used to specify the database on which a command will operate. If not
    221228specified, this option will default to an alias of "default".
    222 .TP
    223229
    224230.SH "SEE ALSO"
    225231Full descriptions of all these options, with examples, as well as documentation
  • docs/ref/django-admin.txt

    diff -r f700b623b8db -r 07ed5e4869c0 docs/ref/django-admin.txt
    a b  
    401401have specified that you want to load data onto the ``master``
    402402database.
    403403
     404makelanginfo
     405------------
     406
     407.. django-admin:: makelanginfo
     408
     409.. versionadded:: 1.3
     410
     411Extracts metadata about the languages that have translations available in
     412Django (like if they are written bidirectionally, their names as represented
     413both in English and in themselves using the appropiate alphabet, etc.) i.e.
     414those present in the :setting:`LANGUAGES` setting. To achieve that it reads
     415their PO message files, and updates the ``django.conf.locale.language_info``
     416module on disk (for performance reasons) with an appropiate structure
     417containing that information.
     418
     419This command is used by the Django developers to make sure this information is
     420up to date before a release.
     421
    404422makemessages
    405423------------
    406424
  • docs/topics/i18n/internationalization.txt

    diff -r f700b623b8db -r 07ed5e4869c0 docs/topics/i18n/internationalization.txt
    a b  
    379379input is a proper string, then add support for lazy translation objects at the
    380380end.
    381381
     382Localized names of languages
     383============================
     384
     385The ``get_language_info()`` function provides detailed information about
     386languages::
     387
     388    >>> from django.utils.translation import get_language_info
     389    >>> li = get_language_info('de')
     390    >>> print li['name'], li['name_local'], li['bidi']
     391    German Deutsch False
     392
     393The ``name`` and ``name_local`` attributes of the dictionary contain the name of
     394the language in English and in the language itself, respectively.  The ``bidi``
     395attribute is True only for bi-directional languages.
     396
     397The source of the language information is the ``django.conf.locale.language_info``
     398module.  If you add a new translation, you should run the :djadmin:`makelanginfo`
     399Django management command to add the information for the new language to it.
     400
     401Similar access to this information is available for template code. See below.
     402
    382403.. _specifying-translation-strings-in-template-code:
    383404
    384405Specifying translation strings: In template code
     
    518539    translator might translate the string ``"yes,no"`` as ``"ja,nein"``
    519540    (keeping the comma intact).
    520541
     542You can also retrieve information about any of the available languages using
     543provided template tags and filters. To get information about a single language,
     544use the ``{% get_language_info %}`` tag::
     545
     546    {% get_language_info for LANGUAGE_CODE as lang %}
     547    {% get_language_info for "pl" as lang %}
     548
     549You can then access the information::
     550
     551    Language code: {{ lang.language_code }}<br />
     552    Name of language: {{ lang.name_local }}<br />
     553    Name in English: {{ lang.name }}<br />
     554    Bi-directional: {{ lang.bidi }}
     555
     556You can also use the ``{% get_language_info_list %}`` template tag to retrieve
     557information for a list of languages (e.g. active languages as specified in
     558:setting:`LANGUAGES`).  See `The set_language redirect view`_ for an example
     559of how to display a language selector using ``{% get_language_info_list %}``.
     560
     561In addition to :setting:`LANGUAGES` -style nested tuples,
     562``{% get_language_info_list %}`` supports simple lists of language codes.  If
     563you do this in your view:
     564
     565.. code-block:: python
     566
     567    return render_to_response('mytemplate.html',
     568               {'available_languages': ['en', 'es', 'fr']},
     569               RequestContext(request))
     570
     571you can iterate over those languages in the template::
     572
     573  {% get_language_info_list available_languages %}
     574  {% for l in available_languages %} ... {% endfor %}
     575
     576There are also simple filters available for convenience:
     577
     578    * ``{{ LANGUAGE_CODE|language_name }}``  ("German")
     579    * ``{{ LANGUAGE_CODE|language_name_local }}`` ("Deutsch")
     580    * ``{{ LANGUAGE_CODE|bidi }}`` (False)
     581
    521582.. _Django templates: ../templates_python/
    522583
    523584Specifying translation strings: In JavaScript code
     
    579640signs in the URL. This is especially useful if your pages use code from
    580641different apps and this changes often and you don't want to pull in one big
    581642catalog file. As a security measure, these values can only be either
    582 ``django.conf`` or any package from the ``INSTALLED_APPS`` setting.
     643``django.conf`` or any package from the :setting:`INSTALLED_APPS` setting.
    583644
    584645Using the JavaScript translation catalog
    585646----------------------------------------
     
    654715parameter set in request. If session support is enabled, the view
    655716saves the language choice in the user's session. Otherwise, it saves the
    656717language choice in a cookie that is by default named ``django_language``.
    657 (The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.)
     718(The name can be changed through the :setting:`LANGUAGE_COOKIE_NAME` setting.)
    658719
    659720After setting the language choice, Django redirects the user, following this
    660721algorithm:
  • tests/regressiontests/i18n/tests.py

    diff -r f700b623b8db -r 07ed5e4869c0 tests/regressiontests/i18n/tests.py
    a b  
    77
    88from django.conf import settings
    99from django.template import Template, Context
    10 from django.test import TestCase
    1110from django.utils.formats import get_format, date_format, time_format, localize, localize_input, iter_format_modules
     11from django.utils.importlib import import_module
    1212from django.utils.numberformat import format as nformat
    1313from django.utils.safestring import mark_safe, SafeString, SafeUnicode
    14 from django.utils.translation import ugettext, ugettext_lazy, activate, deactivate, gettext_lazy, pgettext, npgettext, to_locale
    15 from django.utils.importlib import import_module
     14from django.utils.translation import (ugettext, ugettext_lazy, activate,
     15        deactivate, gettext_lazy, pgettext, npgettext, to_locale,
     16        get_language_info)
     17from django.utils.unittest import TestCase
    1618
    1719
    1820from forms import I18nForm, SelectDateForm, SelectDateWidget, CompanyForm
     
    708710        c.save()
    709711        c.name = SafeString(u'Iñtërnâtiônàlizætiøn1'.encode('utf-8'))
    710712        c.save()
     713
     714
     715class TestLanguageInfo(TestCase):
     716    def test_localized_language_info(self):
     717        li = get_language_info('de')
     718        self.assertEqual(li['language_code'], 'de')
     719        self.assertEqual(li['name_local'], u'Deutsch')
     720        self.assertEqual(li['name'], 'German')
     721        self.assertEqual(li['bidi'], False)
  • tests/regressiontests/templates/tests.py

    diff -r f700b623b8db -r 07ed5e4869c0 tests/regressiontests/templates/tests.py
    a b  
    11491149            # translation of singular form in russian (#14126)
    11501150            'i18n27': ('{% load i18n %}{% blocktrans count number as counter %}1 result{% plural %}{{ counter }} results{% endblocktrans %}', {'number': 1, 'LANGUAGE_CODE': 'ru'}, u'1 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442'),
    11511151
     1152            # retrieving language information
     1153            'i18n28': ('{% 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'),
     1154            'i18n29': ('{% 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'),
     1155            'i18n30': ('{% 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; '),
     1156            'i18n31': ('{% 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; '),
     1157            'i18n32': ('{% load i18n %}{{ "hu"|language_name }} {{ "hu"|language_name_local }} {{ "hu"|language_bidi }}', {}, u'Hungarian Magyar False'),
     1158            'i18n33': ('{% load i18n %}{{ langcode|language_name }} {{ langcode|language_name_local }} {{ langcode|language_bidi }}', {'langcode': 'nl'}, u'Dutch Nederlands False'),
     1159
    11521160            ### HANDLING OF TEMPLATE_STRING_IF_INVALID ###################################
    11531161
    11541162            'invalidstr01': ('{{ var|default:"Foo" }}', {}, ('Foo','INVALID')),
Back to Top