diff --git a/modules/translation/i18n/i18n.go b/modules/translation/i18n/i18n.go index 664e457ecf79f..5dfb52cc31229 100644 --- a/modules/translation/i18n/i18n.go +++ b/modules/translation/i18n/i18n.go @@ -41,14 +41,14 @@ func NewLocaleStore() *LocaleStore { } // AddLocaleByIni adds locale by ini into the store -func (ls *LocaleStore) AddLocaleByIni(langName, langDesc string, localeFile interface{}, otherLocaleFiles ...interface{}) error { +func (ls *LocaleStore) AddLocaleByIni(langName, langDesc string, source, moreSource []byte) error { if _, ok := ls.localeMap[langName]; ok { return ErrLocaleAlreadyExist } iniFile, err := ini.LoadSources(ini.LoadOptions{ IgnoreInlineComment: true, UnescapeValueCommentSymbols: true, - }, localeFile, otherLocaleFiles...) + }, source, moreSource) if err == nil { iniFile.BlockMode = false lc := &locale{store: ls, langName: langName, langDesc: langDesc, messages: iniFile} diff --git a/modules/translation/i18n/i18n_test.go b/modules/translation/i18n/i18n_test.go index 70066016cfe43..85723cb1731b0 100644 --- a/modules/translation/i18n/i18n_test.go +++ b/modules/translation/i18n/i18n_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_Tr(t *testing.T) { +func TestLocaleStore(t *testing.T) { testData1 := []byte(` .dot.name = Dot Name fmt = %[1]s %[2]s @@ -28,8 +28,8 @@ sub = Changed Sub String `) ls := NewLocaleStore() - assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", testData1)) - assert.NoError(t, ls.AddLocaleByIni("lang2", "Lang2", testData2)) + assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", testData1, nil)) + assert.NoError(t, ls.AddLocaleByIni("lang2", "Lang2", testData2, nil)) ls.SetDefaultLang("lang1") result := ls.Tr("lang1", "fmt", "a", "b") @@ -54,3 +54,21 @@ sub = Changed Sub String assert.Equal(t, []string{"lang1", "lang2"}, langs) assert.Equal(t, []string{"Lang1", "Lang2"}, descs) } + +func TestLocaleStoreMoreSource(t *testing.T) { + testData1 := []byte(` +a=11 +b=12 +`) + + testData2 := []byte(` +b=21 +c=22 +`) + + ls := NewLocaleStore() + assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", testData1, testData2)) + assert.Equal(t, "11", ls.Tr("lang1", "a")) + assert.Equal(t, "21", ls.Tr("lang1", "b")) + assert.Equal(t, "22", ls.Tr("lang1", "c")) +} diff --git a/modules/translation/translation.go b/modules/translation/translation.go index da9d9b9b6851c..fc55a54baeaa9 100644 --- a/modules/translation/translation.go +++ b/modules/translation/translation.go @@ -60,9 +60,9 @@ func InitLocales() { log.Fatal("Failed to list locale files: %v", err) } - localFiles := make(map[string][]byte, len(localeNames)) + localeData := make(map[string][]byte, len(localeNames)) for _, name := range localeNames { - localFiles[name], err = options.Locale(name) + localeData[name], err = options.Locale(name) if err != nil { log.Fatal("Failed to load %s locale file. %v", name, err) } @@ -75,8 +75,16 @@ func InitLocales() { matcher = language.NewMatcher(supportedTags) for i := range setting.Names { + var localeDataBase []byte + if i == 0 && setting.Langs[0] != "en-US" { + // Only en-US has complete translations. When use other language as default, the en-US should still be used as fallback. + localeDataBase = localeData["locale_en-US.ini"] + if localeDataBase == nil { + log.Fatal("Failed to load locale_en-US.ini file.") + } + } key := "locale_" + setting.Langs[i] + ".ini" - if err = i18n.DefaultLocales.AddLocaleByIni(setting.Langs[i], setting.Names[i], localFiles[key]); err != nil { + if err = i18n.DefaultLocales.AddLocaleByIni(setting.Langs[i], setting.Names[i], localeDataBase, localeData[key]); err != nil { log.Error("Failed to set messages to %s: %v", setting.Langs[i], err) } }