项目背景:
web项目中,无论是给端上API还是服务API,往往都会设置统一格式返回,全局异常拦截等等功能。 统一格式例如
{
"code": 100010,
"message": "tenant is not exist",
"data": ""
}
国际化主要针对的是messages参数实现多语言化,下面我们将手把手的实现这个功能。
网上的坑
主要是随着包的升级出现的不兼容问题。
flask国际化实现是通过插件flask-babel包,flask-babel包从2.0.0 到3.0.0大版本升级
去掉了localeselector方法
优化成了在初始化Babel的时候传入select_locale参数
如果你使用的最新的flask-babel,
# 设置语言选择逻辑
@babel.localeselector
def get_locale():
# 从 URL 参数获取语言选择,如果没有提供则使用浏览器默认语言
return request.args.get('lang', request.accept_languages.best_match(app.config['LANGUAGES']))
上面方法localeselector方法提示不存在。
实现国际化完整流程
1、创建Flask项目
项目结构
babel-demo/
│
├── app.py # Flask 应用主文件
├── config.py # 配置文件
└── templates/
└── index.html # 模板文件
2. 安装依赖
首先,确保你安装了 Flask
和最新版的 Flask-Babel
:
pip install Flask Flask-Babel
3. 配置 Flask 和 Flask-Babel
在 config.py
中设置配置参数:
# config.py
class Config:
LANGUAGES = ['en', 'zh'] # 支持的语言列表
BABEL_DEFAULT_LOCALE = 'en' # 默认语言
BABEL_TRANSLATION_DIRECTORIES = 'translations' # 翻译文件目录
app.py启动文件
import json
from flask import Flask, render_template, request, jsonify
from flask_babel import Babel, _
app = Flask(__name__)
app.config.from_object('config.Config')
babel = Babel(app)
# 选择语言的函数
def select_locale():
lang = request.args.get('lang', request.accept_languages.best_match(app.config['LANGUAGES']))
print(f"Selected language: {lang}")
return lang
babel.init_app(app, locale_selector=select_locale)
# 上下文处理器,用于在模板中获取当前语言
@app.context_processor
def inject_locale():
return {'get_locale': select_locale}
@app.route('/')
def index():
return render_template('index.html')
if __name__ == "__main__":
app.run()
创建页面模板templates下面index.html
<!DOCTYPE html>
<html lang="{{ get_locale() }}">
<head>
<meta charset="UTF-8">
<title>{{ _("Hello World") }}</title>
</head>
<body>
<h1>{{ _("Hello World") }}</h1>
<p>{{ _("Welcome to our website.") }}</p>
</body>
</html>
4、创建翻译文件
为了支持多语言,你需要生成翻译文件。首先,创建 babel.cfg
文件,指定要提取翻译的文件类型:
# babel.cfg
[python: babel-demo/**.py] # 扫描的文件
[jinja2: **/templates/**.html]
然后,使用以下命令提取项目中的可翻译字符串:
pybabel extract -F babel.cfg -o messages.pot .
接下来,为每种语言初始化翻译文件(例如英语和中文):
pybabel init -i messages.pot -d translations -l en pybabel init -i messages.pot -d translations -l zh
然后,编辑生成的 .po
文件,添加翻译文本。例如,translations/zh/LC_MESSAGES/messages.po
文件:
msgid "Hello World"
msgstr "你好,世界"msgid "Welcome to our website."
msgstr "欢迎来到我们的网站。"
最后,编译翻译文件:
pybabel compile -d translations
测试效果
现在,你可以运行 Flask 应用程序,并通过 URL 参数来切换语言。例如:
- 默认语言(英语):
http://localhost:5000/
- 中文:
http://localhost:5000/?lang=zh
项目中实践
项目全局统一格式
web项目中我们对所有的api接口都统一格式返回。通过flask注解@app.after_request装饰器,用于注册一个函数,该函数将在每次请求后被调用。
@app.after_request
def after_request(response):
print(f"Response status code: {response.status_code}")
if response.is_json:
data = response.get_json()
if 'message' in data and isinstance(data['message'], str):
data['message'] = _(data['message'])
response.set_data(json.dumps(data))
return response
获取全局返回结果,并查看是否包含message参数,如果包含,通过_()方式实现多语言。
全局捕捉异常
@app.errorhandler(Exception)
def handle_error(e):
print(f"Handling error: {e}")
error_message = str(e)
response = {
"status": "error",
"message": error_message,
}
return jsonify(response), 400
这样就可以实现flask项目实现国际化。
一个api请求的过程