mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-15 23:22:59 +08:00
- groups 新增 i18n JSONB 列(迁移 242):语言代码 -> {name, description},只存译文;
name/description 原列语义不变,仍用于唯一性校验、搜索与各类日志
- 用户侧接口由后端按请求语言输出:取 Accept-Language 中权重最高的一项,先按完整
语言代码、再按主语言匹配;该语言有译文的字段换成译文,否则保持原字段,且不再带出
译文表。覆盖密钥、可用分组、订阅(含进度与汇总)、兑换、使用记录、可用渠道、
模型广场、套餐列表
- 管理端接口一律返回原字段;分组管理接口额外带 i18n 供编辑
- 创建/编辑分组:名称、描述的标题行右侧新增语言下拉,同一个输入框在默认内容与各语言
版本之间切换;语种跟随前端 availableLocales
- 管理端写入:创建/更新接受 i18n(更新时缺省不修改,传入则整体替换),校验语言代码
形态与名称长度并丢弃空译文;简易模式同样放行;复制分组只带走描述译文
- 切换界面语言后整页刷新,让已加载的数据换成新语言;模型广场响应加
Vary: Accept-Language
- 网关路径,以及只带 group_name 字符串的统计、错误记录出口不做本地化
72 lines
2.2 KiB
Go
72 lines
2.2 KiB
Go
package dto
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/Wei-Shaw/sub2api/internal/domain"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func localizableGroup() *Group {
|
|
return &Group{
|
|
ID: 1, Name: "标准", Description: "号池",
|
|
I18n: domain.GroupI18n{"en": {Name: "Standard", Description: "Pro + Max pool"}},
|
|
}
|
|
}
|
|
|
|
func TestGroupLocalized_ReplacesTextAndDropsTranslations(t *testing.T) {
|
|
g := localizableGroup().Localized("en")
|
|
|
|
require.Equal(t, "Standard", g.Name)
|
|
require.Equal(t, "Pro + Max pool", g.Description)
|
|
|
|
raw, err := json.Marshal(g)
|
|
require.NoError(t, err)
|
|
var decoded map[string]any
|
|
require.NoError(t, json.Unmarshal(raw, &decoded))
|
|
require.NotContains(t, decoded, "i18n", "user-facing output must not carry the translation table")
|
|
}
|
|
|
|
func TestGroupLocalized_KeepsOriginalWhenLanguageHasNoTranslation(t *testing.T) {
|
|
g := localizableGroup().Localized("zh")
|
|
|
|
require.Equal(t, "标准", g.Name)
|
|
require.Equal(t, "号池", g.Description)
|
|
require.Nil(t, g.I18n)
|
|
}
|
|
|
|
func TestLocalized_NilSafe(t *testing.T) {
|
|
require.Nil(t, (*Group)(nil).Localized("en"))
|
|
require.Nil(t, (*APIKey)(nil).Localized("en"))
|
|
require.Nil(t, (*RedeemCode)(nil).Localized("en"))
|
|
require.Nil(t, (*UsageLog)(nil).Localized("en"))
|
|
require.Nil(t, (*UserSubscription)(nil).Localized("en"))
|
|
|
|
// 未携带分组的记录原样返回
|
|
require.Nil(t, (&APIKey{}).Localized("en").Group)
|
|
}
|
|
|
|
func TestLocalized_NestedGroups(t *testing.T) {
|
|
key := (&APIKey{Group: localizableGroup()}).Localized("en")
|
|
require.Equal(t, "Standard", key.Group.Name)
|
|
|
|
code := (&RedeemCode{Group: localizableGroup()}).Localized("en")
|
|
require.Equal(t, "Standard", code.Group.Name)
|
|
|
|
sub := (&UserSubscription{Group: localizableGroup()}).Localized("en")
|
|
require.Equal(t, "Standard", sub.Group.Name)
|
|
|
|
// 使用记录除自身分组外,还带着 API Key 与订阅各自的分组
|
|
log := (&UsageLog{
|
|
Group: localizableGroup(),
|
|
APIKey: &APIKey{Group: localizableGroup()},
|
|
Subscription: &UserSubscription{Group: localizableGroup()},
|
|
}).Localized("en")
|
|
require.Equal(t, "Standard", log.Group.Name)
|
|
require.Equal(t, "Standard", log.APIKey.Group.Name)
|
|
require.Equal(t, "Standard", log.Subscription.Group.Name)
|
|
require.Nil(t, log.APIKey.Group.I18n)
|
|
require.Nil(t, log.Subscription.Group.I18n)
|
|
}
|