diff --git a/django/core/context_processors.py b/django/core/context_processors.py
index a5f29df..d812ded 100644
|
a
|
b
|
RequestContext.
|
| 10 | 10 | from django.conf import settings |
| 11 | 11 | from django.middleware.csrf import get_token |
| 12 | 12 | from django.utils.functional import lazy |
| | 13 | from django.utils.translation import get_language_names |
| 13 | 14 | |
| 14 | 15 | def auth(request): |
| 15 | 16 | """ |
| … |
… |
def debug(request):
|
| 57 | 58 | return context_extras |
| 58 | 59 | |
| 59 | 60 | def i18n(request): |
| | 61 | """ Returns context variables helpful for i18n and l10n """ |
| 60 | 62 | from django.utils import translation |
| 61 | | |
| 62 | 63 | context_extras = {} |
| 63 | | context_extras['LANGUAGES'] = settings.LANGUAGES |
| | 64 | context_extras['LANGUAGES'] = get_language_names() |
| 64 | 65 | context_extras['LANGUAGE_CODE'] = translation.get_language() |
| 65 | 66 | context_extras['LANGUAGE_BIDI'] = translation.get_language_bidi() |
| 66 | | |
| 67 | 67 | return context_extras |
| 68 | 68 | |
| 69 | 69 | def media(request): |
diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py
index 10ac900..346e413 100644
|
a
|
b
|
from django.template import TemplateSyntaxError, TokenParser, Library
|
| 5 | 5 | from django.template import TOKEN_TEXT, TOKEN_VAR |
| 6 | 6 | from django.utils import translation |
| 7 | 7 | from django.utils.encoding import force_unicode |
| | 8 | from django.utils.translation import get_language_names |
| 8 | 9 | |
| 9 | 10 | register = Library() |
| 10 | 11 | |
| … |
… |
class GetAvailableLanguagesNode(Node):
|
| 14 | 15 | |
| 15 | 16 | def render(self, context): |
| 16 | 17 | from django.conf import settings |
| 17 | | context[self.variable] = [(k, translation.ugettext(v)) for k, v in settings.LANGUAGES] |
| | 18 | context[self.variable] = get_language_names() |
| 18 | 19 | return '' |
| 19 | 20 | |
| 20 | 21 | class GetCurrentLanguageNode(Node): |
diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py
index 6d81726..c64195b 100644
|
a
|
b
|
__all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext',
|
| 10 | 10 | 'get_language', 'get_language_bidi', 'get_date_formats', |
| 11 | 11 | 'get_partial_date_formats', 'check_for_language', 'to_locale', |
| 12 | 12 | 'get_language_from_request', 'templatize', 'ugettext', 'ugettext_lazy', |
| 13 | | 'ungettext', 'deactivate_all'] |
| | 13 | 'ungettext', 'deactivate_all', 'get_language_names'] |
| 14 | 14 | |
| 15 | 15 | # Here be dragons, so a short explanation of the logic won't hurt: |
| 16 | 16 | # We are trying to solve two problems: (1) access settings, in particular |
| … |
… |
def templatize(src):
|
| 95 | 95 | def deactivate_all(): |
| 96 | 96 | return real_deactivate_all() |
| 97 | 97 | |
| | 98 | def get_language_names(): |
| | 99 | return real_get_language_names() |
| | 100 | |
| 98 | 101 | def _string_concat(*strings): |
| 99 | 102 | """ |
| 100 | 103 | Lazy variant of string concatenation, needed for translations that are |
diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index b528f8e..4fdd775 100644
|
a
|
b
|
_active = {}
|
| 20 | 20 | # The default translation is based on the settings file. |
| 21 | 21 | _default = None |
| 22 | 22 | |
| | 23 | # The translation of LANGUAGES is cached |
| | 24 | _language_names = False |
| | 25 | |
| 23 | 26 | # This is a cache for normalized accept-header languages to prevent multiple |
| 24 | 27 | # file lookups when checking the same locale on repeated requests. |
| 25 | 28 | _accepted = {} |
| … |
… |
def get_partial_date_formats():
|
| 547 | 550 | month_day_format = settings.MONTH_DAY_FORMAT |
| 548 | 551 | return year_month_format, month_day_format |
| 549 | 552 | |
| | 553 | def get_language_names(): |
| | 554 | """ |
| | 555 | Returns an array of language names where each language translated |
| | 556 | to its native language. |
| | 557 | """ |
| | 558 | from django.conf import settings |
| | 559 | global _language_names |
| | 560 | if _language_names: |
| | 561 | return _language_names |
| | 562 | else: |
| | 563 | languages = [] |
| | 564 | current_language = get_language() |
| | 565 | for lang, english_name in settings.LANGUAGES: |
| | 566 | activate(lang) |
| | 567 | languages.append((lang, ugettext(english_name))) |
| | 568 | _language_names = languages |
| | 569 | if current_language != get_language(): |
| | 570 | activate(current_language) |
| | 571 | ''' |
| | 572 | deactivate() |
| | 573 | for lang, english_name in settings.LANGUAGES: |
| | 574 | activate(lang) |
| | 575 | languages.append((lang, ugettext(english_name))) |
| | 576 | deactivate() |
| | 577 | _language_names = languages |
| | 578 | ''' |
| | 579 | return languages |
diff --git a/docs/topics/i18n/deployment.txt b/docs/topics/i18n/deployment.txt
index 1a4f5fa..f2bf15a 100644
|
a
|
b
|
Notes:
|
| 116 | 116 | set ``LANGUAGES`` to a list of languages. For example:: |
| 117 | 117 | |
| 118 | 118 | LANGUAGES = ( |
| 119 | | ('de', _('German')), |
| 120 | | ('en', _('English')), |
| | 119 | ('de', 'German'), |
| | 120 | ('en', 'English'), |
| 121 | 121 | ) |
| 122 | 122 | |
| 123 | 123 | This example restricts languages that are available for automatic |
| 124 | 124 | selection to German and English (and any sublanguage, like de-ch or |
| 125 | 125 | en-us). |
| 126 | 126 | |
| 127 | | * If you define a custom ``LANGUAGES`` setting, as explained in the |
| 128 | | previous bullet, it's OK to mark the languages as translation strings |
| 129 | | -- but use a "dummy" ``ugettext()`` function, not the one in |
| 130 | | ``django.utils.translation``. You should *never* import |
| 131 | | ``django.utils.translation`` from within your settings file, because that |
| 132 | | module in itself depends on the settings, and that would cause a circular |
| 133 | | import. |
| 134 | | |
| 135 | | The solution is to use a "dummy" ``ugettext()`` function. Here's a sample |
| 136 | | settings file:: |
| 137 | | |
| 138 | | ugettext = lambda s: s |
| 139 | | |
| 140 | | LANGUAGES = ( |
| 141 | | ('de', ugettext('German')), |
| 142 | | ('en', ugettext('English')), |
| 143 | | ) |
| 144 | | |
| 145 | | With this arrangement, ``django-admin.py makemessages`` will still find |
| 146 | | and mark these strings for translation, but the translation won't happen |
| 147 | | at runtime -- so you'll have to remember to wrap the languages in the |
| 148 | | *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime. |
| 149 | | |
| 150 | 127 | * The ``LocaleMiddleware`` can only select languages for which there is a |
| 151 | 128 | Django-provided base translation. If you want to provide translations |
| 152 | 129 | for your application that aren't already in the set of translations |
diff --git a/docs/topics/i18n/internationalization.txt b/docs/topics/i18n/internationalization.txt
index 7ae8d18..b604df7 100644
|
a
|
b
|
Other tags
|
| 429 | 429 | Each ``RequestContext`` has access to three translation-specific variables: |
| 430 | 430 | |
| 431 | 431 | * ``LANGUAGES`` is a list of tuples in which the first element is the |
| 432 | | :term:`language code` and the second is the language name (translated into |
| 433 | | the currently active locale). |
| | 432 | :term:`language code` and the second is the language name in English |
| | 433 | (magically translated into its native language). |
| 434 | 434 | |
| 435 | 435 | * ``LANGUAGE_CODE`` is the current user's preferred language, as a string. |
| 436 | 436 | Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`.) |
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index 5902e8d..6b37277 100644
|
a
|
b
|
class Templates(unittest.TestCase):
|
| 391 | 391 | output = self.render(test_template, vals) |
| 392 | 392 | end = datetime.now() |
| 393 | 393 | if end-start > timedelta(seconds=0.2): |
| 394 | | failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Took too long to render test" % (is_cached, invalid_str, name)) |
| | 394 | # give it another try allowing caching to spee things up |
| | 395 | start = datetime.now() |
| | 396 | output = self.render(test_template, vals) |
| | 397 | end = datetime.now() |
| | 398 | if end-start > timedelta(seconds=0.2): |
| | 399 | failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Took too long to render test" % (is_cached, invalid_str, name)) |
| 395 | 400 | except ContextStackException: |
| 396 | 401 | failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Context stack was left imbalanced" % (is_cached, invalid_str, name)) |
| 397 | 402 | continue |
| … |
… |
class Templates(unittest.TestCase):
|
| 1082 | 1087 | 'i18n11': ('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'), |
| 1083 | 1088 | |
| 1084 | 1089 | # usage of the get_available_languages tag |
| 1085 | | 'i18n12': ('{% load i18n %}{% get_available_languages as langs %}{% for lang in langs %}{% ifequal lang.0 "de" %}{{ lang.0 }}{% endifequal %}{% endfor %}', {}, 'de'), |
| | 1090 | 'i18n12': ('{% load i18n %}{% get_available_languages as langs %}{% for lang in langs %}{% ifequal lang.0 "de" %}{{ lang.1 }}{% endifequal %}{% endfor %}', {}, u'Deutsch'), |
| 1086 | 1091 | |
| 1087 | 1092 | # translation of constant strings |
| 1088 | 1093 | 'i18n13': ('{{ _("Password") }}', {'LANGUAGE_CODE': 'de'}, 'Passwort'), |