app/__init__.py
: Flask-Babel实例。en-US
,en-GB
和en-CA
来支持美国、英国和加拿大的英语以示区分。Babel
实例提供了一个localeselector
装饰器。 为每个请求调用装饰器函数以选择用于该请求的语言:app/__init__.py
:选择最匹配的语言。request
对象的属性accept_languages
。 request
对象提供了一个高级接口,用于处理客户端发送的带Accept-Language头部的请求。 该头部指定了客户端语言和区域设置首选项。 该头部的内容可以在浏览器的首选项页面中配置,默认情况下通常从计算机操作系统的语言设置中导入。 大多数人甚至不知道存在这样的设置,但是这是有用的,因为应用可以根据每个语言的权重,提供优选语言的列表。 为了满足你的好奇心,下面是一个复杂的Accept-Languages
头部的例子:da
)是首选语言(默认权重= 1.0),其次是英式英语(en-GB
),其权重为0.8,最后是通用英语(en
),权重为0.7。best_match()
方法中了,该方法将应用提供的语言列表作为参数并返回最佳选择。_()
,仅仅是一个下划线。最简单的情况是源代码中出现的字符串。下面是一个flask()
语句的例子:_()
函数用于原始语言文本(在这种情况下是英文)的封装。 该函数将使用由localeselector
装饰器装饰的选择函数,来为给定客户端查找正确的翻译语言。 _()
函数随后返回翻译后的文本,在本处,翻译后的文本将成为flash()
的参数。flash()
调用:_()
函数的语法支持这种类型的文本,但它基于旧版本的字符串替换语法:lazy_gettext()
的_()
函数的延迟评估的版本:_l()
,以使其看起来与原始的_()
相似。 这个新函数将文本包装在一个特殊的对象中,这个对象会在稍后的字符串使用时触发翻译。_l()
函数进行延迟处理:_()
函数也可以在模板中使用,所以过程非常相似。 例如,参考来自404.html的这段HTML代码:_()
包装文本外,还需要添加{{...}}
来强制_()
进行翻译,而不是将其视为模板中的文本字面量。username
是一个超链接,指向用户的个人主页,而不仅仅是名字,所以我必须使用set
和endset
模板指令创建一个名为user_link
的中间变量 ,然后将其作为参数传递给翻译函数。_()
和_l()
都到位了,你可以使用pybabel
命令将它们提取到一个.pot文件中,该文件代表可移植对象模板。 这是一个文本文件,其中包含所有标记为需要翻译的文本。 这个文件的目的是作为一个模板来为每种语言创建翻译文件。pybabel extract
命令读取-F
选项中给出的配置文件,然后从命令给出的目录(当前目录或本处的.
)扫描与配置的源匹配的目录中的所有代码和模板文件。 默认情况下,pybabel
将查找_()
以作为文本标记,但我也使用了重命名为_l()
的延迟版本,所以我需要用-k _l
来告诉该工具也要查找它 。 -o
选项提供输出文件的名称。es
)开始,所以这样做的命令是:pybabel init
命令将messages.pot文件作为输入,并将语言目录写入-d
选项中指定的目录中,-l
选项中指定的是翻译语言。 我将在app/translations目录中安装所有翻译,因为这是Flask-Babel默认提取翻译文件的地方。 该命令将在该目录内为西班牙数据文件创建一个es子目录。 特别是,将会有一个名为app/translations/es/LC_MESSAGES/messages.po的新文件,是需要翻译的文件路径。_()
和_l()
调用中提取的字符串列表。 对每个文本,都会展示其在应用中的引用位置。 然后,msgid
行包含原始语言的文本,后面的msgstr
行包含一个空字符串。 这些空字符串需要被编辑,以使目标语言中的文本内容被填充。pybabel compile
命令,如下所示:localeselector
函数始终返回一种语言来强制实现。 对西班牙语,你可以这样做:app/__init__.py
:选择最佳语言。es
的localeselector
函数,将使所有文本在使用该应用时显示为西班牙文。_()
包装器时错过了一些文本,则会出现另一种常见情况。 在这种情况下,你会发现你错过的那些文本将保持为英文,因为Flask-Babel对他们一无所知。 当你检测到这种情况时,会想要将其用_()
或_l()
包装,然后执行更新过程,这包括两个步骤:extract
命令与我之前执行的命令相同,但现在它会生成messages.pot的新版本,其中包含所有以前的文本以及最近用_()
或_l()
包装的文本。 update
调用采用新的messages.pot
文件并将其合并到与项目相关的所有messages.po文件中。 这将是一个智能合并,其中任何现有的文本将被单独保留,而只有在messages.pot中添加或删除的条目才会受到影响。get_locale()
函数返回给定请求的语言和语言环境,所以我要做的就是将语言环境添加到g
对象,以便我可以从基础模板中访问它:get_locale()
函数返回一个本地语言对象,但我只想获得语言代码,可以通过将该对象转换为字符串来获取语言代码。 现在我有了g.locale
,可以从基础模板中访问它,并以正确的语言配置moment.js:flask
命令集成的自定义命令。 到目前为止,你已经看到我使用Flask-Migrate扩展提供的flask run
、flask shell
和几个flask db
子命令。 将应用特定的命令添加到flask
实际上也很容易。 所以我现在要做的就是创建一些简单的命令,并用这个应用特有的参数触发pybabel
命令。 我要添加的命令是:flask translate init LANG
用于添加新语言flask translate update
用于更新所有语言存储库flask translate compile
用于编译所有语言存储库babel export
步骤不会设置为一个命令,因为生成messages.pot文件始终是运行init
或update
命令的先决条件,因此这些命令的执行将会生成翻译模板文件作为临时文件。translate
这样的命令是几个子命令的根,它们是通过app.cli.group()
装饰器创建的。 我将把这些命令放在一个名为app/cli.py的新模块中:update
和compile
很容易实现,因为它们没有任何参数:translate
父函数派生的。 这似乎令人困惑,因为translate()
是一个函数,但它是Click构建命令组的标准方式。 与translate()
函数相同,这些函数的文档字符串在--help
输出中用作帮助消息。RuntimeError
,这会导致脚本停止。 update()
函数在同一个命令中结合了extract
和update
步骤,如果一切都成功的话,它会在更新完成后删除messages.pot文件,因为当再次需要这个文件时,可以很容易地重新生成 。init
命令将新的语言代码作为参数。 这是其执行流程:@click.argument
装饰器来定义语言代码。 Click将命令中提供的值作为参数传递给处理函数,然后将该参数并入到init
命令中。flask --help
将列出translate
命令作为选项。 flask translate --help
将显示我定义的三个子命令:_()
和_l()
语言标记后更新所有语言: