github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/utils/i18n.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package utils 5 6 import ( 7 "fmt" 8 "io/ioutil" 9 "net/http" 10 "os" 11 "path/filepath" 12 "strings" 13 14 "github.com/mattermost/go-i18n/i18n" 15 16 "github.com/mattermost/mattermost-server/v5/mlog" 17 "github.com/mattermost/mattermost-server/v5/model" 18 "github.com/mattermost/mattermost-server/v5/utils/fileutils" 19 ) 20 21 var T i18n.TranslateFunc 22 var TDefault i18n.TranslateFunc 23 var locales map[string]string = make(map[string]string) 24 var settings model.LocalizationSettings 25 26 // this functions loads translations from filesystem if they are not 27 // loaded already and assigns english while loading server config 28 func TranslationsPreInit() error { 29 if T != nil { 30 return nil 31 } 32 33 // Set T even if we fail to load the translations. Lots of shutdown handling code will 34 // segfault trying to handle the error, and the untranslated IDs are strictly better. 35 T = TfuncWithFallback("en") 36 TDefault = TfuncWithFallback("en") 37 38 translationsDir := "i18n" 39 if mattermostPath := os.Getenv("MM_SERVER_PATH"); mattermostPath != "" { 40 translationsDir = filepath.Join(mattermostPath, "i18n") 41 } 42 43 return InitTranslationsWithDir(translationsDir) 44 } 45 46 func InitTranslations(localizationSettings model.LocalizationSettings) error { 47 settings = localizationSettings 48 49 var err error 50 T, err = GetTranslationsBySystemLocale() 51 return err 52 } 53 54 func InitTranslationsWithDir(dir string) error { 55 i18nDirectory, found := fileutils.FindDirRelBinary(dir) 56 if !found { 57 return fmt.Errorf(fmt.Sprintf("Unable to find i18n directory at %q", dir)) 58 } 59 60 files, _ := ioutil.ReadDir(i18nDirectory) 61 for _, f := range files { 62 if filepath.Ext(f.Name()) == ".json" { 63 filename := f.Name() 64 locales[strings.Split(filename, ".")[0]] = filepath.Join(i18nDirectory, filename) 65 66 if err := i18n.LoadTranslationFile(filepath.Join(i18nDirectory, filename)); err != nil { 67 return err 68 } 69 } 70 } 71 72 return nil 73 } 74 75 func GetTranslationsBySystemLocale() (i18n.TranslateFunc, error) { 76 locale := *settings.DefaultServerLocale 77 if _, ok := locales[locale]; !ok { 78 mlog.Warn("Failed to load system translations for", mlog.String("locale", locale), mlog.String("attempting to fall back to default locale", model.DEFAULT_LOCALE)) 79 locale = model.DEFAULT_LOCALE 80 } 81 82 if locales[locale] == "" { 83 return nil, fmt.Errorf("Failed to load system translations for '%v'", model.DEFAULT_LOCALE) 84 } 85 86 translations := TfuncWithFallback(locale) 87 if translations == nil { 88 return nil, fmt.Errorf("Failed to load system translations") 89 } 90 91 mlog.Info("Loaded system translations", mlog.String("for locale", locale), mlog.String("from locale", locales[locale])) 92 return translations, nil 93 } 94 95 func GetUserTranslations(locale string) i18n.TranslateFunc { 96 if _, ok := locales[locale]; !ok { 97 locale = model.DEFAULT_LOCALE 98 } 99 100 translations := TfuncWithFallback(locale) 101 return translations 102 } 103 104 func GetTranslationsAndLocale(r *http.Request) (i18n.TranslateFunc, string) { 105 // This is for checking against locales like pt_BR or zn_CN 106 headerLocaleFull := strings.Split(r.Header.Get("Accept-Language"), ",")[0] 107 // This is for checking against locales like en, es 108 headerLocale := strings.Split(strings.Split(r.Header.Get("Accept-Language"), ",")[0], "-")[0] 109 defaultLocale := *settings.DefaultClientLocale 110 if locales[headerLocaleFull] != "" { 111 translations := TfuncWithFallback(headerLocaleFull) 112 return translations, headerLocaleFull 113 } else if locales[headerLocale] != "" { 114 translations := TfuncWithFallback(headerLocale) 115 return translations, headerLocale 116 } else if locales[defaultLocale] != "" { 117 translations := TfuncWithFallback(defaultLocale) 118 return translations, headerLocale 119 } 120 121 translations := TfuncWithFallback(model.DEFAULT_LOCALE) 122 return translations, model.DEFAULT_LOCALE 123 } 124 125 func GetSupportedLocales() map[string]string { 126 return locales 127 } 128 129 func TfuncWithFallback(pref string) i18n.TranslateFunc { 130 t, _ := i18n.Tfunc(pref) 131 return func(translationID string, args ...interface{}) string { 132 if translated := t(translationID, args...); translated != translationID { 133 return translated 134 } 135 136 t, _ := i18n.Tfunc(model.DEFAULT_LOCALE) 137 return t(translationID, args...) 138 } 139 }