国际化与时区
借助 starlette-admin,你可以按用户本地化 UI 字符串,并将显示的日期时间转换为查看者所在的时区,而不受数据库存储方式的约束。
完整示例: 如需查看演示国际化与时区功能的完整可运行应用,请参阅 GitHub 仓库中的 examples/10-i18n-timezone。
安装 i18n extra
翻译支持需要 Babel。缺少它时管理后台仍然可用,但会回退到英文,并跳过区域设置感知的日期与数字格式化。
设置区域设置
from sqlalchemy import create_engine
from starlette_admin import I18nConfig
from starlette_admin.contrib.sqla import Admin
from starlette_admin.i18n import SUPPORTED_LOCALES
engine = create_engine("sqlite:///admin.sqlite")
admin = Admin(
engine,
title="My Admin",
i18n_config=I18nConfig(
default_locale="en",
language_switcher=SUPPORTED_LOCALES,
),
secret_key="a-long-random-string",
)
i18n_config 默认为 None,此时管理界面以英文运行。传入 I18nConfig 后,管理后台会安装 LocaleMiddleware。该中间件会在每个请求上解析出一个区域设置,并将其暴露给模板以及你字段和视图代码中使用的翻译函数(gettext 和 lazy_gettext)。
language_switcher 参数会在管理导航栏中添加一个下拉菜单,供用户选择自己的区域设置。将其保持为默认值 None 即可隐藏切换器,仅依靠 default_locale 和逐请求检测。
I18nConfig 参考
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
default_locale |
str |
"en" |
当没有任何 cookie 或请求头匹配受支持的区域设置时使用的区域设置。 |
language_cookie_name |
str | None |
"language" |
用于检测用户区域设置的 cookie。设为 None 可禁用。 |
language_header_name |
str | None |
"Accept-Language" |
cookie 缺失时读取的请求头。设为 None 可禁用。 |
language_switcher |
list[str] | None |
None |
导航栏切换器中提供的区域设置。None 表示隐藏切换器。 |
区域设置的检测方式
LocaleMiddleware 按照以下顺序在每个请求中解析一次区域设置:
- Cookie:
language_cookie_name的值,前提是它匹配某个内置支持的区域设置。 - 请求头:
Accept-Language请求头,或你在language_header_name中指定的请求头,同样需要通过有效性检查。 - 默认值:当 cookie 和请求头都不匹配时,使用
default_locale。
内置支持的区域设置(starlette_admin.i18n.SUPPORTED_LOCALES)包括德语、英语、法语、葡萄牙语、俄语、土耳其语以及简体中文和繁体中文。当用户在导航栏中选择语言时,切换器会写入语言 cookie,因此该选择会跨请求持久保留,而无需服务器端会话存储。
时区
from sqlalchemy import create_engine
from starlette_admin import TimezoneConfig
from starlette_admin.contrib.sqla import Admin
engine = create_engine("sqlite:///admin.sqlite")
admin = Admin(
engine,
title="My Admin",
timezone_config=TimezoneConfig(
default_timezone="UTC",
database_timezone="UTC",
timezone_switcher=["UTC", "Europe/Paris", "America/New_York", "Asia/Tokyo"],
),
secret_key="a-long-random-string",
)
Note
与 i18n_config 不同,timezone_config 默认不为 None。如果省略它,Admin 类会为你构造一个 TimezoneConfig(),因此时区转换开箱即用。管理后台会将不含时区的日期时间视为 database_timezone 中的值(默认为 "UTC"),并向每位用户显示为 "UTC"(即默认的 default_timezone),除非该用户选择了其他时区。
时区的检测方式
TimezoneMiddleware 在每个请求中解析一次时区:
- Cookie:
timezone_cookie_name的值(默认为"timezone"),如果存在的话。 - 默认值:否则使用
default_timezone。
导航栏的时区切换器会写入这个 cookie,与语言切换器完全一样。时区没有类似 Accept-Language 的请求头可用,因为浏览器不会发送此类信息,所以检测完全依赖 cookie。读取 Intl.DateTimeFormat().resolvedOptions().timeZone 的客户端 JavaScript 通常会设置该 cookie,切换器本身也是如此。
字段值的转换方式
DateTimeField 和 ArrowField 会在 database_timezone 与查看者解析出的时区之间转换值。
- 读取(列表、详情、导出):管理后台将数据库中不含时区的值视为
database_timezone中的值,并在格式化之前将其转换为查看者的时区。 - 写入(新建和编辑表单):管理后台将提交的值视为查看者时区中的值,并在其到达模型之前将其转换为
database_timezone。
这样一来,身处不同时区的两名管理员可以编辑同一行数据,各自看到自己本地的时间,而数据库则始终保持单一、一致的时区。
TimezoneConfig 参考
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
default_timezone |
str |
"UTC" |
未设置 cookie 时使用的时区。接受任意 IANA 时区名称。 |
timezone_cookie_name |
str | None |
"timezone" |
用于检测查看者时区的 cookie。设为 None 可禁用。 |
database_timezone |
str |
"UTC" |
存储的日期时间所假定的时区。 |
timezone_switcher |
list[str] | None |
None |
导航栏切换器中提供的时区。None 表示隐藏切换器。 |
use_user_locale_timezone |
bool |
True |
优先使用根据用户区域设置推断出的时区,而非 default_timezone。 |
要限制用户可选择的范围,请传入一个较短的 timezone_switcher 列表。要对所有查看者强制使用单一时区,请将 timezone_switcher 设为 None 并直接设置 default_timezone,例如全公司统一的 "Europe/Paris"。
导航栏切换器通过 get_timezone 和 get_timezone_display_name 模板全局变量渲染每个时区的显示名称和 UTC 偏移量。模板指南对这些全局变量以及其他所有全局变量都有说明。
下一步: