Flask API 如何接入 i18n 实现国际化多语言

1. 介绍

上一篇文章分享了 Vue3 如何如何接入 i18n 实现国际化多语言,这里继续和大家分享 Flask 后端如何接入 i18n 实现国际化多语言。

用户请求 API 的多语言化其实有两种解决方案:

  1. 后端返回:"USER_ERROR"  => 前端渲染:"用户错误"
  1. 后端接收请求中 "Accept-Language" 信息为 "zh-CN" => 后端返回:"用户错误" => 前端渲染:"用户错误"


这里我们采用的是第二种方案,也就是后端直接处理 i18n 逻辑。

对于 Flask 我们常用 flask-babel,这个包对于将原本单语言的程序转为国际化多语言非常友好,我们只要用 gettext() 包裹我们原来的文本:

@api.route("/", methods=["GET"])
def info():return jsonify({"msg": gettext("欢迎访问 Githubstar API 服务器.")}), 200

然后工具就可以自动生成翻译文件,我们只要编辑不同语言的翻译文件就可以了:

#: githubstar_api/api.py:39
msgid "欢迎访问 Githubstar API 服务器."
msgstr "Welcome to the Githubstar API server."

2. 基本实现


本文以 GithubStar.Pro 后端的实现为例进行介绍。

要将 flask-babel 引入项目,这里首先安装 flask-babel:

pip install flask-babel

如果你开发包的话,这个依赖也要加入到项目依赖中。

然后,在 Flask 初始化时安装 Babel 插件:

from flask import Flask
from flask_babel import Babelapp = Flask('githubstar_api')
babel = Babel(app)

如果你需要使用工厂模式初始化你的 Flask 实例,可以用:

from flask import Flask
from flask_babel import Babelapp = Flask('githubstar_api')
babel = Babel()def init_app():babel.init_app(app)

然后,将你的所有业务相关的文字都包裹上 gettext():

return (jsonify({"errors": [gettext('用户 "%(username)s" 已被封禁.', username=user.username)]}),400,
)

句子中的变量,可以用 %()s 包裹,其中 s 代表字符串。

更多的使用方法详见:文档

然后,在项目根目录新建一个 babel.cfg:

[python: githubstar_api/**.py]

​这里的路径应该指向你的所有需要国际化的代码文件。

然后,运行命令,将这些文件中被 gettext() 包裹的文字都提取到模板文件中:

pybabel extract -F babel.cfg -o messages.pot .

这会在项目根目录生成 messages.pot 文件,可以看到包含了所有需要翻译的文本:

#: githubstar_api/api.py:39
msgid "欢迎访问 Githubstar API 服务器."
msgstr ""

随后,我们需要开始进行一个新语言的翻译,例如英文,运行命令:

pybabel init -i messages.pot -d ./githubstar_api/res/locales -l en

我们就可以在 ./githubstar_api/res/locales 中看到生成了一个 en 文件夹, 里面有 messages.po 文件,这就是一个空的全新的翻译文件了。

这里我们可以将文本内容全部发送给 OpenAI GPT4 或者是 Github Copilot,告诉他:

这是一个 babel 翻译文件,请根据中文翻译为英文并填入msgstr中,以下是文件内容:
...

AI 可以很好地完成翻译任务,只需要检查并稍微调整即可。

完成翻译后,需要将翻译文件编译为二进制文件:

pybabel compile -d ./githubstar_api/res/locales

这样,locale 文件夹中的所有语言都被翻译,生产了 messages.po 文件。

现在,文件目录应该是这样的:

./githubstar
├── githubstar_api
│   ├── __init__.py
│   ├── res
│   │   ├── __init__.py
│   │   └── locales
│   │       └── en
│   │           └── LC_MESSAGES
│   │               ├── messages.mo
│   │               └── messages.po
│   ├── api.py
│   ├── app.py
│   └── cli.py
├── messages.pot
└── pyproject.toml

所以,用加载包数据的方式导入:

import importlib.resources as pkg_resourcesfrom . import restraversable = pkg_resources.files(res)
with pkg_resources.as_file(traversable) as path:babel.init_app(app,default_translation_directories=str(path / "locales"),)

接下来,我们需要设定,需要检测请求的 Accept-Language,以下就是完整的 app.py 文件:

from flask import Flask, request
from flask_babel import Babelapp = Flask("githubstar_api")
babel = Babel()def get_locale():return request.accept_languages.best_match(["zh_CN", "en"])def init_app():traversable = pkg_resources.files(res)with pkg_resources.as_file(traversable) as path:babel.init_app(app,default_translation_directories=str(path / "locales"),locale_selector=get_locale,default_locale="zh_CN",)

这样,就实现了 Flask API 后端根据请求的 Accept-Language 自动调整返回值的语言了。

注意:如果你要将翻译文件包含在输出的 Python 包中,你需要调整你的 pyproject.toml:

[tool.setuptools]
zip-safe = false
include-package-data = true[tool.setuptools.packages]
find = {namespaces = false}[tool.setuptools.package-data]
"githubstar_api.res" = ["**/*.mo"]

3. 与 Vue3 前端联动

接下来,需要让前端发送的请求以当前语言作为 Accept-Language。

这里,我们以用户操作相关 API 为例,这里我们使用一个 Pinia Store 来管理所有的用户状态和相关请求。API 请求用 axios 发送,详见开源仓库:Github: GithubStarPro。

export const useUserStore = defineStore('user', {state: () => {const { locale } = useI18n({ inheritLocale: true, useScope: 'local' });const user = useStorage<User | null>('user', null, undefined, { serializer: StorageSerializers.object });const api = axios.create({ baseURL: import.meta.env.VITE_API_URL });api.interceptors.request.use((config) => {config.headers['Accept-Language'] = locale.value;if (user.value && user.value.token) {config.headers.Authorization = `Bearer ${user.value.token.token}`;}return config;});},actions: {login(username: string, password: string) {const payload = {username: username,password: password,};this.api.post('/user/login', payload).then((response) => {this.user = response.data;});}},
});

​我们重点关注的是:

api.interceptors.request.use((config) => {config.headers['Accept-Language'] = locale.value;if (user.value && user.value.token) {config.headers.Authorization = `Bearer ${user.value.token.token}`;}return config;
});


这一块是在 axios 对象上定义了一个预处理器,也就是在每个发送的请求上加入当前的 locale,如果用户已登录,还需要加入用户的 Token,这里的 locale 参见我的上一篇文章:Vue3 如何如何接入 i18n 实现国际化多语言。

这样,就实现了在每次发送请求时候自动发送当前的 locale。

这样我们就实现了前后端的国际化,如果这篇文章对您有帮助的话,欢迎关注我,我会分享更多全栈网页开发的实用经验。

您也可以关注 Github 互赞平台 GithubStar.Pro,快速提升您的项目关注度。

感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/741196.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1 python介绍、基本语法、流程控制

一、 Python介绍python的创始人为吉多范罗苏姆(Guido van Rossum)。1989年的圣诞节期间,吉多范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承。 最新的TIOBE排行榜,Python赶超PHP占据第五, Python崇尚优美、清晰、简单,是一个优…

记录 中**信 ruoyi项目 部署全流程

零 本地环境改为线上环境 包括 1 后端的数据库连接地址 2 后端的文件存储本地地址 3 后端的文件存储ip地址 4 前端baseUrl 一 后端项目打包双击package 二 mstsc 进入服务器 三 备份四 后端jar包替换五 前端文件替换六 检查数据库需不需要备份 七 启动 java -jar ruoyi-admin.j…

hackmyvm-airbind

环境 靶机ip:未知 攻击机kali:ip1:192.168.96.59 ip2:192.168.56.103 主机探测 arp-scan -l发现了56.104这个机子应该就是我们的靶机,接下来先对其进行端口扫描 端口扫描发现开放了80端口,但是22端口状态显示为filtered,不知道开放还是关闭 访问80端口,发现是wallos的管理…

Vue3-slot

描述为了能在当前组件中使用其他组件中的内容,并且可以改变其他组件中的内容结构。使用的技术就叫做“插槽”。在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。举例:子组件<FancyButton/>: <template><button cl…

FPGA bit转bin文件

首先科普一下 什么是bitstream文件 FPGA比特流(bitstream)是一种用于配置可编程逻辑器件的数据格式,特别是现场可编程门阵列(FPGA)。比特流包含了硬件逻辑电路、路由信息以及芯片上寄存器和存储器(如查找表LUT)的初始值。通常认为比特流具有厂商特定的格式,因此很难反向…

mysql集群高可用架构MHA

一、MHA概述 1.为什么要用MHA Master的单点故障问题 2.什么是 MHA MHA(Master High Availability)是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。MHA 的出现就是解决MySQL 单点的问题。MySQL故障切换过程中,MHA能做到0-30秒内自动完成故障切换操作。MHA能在故障切…

coca 经常过期

re-doHELP ADD NOTE DELETERE-DOSHARE LINKCORPUSWORD(S)SECTIONSTYPEWHENELAPSED (MS) 1COCAliable for + *COLL7/7/2024754

Git Commit 提交规范

背景 Git每次提交代码都需要写commit message,否则就不允许提交。一般来说,commit message应该清晰明了,说明本次提交的目的,具体做了什么操作。但是在日常开发中,大家的commit message千奇百怪,中英文混合使用、fix bug等各种笼统的message司空见怪,这就导致后续代码维…

docker-compose创建haproxy教程

本文主要讲解通过docker-compose创建haproxy并进行代理 一、haproxy简介HAProxy是一款基于事件驱动、单进程模型设计的四层与七层负载均衡器,它能够在TCP/UDP层面以及HTTP(S)等应用层协议上实现高效的流量分发。HAProxy不仅适用于Web服务器负载均衡,还能应用于数据库、邮件服…

Pytorch实现基于MNIST的手写数字识别

本文目的在于训练一个模型,使其能对手写的数字图片进行分类识别,并不断优化使其准确度尽可能地提高 一、数据预处理 (1)运行时所需库 import numpy as np import torch import torchvision from torch import nn from torch.utils.data import DataLoader from t…

【proto】python根据proto文件构造message,并换为二进制

一、场景测试需要构造数据,而且存储的格式为grpc消息的二进制格式,所以必须要根据proto构造二进制二、构造方法 1、根据proto文件生成python格式的pb文件python3 -m grpc_tools.protoc -I. proto/upload_state.proto --python_out=. --grpc_python_out=. 2、检查文件生成 3…

electron 跨域/CSP问题

请求报错:Refused to connect to http://127.0.0.1:8000/get?name=kv-grpc because it violates the following Content Security Policy directive: "default-src self". Note that connect-src was not explicitly set, so default-src is used as a fallback 这…