// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package language_test import ( "fmt" "net/http" "golang.org/x/text/language" ) func ExampleCanonType() { p := func(id string) { fmt.Printf("Default(%s) -> %s\n", id, language.Make(id)) fmt.Printf("BCP47(%s) -> %s\n", id, language.BCP47.Make(id)) fmt.Printf("Macro(%s) -> %s\n", id, language.Macro.Make(id)) fmt.Printf("All(%s) -> %s\n", id, language.All.Make(id)) } p("en-Latn") p("sh") p("zh-cmn") p("bjd") p("iw-Latn-fonipa-u-cu-usd") // Output: // Default(en-Latn) -> en-Latn // BCP47(en-Latn) -> en // Macro(en-Latn) -> en-Latn // All(en-Latn) -> en // Default(sh) -> sr-Latn // BCP47(sh) -> sh // Macro(sh) -> sh // All(sh) -> sr-Latn // Default(zh-cmn) -> cmn // BCP47(zh-cmn) -> cmn // Macro(zh-cmn) -> zh // All(zh-cmn) -> zh // Default(bjd) -> drl // BCP47(bjd) -> drl // Macro(bjd) -> bjd // All(bjd) -> drl // Default(iw-Latn-fonipa-u-cu-usd) -> he-Latn-fonipa-u-cu-usd // BCP47(iw-Latn-fonipa-u-cu-usd) -> he-Latn-fonipa-u-cu-usd // Macro(iw-Latn-fonipa-u-cu-usd) -> iw-Latn-fonipa-u-cu-usd // All(iw-Latn-fonipa-u-cu-usd) -> he-Latn-fonipa-u-cu-usd } func ExampleTag_Base() { fmt.Println(language.Make("und").Base()) fmt.Println(language.Make("und-US").Base()) fmt.Println(language.Make("und-NL").Base()) fmt.Println(language.Make("und-419").Base()) // Latin America fmt.Println(language.Make("und-ZZ").Base()) // Output: // en Low // en High // nl High // es Low // en Low } func ExampleTag_Script() { en := language.Make("en") sr := language.Make("sr") sr_Latn := language.Make("sr_Latn") fmt.Println(en.Script()) fmt.Println(sr.Script()) // Was a script explicitly specified? _, c := sr.Script() fmt.Println(c == language.Exact) _, c = sr_Latn.Script() fmt.Println(c == language.Exact) // Output: // Latn High // Cyrl Low // false // true } func ExampleTag_Region() { ru := language.Make("ru") en := language.Make("en") fmt.Println(ru.Region()) fmt.Println(en.Region()) // Output: // RU Low // US Low } func ExampleRegion_TLD() { us := language.MustParseRegion("US") gb := language.MustParseRegion("GB") uk := language.MustParseRegion("UK") bu := language.MustParseRegion("BU") fmt.Println(us.TLD()) fmt.Println(gb.TLD()) fmt.Println(uk.TLD()) fmt.Println(bu.TLD()) fmt.Println(us.Canonicalize().TLD()) fmt.Println(gb.Canonicalize().TLD()) fmt.Println(uk.Canonicalize().TLD()) fmt.Println(bu.Canonicalize().TLD()) // Output: // US // UK // UK // ZZ language: region is not a valid ccTLD // US // UK // UK // MM } func ExampleCompose() { nl, _ := language.ParseBase("nl") us, _ := language.ParseRegion("US") de := language.Make("de-1901-u-co-phonebk") jp := language.Make("ja-JP") fi := language.Make("fi-x-ing") u, _ := language.ParseExtension("u-nu-arabic") x, _ := language.ParseExtension("x-piglatin") // Combine a base language and region. fmt.Println(language.Compose(nl, us)) // Combine a base language and extension. fmt.Println(language.Compose(nl, x)) // Replace the region. fmt.Println(language.Compose(jp, us)) // Combine several tags. fmt.Println(language.Compose(us, nl, u)) // Replace the base language of a tag. fmt.Println(language.Compose(de, nl)) fmt.Println(language.Compose(de, nl, u)) // Remove the base language. fmt.Println(language.Compose(de, language.Base{})) // Remove all variants. fmt.Println(language.Compose(de, []language.Variant{})) // Remove all extensions. fmt.Println(language.Compose(de, []language.Extension{})) fmt.Println(language.Compose(fi, []language.Extension{})) // Remove all variants and extensions. fmt.Println(language.Compose(de.Raw())) // An error is gobbled or returned if non-nil. fmt.Println(language.Compose(language.ParseRegion("ZA"))) fmt.Println(language.Compose(language.ParseRegion("HH"))) // Compose uses the same Default canonicalization as Make. fmt.Println(language.Compose(language.Raw.Parse("en-Latn-UK"))) // Call compose on a different CanonType for different results. fmt.Println(language.All.Compose(language.Raw.Parse("en-Latn-UK"))) // Output: // nl-US // nl-x-piglatin // ja-US // nl-US-u-nu-arabic // nl-1901-u-co-phonebk // nl-1901-u-nu-arabic // und-1901-u-co-phonebk // de-u-co-phonebk // de-1901 // fi // de // und-ZA // und language: subtag "HH" is well-formed but unknown // en-Latn-GB // en-GB } func ExampleParse_errors() { for _, s := range []string{"Foo", "Bar", "Foobar"} { _, err := language.Parse(s) if err != nil { if inv, ok := err.(language.ValueError); ok { fmt.Println(inv.Subtag()) } else { fmt.Println(s) } } } for _, s := range []string{"en", "aa-Uuuu", "AC", "ac-u"} { _, err := language.Parse(s) switch e := err.(type) { case language.ValueError: fmt.Printf("%s: culprit %q\n", s, e.Subtag()) case nil: // No error. default: // A syntax error. fmt.Printf("%s: ill-formed\n", s) } } // Output: // foo // Foobar // aa-Uuuu: culprit "Uuuu" // AC: culprit "ac" // ac-u: ill-formed } func ExampleParent() { p := func(tag string) { fmt.Printf("parent(%v): %v\n", tag, language.Make(tag).Parent()) } p("zh-CN") // Australian English inherits from World English. p("en-AU") // If the tag has a different maximized script from its parent, a tag with // this maximized script is inserted. This allows different language tags // which have the same base language and script in common to inherit from // a common set of settings. p("zh-HK") // If the maximized script of the parent is not identical, CLDR will skip // inheriting from it, as it means there will not be many entries in common // and inheriting from it is nonsensical. p("zh-Hant") // The parent of a tag with variants and extensions is the tag with all // variants and extensions removed. p("de-1994-u-co-phonebk") // Remove default script. p("de-Latn-LU") // Output: // parent(zh-CN): zh // parent(en-AU): en-001 // parent(zh-HK): zh-Hant // parent(zh-Hant): und // parent(de-1994-u-co-phonebk): de // parent(de-Latn-LU): de } // 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("----") // Someone specifying sr-Latn is probably fine with getting Croatian. 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"))) fmt.Println("----") // User settings passed to the Unicode extension are ignored for matching // and preserved in the returned tag. fmt.Println(m.Match(language.Make("de-u-co-phonebk"), language.Make("fr-u-cu-frf"))) // Even if the matching language is different. fmt.Println(m.Match(language.Make("de-u-co-phonebk"), language.Make("br-u-cu-frf"))) // If there is no matching language, the options of the first preferred tag are used. fmt.Println(m.Match(language.Make("de-u-co-phonebk"))) // 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 // he 10 Exact // ---- // fr-u-cu-frf 2 Exact // fr-u-cu-frf 2 High // en-u-co-phonebk 0 No // TODO: "he" should be "he-u-rg-IL High" } func ExampleMatchStrings() { // languages supported by this service: matcher := language.NewMatcher([]language.Tag{ language.English, language.Dutch, language.German, }) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { lang, _ := r.Cookie("lang") tag, _ := language.MatchStrings(matcher, lang.String(), r.Header.Get("Accept-Language")) fmt.Println("User language:", tag) }) } func ExampleComprehends() { // Various levels of comprehensibility. fmt.Println(language.Comprehends(language.English, language.English)) fmt.Println(language.Comprehends(language.AmericanEnglish, language.BritishEnglish)) // An explicit Und results in no match. fmt.Println(language.Comprehends(language.English, language.Und)) fmt.Println("----") // There is usually no mutual comprehensibility between different scripts. fmt.Println(language.Comprehends(language.Make("en-Dsrt"), language.English)) // One exception is for Traditional versus Simplified Chinese, albeit with // a low confidence. fmt.Println(language.Comprehends(language.TraditionalChinese, language.SimplifiedChinese)) fmt.Println("----") // A Swiss German speaker will often understand High German. fmt.Println(language.Comprehends(language.Make("gsw"), language.Make("de"))) // The converse is not generally the case. fmt.Println(language.Comprehends(language.Make("de"), language.Make("gsw"))) // Output: // Exact // High // No // ---- // No // Low // ---- // High // No } func ExampleTag_values() { us := language.MustParseRegion("US") en := language.MustParseBase("en") lang, _, region := language.AmericanEnglish.Raw() fmt.Println(lang == en, region == us) lang, _, region = language.BritishEnglish.Raw() fmt.Println(lang == en, region == us) // Tags can be compared for exact equivalence using '=='. en_us, _ := language.Compose(en, us) fmt.Println(en_us == language.AmericanEnglish) // Output: // true true // true false // true }