feat(i18n): add completeness test and fix missing JP strings

TestLangCompleteness uses reflection to walk the i18n struct and fail
on any empty string field, catching incomplete translations at CI time.
Running it immediately found three missing strings in lang_jp.go
(playtime, timer.enabled, timer.disabled), which are now filled in.
CHANGELOG updated with i18n refactor, FR/ES languages, and the new test.
This commit is contained in:
Houmgaor
2026-03-22 17:09:16 +01:00
parent aff7953ab1
commit 05adda00d7
3 changed files with 43 additions and 0 deletions

View File

@@ -34,6 +34,11 @@ func langJapanese() i18n {
i.commands.ban.error = "Error in command. Format: %s <id> [length]"
i.commands.ban.length = " until %s"
i.commands.playtime = "プレイ時間:%d時間%d分%d秒"
i.commands.timer.enabled = "クエストタイマーが有効になりました"
i.commands.timer.disabled = "クエストタイマーが無効になりました"
i.commands.ravi.noCommand = "ラヴィコマンドが指定されていません"
i.commands.ravi.start.success = "大討伐を開始します"
i.commands.ravi.start.error = "大討伐は既に開催されています"

View File

@@ -1,6 +1,8 @@
package channelserver
import (
"fmt"
"reflect"
"testing"
cfg "erupe-ce/config"
@@ -92,3 +94,36 @@ func TestGetLangStrings_EmptyLanguage(t *testing.T) {
t.Errorf("Empty language should default to English, got %q", lang.language)
}
}
// checkNoEmptyStrings recursively walks v and fails the test for any empty string field.
func checkNoEmptyStrings(t *testing.T, v reflect.Value, path string) {
t.Helper()
switch v.Kind() {
case reflect.String:
if v.String() == "" {
t.Errorf("missing translation: %s is empty", path)
}
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
checkNoEmptyStrings(t, v.Field(i), path+"."+v.Type().Field(i).Name)
}
case reflect.Slice:
for i := 0; i < v.Len(); i++ {
checkNoEmptyStrings(t, v.Index(i), fmt.Sprintf("%s[%d]", path, i))
}
}
}
func TestLangCompleteness(t *testing.T) {
languages := map[string]i18n{
"en": langEnglish(),
"jp": langJapanese(),
"fr": langFrench(),
"es": langSpanish(),
}
for code, lang := range languages {
t.Run(code, func(t *testing.T) {
checkNoEmptyStrings(t, reflect.ValueOf(lang), code)
})
}
}