summaryrefslogtreecommitdiffstats
path: root/pkg/i18n/i18n.go
diff options
context:
space:
mode:
authorStefan Haller <stefan@haller-berlin.de>2024-06-23 14:51:03 +0200
committerGitHub <noreply@github.com>2024-06-23 14:51:03 +0200
commitbfe9f233accc31c8ffeecae34ddd9b24c0545d48 (patch)
treee5e6b6282ce81cc5b95486863cfe9d31d6c80d1b /pkg/i18n/i18n.go
parent2ccd9980e3424ca80dfb6564883b0abb38564bfd (diff)
parent741d9a26b626d4dc72d1f8873e0499997e6a7f1e (diff)
Convert TranslationSets to json (#3649)HEADmaster
- **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.go110
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