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  }