func MobileInit() { initChan := make(chan struct{}) initDone = initChan go func() { defer close(initChan) langs := preferredLanguages() fmt.Printf("PREFERRED LANGUAGES: %v\n", langs) matcher := language.NewMatcher([]language.Tag{ language.MustParse("en_US"), language.MustParse("es_MX"), }) tag, idx, conf := matcher.Match(langs...) fmt.Printf("I think we'll go with %s (%d th place choice with %s confidence)\n", tag, idx, conf) if locale := tag.String(); locale != "en-us" { t, err := loadDictionary(locale) if err != nil { panic(fmt.Sprintf("Cannot load '%s': %s", locale, err)) } translate = t } if t, err := loadDictionary("en-us"); err != nil { panic(fmt.Sprintf("Cannot load 'en-us': %s", err)) } else { translateFallback = t } }() }
func init() { tags := []language.Tag{} for _, s := range strings.Split(supported, " ") { tags = append(tags, language.MustParse(s)) } matcher = language.NewMatcher(tags) Supported = language.NewCoverage(tags) }
func getLanguage(w http.ResponseWriter, r *http.Request) string { var preferred []language.Tag var err error save := false r.ParseForm() lang := r.Form.Get("lang") if lang != "" { preferred, _, err = language.ParseAcceptLanguage(lang) if err != nil { // log err } else { save = true } } if preferred == nil { cookie, err := r.Cookie("lang") if err == nil { preferred, _, err = language.ParseAcceptLanguage(cookie.Value) if err != nil { // log err } } } if preferred == nil { preferred, _, err = language.ParseAcceptLanguage(r.Header.Get("Accept-Language")) if err != nil { // log err } } matcher := language.NewMatcher([]language.Tag{ language.English, language.Italian, language.French, }) code, _, _ := matcher.Match(preferred...) base, _ := code.Base() if save { now := time.Now() expires := now.AddDate(1, 0, 0) http.SetCookie(w, &http.Cookie{ Name: "lang", Value: base.String(), Path: "/", Expires: expires, }) } return base.String() }
// LanguageDefault returns the canonical name of the default encoding for a // given language. func LanguageDefault(tag language.Tag) string { matcherOnce.Do(func() { tags := []language.Tag{} for _, t := range strings.Split(locales, " ") { tags = append(tags, language.MustParse(t)) } matcher = language.NewMatcher(tags) }) _, i, _ := matcher.Match(tag) return canonical[localeMap[i]] // Default is Windows-1252. }
func init() { tags := make([]language.Tag, numSupported) s := supported for i := range tags { p := strings.IndexByte(s, '|') tags[i] = language.Raw.Make(s[:p]) s = s[p+1:] } matcher = language.NewMatcher(tags) Supported = language.NewCoverage(tags) Values = language.NewCoverage(langTagSet.Tags, supportedScripts, supportedRegions) }
func checkLang(srcStr, targStr string) tree.Bool { srcLang := language.Make(srcStr) srcRegion, srcRegionConf := srcLang.Region() targLang := language.Make(targStr) targRegion, targRegionConf := targLang.Region() if srcRegionConf == language.Exact && targRegionConf != language.Exact { return tree.Bool(false) } if srcRegion != targRegion && srcRegionConf == language.Exact && targRegionConf == language.Exact { return tree.Bool(false) } _, _, conf := language.NewMatcher([]language.Tag{srcLang}).Match(targLang) return tree.Bool(conf >= language.High) }
func ExampleParseAcceptLanguage() { // Tags are reordered based on their q rating. A missing q value means 1.0. fmt.Println(language.ParseAcceptLanguage(" nn;q=0.3, en-gb;q=0.8, en,")) m := language.NewMatcher([]language.Tag{language.Norwegian, language.Make("en-AU")}) t, _, _ := language.ParseAcceptLanguage("da, en-gb;q=0.8, en;q=0.7") fmt.Println(m.Match(t...)) // Danish is pretty close to Norwegian. t, _, _ = language.ParseAcceptLanguage(" da, nl") fmt.Println(m.Match(t...)) // Output: // [en en-GB nn] [1 0.8 0.3] <nil> // en-AU 1 High // no 0 High }
//Read all .ini files in dir, where the filenames are BCP 47 tags //Use the language matcher to get the best match for the locale preference func InitI18n(locale, dir string) { pref := language.Make(locale) // falls back to en-US on parse error files, err := ioutil.ReadDir(dir) if err != nil { log.Fatal(err) } serverLangs := make([]language.Tag, 1) serverLangs[0] = language.AmericanEnglish // en-US fallback for _, file := range files { if filepath.Ext(file.Name()) == ".ini" { name := strings.TrimSuffix(file.Name(), ".ini") tag, err := language.Parse(name) if err == nil { serverLangs = append(serverLangs, tag) } } } matcher := language.NewMatcher(serverLangs) tag, _, _ := matcher.Match(pref) fname := filepath.Join(dir, tag.String()+".ini") conf, err := configparser.Read(fname) if err != nil { log.Fatal("cannot read translation file for", tag.String(), err) } formats, err := conf.Section("formats") if err != nil { log.Fatal("Cannot read formats sections in translations for", tag.String(), err) } translations, err := conf.Section("strings") if err != nil { log.Fatal("Cannot read strings sections in translations for", tag.String(), err) } i18nProvider = &i18n{ translation_dir: dir, formats: formats.Options(), translations: translations.Options(), locale: tag, } }
// Init registers locales ll and default locale def for the entire app. func Init(ll Locales, def language.Tag) { if locales != nil { panic(errors.New("i18n: Init called multiple times")) } locales = ll defaultLocale = def if !locales.Has(def) { panic(fmt.Errorf("i18n: default locale %q doesn't exist", def)) } tt := []language.Tag{def} for t := range ll { if t != def { tt = append(tt, t) } } matcher = language.NewMatcher(tt) }
// ExampleDictionary shows how to reduce the amount of data linked into your // binary by only using the predefined Dictionary variables of the languages you // wish to support. func ExampleDictionary() { tags := []language.Tag{ language.English, language.German, language.Japanese, language.Russian, } dicts := []*display.Dictionary{ display.English, display.German, display.Japanese, display.Russian, } m := language.NewMatcher(tags) getDict := func(t language.Tag) *display.Dictionary { _, i, confidence := m.Match(t) // Skip this check if you want to support a fall-back language, which // will be the first one passed to NewMatcher. if confidence == language.No { return nil } return dicts[i] } // The matcher will match Swiss German to German. n := getDict(language.Make("gsw")).Languages() fmt.Println(n.Name(language.German)) fmt.Println(n.Name(language.Make("de-CH"))) fmt.Println(n.Name(language.Make("gsw"))) // Output: // Deutsch // Schweizer Hochdeutsch // Schweizerdeutsch }
package util import ( "golang.org/x/text/language" "net/http" ) var SupportedLanguageMatcher = language.NewMatcher([]language.Tag{ language.SimplifiedChinese, language.English, }) func Language(req *http.Request) language.Tag { tags, _, _ := language.ParseAcceptLanguage(req.Header.Get("Accept-Language")) tag, _, _ := SupportedLanguageMatcher.Match(tags...) return tag }
// license that can be found in the LICENSE file. package language_test import ( "fmt" "net/http" "strings" "golang.org/x/text/language" ) // matcher is a language.Matcher configured for all supported languages. var matcher = language.NewMatcher([]language.Tag{ language.BritishEnglish, language.Norwegian, language.German, }) // handler is a http.HandlerFunc. func handler(w http.ResponseWriter, r *http.Request) { t, q, err := language.ParseAcceptLanguage(r.Header.Get("Accept-Language")) // We ignore the error: the default language will be selected for t == nil. tag, _, _ := matcher.Match(t...) fmt.Printf("%5v (t: %6v; q: %3v; err: %v)\n", tag, t, q, err) } func ExampleParseAcceptLanguage() { for _, al := range []string{ "nn;q=0.3, en-us;q=0.8, en,", "gsw, en;q=0.7, en-US;q=0.8",
func (c *Collator) iter(i int) *iter { // TODO: evaluate performance for making the second iterator optional. return &c._iter[i] } // Supported returns the list of languages for which collating differs from its parent. func Supported() []language.Tag { ids := strings.Split(availableLocales, ",") tags := make([]language.Tag, len(ids)) for i, s := range ids { tags[i] = language.Make(s) } return tags } var matcher = language.NewMatcher(Supported()) // New returns a new Collator initialized for the given locale. func New(t language.Tag, o ...Option) *Collator { tt, index, _ := matcher.Match(t) c := newCollator(colltab.Init(locales[index])) // Set the default options for the retrieved locale. c.setFromTag(tt) // Set options from the user-supplied tag. c.setFromTag(t) // Set the user-supplied options. c.setOptions(o)
package main import ( "C" "golang.org/x/text/language" "log" ) var ( mather = language.NewMatcher([]language.Tag{language.Make("en"), language.Make("ja"), language.Make("zh-TW"), language.Make("zh-CN")}) ) //export preferredLanguageFrom func preferredLanguageFrom(httpAcceptLanguage *string) *string { tag, _, _ := language.ParseAcceptLanguage(*httpAcceptLanguage) t, _, _ := mather.Match(tag...) l := t.String() return &l } //export preferredLanguageFromUseCString func preferredLanguageFromUseCString(cHttpAcceptLanguage *C.char) *C.char { httpAcceptLanguage := C.GoString(cHttpAcceptLanguage) tag, _, _ := language.ParseAcceptLanguage(httpAcceptLanguage) t, _, _ := mather.Match(tag...) return C.CString(t.String()) } func init() {
package admin import ( "github.com/hypertornado/prago" "golang.org/x/text/language" ) var ( supportedLocales = []language.Tag{language.Czech, language.English} languageMatcher = language.NewMatcher(supportedLocales) localeNames = map[string]string{ "cs": "Čeština", "en": "English", } availableLocales = [][2]string{{"en", "English"}, {"cs", "Čeština"}} ) //GetLocale from request func GetLocale(request prago.Request) string { user, hasUser := request.GetData("currentuser").(*User) if hasUser { if validLocale(user.Locale) { return user.Locale } } return localeFromRequest(request) } func validLocale(in string) bool { _, ok := localeNames[in] return ok
// ExampleMatcher_bestMatch gives some examples of getting the best match of // a set of tags to any of the tags of given set. func ExampleMatcher() { // This is the set of tags from which we want to pick the best match. These // can be, for example, the supported languages for some package. tags := []language.Tag{ language.English, language.BritishEnglish, language.French, language.Afrikaans, language.BrazilianPortuguese, language.EuropeanPortuguese, language.Croatian, language.SimplifiedChinese, language.Raw.Make("iw-IL"), language.Raw.Make("iw"), language.Raw.Make("he"), } m := language.NewMatcher(tags) // A simple match. fmt.Println(m.Match(language.Make("fr"))) // Australian English is closer to British than American English. fmt.Println(m.Match(language.Make("en-AU"))) // Default to the first tag passed to the Matcher if there is no match. fmt.Println(m.Match(language.Make("ar"))) // Get the default tag. fmt.Println(m.Match()) fmt.Println("----") // Croatian speakers will likely understand Serbian written in Latin script. fmt.Println(m.Match(language.Make("sr-Latn"))) // We match SimplifiedChinese, but with Low confidence. fmt.Println(m.Match(language.TraditionalChinese)) // Serbian in Latin script is a closer match to Croatian than Traditional // Chinese to Simplified Chinese. fmt.Println(m.Match(language.TraditionalChinese, language.Make("sr-Latn"))) fmt.Println("----") // In case a multiple variants of a language are available, the most spoken // variant is typically returned. fmt.Println(m.Match(language.Portuguese)) // Pick the first value passed to Match in case of a tie. fmt.Println(m.Match(language.Dutch, language.Make("fr-BE"), language.Make("af-NA"))) fmt.Println(m.Match(language.Dutch, language.Make("af-NA"), language.Make("fr-BE"))) fmt.Println("----") // If a Matcher is initialized with a language and it's deprecated version, // it will distinguish between them. fmt.Println(m.Match(language.Raw.Make("iw"))) // However, for non-exact matches, it will treat deprecated versions as // equivalent and consider other factors first. fmt.Println(m.Match(language.Raw.Make("he-IL"))) // Output: // fr 2 Exact // en-GB 1 High // en 0 No // en 0 No // ---- // hr 6 High // zh-Hans 7 Low // hr 6 High // ---- // pt-BR 4 High // fr 2 High // af 3 High // ---- // iw 9 Exact // iw-IL 8 Exact }
func init() { matcher = language.NewMatcher([]language.Tag{ language.AmericanEnglish, language.SimplifiedChinese, }) }
language.French, language.Italian, language.Spanish, language.Japanese, language.Ukrainian, } dicts = []*display.Dictionary{ display.English, display.German, display.French, display.Italian, display.Spanish, display.Japanese, display.Ukrainian, } matcher = language.NewMatcher(tags) ) func init() { // @todo check if this is the proper way to generate the locales for _, tag := range display.Values.Tags() { b, bc := tag.Base() r, rc := tag.Region() if bc >= language.Exact && rc >= language.Low && !b.IsPrivateUse() && !r.IsPrivateUse() && r.IsCountry() { LocaleAvailable.Append(b.String() + LocaleSeparator + r.String()) } } for _, tag := range tags { b, bc := tag.Base() r, rc := tag.Region() if bc >= language.High && rc >= language.Low {
package main import ( "fmt" "golang.org/x/text/language" "golang.org/x/text/language/display" ) var userPrefs = []language.Tag{ language.Make("gsw"), // Swiss German language.Make("fr"), // French } var serverLangs = []language.Tag{ language.AmericanEnglish, // en-US fallback language.German, // de } var matcher = language.NewMatcher(serverLangs) func main() { tag, index, confidence := matcher.Match(userPrefs...) fmt.Printf("best match: %s (%s) index=%d confidence=%v\n", display.English.Tags().Name(tag), display.Self.Name(tag), index, confidence) // best match: German (Deutsch) index=1 confidence=High }