一文搞懂利用Flask-Babel实现网页多语言翻译切换
前言
课程设计总是Flask开发。。网站经常要求双语翻译,开发中英文两份html自然是最麻烦的方法,而babel库的使用就是一个熟练工。本文将详细总结使用flask_babel库进行多语种切换的方法,以英文切换成中文为例。
一、安装flask_babel
我使用的编译器是pycharm, 在虚拟环境终端pip install flask_babel,稍等片刻即下载成功。
二、在flask项目应用babel
这里用一个常见的例子,以下代码出自app.py,即flask项目的启动文件。
from flask import Flask, render_template, requestfrom flask_babel import Babel, gettext as _app = Flask(__name__)
app.config['BABEL_DEFAULT_LOCALE'] = 'en'
app.config['BABEL_DEFAULT_TIMEZONE'] = 'UTC'babel = Babel(app)@babel.localeselector
def get_locale():return request.accept_languages.best_match(['zh', 'en'])@app.route('/')
def hello():day = _("Saturday")return render_template('index.html', day=day)if __name__ == '__main__':app.debug = Trueapp.run()
下面分步骤详细解释:
- 从 flask_babel 引入 Babel 模块和 gettext 函数,由于 gettext 函数被引用的次数太多了,为了方便手写,一般将其重命名为 “_”
- 设置babel默认的地区语言和区时(可不设置)
app.config['BABEL_DEFAULT_LOCALE'] = 'en' app.config['BABEL_DEFAULT_TIMEZONE'] = 'UTC'
- 初始化 babel 应用
babel = Babel(app)
- 定义一个函数来实现地区语言选择
使用babel库自带的@babel.localeselector来修饰函数,此函数会在所有路由函数运行前执行。 request.accept_languages.best_match([‘zh’, ‘en’])函数会调用当前浏览器的默认语言,然后将其设置为当前语言。例如下图的情况,此函数返回值为“zh_CN”
三、生成翻译模板
- 把所有需要翻译的html中的文字用{{ _( " 翻译文字") }}框起来,别忘前面的下划线
这是一项十分繁琐的工作,在pycharm可以先用鼠标选中待翻译文字,然后按住shift的同时按两下"{"(左花括号),再按一下"("(左括号),再按一下"(左引号),最后再左括号前面加下划线即可。 - 在 app.py 的同级目录创建一个叫 babel.cfg 的文件,内容如下
[python: **.py] [jinja2: **/templates/**.html] extensions=jinja2.ext.autoescape,jinja2.ext.with_
目录可以根据实际情况修改,例如**/templates/news/**只翻译news里的所有html.
- 在终端执行输入以下代码生成翻译模板,即提取所有框起来的文字
pybabel extract -F babel.cfg -o messages.pot .
执行完后会在app.py同级目录下产生一个新文件messages.pot,其中含有所有需要翻译的文字空白模板,此文件不需要任何操作!
- 在终端输入一下代码, 创建中文翻译
pybabel init -i messages.pot -d translations -l zh_CN
此时会在app.py同级目录产生一个新的translation文件夹,结构如下。LC开头的文件夹下还有一个名为message.po的文件。
- 手动添加翻译
是的你没有看错!还是需要手动翻译!
在message.po中,msgid对应的是提取出的待翻译的词,msgstr是需要我们手动填入的翻译结果。 我们需要做的就是把所有词对应翻译好。
- 在终端执行以下命令,编译翻译结果
pybabel compile -d translations
执行完后会生成一个messages.mo的编译文件,此文件生成即代表翻译结束!
四、运行flask项目
大功告成,此时运行flask项目,虽然我们默认的babel地区语言是‘en’英文,但get_locale函数会获取到我们的浏览器推荐语言,返回"zh_CN",所以页面将会呈现中文翻译。
五、翻译的更新或修改
很简单,如果需要增加翻译,首先去相应的html用之前相同的方法把需要翻译的内容框起来。然后重新执行一次翻译模板提取语句:
pybabel extract -F babel.cfg -o messages.pot .
message.pot文件会更新, 此时再执行一次翻译更新语句:
pybabel update -i messages.pot -d translations
此命令可以将之前的翻译合并到新的文件中,此时translation文件夹中的messages.po文件会更新,在其中将需要添加的翻译补充上,或是将需要修改的翻译修改即可。
最后再次执行编译语句,更新完成!
pybabel compile -d translations
六、翻译套路总结
固定套路:flask_babel配置好以后
- pybabel extract -F babel.cfg -o messages.pot . 提取翻译模板
- pybabel init -i messages.pot -d translations -l zh 生成需要翻译成的语言模板
- 在对应文件夹中修改messages.po 添加相应翻译
- pybabel compile -d translations 编译生成翻译文件
修改翻译套路 (如果没有添加 1、2、3可省略):
- 添加或改变html中框起来的文字
- pybabel extract -F babel.cfg -o messages.pot . 重新提取翻译模板
- pybabel update -i messages.pot -d translations 合并更新翻译
- 在对应文件夹中编辑messages.po 添加或修改相应翻译
- pybabel compile -d translations 重新编译生成翻译文件
拓展:在页面中实现手动切换语言
这里简单介绍我采用的思路,我们的页面右上角有一个select下拉框(如下),用于点击切换语言。在某一页点击后,整个页面的语言就会切换,已中英切换为例。
首先给select下选框添加一个id,方便定位
之后修改get_locale函数并且新建一个函数set_locale ,代码如下
set_locale函数是点击切换语言后,利用ajax调用的函数。它会首先获取前端传递过来的语言,然后判断语言,利用response给页面设置一个cookie,用来标识当前页面应该翻译成的语言。
get_locale函数中获取前面设置的cookie值,然后返回cookie值中的语言,zh_CN或en,也就是设置当前babel的语言
@babel.localeselector def get_locale():cookie = request.cookies.get('locale')if cookie in ['zh_CN', 'en']:return cookiereturn request.accept_languages.best_match(app.config.get('BABEL_DEFAULT_LOCALE'))# 没有cookie时,默认为 en@app.route("/set_locale") def set_locale():lang = request.args.get("language")response = make_response(jsonify(message=lang))if lang == 'English':refresh()response.set_cookie('locale', 'en')return responseif lang == '汉语':refresh()response.set_cookie('locale', 'zh_CN')return responsereturn jsonify({"data": "success"})
js代码,设置select下拉框的change函数,一旦当前选择改变(切换语言),就用ajax调用上面的set_locale函数。
<script>$("#language_switch").change(function(){$.ajax({url: '/set_locale',type: 'GET',data:{"language": $(this).val()},success: function (ret) {location.reload();}})}); </script>
下拉框改变后,右上角显示的语言也需要改变。例如点击汉语,右上角就需要一直显示汉语。一般需要用js来实现动态改变。这里有个小技巧:可以将English和汉语都用{{ _(" ") }}框起来进行翻译,English翻译成汉语,汉语翻译成中文,这样就实现了动态改变!
部分效果图
踩坑总结
在更新翻译时,有的词汇框起来后,提取后但并没有在messages.po中发现,一般是因为#, fuzzy关键字。此关键字我的理解是它会判断出一些重复的字词,然后将其按照你之前的翻译进行自动翻译。但有时会不准确(经常。。) 如以下图片中,原文和自动翻译不符。删掉这一行(红色框起来的部分)即可。
课设开发时需要使用git,我为了防止代码在merge时出问题,一般会将整个项目文件夹复制备份。这种情况下,我有时会遇到执行pybabel extract -F babel.cfg -o messages.pot . 提取命令没有反应的情况。多次观察后发现,我在源项目中执行这个语句,结果在备份文件夹中新建了messages.po文件。目前为止原因,可能是它会自动寻找路径,但由于我两份项目文件夹是复制,它就找错了根目录。
遇到特殊符号,例如原文或翻译中带有单引号’或双引号"等,要用转义字符反斜杠\进行转义,否则会报错。
大段文字直接框选即可,不用担心行间空格,没有影响。
字符等建议不框起来,只框纯文字部分,这样后面翻译也好操作。例如“单位:$”,只需按照{{ _(“单位”) }}操作即可。
极少数情况下设置好zh_CN语言页面却没有翻译,那么可以将上面的zh_CN改成zh_Hans_CN用同样的方法生成文件夹进行翻译。但据我观察zh_CN生成的messages.po文件中自动标识的语言也是zh_Hans_CN,所以此问题可能一般不会遇见。
最后推荐另一篇好文Flask-Babel实现国际化,欢迎大家交流指正!
一文搞懂利用Flask-Babel实现网页多语言翻译切换相关推荐
- 一文搞懂HMM(隐马尔可夫模型)-Viterbi algorithm
***一文搞懂HMM(隐马尔可夫模型)*** 简单来说,熵是表示物质系统状态的一种度量,用它老表征系统的无序程度.熵越大,系统越无序,意味着系统结构和运动的不确定和无规则:反之,,熵越小,系统越有序, ...
- 一文搞懂AWS EC2, IGW, RT, NAT, SG 基础篇下
B站实操视频更新 跟着拉面学习AWS--EC2, IGW, RT, NAT, SG 简介 长文多图预警,看结论可以直接拖到"总结"部分 本文承接上一篇文章介绍以下 AWS 基础概念 ...
- 一文搞懂 Traefik2.1 的使用
原文链接:一文搞懂 Traefik2.1 的使用 一文搞懂 Traefik2.1 的使用 核心概念 安装 ACME 中间件 灰度发布 流量复制 TCP 简单 TCP 服务 带 TLS 证书的 TCP ...
- 一文搞懂 Cocos Creator 3.0 坐标转换原理
一文搞懂 Cocos Creator 3.0 坐标转换原理 屏幕坐标 UI 触点坐标 UI 多分辨率适配方案 UI 触点获取 不同坐标之间的转换 屏幕坐标与 3D 节点世界坐标互转 3D 节点之间的坐 ...
- 一文搞懂BN、LN、IN、GN的区别
一文搞懂BN.LN.IN.GN的区别 批归一化(BN)已经成为许多先进深度学习模型的重要组成部分,特别是在计算机视觉领域.它通过批处理中计算的平均值和方差来规范化层输入,因此得名.要使BN工作,批大小 ...
- 一文搞懂如何使用ArcGIS API for Python训练深度学习模型
一文搞懂如何使用ArcGIS API for Python训练深度学习模型 文章目录 一文搞懂如何使用ArcGIS API for Python训练深度学习模型 写在前面 一.ArcGIS API f ...
- 网络知识扫盲,一文搞懂 DNS
在找工作面试的过程中,面试官非常喜欢考察基础知识,除了数据结构与算法之外,网络知识也是一个非常重要的考察对象. 而网络知识,通常是很抽象,不容易理解的,有很多同学就在这里裁了跟头.为了更好地通过面试, ...
- 【显卡】一文搞懂显卡
[显卡]一文搞懂显卡 文章目录 [显卡]一文搞懂显卡 1. 前言介绍 1.1 CPU和显卡的区别 1.1.1 作用不同 1.1.2 结构不同 1.1.3 应用场景不同 1.2 三个著名的显卡公司 2. ...
- 一文搞懂极大似然估计
极大似然估计,通俗理解来说,就是利用已知的样本结果信息,反推最具有可能(最大概率)导致这些样本结果出现的模型参数值! 换句话说,极大似然估计提供了一种给定观察数据来评估模型参数的方法,即:" ...
- 计算机科学与技术要机械硬盘,机械硬盘避坑大法:一文搞懂PMR和SMR有什么区别...
原标题:机械硬盘避坑大法:一文搞懂PMR和SMR有什么区别 存储市场上一直存在固态硬盘(SSD)和机械硬盘(HDD)的竞争.论综合性能,SSD远高于HDD,是大家选购存储设备时的理想选择.早期消费级S ...
最新文章
- 酷狗kuGoo 2007 和 flex有冲突
- 实现BFS之“营救”
- 排序算法有哪些_超强整理,科班算法岗的秋招之路
- android 弹窗in,Android监听程序处于INACTIVITY(未操作状态)时间并作出相应的操作
- zabbix数据库分表的实现
- fat32文件系统详细介绍_文件系统介绍
- 阿里云免费证书SSL下载及安装
- 使用Laravel和Vue.js2.5进行服务器端渲染
- 模拟一个简单的购房商贷月供计算器,按照总利息和每月还款金额
- html桌面共享文件夹,win7共享文件夹在哪? win7和win10怎么共享文件夹
- BaiduMap SDK-Location自定义定位图标
- manjaro xfce 环境配置
- 《和平精英》新模式,玩法竟跟《使命召唤》和《王牌战士》类似?
- Nature子刊:教你零基础开展微生物组数据分析和可视化
- WormHole是一个简单、易用的api管理平台,支持dubbo服务调用
- 优化问题-目标函数确定
- 如何使用eclipse开发单片机程序
- git删除未监视的文件(untracked files)命令用法
- classList属性配合内置方法add()、remove()、toggle(),添加或删除某个类,以此改变CSS样式
- java 继承、super、this、抽象类