mirror of
https://github.com/keven1024/015.git
synced 2026-05-26 07:08:02 +00:00
refactor(i18n): consolidate i18n logic into pkg/i18n, fix TOML loading issue, and migrate translation files
This commit is contained in:
2
openspec/changes/refactor-i18n-use-pkg/.openspec.yaml
Normal file
2
openspec/changes/refactor-i18n-use-pkg/.openspec.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-01
|
||||
49
openspec/changes/refactor-i18n-use-pkg/design.md
Normal file
49
openspec/changes/refactor-i18n-use-pkg/design.md
Normal file
@@ -0,0 +1,49 @@
|
||||
## Context
|
||||
|
||||
项目使用 Go workspace(go.work),`pkg/` 下有多个共享包(models、utils、services、i18n)。worker 模块通过 workspace 引用这些包。
|
||||
|
||||
当前 `pkg/i18n` 存在两个问题:
|
||||
1. `Init()` 中注册的是 JSON 格式解析器,但 locales 目录下的文件是 `.toml`,导致实际加载翻译时什么都加载不到
|
||||
2. 只有英文一种翻译,缺少其他语言
|
||||
|
||||
worker 独立维护了 7 种语言的翻译文件和一套完整的 i18n 初始化/加载逻辑,但这套逻辑使用动态路径查找(尝试多个相对路径),在容器化部署中脆弱。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 修复 `pkg/i18n` 的 TOML 加载 bug
|
||||
- 将所有翻译文件集中到 `pkg/i18n/locales/`,通过 `embed.FS` 编译进二进制,消除运行时路径依赖
|
||||
- worker 移除本地 i18n 实现,改用 `pkg/i18n`
|
||||
|
||||
**Non-Goals:**
|
||||
- 不增加新的翻译 key
|
||||
- 不修改 `Init()` 函数签名
|
||||
- 不影响任何 HTTP API 或前端行为
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. 使用 embed.FS 而非动态路径
|
||||
|
||||
worker 当前通过 `filepath.Glob` 查找翻译文件,需要尝试 4 个不同路径。`pkg/i18n` 已使用 `//go:embed` 将文件编译进二进制,更可靠。翻译文件全部迁移到 `pkg/i18n/locales/`,worker 不再携带翻译文件。
|
||||
|
||||
### 2. 保留 Init() 函数不变
|
||||
|
||||
`Init()` 函数对外保持现有签名,只修改内部实现:将 `bundle.RegisterUnmarshalFunc("json", json.Unmarshal)` 改为 `bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)`,并将文件后缀过滤从 `.json` 改为 `.toml`。
|
||||
|
||||
### 3. worker 调用方式
|
||||
|
||||
worker 在 `main.go` 中调用 `pkgi18n.Init()`,`notify.go` 中将原来的三个本地函数替换为两次 `pkgi18n.TWithData()` 调用。
|
||||
|
||||
### 4. go.mod 依赖调整
|
||||
|
||||
`pkg/i18n/go.mod` 新增:
|
||||
- `github.com/BurntSushi/toml`
|
||||
- `github.com/nicksnyder/go-i18n/v2`
|
||||
- `golang.org/x/text`
|
||||
|
||||
worker/go.mod 新增 `pkg/i18n`,如果 `go-i18n`、`BurntSushi/toml`、`golang.org/x/text` 不再被 worker 直接使用则移至 indirect。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [翻译文件删除] 删除 `worker/internal/i18n/` 不可逆 → 迁移前确认 pkg/i18n/locales/ 中所有文件正确
|
||||
- [go.mod 变动] worker 依赖关系变化可能引起 `go mod tidy` 意外移除仍需要的包 → 执行后检查 go.sum 和编译结果
|
||||
29
openspec/changes/refactor-i18n-use-pkg/proposal.md
Normal file
29
openspec/changes/refactor-i18n-use-pkg/proposal.md
Normal file
@@ -0,0 +1,29 @@
|
||||
## Why
|
||||
|
||||
worker 模块自己实现了一套独立的 i18n 加载逻辑(动态文件路径查找、手动注册 TOML 解析),而 `pkg/i18n` 已经提供了通用的 i18n 封装但从未被使用,且其实现存在 bug(注册的是 JSON 格式,实际文件是 TOML)。统一到 `pkg/i18n` 可以消除重复、修复 bug、让后续模块复用。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 修复 `pkg/i18n`:将格式从 JSON 改为 TOML,更新 `go.mod` 添加缺失依赖
|
||||
- 将 worker/internal/i18n/ 的 7 种语言翻译文件迁移到 `pkg/i18n/locales/`
|
||||
- 将 `pkg/i18n` 加入 `go.work` 工作区
|
||||
- worker/go.mod 中添加 `pkg/i18n` 依赖,移除对 `go-i18n`、`BurntSushi/toml`、`golang.org/x/text/language` 的直接引用
|
||||
- 删除 worker 中的 `loadI18nBundle`、`mustLocalize`、`localizeEmail` 函数,改用 `pkg/i18n.TWithData`
|
||||
- 删除 `worker/internal/i18n/` 目录
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
无新能力,纯重构。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `share-download-notify`:i18n 实现层迁移到 `pkg/i18n`,接口行为(邮件本地化主题和正文)不变
|
||||
|
||||
## Impact
|
||||
|
||||
- **pkg/i18n**:go.mod 新增 `github.com/BurntSushi/toml`、`github.com/nicksnyder/go-i18n/v2`、`golang.org/x/text` 依赖,locales 目录新增 6 种语言文件
|
||||
- **go.work**:新增 `./pkg/i18n` 模块
|
||||
- **worker**:notify.go 逻辑简化,go.mod 依赖变化,`worker/internal/i18n/` 目录删除
|
||||
- 不影响任何 API 或前端
|
||||
@@ -0,0 +1,16 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Localized email notification sent on download
|
||||
`share:notify` Worker 任务 SHALL 对 `notify_emails` 中每个邮件地址通过 SMTP 发送通知邮件,邮件语言使用 `RedisShareInfo.Locale` 对应的翻译,不支持的 locale 回退到英文。支持的语言为:`en`、`de`、`fr`、`ja`、`ko`、`zh-CN`、`zh-TW`。翻译由 `pkg/i18n` 提供,翻译文件以 TOML 格式嵌入二进制。
|
||||
|
||||
#### Scenario: Email sent in creator's locale
|
||||
- **WHEN** SMTP 配置完整(`smtp.host` 非空)且 `shareInfo.Locale="zh-CN"`
|
||||
- **THEN** Worker 向目标地址发送邮件,邮件 Subject 和 Body 为中文内容
|
||||
|
||||
#### Scenario: Email locale fallback to English
|
||||
- **WHEN** `shareInfo.Locale` 为空或不支持的语言代码
|
||||
- **THEN** Worker 使用英文模板发送邮件
|
||||
|
||||
#### Scenario: SMTP not configured
|
||||
- **WHEN** `smtp.host` 为空
|
||||
- **THEN** 邮件通知被跳过(不计入失败数),记录 warn 日志
|
||||
23
openspec/changes/refactor-i18n-use-pkg/tasks.md
Normal file
23
openspec/changes/refactor-i18n-use-pkg/tasks.md
Normal file
@@ -0,0 +1,23 @@
|
||||
## 1. 修复 pkg/i18n
|
||||
|
||||
- [x] 1.1 修改 `pkg/i18n/go.mod`:添加 `github.com/BurntSushi/toml`、`github.com/nicksnyder/go-i18n/v2`、`golang.org/x/text` 依赖
|
||||
- [x] 1.2 修改 `pkg/i18n/i18n.go`:将 `Init()` 内部的 JSON 解析器替换为 TOML 解析器,文件后缀过滤从 `.json` 改为 `.toml`
|
||||
- [x] 1.3 将 `worker/internal/i18n/` 下的所有 `.toml` 文件复制到 `pkg/i18n/locales/`(保留已有的 active.en.toml,添加 de/fr/ja/ko/zh-CN/zh-TW)
|
||||
- [x] 1.4 在 `pkg/i18n/` 目录下运行 `go mod tidy`,生成 go.sum
|
||||
|
||||
## 2. 更新 go.work
|
||||
|
||||
- [x] 2.1 在 `go.work` 的 `use` 块中添加 `./pkg/i18n`
|
||||
- [x] 2.2 在项目根目录运行 `go work sync` 更新 go.work.sum
|
||||
|
||||
## 3. 更新 worker
|
||||
|
||||
- [x] 3.1 在 `worker/go.mod` 中添加 `pkg/i18n` 依赖
|
||||
- [x] 3.2 在 `worker/main.go` 中调用 `pkgi18n.Init()`,处理返回的 error
|
||||
- [x] 3.3 修改 `worker/internal/tasks/notify.go`:删除 `loadI18nBundle`、`mustLocalize`、`localizeEmail` 三个函数及其相关 import,改用 `pkgi18n.TWithData` 生成邮件主题和正文
|
||||
- [x] 3.4 在 `worker/` 目录下运行 `go mod tidy`,确认 `go-i18n`、`BurntSushi/toml`、`golang.org/x/text` 被正确移至 indirect 或移除
|
||||
|
||||
## 4. 清理
|
||||
|
||||
- [x] 4.1 删除 `worker/internal/i18n/` 目录
|
||||
- [x] 4.2 在项目根目录运行 `go build ./...` 确认编译通过
|
||||
Reference in New Issue
Block a user