# python: 区域设置检测与中间件
URL: https://generaltranslation.com/zh/docs/python/guides/middleware.mdx
---
title: 区域设置检测与中间件
description: Flask 和 FastAPI 中区域设置检测的工作方式,以及如何进行自定义
---
GT 的 Python 中间件会在每次请求时自动检测用户的区域设置,并将其提供给 [`t()`](/docs/python/api/t) 和 [`get_locale()`](/docs/python/api/get-locale)。本指南将介绍检测机制的工作方式,以及自定义时可用的高级 pattern。
如需了解自定义区域设置检测的基础内容,请参阅[自定义区域设置检测教程](/docs/python/tutorials/custom-locale-detection)。本指南会在这些 pattern 的基础上进一步展开。
## 默认行为
如果未提供 `get_locale` 回调函数,GT 会解析 `Accept-Language` 请求头,与已配置的 `locales` 匹配,并回退到 `default_locale`:
```python
from flask import Flask
from gt_flask import initialize_gt
app = Flask(__name__)
initialize_gt(app, default_locale='en', locales=['es', 'fr'])
```
```python
from fastapi import FastAPI
from gt_fastapi import initialize_gt
app = FastAPI()
initialize_gt(app, default_locale='en', locales=['es', 'fr'])
```
## 串联检测策略
在生产环境中,通常需要按优先级顺序依次尝试多个来源。为此,向 `initialize_gt` 传入一个 `get_locale` 回调函数:
```python
from flask import Flask
from gt_flask import initialize_gt
app = Flask(__name__)
def get_locale(request) -> str:
# 1. 显式查询参数
lang = request.args.get('lang')
if lang:
return lang
# 2. cookie(用户保存的偏好)
locale = request.cookies.get('locale')
if locale:
return locale
# 3. URL 路径前缀(/es/about)
parts = request.path.strip('/').split('/')
if parts and parts[0] in ('es', 'fr', 'de'):
return parts[0]
# 4. Accept-Language 请求头
accept = request.headers.get('Accept-Language', '')
if accept:
return accept.split(',')[0].split(';')[0].strip()
return 'en'
initialize_gt(app, default_locale='en', locales=['es', 'fr', 'de'], get_locale=get_locale)
```
```python
from fastapi import FastAPI, Request
from gt_fastapi import initialize_gt
app = FastAPI()
def get_locale(request: Request) -> str:
# 1. 显式查询参数
lang = request.query_params.get('lang')
if lang:
return lang
# 2. cookie(用户保存的偏好)
locale = request.cookies.get('locale')
if locale:
return locale
# 3. URL 路径前缀(/es/about)
parts = request.url.path.strip('/').split('/')
if parts and parts[0] in ('es', 'fr', 'de'):
return parts[0]
# 4. Accept-Language 请求头
accept = request.headers.get('accept-language', '')
if accept:
return accept.split(',')[0].split(';')[0].strip()
return 'en'
initialize_gt(app, default_locale='en', locales=['es', 'fr', 'de'], get_locale=get_locale)
```
## 使用 cookie 持久化区域设置
让用户选择语言,并记住该设置:
```python
from flask import request, make_response, jsonify
@app.route('/api/set-language', methods=['POST'])
def set_language():
locale = request.json.get('locale', 'en')
response = make_response(jsonify({'ok': True}))
response.set_cookie('locale', locale, max_age=365 * 24 * 60 * 60)
return response
```
```python
from fastapi import Request
from fastapi.responses import JSONResponse
@app.post('/api/set-language')
async def set_language(request: Request):
body = await request.json()
locale = body.get('locale', 'en')
response = JSONResponse({'ok': True})
response.set_cookie('locale', locale, max_age=365 * 24 * 60 * 60)
return response
```
## 基于用户资料的检测
对于已登录的应用,从用户偏好中读取区域设置:
```python
def get_locale(request) -> str:
user = get_current_user(request) # 你的认证逻辑
if user and user.preferred_locale:
return user.preferred_locale
# 回退到 cookie 或请求头
return request.cookies.get('locale') or 'en'
```
## 读取解析后的区域设置
在处理请求时,你可以在任意位置使用 [`get_locale()`](/docs/python/api/get-locale) 读取解析后的区域设置:
```python
from gt_flask import get_locale # 或 gt_fastapi
@app.route('/api/info')
def info():
return { 'locale': get_locale() }
```
## 后续步骤
* [自定义区域设置检测教程](/docs/python/tutorials/custom-locale-detection) — 基础入门
* [`get_locale()` API 参考](/docs/python/api/get-locale)
* [字符串翻译模式](/docs/python/guides/strings) — 了解如何翻译内容