# python: 自定义区域设置检测
URL: https://generaltranslation.com/zh/docs/python/tutorials/custom-locale-detection.mdx
---
title: 自定义区域设置检测
description: 如何使用 get_locale 自定义区域设置检测,以及默认行为的运作方式
---
## 默认行为
如果没有向 [`initialize_gt`](/docs/python/api/initialize-gt) 提供 `get_locale` 回调,GT 会在每次请求时根据 HTTP `Accept-Language` 标头自动检测用户的区域设置:
1. 读取 `Accept-Language` 标头 (例如 `en-US,en;q=0.9,es;q=0.8`)
2. 将其解析为按质量值排序的区域设置列表 (质量值最高的排在最前)
3. 与你配置的 `locales` 进行匹配,找出最合适的区域设置
4. 如果找不到匹配项,则回退到 `default_locale`
这意味着开箱即用时,用户会看到其浏览器请求语言的内容——前提是你已经为该语言提供了翻译。
```python
from flask import Flask
from gt_flask import initialize_gt
app = Flask(__name__)
# 未提供 get_locale —— 默认按 Accept-Language 解析
initialize_gt(
app,
default_locale="en",
locales=["es", "fr"],
)
```
```python
from fastapi import FastAPI
from gt_fastapi import initialize_gt
app = FastAPI()
# 未提供 get_locale —— 默认按 Accept-Language 解析
initialize_gt(
app,
default_locale="en",
locales=["es", "fr"],
)
```
***
## 自定义 `get_locale`
如需覆盖默认行为,请向 `initialize_gt` 传入 `get_locale` 回调。它会接收请求对象,并且必须返回一个区域设置字符串。
```python
from flask import Flask
from gt_flask import initialize_gt
app = Flask(__name__)
def get_locale(request) -> str:
# 先检查查询参数
locale = request.args.get("lang")
if locale:
return locale
# 然后检查 cookie
locale = request.cookies.get("locale")
if locale:
return locale
# 最后回退到默认值
return "en"
initialize_gt(
app,
default_locale="en",
locales=["es", "fr"],
get_locale=get_locale,
)
```
```python
from fastapi import FastAPI, Request
from gt_fastapi import initialize_gt
app = FastAPI()
def get_locale(request: Request) -> str:
# 先检查查询参数
locale = request.query_params.get("lang")
if locale:
return locale
# 然后检查 cookie
locale = request.cookies.get("locale")
if locale:
return locale
# 最后回退到默认值
return "en"
initialize_gt(
app,
default_locale="en",
locales=["es", "fr"],
get_locale=get_locale,
)
```
***
## 内部工作机制
* **FastAPI**:`initialize_gt` 会注册一个在每次请求时运行的 HTTP 中间件。如果提供了 `get_locale`,就会调用 `get_locale(request)`;否则会解析 `Accept-Language`。解析出的区域设置会设置到 `I18nManager` 中,而 [`t()`](/docs/python/api/t) 会从中读取。
* **Flask**:`initialize_gt` 会注册一个逻辑相同的 `before_request` 钩子。
***
## 常见模式
### URL 路径前缀
从 URL 路径中提取区域设置 (例如:`/es/about`、`/fr/home`) :
```python
def get_locale(request) -> str:
parts = request.url.path.strip("/").split("/")
supported = {"es", "fr", "de"}
if parts and parts[0] in supported:
return parts[0]
return "en"
```
### 用户资料
从已认证用户的偏好设置中获取区域设置:
```python
def get_locale(request) -> str:
user = get_current_user(request) # 你的认证逻辑
if user and user.preferred_locale:
return user.preferred_locale
return "en"
```
### 子域名
通过类似 `es.example.com` 的子域名检测区域设置:
```python
def get_locale(request) -> str:
host = request.headers.get("host", "")
subdomain = host.split(".")[0]
if subdomain in ("es", "fr", "de"):
return subdomain
return "en"
```
***
## 注意事项
* 你的 `get_locale` 函数应始终返回有效的区域设置字符串
* 如果它返回的区域设置没有对应的翻译,`t()` 会回退到 `default_locale` 中的原始内容
* 该函数接收框架的原始请求对象——FastAPI 中为 `Request`,Flask 中为 Flask 的 `request`
* 你也可以在代码的其他地方使用 [`get_locale()`](/docs/python/api/get-locale) 读取解析后的区域设置