examples_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package language_test
  5. import (
  6. "fmt"
  7. "net/http"
  8. "golang.org/x/text/language"
  9. )
  10. func ExampleCanonType() {
  11. p := func(id string) {
  12. fmt.Printf("Default(%s) -> %s\n", id, language.Make(id))
  13. fmt.Printf("BCP47(%s) -> %s\n", id, language.BCP47.Make(id))
  14. fmt.Printf("Macro(%s) -> %s\n", id, language.Macro.Make(id))
  15. fmt.Printf("All(%s) -> %s\n", id, language.All.Make(id))
  16. }
  17. p("en-Latn")
  18. p("sh")
  19. p("zh-cmn")
  20. p("bjd")
  21. p("iw-Latn-fonipa-u-cu-usd")
  22. // Output:
  23. // Default(en-Latn) -> en-Latn
  24. // BCP47(en-Latn) -> en
  25. // Macro(en-Latn) -> en-Latn
  26. // All(en-Latn) -> en
  27. // Default(sh) -> sr-Latn
  28. // BCP47(sh) -> sh
  29. // Macro(sh) -> sh
  30. // All(sh) -> sr-Latn
  31. // Default(zh-cmn) -> cmn
  32. // BCP47(zh-cmn) -> cmn
  33. // Macro(zh-cmn) -> zh
  34. // All(zh-cmn) -> zh
  35. // Default(bjd) -> drl
  36. // BCP47(bjd) -> drl
  37. // Macro(bjd) -> bjd
  38. // All(bjd) -> drl
  39. // Default(iw-Latn-fonipa-u-cu-usd) -> he-Latn-fonipa-u-cu-usd
  40. // BCP47(iw-Latn-fonipa-u-cu-usd) -> he-Latn-fonipa-u-cu-usd
  41. // Macro(iw-Latn-fonipa-u-cu-usd) -> iw-Latn-fonipa-u-cu-usd
  42. // All(iw-Latn-fonipa-u-cu-usd) -> he-Latn-fonipa-u-cu-usd
  43. }
  44. func ExampleTag_Base() {
  45. fmt.Println(language.Make("und").Base())
  46. fmt.Println(language.Make("und-US").Base())
  47. fmt.Println(language.Make("und-NL").Base())
  48. fmt.Println(language.Make("und-419").Base()) // Latin America
  49. fmt.Println(language.Make("und-ZZ").Base())
  50. // Output:
  51. // en Low
  52. // en High
  53. // nl High
  54. // es Low
  55. // en Low
  56. }
  57. func ExampleTag_Script() {
  58. en := language.Make("en")
  59. sr := language.Make("sr")
  60. sr_Latn := language.Make("sr_Latn")
  61. fmt.Println(en.Script())
  62. fmt.Println(sr.Script())
  63. // Was a script explicitly specified?
  64. _, c := sr.Script()
  65. fmt.Println(c == language.Exact)
  66. _, c = sr_Latn.Script()
  67. fmt.Println(c == language.Exact)
  68. // Output:
  69. // Latn High
  70. // Cyrl Low
  71. // false
  72. // true
  73. }
  74. func ExampleTag_Region() {
  75. ru := language.Make("ru")
  76. en := language.Make("en")
  77. fmt.Println(ru.Region())
  78. fmt.Println(en.Region())
  79. // Output:
  80. // RU Low
  81. // US Low
  82. }
  83. func ExampleRegion_TLD() {
  84. us := language.MustParseRegion("US")
  85. gb := language.MustParseRegion("GB")
  86. uk := language.MustParseRegion("UK")
  87. bu := language.MustParseRegion("BU")
  88. fmt.Println(us.TLD())
  89. fmt.Println(gb.TLD())
  90. fmt.Println(uk.TLD())
  91. fmt.Println(bu.TLD())
  92. fmt.Println(us.Canonicalize().TLD())
  93. fmt.Println(gb.Canonicalize().TLD())
  94. fmt.Println(uk.Canonicalize().TLD())
  95. fmt.Println(bu.Canonicalize().TLD())
  96. // Output:
  97. // US <nil>
  98. // UK <nil>
  99. // UK <nil>
  100. // ZZ language: region is not a valid ccTLD
  101. // US <nil>
  102. // UK <nil>
  103. // UK <nil>
  104. // MM <nil>
  105. }
  106. func ExampleCompose() {
  107. nl, _ := language.ParseBase("nl")
  108. us, _ := language.ParseRegion("US")
  109. de := language.Make("de-1901-u-co-phonebk")
  110. jp := language.Make("ja-JP")
  111. fi := language.Make("fi-x-ing")
  112. u, _ := language.ParseExtension("u-nu-arabic")
  113. x, _ := language.ParseExtension("x-piglatin")
  114. // Combine a base language and region.
  115. fmt.Println(language.Compose(nl, us))
  116. // Combine a base language and extension.
  117. fmt.Println(language.Compose(nl, x))
  118. // Replace the region.
  119. fmt.Println(language.Compose(jp, us))
  120. // Combine several tags.
  121. fmt.Println(language.Compose(us, nl, u))
  122. // Replace the base language of a tag.
  123. fmt.Println(language.Compose(de, nl))
  124. fmt.Println(language.Compose(de, nl, u))
  125. // Remove the base language.
  126. fmt.Println(language.Compose(de, language.Base{}))
  127. // Remove all variants.
  128. fmt.Println(language.Compose(de, []language.Variant{}))
  129. // Remove all extensions.
  130. fmt.Println(language.Compose(de, []language.Extension{}))
  131. fmt.Println(language.Compose(fi, []language.Extension{}))
  132. // Remove all variants and extensions.
  133. fmt.Println(language.Compose(de.Raw()))
  134. // An error is gobbled or returned if non-nil.
  135. fmt.Println(language.Compose(language.ParseRegion("ZA")))
  136. fmt.Println(language.Compose(language.ParseRegion("HH")))
  137. // Compose uses the same Default canonicalization as Make.
  138. fmt.Println(language.Compose(language.Raw.Parse("en-Latn-UK")))
  139. // Call compose on a different CanonType for different results.
  140. fmt.Println(language.All.Compose(language.Raw.Parse("en-Latn-UK")))
  141. // Output:
  142. // nl-US <nil>
  143. // nl-x-piglatin <nil>
  144. // ja-US <nil>
  145. // nl-US-u-nu-arabic <nil>
  146. // nl-1901-u-co-phonebk <nil>
  147. // nl-1901-u-co-phonebk-nu-arabic <nil>
  148. // und-1901-u-co-phonebk <nil>
  149. // de-u-co-phonebk <nil>
  150. // de-1901 <nil>
  151. // fi <nil>
  152. // de <nil>
  153. // und-ZA <nil>
  154. // und language: subtag "HH" is well-formed but unknown
  155. // en-Latn-GB <nil>
  156. // en-GB <nil>
  157. }
  158. func ExampleParse_errors() {
  159. for _, s := range []string{"Foo", "Bar", "Foobar"} {
  160. _, err := language.Parse(s)
  161. if err != nil {
  162. if inv, ok := err.(language.ValueError); ok {
  163. fmt.Println(inv.Subtag())
  164. } else {
  165. fmt.Println(s)
  166. }
  167. }
  168. }
  169. for _, s := range []string{"en", "aa-Uuuu", "AC", "ac-u"} {
  170. _, err := language.Parse(s)
  171. switch e := err.(type) {
  172. case language.ValueError:
  173. fmt.Printf("%s: culprit %q\n", s, e.Subtag())
  174. case nil:
  175. // No error.
  176. default:
  177. // A syntax error.
  178. fmt.Printf("%s: ill-formed\n", s)
  179. }
  180. }
  181. // Output:
  182. // foo
  183. // Foobar
  184. // aa-Uuuu: culprit "Uuuu"
  185. // AC: culprit "ac"
  186. // ac-u: ill-formed
  187. }
  188. func ExampleTag_Parent() {
  189. p := func(tag string) {
  190. fmt.Printf("parent(%v): %v\n", tag, language.Make(tag).Parent())
  191. }
  192. p("zh-CN")
  193. // Australian English inherits from World English.
  194. p("en-AU")
  195. // If the tag has a different maximized script from its parent, a tag with
  196. // this maximized script is inserted. This allows different language tags
  197. // which have the same base language and script in common to inherit from
  198. // a common set of settings.
  199. p("zh-HK")
  200. // If the maximized script of the parent is not identical, CLDR will skip
  201. // inheriting from it, as it means there will not be many entries in common
  202. // and inheriting from it is nonsensical.
  203. p("zh-Hant")
  204. // The parent of a tag with variants and extensions is the tag with all
  205. // variants and extensions removed.
  206. p("de-1994-u-co-phonebk")
  207. // Remove default script.
  208. p("de-Latn-LU")
  209. // Output:
  210. // parent(zh-CN): zh
  211. // parent(en-AU): en-001
  212. // parent(zh-HK): zh-Hant
  213. // parent(zh-Hant): und
  214. // parent(de-1994-u-co-phonebk): de
  215. // parent(de-Latn-LU): de
  216. }
  217. // ExampleMatcher_bestMatch gives some examples of getting the best match of
  218. // a set of tags to any of the tags of given set.
  219. func ExampleMatcher() {
  220. // This is the set of tags from which we want to pick the best match. These
  221. // can be, for example, the supported languages for some package.
  222. tags := []language.Tag{
  223. language.English,
  224. language.BritishEnglish,
  225. language.French,
  226. language.Afrikaans,
  227. language.BrazilianPortuguese,
  228. language.EuropeanPortuguese,
  229. language.Croatian,
  230. language.SimplifiedChinese,
  231. language.Raw.Make("iw-IL"),
  232. language.Raw.Make("iw"),
  233. language.Raw.Make("he"),
  234. }
  235. m := language.NewMatcher(tags)
  236. // A simple match.
  237. fmt.Println(m.Match(language.Make("fr")))
  238. // Australian English is closer to British than American English.
  239. fmt.Println(m.Match(language.Make("en-AU")))
  240. // Default to the first tag passed to the Matcher if there is no match.
  241. fmt.Println(m.Match(language.Make("ar")))
  242. // Get the default tag.
  243. fmt.Println(m.Match())
  244. fmt.Println("----")
  245. // Someone specifying sr-Latn is probably fine with getting Croatian.
  246. fmt.Println(m.Match(language.Make("sr-Latn")))
  247. // We match SimplifiedChinese, but with Low confidence.
  248. fmt.Println(m.Match(language.TraditionalChinese))
  249. // Serbian in Latin script is a closer match to Croatian than Traditional
  250. // Chinese to Simplified Chinese.
  251. fmt.Println(m.Match(language.TraditionalChinese, language.Make("sr-Latn")))
  252. fmt.Println("----")
  253. // In case a multiple variants of a language are available, the most spoken
  254. // variant is typically returned.
  255. fmt.Println(m.Match(language.Portuguese))
  256. // Pick the first value passed to Match in case of a tie.
  257. fmt.Println(m.Match(language.Dutch, language.Make("fr-BE"), language.Make("af-NA")))
  258. fmt.Println(m.Match(language.Dutch, language.Make("af-NA"), language.Make("fr-BE")))
  259. fmt.Println("----")
  260. // If a Matcher is initialized with a language and it's deprecated version,
  261. // it will distinguish between them.
  262. fmt.Println(m.Match(language.Raw.Make("iw")))
  263. // However, for non-exact matches, it will treat deprecated versions as
  264. // equivalent and consider other factors first.
  265. fmt.Println(m.Match(language.Raw.Make("he-IL")))
  266. fmt.Println("----")
  267. // User settings passed to the Unicode extension are ignored for matching
  268. // and preserved in the returned tag.
  269. fmt.Println(m.Match(language.Make("de-u-co-phonebk"), language.Make("fr-u-cu-frf")))
  270. // Even if the matching language is different.
  271. fmt.Println(m.Match(language.Make("de-u-co-phonebk"), language.Make("br-u-cu-frf")))
  272. // If there is no matching language, the options of the first preferred tag are used.
  273. fmt.Println(m.Match(language.Make("de-u-co-phonebk")))
  274. // Output:
  275. // fr 2 Exact
  276. // en-GB 1 High
  277. // en 0 No
  278. // en 0 No
  279. // ----
  280. // hr 6 High
  281. // zh-Hans 7 Low
  282. // hr 6 High
  283. // ----
  284. // pt-BR 4 High
  285. // fr 2 High
  286. // af 3 High
  287. // ----
  288. // iw 9 Exact
  289. // he 10 Exact
  290. // ----
  291. // fr-u-cu-frf 2 Exact
  292. // fr-u-cu-frf 2 High
  293. // en-u-co-phonebk 0 No
  294. // TODO: "he" should be "he-u-rg-IL High"
  295. }
  296. func ExampleMatchStrings() {
  297. // languages supported by this service:
  298. matcher := language.NewMatcher([]language.Tag{
  299. language.English, language.Dutch, language.German,
  300. })
  301. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  302. lang, _ := r.Cookie("lang")
  303. tag, _ := language.MatchStrings(matcher, lang.String(), r.Header.Get("Accept-Language"))
  304. fmt.Println("User language:", tag)
  305. })
  306. }
  307. func ExampleComprehends() {
  308. // Various levels of comprehensibility.
  309. fmt.Println(language.Comprehends(language.English, language.English))
  310. fmt.Println(language.Comprehends(language.AmericanEnglish, language.BritishEnglish))
  311. // An explicit Und results in no match.
  312. fmt.Println(language.Comprehends(language.English, language.Und))
  313. fmt.Println("----")
  314. // There is usually no mutual comprehensibility between different scripts.
  315. fmt.Println(language.Comprehends(language.Make("en-Dsrt"), language.English))
  316. // One exception is for Traditional versus Simplified Chinese, albeit with
  317. // a low confidence.
  318. fmt.Println(language.Comprehends(language.TraditionalChinese, language.SimplifiedChinese))
  319. fmt.Println("----")
  320. // A Swiss German speaker will often understand High German.
  321. fmt.Println(language.Comprehends(language.Make("gsw"), language.Make("de")))
  322. // The converse is not generally the case.
  323. fmt.Println(language.Comprehends(language.Make("de"), language.Make("gsw")))
  324. // Output:
  325. // Exact
  326. // High
  327. // No
  328. // ----
  329. // No
  330. // Low
  331. // ----
  332. // High
  333. // No
  334. }
  335. func ExampleTag_values() {
  336. us := language.MustParseRegion("US")
  337. en := language.MustParseBase("en")
  338. lang, _, region := language.AmericanEnglish.Raw()
  339. fmt.Println(lang == en, region == us)
  340. lang, _, region = language.BritishEnglish.Raw()
  341. fmt.Println(lang == en, region == us)
  342. // Tags can be compared for exact equivalence using '=='.
  343. en_us, _ := language.Compose(en, us)
  344. fmt.Println(en_us == language.AmericanEnglish)
  345. // Output:
  346. // true true
  347. // true false
  348. // true
  349. }