6

我对 Python 和 Flask(使用 Jinja2 作为模板引擎)都很陌生,我不确定我的做法是否正确。我正在使用 Flask-Babel 扩展为我的 Web 应用程序添加 i18n 支持。我想从我的 js 代码中获取本地化字符串,例如:

var helloWorld = gettext('Hello, world');
console.log(helloWorld); //should log a localized hello world message

为此,我配置了 babel (babel.cfg):

[python: **/**.py]
[jinja2: **/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_
[javascript: **/**.js]
encoding = utf-8

它的初始化是(为简单起见省略了导入):

#main Flask app
app = Flask(__name__)

#localization
babel = Babel(app)

LANGUAGES = {
    'ca': 'Catalan',
    'en': 'English',
    'de': 'Deutsch',
    'es': 'Español',
    'fi': 'Finnish',
    'it': 'Italian'
}

@babel.localeselector
def get_locale():
    return request.accept_languages.best_match(LANGUAGES.keys())

#some more stuff...

Babel 在构建 POT/PO 语言文件时识别该字符串,但由于未定义 gettext 函数,因此我似乎无法从 js 代码访问这些本地化字符串。Jinja2 似乎忽略了这部分。

有什么提示吗?

4

2 回答 2

2

我终于找到了解决方案,尽管我不确定这是要走的路。这个想法是将 javascript 代码包装在一个 html 模板中,该模板在呈现之前由 Jinja2 解释,并应用自定义 Jinja2 过滤器来消除一些小问题。我试图单独保留 js 文件,但它不起作用。

似乎 gettext 函数可以这样使用:

var helloWorld = {{gettext('Hello, world')}};

但是,没有插入引号,因此 js 解释器会抛出错误:

var helloWorld = Hello, world;

这就是我最终应用自定义过滤器的原因。一个工作示例如下。

hello_world.html:

<script type="text/javascript">
   var x = {{gettext('Hello, world')|generate_string|safe}};
   console.log(x);    //logs the localized hello world message
</script>

应用程序.py:

#Jinja2 filters
from jinja2 import evalcontextfilter, Markup

#Mind the hack! Babel does not work well within js code
@app.template_filter()
@evalcontextfilter
def generate_string(eval_ctx, localized_value):
    if localized_value is None:
        return ""
    else:
        return Markup("\"" + localized_value + "\"").unescape()

希望这可以帮助!

于 2014-03-13T16:23:54.397 回答
0

在呈现的 JavaScript 中提供翻译有点脆弱。另外,我通常不使用 Jinja 生成 JavaScript,因为它使用相同类型的括号,并且在被滥用时很容易变成一团糟(动态数据和静态 JavaScript 总是可能的)。

另一种轻量级方法是使用相同的 JSON 技巧,但使用数据属性:

<div id="view-i18n" data-i18n='{{ view_i18n|tojson }}'> ... </div>

(注意:单引号!)

但它也适用于有限数量的翻译。

也许,最可靠的方法是在 JavaScript 中使用与 Flask 应用程序中相同的翻译。

借助一个名为的实用程序pojson,可以将 po-files 转换为 json(参见https://github.com/ZeWaren/flask-i18n-example示例)作为构建过程的一部分(例如,就在制作mo-文件)。翻译可以很容易地添加到一些足够独特的全局命名空间变量中,方法是在pojsonwith的输出之前添加var some_unique_name =访问它。或者将文件static放入特定于语言环境的文件(例如static/view-es.jsonstatic/view-fr.json等)并通过ajax调用获取它。

不过有些事情要考虑。如果您真的想让 JSON 更小,您可能需要通过控制 babel 提取选项将您的翻译域分解为单独的 Python 和 Javascript。此外,在 Javascript 中包含所有翻译字符串具有安全性。也许,您不想公开某些只有管理员才能看到对其他类别用户开放的短语。但是不同的访问级别需要更多的翻译域。此外,可能需要删除标题信息,以防止泄露翻译者的电子邮件等。当然,这会在一定程度上使构建过程复杂化,但是随着时间的推移,JavaScript 端需要的翻译越多,自动化就越能得到回报。

于 2018-08-11T15:36:06.700 回答