3.6 KiB
3.6 KiB
PRD: App启动时语言和时区自动设置
背景
当前App启动时语言硬编码为 zh,不读取iOS系统语言;时区完全不处理。需要实现三种场景的自动设置逻辑。
需求
场景1:新用户首次打开App → 注册时写入后端
- App无本地存储信息(首次打开)
- 读取iOS系统语言和时区
- 自动设置App界面语言和时区
- 用户注册时,将语言和时区作为请求参数传给后端
- 后端创建用户Profile时使用传入值
场景2:已有用户在新设备首次登录 → 从服务器同步
- App无本地存储信息(新设备首次打开)
- 读取iOS系统语言和时区作为临时值
- 自动设置App界面语言和时区(临时)
- 用户登录成功后,从服务器拉取Profile中的语言和时区
- 用服务器值更新本地存储和App设置
场景3:有本地存储 → 使用本地值
- App有本地存储的语言和时区信息
- 直接使用本地值,不读取系统语言和时区
- 登录后仍从服务器同步(确保一致性)
技术方案
前端
-
读取系统语言
- 使用
PlatformDispatcher.instance.locale获取系统首选语言 - 通过
resolveSystemLocale()映射到 App 支持的 Locale
- 使用
-
读取系统时区
- 使用
flutter_timezone包的getLocalTimezone()获取 IANA 时区 ID - 直接使用返回值,后端会验证有效性
- 使用
-
本地存储扩展
SessionStore新增saveTimezone()/getTimezone()- 现有
saveLocaleTag()/getLocaleTag()已支持语言
-
启动流程修改 (
app.dart:_bootstrap)if (本地有locale) { 使用本地locale } else { 读取系统locale → 保存到本地 } if (本地有时区) { 使用本地时区 } else { 读取系统时区 → 保存到本地 } -
注册请求扩展
AuthApi.createEmailSession新增language和timezone参数EmailSessionCreateRequestschema 扩展
-
登录后同步
- 现有
_refreshProfile()已同步语言 - 扩展同步时区
- 现有
后端
-
Schema扩展 (
v1/auth/schemas.py)class EmailSessionCreateRequest(BaseModel): email: str token: str language: str | None = None # BCP-47 tag timezone: str | None = None # IANA timezone -
Service逻辑 (
v1/auth/service.py)create_email_session接收语言/时区- 创建/更新Profile时使用传入值(如果提供)
-
Profile默认值保持不变
language: str = "zh-CN"timezone: str = "Asia/Shanghai"
验收标准
- 新设备首次打开App,界面语言与iOS系统语言一致
- 新用户注册后,后端Profile的语言/时区与App一致
- 已有用户登录后,App语言/时区与服务器Profile一致
- 有本地存储时,App启动不请求系统语言/时区
- 支持的语言映射:
- iOS
en/en-US/en-GB→ FlutterLocale('en')→ 存储en-US - iOS
zh/zh-CN/zh-SG/zh-Hans-*→ FlutterLocale('zh')→ 存储zh-CN - iOS
zh-Hant/zh-TW/zh-HK/zh-MO→ FlutterLocale(zh, Hant)→ 存储zh-Hant
- iOS
- 时区为有效IANA ID (如
Asia/Shanghai,America/New_York)
风险
- iOS系统语言可能不在支持列表中 → 回退到
zh-CN flutter_timezone包可能返回无效时区 → 后端验证 + 前端回退默认值- 用户修改系统语言/时区后,App不会自动更新(符合场景3设计)
- 新用户注册时网络请求失败 → Profile 使用后端默认值,用户可在设置中修改