| @@ -0,0 +1,114 @@ | |||||
| --- | |||||
| created: 2026-04-17 | |||||
| status: approved | |||||
| scope: backend + frontend | |||||
| files: 6 | |||||
| --- | |||||
| # 后台设置默认语言 | |||||
| > 管理员可在系统设置中配置全局默认语言,影响未登录用户和未设置语言偏好的已登录用户。 | |||||
| ## 需求 | |||||
| - 管理员在**系统设置**页面配置一个「默认语言」 | |||||
| - **未登录用户**:强制使用管理员设定的默认语言,忽略浏览器语言检测 | |||||
| - **已登录但未设置语言偏好的用户**:使用管理员设定的默认语言 | |||||
| - **已登录且已设置语言偏好的用户**:使用个人设置的语言(不受默认语言影响) | |||||
| - 支持的语言:zh-CN、zh-TW、en、fr、ja、ru、vi | |||||
| - 可选"自动(跟随浏览器)"选项,等于未设定,保持现有行为 | |||||
| ## 语言优先级 | |||||
| ``` | |||||
| 1. 用户个人设置语言(已登录 + 已设置语言偏好) | |||||
| 2. 管理员设定的默认语言(强制使用,忽略浏览器语言) | |||||
| 3. zh-CN(fallbackLng) | |||||
| ``` | |||||
| ## 后端改动 | |||||
| ### 1. `common/constants.go` | |||||
| 新增变量: | |||||
| ```go | |||||
| var DefaultLanguage = "" // 空字符串=未设定,保持现有浏览器检测行为 | |||||
| ``` | |||||
| ### 2. `model/option.go` | |||||
| 在 `updateOptionMap` 的 switch 中新增 case: | |||||
| ```go | |||||
| case "DefaultLanguage": | |||||
| common.DefaultLanguage = value | |||||
| ``` | |||||
| ### 3. `controller/misc.go` — `GetStatus()` | |||||
| 在 status 响应 JSON 中新增字段: | |||||
| ```go | |||||
| "default_language": common.DefaultLanguage, | |||||
| ``` | |||||
| ## 前端改动 | |||||
| ### 4. `web/src/components/settings/SystemSetting.jsx` | |||||
| - `inputs` state 新增 `DefaultLanguage: ''` | |||||
| - 在系统设置表单中添加一个 `Select` 下拉框 | |||||
| - 选项:7 种语言 + 空字符串选项("自动 / 跟随浏览器") | |||||
| - 与其他系统设置一起通过 `/api/option/` 保存 | |||||
| ### 5. `web/src/components/layout/PageLayout.jsx` | |||||
| 在 `loadStatus` 回调中,获取 `data.default_language` 后: | |||||
| ```javascript | |||||
| if (data.default_language && data.default_language !== '') { | |||||
| const savedLang = localStorage.getItem('i18nextLng'); | |||||
| // 仅在没有用户个人设置语言时应用默认语言 | |||||
| // 注意:UserContext 会在用户加载后覆盖此设置 | |||||
| if (!localStorage.getItem('user')) { | |||||
| i18n.changeLanguage(data.default_language); | |||||
| } | |||||
| } | |||||
| ``` | |||||
| 同时保留现有的 `localStorage.getItem('i18nextLng')` 逻辑作为 fallback。 | |||||
| ### 6. `web/src/context/User/index.jsx` | |||||
| 调整语言同步逻辑: | |||||
| ```javascript | |||||
| // 当前:仅在有 settings.language 时切换 | |||||
| // 新增:无 settings.language 时,回退到 status 中的 default_language | |||||
| if (settings.language) { | |||||
| i18n.changeLanguage(settings.language); | |||||
| } else if (statusDefaultLanguage) { | |||||
| i18n.changeLanguage(statusDefaultLanguage); | |||||
| } | |||||
| ``` | |||||
| 需要从 StatusContext 获取 `default_language` 值。 | |||||
| ## 涉及文件 | |||||
| | 文件 | 改动类型 | 改动量 | | |||||
| |------|---------|-------| | |||||
| | `common/constants.go` | 新增变量 | +1 行 | | |||||
| | `model/option.go` | 新增 switch case | +2 行 | | |||||
| | `controller/misc.go` | 新增 status 字段 | +1 行 | | |||||
| | `web/src/components/settings/SystemSetting.jsx` | inputs + 表单 UI | ~30 行 | | |||||
| | `web/src/components/layout/PageLayout.jsx` | loadStatus 后应用默认语言 | ~5 行 | | |||||
| | `web/src/context/User/index.jsx` | 无偏好时回退到默认语言 | ~5 行 | | |||||
| ## 不涉及 | |||||
| - 不修改 i18n.js 的初始化配置 | |||||
| - 不修改 LanguageSelector 组件 | |||||
| - 不添加新的 API 端点 | |||||
| - 不修改数据库 schema(使用现有 options 表) | |||||