# 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) — 了解如何翻译内容