196 lines
6.2 KiB
Go
196 lines
6.2 KiB
Go
package langx_test
|
|
|
|
import (
|
|
"embed"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"testing/fstest"
|
|
|
|
"github.com/yuninks/langx"
|
|
)
|
|
|
|
//go:embed testdata/langs
|
|
var embeddedLangs embed.FS
|
|
|
|
func writeFile(t *testing.T, dir, rel, body string) {
|
|
t.Helper()
|
|
p := filepath.Join(dir, filepath.FromSlash(rel))
|
|
if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
|
|
t.Fatalf("创建目录失败: %v", err)
|
|
}
|
|
if err := os.WriteFile(p, []byte(body), 0o644); err != nil {
|
|
t.Fatalf("写入文件失败: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRegisterDir(t *testing.T) {
|
|
reset(t)
|
|
dir := t.TempDir()
|
|
writeFile(t, dir, "code.json", "{\"login_success\":200,\"error\":400}")
|
|
writeFile(t, dir, "zh.json", "{\"login_success\":\"成功\",\"welcome\":\"你好 #name#\"}")
|
|
writeFile(t, dir, "en-US.json", "{\"login_success\":\"success\"}")
|
|
writeFile(t, dir, "notes.txt", "这不是 json")
|
|
writeFile(t, dir, "zh/extra.json", "{\"bye\":\"再见\"}") // 子目录并入 zh
|
|
writeFile(t, dir, "en-US/more.json", "{\"bye\":\"bye\"}") // 子目录并入 en-US
|
|
|
|
if err := langx.RegisterDir(dir); err != nil {
|
|
t.Fatalf("RegisterDir: %v", err)
|
|
}
|
|
assertStrings(t, "Langs()", langx.Langs(), []string{"en-us", "zh"})
|
|
if got := langx.GetCode("login_success"); got != 200 {
|
|
t.Fatalf("code.json 未生效: %d", got)
|
|
}
|
|
if got := langx.GetMsg("zh", "bye"); got != "再见" {
|
|
t.Fatalf("子目录文件未并入 zh: %q", got)
|
|
}
|
|
if got := langx.GetMsg("en-US", "bye"); got != "bye" {
|
|
t.Fatalf("子目录文件未并入 en-US: %q", got)
|
|
}
|
|
if got := langx.GetMsg("en-GB", "login_success"); got != "success" {
|
|
t.Fatalf("区域回退失败: %q", got)
|
|
}
|
|
// 再次加载同一目录: 合并语义, 不报错也不丢数据
|
|
if err := langx.RegisterDir(dir); err != nil {
|
|
t.Fatalf("重复加载: %v", err)
|
|
}
|
|
if got := langx.GetMsg("zh", "login_success"); got != "成功" {
|
|
t.Fatalf("重复加载后数据异常: %q", got)
|
|
}
|
|
}
|
|
|
|
// 旧实现在目录不存在时会 panic
|
|
func TestRegisterDirMissing(t *testing.T) {
|
|
reset(t)
|
|
if err := langx.RegisterDir(filepath.Join(t.TempDir(), "not-exist")); err == nil {
|
|
t.Fatal("目录不存在时应返回错误")
|
|
}
|
|
if err := langx.RegisterDir(" "); err == nil {
|
|
t.Fatal("空目录名应返回错误")
|
|
}
|
|
if err := langx.RegisterDir(t.TempDir()); err != nil {
|
|
t.Fatalf("空目录应加载成功(无数据): %v", err)
|
|
}
|
|
}
|
|
|
|
// 解析失败必须整体失败, 不能留下半加载状态
|
|
func TestRegisterDirInvalidJSON(t *testing.T) {
|
|
reset(t)
|
|
dir := t.TempDir()
|
|
writeFile(t, dir, "zh.json", "{\"k\":\"v\"}")
|
|
writeFile(t, dir, "en.json", "{坏掉的 json")
|
|
writeFile(t, dir, "code.json", "{\"k\":200}")
|
|
|
|
if err := langx.RegisterDir(dir); err == nil {
|
|
t.Fatal("非法 json 应返回错误")
|
|
}
|
|
if len(langx.Langs()) != 0 || langx.HasCode("k") {
|
|
t.Fatalf("加载失败却写入了数据: langs=%v", langx.Langs())
|
|
}
|
|
}
|
|
|
|
// 结构不符合约定时也应报错
|
|
func TestRegisterDirWrongSchema(t *testing.T) {
|
|
reset(t)
|
|
dir := t.TempDir()
|
|
writeFile(t, dir, "code.json", "{\"k\":\"not-int\"}")
|
|
if err := langx.RegisterDir(dir); err == nil {
|
|
t.Fatal("code.json 类型错误应返回错误")
|
|
}
|
|
dir2 := t.TempDir()
|
|
writeFile(t, dir2, "zh.json", "[\"not\",\"object\"]")
|
|
if err := langx.RegisterDir(dir2); err == nil {
|
|
t.Fatal("语言文件类型错误应返回错误")
|
|
}
|
|
}
|
|
|
|
func TestRegisterFSContainer(t *testing.T) {
|
|
reset(t)
|
|
fsys := fstest.MapFS{
|
|
"i18n/code.json": {Data: []byte("{\"ok\":200}")},
|
|
"i18n/zh.json": {Data: []byte("{\"hello\":\"你好\"}")},
|
|
"i18n/en.json": {Data: []byte("{\"hello\":\"Hello\"}")},
|
|
"i18n/README.md": {Data: []byte("忽略我")},
|
|
"i18n/zh/extra.json": {Data: []byte("{\"bye\":\"再见\"}")},
|
|
}
|
|
if err := langx.RegisterFS(fsys); err != nil {
|
|
t.Fatalf("RegisterFS: %v", err)
|
|
}
|
|
// 容器目录 i18n 被自动跳过, 非 json 文件被忽略
|
|
assertStrings(t, "Langs()", langx.Langs(), []string{"en", "zh"})
|
|
if got := langx.GetCode("ok"); got != 200 {
|
|
t.Fatalf("容器内的 code.json 未生效: %d", got)
|
|
}
|
|
if got := langx.GetMsg("zh", "hello"); got != "你好" {
|
|
t.Fatalf("GetMsg = %q", got)
|
|
}
|
|
if got := langx.GetMsg("zh", "bye"); got != "再见" {
|
|
t.Fatalf("语言子目录未合并: %q", got)
|
|
}
|
|
}
|
|
|
|
// 只有语言目录、根目录没有 json 的布局
|
|
func TestRegisterFSLanguageDirs(t *testing.T) {
|
|
reset(t)
|
|
fsys := fstest.MapFS{
|
|
"langs/zh/a.json": {Data: []byte("{\"a\":\"甲\"}")},
|
|
"langs/zh/b.json": {Data: []byte("{\"b\":\"乙\"}")},
|
|
"langs/en/a.json": {Data: []byte("{\"a\":\"A\"}")},
|
|
"langs/code.json": {Data: []byte("{\"ok\":200}")},
|
|
}
|
|
if err := langx.RegisterFS(fsys); err != nil {
|
|
t.Fatalf("RegisterFS: %v", err)
|
|
}
|
|
assertStrings(t, "Langs()", langx.Langs(), []string{"en", "zh"})
|
|
if got := langx.GetMsg("zh", "a"); got != "甲" {
|
|
t.Fatalf("zh/a.json = %q", got)
|
|
}
|
|
if got := langx.GetMsg("zh", "b"); got != "乙" {
|
|
t.Fatalf("zh/b.json 未合并 = %q", got)
|
|
}
|
|
if got := langx.GetMsg("en", "a"); got != "A" {
|
|
t.Fatalf("en/a.json = %q", got)
|
|
}
|
|
if got := langx.GetCode("ok"); got != 200 {
|
|
t.Fatalf("code.json 未生效: %d", got)
|
|
}
|
|
}
|
|
|
|
func TestRegisterFSErrors(t *testing.T) {
|
|
reset(t)
|
|
if err := langx.RegisterFS(nil); err == nil {
|
|
t.Fatal("nil fs.FS 应返回错误")
|
|
}
|
|
fsys := fstest.MapFS{"zh.json": {Data: []byte("{坏")}}
|
|
if err := langx.RegisterFS(fsys); err == nil {
|
|
t.Fatal("非法 json 应返回错误")
|
|
}
|
|
if len(langx.Langs()) != 0 {
|
|
t.Fatalf("失败后不应有数据: %v", langx.Langs())
|
|
}
|
|
// 没有任何 json 文件
|
|
empty := fstest.MapFS{"readme.md": {Data: []byte("x")}}
|
|
if err := langx.RegisterFS(empty); err != nil {
|
|
t.Fatalf("无 json 文件不应报错: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRegisterEmbed(t *testing.T) {
|
|
reset(t)
|
|
if err := langx.RegisterEmbed(embeddedLangs); err != nil {
|
|
t.Fatalf("RegisterEmbed: %v", err)
|
|
}
|
|
// testdata/langs 是容器目录, 会被自动跳过; notes.txt 会被忽略
|
|
assertStrings(t, "Langs()", langx.Langs(), []string{"en", "zh"})
|
|
if got := langx.GetCode("login_success"); got != 200 {
|
|
t.Fatalf("响应码未加载: %d", got)
|
|
}
|
|
code, msg := langx.GetTransFormat("en", "welcome", map[string]string{"name": "Tom"})
|
|
if code != 200 || msg != "Hello Tom" {
|
|
t.Fatalf("GetTransFormat = (%d, %q)", code, msg)
|
|
}
|
|
if got := langx.GetMsg("zh", "bye"); got != "再见" {
|
|
t.Fatalf("testdata/langs/zh/extra.json 未合并: %q", got)
|
|
}
|
|
}
|