diff options
author | Stefan Haller <stefan@haller-berlin.de> | 2024-06-23 14:51:03 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-23 14:51:03 +0200 |
commit | bfe9f233accc31c8ffeecae34ddd9b24c0545d48 (patch) | |
tree | e5e6b6282ce81cc5b95486863cfe9d31d6c80d1b /pkg/i18n/i18n.go | |
parent | 2ccd9980e3424ca80dfb6564883b0abb38564bfd (diff) | |
parent | 741d9a26b626d4dc72d1f8873e0499997e6a7f1e (diff) |
- **PR Description**
This lays the ground for translating lazygit's texts using a translation
system such as Crowdin, Weblate, or Poeditor.
See #3070.
Diffstat (limited to 'pkg/i18n/i18n.go')
-rw-r--r-- | pkg/i18n/i18n.go | 110 |
1 files changed, 85 insertions, 25 deletions
diff --git a/pkg/i18n/i18n.go b/pkg/i18n/i18n.go index d7358775f..ea5fcbb06 100644 --- a/pkg/i18n/i18n.go +++ b/pkg/i18n/i18n.go @@ -1,60 +1,120 @@ package i18n import ( + "embed" + "encoding/json" + "io/fs" + "path/filepath" "strings" "github.com/cloudfoundry/jibber_jabber" "github.com/go-errors/errors" "github.com/imdario/mergo" + "github.com/samber/lo" "github.com/sirupsen/logrus" ) -// Localizer will translate a message into the user's language -type Localizer struct { - Log *logrus.Entry - S TranslationSet -} - func NewTranslationSetFromConfig(log *logrus.Entry, configLanguage string) (*TranslationSet, error) { + languageCodes, err := getSupportedLanguageCodes() + if err != nil { + return nil, err + } + if configLanguage == "auto" { language := detectLanguage(jibber_jabber.DetectIETF) - return NewTranslationSet(log, language), nil + for _, languageCode := range languageCodes { + if strings.HasPrefix(language, languageCode) { + return newTranslationSet(log, language) + } + } + + // Detecting a language that we don't have a translation for is not an + // error, we'll just use English. + return EnglishTranslationSet(), nil } - for key := range GetTranslationSets() { + if configLanguage == "en" { + return EnglishTranslationSet(), nil + } + + for _, key := range languageCodes { if key == configLanguage { - return NewTranslationSet(log, configLanguage), nil + return newTranslationSet(log, configLanguage) } } - return NewTranslationSet(log, "en"), errors.New("Language not found: " + configLanguage) + // Configuring a language that we don't have a translation for *is* an + // error, though. + return nil, errors.New("Language not found: " + configLanguage) } -func NewTranslationSet(log *logrus.Entry, language string) *TranslationSet { +func newTranslationSet(log *logrus.Entry, language string) (*TranslationSet, error) { log.Info("language: " + language) baseSet := EnglishTranslationSet() - for languageCode, translationSet := range GetTranslationSets() { - if strings.HasPrefix(language, languageCode) { - _ = mergo.Merge(&baseSet, translationSet, mergo.WithOverride) + if language != "en" { + translationSet, err := readLanguageFile(language) + if err != nil { + return nil, err + } + err = mergo.Merge(baseSet, *translationSet, mergo.WithOverride) + if err != nil { + return nil, err } } - return &baseSet + + return baseSet, nil +} + +//go:embed translations/*.json +var embedFS embed.FS + +// getSupportedLanguageCodes gets all the supported language codes. +// Note: this doesn't include "en" +func getSupportedLanguageCodes() ([]string, error) { + dirEntries, err := embedFS.ReadDir("translations") + if err != nil { + return nil, err + } + return lo.Map(dirEntries, func(entry fs.DirEntry, _ int) string { + return strings.TrimSuffix(entry.Name(), ".json") + }), nil +} + +func readLanguageFile(languageCode string) (*TranslationSet, error) { + jsonData, err := embedFS.ReadFile(filepath.Join("translations", languageCode+".json")) + if err != nil { + return nil, err + } + var translationSet TranslationSet + err = json.Unmarshal(jsonData, &translationSet) + if err != nil { + return nil, err + } + return &translationSet, nil } // GetTranslationSets gets all the translation sets, keyed by language code -func GetTranslationSets() map[string]TranslationSet { - return map[string]TranslationSet{ - "pl": polishTranslationSet(), - "nl": dutchTranslationSet(), - "en": EnglishTranslationSet(), - "zh-CN": chineseTranslationSet(), // Simplified Chinese - "zh-TW": traditionalChineseTranslationSet(), - "ja": japaneseTranslationSet(), - "ko": koreanTranslationSet(), - "ru": RussianTranslationSet(), +// This includes "en". +func GetTranslationSets() (map[string]*TranslationSet, error) { + languageCodes, err := getSupportedLanguageCodes() + if err != nil { + return nil, err } + + result := make(map[string]*TranslationSet) + result["en"] = EnglishTranslationSet() + + for _, languageCode := range languageCodes { + translationSet, err := readLanguageFile(languageCode) + if err != nil { + return nil, err + } + result[languageCode] = translationSet + } + + return result, nil } // detectLanguage extracts user language from environment |