FastAPI 实现国际化(i18n)和多语言支持的完整方案

一、整体思路

实现多语言支持的核心流程其实很简单:

  1. 识别用户语言 ------ 从 Accept-Language header 或 URL 参数中获取;
  2. 加载对应语言的翻译文件 (.po / .mo);
  3. 在代码中动态翻译文本。

简单来说,就是让接口返回不同语言的内容。

二、安装依赖

我们主要用到 Babel 来提取和编译翻译文件:

复制代码
pip install Babel

三、项目结构

建议的目录结构如下:

bash 复制代码
app/
 ├─ main.py
 ├─ i18n/
 │   ├─ locales/
 │   │   ├─ en/LC_MESSAGES/messages.po
 │   │   └─ zh_CN/LC_MESSAGES/messages.po
 │   └─ babel.cfg

babel.cfg 文件内容如下:

ini 复制代码
[python: **.py]
encoding = utf-8

四、编写中间件自动切换语言

我们可以编写一个中间件,在请求到来时自动根据 Accept-Language 选择语言环境:

python 复制代码
from fastapi import FastAPI, Request
from starlette.middleware.base import BaseHTTPMiddleware
import gettext

class I18nMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        lang = request.headers.get("Accept-Language", "en").split(",")[0]
        try:
            translation = gettext.translation(
                domain="messages",
                localedir="app/i18n/locales",
                languages=[lang],
            )
            translation.install()
            request.state._ = translation.gettext
        except FileNotFoundError:
            gettext.install("messages", localedir="app/i18n/locales")
            request.state._ = gettext.gettext
        return await call_next(request)

app = FastAPI()
app.add_middleware(I18nMiddleware)

@app.get("/")
async def read_root(request: Request):
    _ = request.state._
    return {"message": _("Hello, world!")}

上面的中间件会自动根据请求头里的语言加载对应翻译文件,比如:

arduino 复制代码
curl -H "Accept-Language: zh_CN" http://127.0.0.1:8000/

就会返回中文翻译。


五、提取和编译翻译文件

接下来生成翻译模板并创建不同语言的 .po 文件。

bash 复制代码
# 提取字符串
pybabel extract -F app/i18n/babel.cfg -o app/i18n/messages.pot app

# 初始化中文翻译
pybabel init -i app/i18n/messages.pot -d app/i18n/locales -l zh_CN

# 编辑 po 文件后编译
pybabel compile -d app/i18n/locales

编辑 messages.po 时,只需要翻译字符串,例如:

arduino 复制代码
msgid "Hello, world!"
msgstr "你好,世界!"
相关推荐
Mk598782 分钟前
给 Agent 装上对话框 —— AgentScope-Java 接入 Spring Boot 与 SSE 流式实战
后端
付威20234 分钟前
从 Loop 到 Runtime:rpi Agent Loop 与 Cordis 的边界、取舍与组合
后端
IT_陈寒7 分钟前
Redis的LRU淘汰策略坑了我一整天
前端·人工智能·后端
考虑考虑1 小时前
JDK26的JEP 500属性
java·后端·java ee
Mia_墨黎2 小时前
2026 Windows 11 终端美化完全指南
前端·后端
foreverYoung2 小时前
给开源后台做等保适配,我发现了 5 个"看起来有、其实没用"的功能 从一个尴尬的现场测试说起
后端
程序猿阿越2 小时前
从 StatefulSet 到容器挂载:CSI 源码走读
后端·kubernetes·源码阅读
苏三说技术3 小时前
继PHP之后,Java也爆出了重大安全漏洞!
后端
程序猿乐锅4 小时前
【从0-1学习Python | 第七篇】Python 面向对象基础
开发语言·笔记·后端·python·学习·1024程序员节