在 jinja 模板中切换语言

Posted

技术标签:

【中文标题】在 jinja 模板中切换语言【英文标题】:Switch language in jinja template 【发布时间】:2017-12-06 12:23:10 【问题描述】:

我正在将一个多语言 Django 应用程序从 Django 的模板引擎迁移到 Jinja2。在模板中,我目前使用Django's language template tag 逐个对象切换活动语言,即:

% load i18n %
<h1>% trans 'Page title' %</h1>
<ul>
% for obj in object_list %
% language obj.language_code %
    <li><a href=" obj.get_absolute_url ">% trans 'view' %:  obj.title </a>
% endlanguage %
% endfor %
</ul>

我们还使用i18n_patterns,因此每个对象的网址也是特定于语言的。

我不知道如何将其转换为 Jinja。我无法使用 Django 的 i18n 模板标签,也找不到与 Jinja 等效的东西。

我还在查看 Babel 以帮助从模板中提取消息。因此,首选与 Babel 以及 Django 一起使用的解决方案。

【问题讨论】:

你看到它是如何在django-jinja app 中实现的了吗? 我假设你的意思是this django-jinja?我在那里找不到language 模板标签的实现。 你试过这个语法吗? jinja.pocoo.org/docs/2.9/templates/#i18n 翻译位不是问题。我正在寻找一种在模板呈现期间在消息目录的活动语言之间切换的方法。所以模板的一部分使用即德语翻译,而同一模板中的某些部分使用英文翻译。 【参考方案1】:

事实证明,通过编写自定义 jinja2 扩展来实现这一点相当简单(我基于 example in the jinja2 docs):

from django.utils import translation
from jinja2.ext import Extension, nodes

class LanguageExtension(Extension):
    tags = 'language'

    def parse(self, parser):
        lineno = next(parser.stream).lineno
        # Parse the language code argument
        args = [parser.parse_expression()]
        # Parse everything between the start and end tag:
        body = parser.parse_statements(['name:endlanguage'], drop_needle=True)
        # Call the _switch_language method with the given language code and body
        return nodes.CallBlock(self.call_method('_switch_language', args), [], [], body).set_lineno(lineno)

    def _switch_language(self, language_code, caller):
        with translation.override(language_code):
            # Temporarily override the active language and render the body
            output = caller()
        return output

# Add jinja2's i18n extension
env.add_extension('jinja2.ext.i18n')
# Install Django's translation module as the gettext provider
env.install_gettext_translations(translation, newstyle=True)
# Add the language extension to the jinja2 environment
environment.add_extension(LanguageExtension)

有了这个扩展,切换活跃的翻译语言就和你在 Django 中的操作一样:

% language 'en' % _('Hello World')% endlanguage %

唯一需要注意的是,当使用 Django 作为 gettext 提供程序并使用 Babel 作为消息提取器时,告诉 Babel 在运行 init/update/compile_catalog 时将消息域设置为 django 很重要。

【讨论】:

【参考方案2】:

我有这个代码 sn-p 在 jinja2 中切换语言。

def change_lang(request, lang=None, *args, **kwargs):
"""
Get active page's url by a specified language, it activates 
Usage:  change_lang(request, 'en') 
"""

path = request.path
url_parts = resolve(path)

url = path
cur_language = get_language()
try:
    activate(lang)
    url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
finally:
    activate(cur_language)

return "%s" % url

在 settings.py 中

TEMPLATES = [

    "BACKEND": "django_jinja.backend.Jinja2",
    'DIRS': [
        os.path.join(BASE_DIR, 'templates/jinja'),
    ],
    "OPTIONS": 
        # Match the template names ending in .html but not the ones in the admin folder.
        "match_extension": ".html",
        "match_regex": r"^(?!admin/).*",
        "newstyle_gettext": True,
        "extensions": [
            "jinja2.ext.do",
            "jinja2.ext.loopcontrols",
            "jinja2.ext.with_",
            "jinja2.ext.i18n",
            "jinja2.ext.autoescape",
            "django_jinja.builtins.extensions.CsrfExtension",
            "django_jinja.builtins.extensions.CacheExtension",
            "django_jinja.builtins.extensions.TimezoneExtension",
            "django_jinja.builtins.extensions.UrlsExtension",
            "django_jinja.builtins.extensions.StaticFilesExtension",
            "django_jinja.builtins.extensions.DjangoFiltersExtension",
        ],
        'globals': 
            'change_lang': 'drug.utils.change_lang'
        ,
        "bytecode_cache": 
            "name": "default",
            "backend": "django_jinja.cache.BytecodeCache",
            "enabled": False,
        ,
        "autoescape": True,
        "auto_reload": DEBUG,
        "translation_engine": "django.utils.translation",
        "context_processors": [
            "dashboard.context_processors.auth",
            # "django.template.context_processors.debug",
            "django.template.context_processors.i18n",
            # "django.template.context_processors.media",
            # "django.template.context_processors.static",
            # "django.template.context_processors.tz",
            "django.contrib.messages.context_processors.messages",
        ]
    
,

    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [
        os.path.join(BASE_DIR, 'templates'),
    ],
    'APP_DIRS': True,
    'OPTIONS': 
        'context_processors': [
            'django.template.context_processors.debug',
            'django.template.context_processors.request',
            'django.contrib.auth.context_processors.auth',
            'django.contrib.messages.context_processors.messages',
        ]
    ,
,]

然后您可以在模板中的任何位置使用它 _('Hello World')

【讨论】:

以上是关于在 jinja 模板中切换语言的主要内容,如果未能解决你的问题,请参考以下文章

Flask Jinja2模板语言

jinja模板语言

理解 JINJA 模板

Flask中的模板语言Jinja2及render_template

3,Flask 中的模板语言 Jinja2 及 render_template 的深度用法

第四篇 Flask 中的模板语言 Jinja2 及 render_template 的深度用法