4
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2025-07-04 11:17:45 +00:00

Add vendor github.com/dfordsoft/golib/ic

This commit is contained in:
Wim
2018-05-11 21:54:32 +02:00
parent 406a54b597
commit bf0b9959d1
60 changed files with 36737 additions and 28431 deletions

View File

@ -1,16 +0,0 @@
// This file was generated by go generate; DO NOT EDIT
package language
// This file contains code common to the maketables.go and the package code.
// langAliasType is the type of an alias in langAliasMap.
type langAliasType int8
const (
langDeprecated langAliasType = iota
langMacro
langLegacy
langAliasTypeUnknown langAliasType = -1
)

View File

@ -7,6 +7,8 @@ package language
import (
"fmt"
"sort"
"golang.org/x/text/internal/language"
)
// The Coverage interface is used to define the level of coverage of an
@ -44,9 +46,9 @@ type allSubtags struct{}
// consecutive range, it simply returns a slice of numbers in increasing order.
// The "undefined" region is not returned.
func (s allSubtags) Regions() []Region {
reg := make([]Region, numRegions)
reg := make([]Region, language.NumRegions)
for i := range reg {
reg[i] = Region{regionID(i + 1)}
reg[i] = Region{language.Region(i + 1)}
}
return reg
}
@ -55,9 +57,9 @@ func (s allSubtags) Regions() []Region {
// consecutive range, it simply returns a slice of numbers in increasing order.
// The "undefined" script is not returned.
func (s allSubtags) Scripts() []Script {
scr := make([]Script, numScripts)
scr := make([]Script, language.NumScripts)
for i := range scr {
scr[i] = Script{scriptID(i + 1)}
scr[i] = Script{language.Script(i + 1)}
}
return scr
}
@ -65,22 +67,10 @@ func (s allSubtags) Scripts() []Script {
// BaseLanguages returns the list of all supported base languages. It generates
// the list by traversing the internal structures.
func (s allSubtags) BaseLanguages() []Base {
base := make([]Base, 0, numLanguages)
for i := 0; i < langNoIndexOffset; i++ {
// We included "und" already for the value 0.
if i != nonCanonicalUnd {
base = append(base, Base{langID(i)})
}
}
i := langNoIndexOffset
for _, v := range langNoIndex {
for k := 0; k < 8; k++ {
if v&1 == 1 {
base = append(base, Base{langID(i)})
}
v >>= 1
i++
}
bs := language.BaseLanguages()
base := make([]Base, len(bs))
for i, b := range bs {
base[i] = Base{b}
}
return base
}
@ -134,7 +124,7 @@ func (s *coverage) BaseLanguages() []Base {
}
a := make([]Base, len(tags))
for i, t := range tags {
a[i] = Base{langID(t.lang)}
a[i] = Base{language.Language(t.lang())}
}
sort.Sort(bases(a))
k := 0

View File

@ -15,8 +15,10 @@
package display // import "golang.org/x/text/language/display"
import (
"fmt"
"strings"
"golang.org/x/text/internal/format"
"golang.org/x/text/language"
)
@ -32,6 +34,65 @@ All fairly low priority at the moment:
- Consider compressing infrequently used languages and decompress on demand.
*/
// A Formatter formats a tag in the current language. It is used in conjunction
// with the message package.
type Formatter struct {
lookup func(tag int, x interface{}) string
x interface{}
}
// Format implements "golang.org/x/text/internal/format".Formatter.
func (f Formatter) Format(state format.State, verb rune) {
// TODO: there are a lot of inefficiencies in this code. Fix it when we
// language.Tag has embedded compact tags.
t := state.Language()
_, index, _ := matcher.Match(t)
str := f.lookup(index, f.x)
if str == "" {
// TODO: use language-specific punctuation.
// TODO: use codePattern instead of language?
if unknown := f.lookup(index, language.Und); unknown != "" {
fmt.Fprintf(state, "%v (%v)", unknown, f.x)
} else {
fmt.Fprintf(state, "[language: %v]", f.x)
}
} else {
state.Write([]byte(str))
}
}
// Language returns a Formatter that renders the name for lang in the
// the current language. x may be a language.Base or a language.Tag.
// It renders lang in the default language if no translation for the current
// language is supported.
func Language(lang interface{}) Formatter {
return Formatter{langFunc, lang}
}
// Region returns a Formatter that renders the name for region in the current
// language. region may be a language.Region or a language.Tag.
// It renders region in the default language if no translation for the current
// language is supported.
func Region(region interface{}) Formatter {
return Formatter{regionFunc, region}
}
// Script returns a Formatter that renders the name for script in the current
// language. script may be a language.Script or a language.Tag.
// It renders script in the default language if no translation for the current
// language is supported.
func Script(script interface{}) Formatter {
return Formatter{scriptFunc, script}
}
// Script returns a Formatter that renders the name for tag in the current
// language. tag may be a language.Tag.
// It renders tag in the default language if no translation for the current
// language is supported.
func Tag(tag interface{}) Formatter {
return Formatter{tagFunc, tag}
}
// A Namer is used to get the name for a given value, such as a Tag, Language,
// Script or Region.
type Namer interface {
@ -84,6 +145,10 @@ func Languages(t language.Tag) Namer {
type languageNamer int
func langFunc(i int, x interface{}) string {
return nameLanguage(languageNamer(i), x)
}
func (n languageNamer) name(i int) string {
return lookup(langHeaders[:], int(n), i)
}
@ -116,6 +181,10 @@ func Scripts(t language.Tag) Namer {
type scriptNamer int
func scriptFunc(i int, x interface{}) string {
return nameScript(scriptNamer(i), x)
}
func (n scriptNamer) name(i int) string {
return lookup(scriptHeaders[:], int(n), i)
}
@ -140,6 +209,10 @@ func Regions(t language.Tag) Namer {
type regionNamer int
func regionFunc(i int, x interface{}) string {
return nameRegion(regionNamer(i), x)
}
func (n regionNamer) name(i int) string {
return lookup(regionHeaders[:], int(n), i)
}
@ -162,6 +235,10 @@ func Tags(t language.Tag) Namer {
type tagNamer int
func tagFunc(i int, x interface{}) string {
return nameTag(languageNamer(i), scriptNamer(i), regionNamer(i), x)
}
// Name implements the Namer interface for tag names.
func (n tagNamer) Name(x interface{}) string {
return nameTag(languageNamer(n), scriptNamer(n), regionNamer(n), x)

View File

@ -205,7 +205,13 @@ func (b *builder) generate() {
b.setData("lang", func(g *group, loc language.Tag, ldn *cldr.LocaleDisplayNames) {
if ldn.Languages != nil {
for _, v := range ldn.Languages.Language {
tag := tagForm.MustParse(v.Type)
lang := v.Type
if lang == "root" {
// We prefer the data from "und"
// TODO: allow both the data for root and und somehow.
continue
}
tag := tagForm.MustParse(lang)
if tags.contains(tag) {
g.set(loc, tag.String(), v.Data())
}

File diff suppressed because it is too large Load Diff

102
vendor/golang.org/x/text/language/doc.go generated vendored Normal file
View File

@ -0,0 +1,102 @@
// Copyright 2017 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 implements BCP 47 language tags and related functionality.
//
// The most important function of package language is to match a list of
// user-preferred languages to a list of supported languages.
// It alleviates the developer of dealing with the complexity of this process
// and provides the user with the best experience
// (see https://blog.golang.org/matchlang).
//
//
// Matching preferred against supported languages
//
// A Matcher for an application that supports English, Australian English,
// Danish, and standard Mandarin can be created as follows:
//
// var matcher = language.NewMatcher([]language.Tag{
// language.English, // The first language is used as fallback.
// language.MustParse("en-AU"),
// language.Danish,
// language.Chinese,
// })
//
// This list of supported languages is typically implied by the languages for
// which there exists translations of the user interface.
//
// User-preferred languages usually come as a comma-separated list of BCP 47
// language tags.
// The MatchString finds best matches for such strings:
//
// handler(w http.ResponseWriter, r *http.Request) {
// lang, _ := r.Cookie("lang")
// accept := r.Header.Get("Accept-Language")
// tag, _ := language.MatchStrings(matcher, lang.String(), accept)
//
// // tag should now be used for the initialization of any
// // locale-specific service.
// }
//
// The Matcher's Match method can be used to match Tags directly.
//
// Matchers are aware of the intricacies of equivalence between languages, such
// as deprecated subtags, legacy tags, macro languages, mutual
// intelligibility between scripts and languages, and transparently passing
// BCP 47 user configuration.
// For instance, it will know that a reader of Bokmål Danish can read Norwegian
// and will know that Cantonese ("yue") is a good match for "zh-HK".
//
//
// Using match results
//
// To guarantee a consistent user experience to the user it is important to
// use the same language tag for the selection of any locale-specific services.
// For example, it is utterly confusing to substitute spelled-out numbers
// or dates in one language in text of another language.
// More subtly confusing is using the wrong sorting order or casing
// algorithm for a certain language.
//
// All the packages in x/text that provide locale-specific services
// (e.g. collate, cases) should be initialized with the tag that was
// obtained at the start of an interaction with the user.
//
// Note that Tag that is returned by Match and MatchString may differ from any
// of the supported languages, as it may contain carried over settings from
// the user tags.
// This may be inconvenient when your application has some additional
// locale-specific data for your supported languages.
// Match and MatchString both return the index of the matched supported tag
// to simplify associating such data with the matched tag.
//
//
// Canonicalization
//
// If one uses the Matcher to compare languages one does not need to
// worry about canonicalization.
//
// The meaning of a Tag varies per application. The language package
// therefore delays canonicalization and preserves information as much
// as possible. The Matcher, however, will always take into account that
// two different tags may represent the same language.
//
// By default, only legacy and deprecated tags are converted into their
// canonical equivalent. All other information is preserved. This approach makes
// the confidence scores more accurate and allows matchers to distinguish
// between variants that are otherwise lost.
//
// As a consequence, two tags that should be treated as identical according to
// BCP 47 or CLDR, like "en-Latn" and "en", will be represented differently. The
// Matcher handles such distinctions, though, and is aware of the
// equivalence relations. The CanonType type can be used to alter the
// canonicalization form.
//
// References
//
// BCP 47 - Tags for Identifying Languages http://tools.ietf.org/html/bcp47
//
package language // import "golang.org/x/text/language"
// TODO: explanation on how to match languages for your own locale-specific
// service.

305
vendor/golang.org/x/text/language/gen.go generated vendored Normal file
View File

@ -0,0 +1,305 @@
// 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.
// +build ignore
// Language tag table generator.
// Data read from the web.
package main
import (
"flag"
"fmt"
"io"
"log"
"sort"
"strconv"
"strings"
"golang.org/x/text/internal/gen"
"golang.org/x/text/internal/language"
"golang.org/x/text/unicode/cldr"
)
var (
test = flag.Bool("test",
false,
"test existing tables; can be used to compare web data with package data.")
outputFile = flag.String("output",
"tables.go",
"output file for generated tables")
)
func main() {
gen.Init()
w := gen.NewCodeWriter()
defer w.WriteGoFile("tables.go", "language")
b := newBuilder(w)
gen.WriteCLDRVersion(w)
b.writeConstants()
b.writeMatchData()
}
type builder struct {
w *gen.CodeWriter
hw io.Writer // MultiWriter for w and w.Hash
data *cldr.CLDR
supp *cldr.SupplementalData
}
func (b *builder) langIndex(s string) uint16 {
return uint16(language.MustParseBase(s))
}
func (b *builder) regionIndex(s string) int {
return int(language.MustParseRegion(s))
}
func (b *builder) scriptIndex(s string) int {
return int(language.MustParseScript(s))
}
func newBuilder(w *gen.CodeWriter) *builder {
r := gen.OpenCLDRCoreZip()
defer r.Close()
d := &cldr.Decoder{}
data, err := d.DecodeZip(r)
if err != nil {
log.Fatal(err)
}
b := builder{
w: w,
hw: io.MultiWriter(w, w.Hash),
data: data,
supp: data.Supplemental(),
}
return &b
}
// writeConsts computes f(v) for all v in values and writes the results
// as constants named _v to a single constant block.
func (b *builder) writeConsts(f func(string) int, values ...string) {
fmt.Fprintln(b.w, "const (")
for _, v := range values {
fmt.Fprintf(b.w, "\t_%s = %v\n", v, f(v))
}
fmt.Fprintln(b.w, ")")
}
// TODO: region inclusion data will probably not be use used in future matchers.
var langConsts = []string{
"de", "en", "fr", "it", "mo", "no", "nb", "pt", "sh", "mul", "und",
}
var scriptConsts = []string{
"Latn", "Hani", "Hans", "Hant", "Qaaa", "Qaai", "Qabx", "Zinh", "Zyyy",
"Zzzz",
}
var regionConsts = []string{
"001", "419", "BR", "CA", "ES", "GB", "MD", "PT", "UK", "US",
"ZZ", "XA", "XC", "XK", // Unofficial tag for Kosovo.
}
func (b *builder) writeConstants() {
b.writeConsts(func(s string) int { return int(b.langIndex(s)) }, langConsts...)
b.writeConsts(b.regionIndex, regionConsts...)
b.writeConsts(b.scriptIndex, scriptConsts...)
}
type mutualIntelligibility struct {
want, have uint16
distance uint8
oneway bool
}
type scriptIntelligibility struct {
wantLang, haveLang uint16
wantScript, haveScript uint8
distance uint8
// Always oneway
}
type regionIntelligibility struct {
lang uint16 // compact language id
script uint8 // 0 means any
group uint8 // 0 means any; if bit 7 is set it means inverse
distance uint8
// Always twoway.
}
// writeMatchData writes tables with languages and scripts for which there is
// mutual intelligibility. The data is based on CLDR's languageMatching data.
// Note that we use a different algorithm than the one defined by CLDR and that
// we slightly modify the data. For example, we convert scores to confidence levels.
// We also drop all region-related data as we use a different algorithm to
// determine region equivalence.
func (b *builder) writeMatchData() {
lm := b.supp.LanguageMatching.LanguageMatches
cldr.MakeSlice(&lm).SelectAnyOf("type", "written_new")
regionHierarchy := map[string][]string{}
for _, g := range b.supp.TerritoryContainment.Group {
regions := strings.Split(g.Contains, " ")
regionHierarchy[g.Type] = append(regionHierarchy[g.Type], regions...)
}
regionToGroups := make([]uint8, language.NumRegions)
idToIndex := map[string]uint8{}
for i, mv := range lm[0].MatchVariable {
if i > 6 {
log.Fatalf("Too many groups: %d", i)
}
idToIndex[mv.Id] = uint8(i + 1)
// TODO: also handle '-'
for _, r := range strings.Split(mv.Value, "+") {
todo := []string{r}
for k := 0; k < len(todo); k++ {
r := todo[k]
regionToGroups[b.regionIndex(r)] |= 1 << uint8(i)
todo = append(todo, regionHierarchy[r]...)
}
}
}
b.w.WriteVar("regionToGroups", regionToGroups)
// maps language id to in- and out-of-group region.
paradigmLocales := [][3]uint16{}
locales := strings.Split(lm[0].ParadigmLocales[0].Locales, " ")
for i := 0; i < len(locales); i += 2 {
x := [3]uint16{}
for j := 0; j < 2; j++ {
pc := strings.SplitN(locales[i+j], "-", 2)
x[0] = b.langIndex(pc[0])
if len(pc) == 2 {
x[1+j] = uint16(b.regionIndex(pc[1]))
}
}
paradigmLocales = append(paradigmLocales, x)
}
b.w.WriteVar("paradigmLocales", paradigmLocales)
b.w.WriteType(mutualIntelligibility{})
b.w.WriteType(scriptIntelligibility{})
b.w.WriteType(regionIntelligibility{})
matchLang := []mutualIntelligibility{}
matchScript := []scriptIntelligibility{}
matchRegion := []regionIntelligibility{}
// Convert the languageMatch entries in lists keyed by desired language.
for _, m := range lm[0].LanguageMatch {
// Different versions of CLDR use different separators.
desired := strings.Replace(m.Desired, "-", "_", -1)
supported := strings.Replace(m.Supported, "-", "_", -1)
d := strings.Split(desired, "_")
s := strings.Split(supported, "_")
if len(d) != len(s) {
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
continue
}
distance, _ := strconv.ParseInt(m.Distance, 10, 8)
switch len(d) {
case 2:
if desired == supported && desired == "*_*" {
continue
}
// language-script pair.
matchScript = append(matchScript, scriptIntelligibility{
wantLang: uint16(b.langIndex(d[0])),
haveLang: uint16(b.langIndex(s[0])),
wantScript: uint8(b.scriptIndex(d[1])),
haveScript: uint8(b.scriptIndex(s[1])),
distance: uint8(distance),
})
if m.Oneway != "true" {
matchScript = append(matchScript, scriptIntelligibility{
wantLang: uint16(b.langIndex(s[0])),
haveLang: uint16(b.langIndex(d[0])),
wantScript: uint8(b.scriptIndex(s[1])),
haveScript: uint8(b.scriptIndex(d[1])),
distance: uint8(distance),
})
}
case 1:
if desired == supported && desired == "*" {
continue
}
if distance == 1 {
// nb == no is already handled by macro mapping. Check there
// really is only this case.
if d[0] != "no" || s[0] != "nb" {
log.Fatalf("unhandled equivalence %s == %s", s[0], d[0])
}
continue
}
// TODO: consider dropping oneway field and just doubling the entry.
matchLang = append(matchLang, mutualIntelligibility{
want: uint16(b.langIndex(d[0])),
have: uint16(b.langIndex(s[0])),
distance: uint8(distance),
oneway: m.Oneway == "true",
})
case 3:
if desired == supported && desired == "*_*_*" {
continue
}
if desired != supported {
// This is now supported by CLDR, but only one case, which
// should already be covered by paradigm locales. For instance,
// test case "und, en, en-GU, en-IN, en-GB ; en-ZA ; en-GB" in
// testdata/CLDRLocaleMatcherTest.txt tests this.
if supported != "en_*_GB" {
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
}
continue
}
ri := regionIntelligibility{
lang: b.langIndex(d[0]),
distance: uint8(distance),
}
if d[1] != "*" {
ri.script = uint8(b.scriptIndex(d[1]))
}
switch {
case d[2] == "*":
ri.group = 0x80 // not contained in anything
case strings.HasPrefix(d[2], "$!"):
ri.group = 0x80
d[2] = "$" + d[2][len("$!"):]
fallthrough
case strings.HasPrefix(d[2], "$"):
ri.group |= idToIndex[d[2]]
}
matchRegion = append(matchRegion, ri)
default:
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
}
}
sort.SliceStable(matchLang, func(i, j int) bool {
return matchLang[i].distance < matchLang[j].distance
})
b.w.WriteComment(`
matchLang holds pairs of langIDs of base languages that are typically
mutually intelligible. Each pair is associated with a confidence and
whether the intelligibility goes one or both ways.`)
b.w.WriteVar("matchLang", matchLang)
b.w.WriteComment(`
matchScript holds pairs of scriptIDs where readers of one script
can typically also read the other. Each is associated with a confidence.`)
sort.SliceStable(matchScript, func(i, j int) bool {
return matchScript[i].distance < matchScript[j].distance
})
b.w.WriteVar("matchScript", matchScript)
sort.SliceStable(matchRegion, func(i, j int) bool {
return matchRegion[i].distance < matchRegion[j].distance
})
b.w.WriteVar("matchRegion", matchRegion)
}

View File

@ -1,20 +0,0 @@
// Copyright 2014 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.
// +build ignore
package main
// This file contains code common to the maketables.go and the package code.
// langAliasType is the type of an alias in langAliasMap.
type langAliasType int8
const (
langDeprecated langAliasType = iota
langMacro
langLegacy
langAliasTypeUnknown langAliasType = -1
)

View File

@ -1,162 +0,0 @@
// Copyright 2015 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.
// +build ignore
package main
// This file generates derivative tables based on the language package itself.
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"reflect"
"sort"
"strings"
"golang.org/x/text/internal/gen"
"golang.org/x/text/language"
"golang.org/x/text/unicode/cldr"
)
var (
test = flag.Bool("test", false,
"test existing tables; can be used to compare web data with package data.")
draft = flag.String("draft",
"contributed",
`Minimal draft requirements (approved, contributed, provisional, unconfirmed).`)
)
func main() {
gen.Init()
// Read the CLDR zip file.
r := gen.OpenCLDRCoreZip()
defer r.Close()
d := &cldr.Decoder{}
data, err := d.DecodeZip(r)
if err != nil {
log.Fatalf("DecodeZip: %v", err)
}
w := gen.NewCodeWriter()
defer func() {
buf := &bytes.Buffer{}
if _, err = w.WriteGo(buf, "language"); err != nil {
log.Fatalf("Error formatting file index.go: %v", err)
}
// Since we're generating a table for our own package we need to rewrite
// doing the equivalent of go fmt -r 'language.b -> b'. Using
// bytes.Replace will do.
out := bytes.Replace(buf.Bytes(), []byte("language."), nil, -1)
if err := ioutil.WriteFile("index.go", out, 0600); err != nil {
log.Fatalf("Could not create file index.go: %v", err)
}
}()
m := map[language.Tag]bool{}
for _, lang := range data.Locales() {
// We include all locales unconditionally to be consistent with en_US.
// We want en_US, even though it has no data associated with it.
// TODO: put any of the languages for which no data exists at the end
// of the index. This allows all components based on ICU to use that
// as the cutoff point.
// if x := data.RawLDML(lang); false ||
// x.LocaleDisplayNames != nil ||
// x.Characters != nil ||
// x.Delimiters != nil ||
// x.Measurement != nil ||
// x.Dates != nil ||
// x.Numbers != nil ||
// x.Units != nil ||
// x.ListPatterns != nil ||
// x.Collations != nil ||
// x.Segmentations != nil ||
// x.Rbnf != nil ||
// x.Annotations != nil ||
// x.Metadata != nil {
// TODO: support POSIX natively, albeit non-standard.
tag := language.Make(strings.Replace(lang, "_POSIX", "-u-va-posix", 1))
m[tag] = true
// }
}
// Include locales for plural rules, which uses a different structure.
for _, plurals := range data.Supplemental().Plurals {
for _, rules := range plurals.PluralRules {
for _, lang := range strings.Split(rules.Locales, " ") {
m[language.Make(lang)] = true
}
}
}
var core, special []language.Tag
for t := range m {
if x := t.Extensions(); len(x) != 0 && fmt.Sprint(x) != "[u-va-posix]" {
log.Fatalf("Unexpected extension %v in %v", x, t)
}
if len(t.Variants()) == 0 && len(t.Extensions()) == 0 {
core = append(core, t)
} else {
special = append(special, t)
}
}
w.WriteComment(`
NumCompactTags is the number of common tags. The maximum tag is
NumCompactTags-1.`)
w.WriteConst("NumCompactTags", len(core)+len(special))
sort.Sort(byAlpha(special))
w.WriteVar("specialTags", special)
// TODO: order by frequency?
sort.Sort(byAlpha(core))
// Size computations are just an estimate.
w.Size += int(reflect.TypeOf(map[uint32]uint16{}).Size())
w.Size += len(core) * 6 // size of uint32 and uint16
fmt.Fprintln(w)
fmt.Fprintln(w, "var coreTags = map[uint32]uint16{")
fmt.Fprintln(w, "0x0: 0, // und")
i := len(special) + 1 // Und and special tags already written.
for _, t := range core {
if t == language.Und {
continue
}
fmt.Fprint(w.Hash, t, i)
b, s, r := t.Raw()
fmt.Fprintf(w, "0x%s%s%s: %d, // %s\n",
getIndex(b, 3), // 3 is enough as it is guaranteed to be a compact number
getIndex(s, 2),
getIndex(r, 3),
i, t)
i++
}
fmt.Fprintln(w, "}")
}
// getIndex prints the subtag type and extracts its index of size nibble.
// If the index is less than n nibbles, the result is prefixed with 0s.
func getIndex(x interface{}, n int) string {
s := fmt.Sprintf("%#v", x) // s is of form Type{typeID: 0x00}
s = s[strings.Index(s, "0x")+2 : len(s)-1]
return strings.Repeat("0", n-len(s)) + s
}
type byAlpha []language.Tag
func (a byAlpha) Len() int { return len(a) }
func (a byAlpha) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byAlpha) Less(i, j int) bool { return a[i].String() < a[j].String() }

View File

@ -1,767 +0,0 @@
// This file was generated by go generate; DO NOT EDIT
package language
// NumCompactTags is the number of common tags. The maximum tag is
// NumCompactTags-1.
const NumCompactTags = 752
var specialTags = []Tag{ // 2 elements
0: {lang: 0xd5, region: 0x6d, script: 0x0, pVariant: 0x5, pExt: 0xe, str: "ca-ES-valencia"},
1: {lang: 0x134, region: 0x134, script: 0x0, pVariant: 0x5, pExt: 0x5, str: "en-US-u-va-posix"},
} // Size: 72 bytes
var coreTags = map[uint32]uint16{
0x0: 0, // und
0x01500000: 3, // af
0x015000d1: 4, // af-NA
0x01500160: 5, // af-ZA
0x01b00000: 6, // agq
0x01b00051: 7, // agq-CM
0x02000000: 8, // ak
0x0200007f: 9, // ak-GH
0x02600000: 10, // am
0x0260006e: 11, // am-ET
0x03900000: 12, // ar
0x03900001: 13, // ar-001
0x03900022: 14, // ar-AE
0x03900038: 15, // ar-BH
0x03900061: 16, // ar-DJ
0x03900066: 17, // ar-DZ
0x0390006a: 18, // ar-EG
0x0390006b: 19, // ar-EH
0x0390006c: 20, // ar-ER
0x03900096: 21, // ar-IL
0x0390009a: 22, // ar-IQ
0x039000a0: 23, // ar-JO
0x039000a7: 24, // ar-KM
0x039000ab: 25, // ar-KW
0x039000af: 26, // ar-LB
0x039000b8: 27, // ar-LY
0x039000b9: 28, // ar-MA
0x039000c8: 29, // ar-MR
0x039000e0: 30, // ar-OM
0x039000ec: 31, // ar-PS
0x039000f2: 32, // ar-QA
0x03900107: 33, // ar-SA
0x0390010a: 34, // ar-SD
0x03900114: 35, // ar-SO
0x03900116: 36, // ar-SS
0x0390011b: 37, // ar-SY
0x0390011f: 38, // ar-TD
0x03900127: 39, // ar-TN
0x0390015d: 40, // ar-YE
0x03f00000: 41, // ars
0x04200000: 42, // as
0x04200098: 43, // as-IN
0x04300000: 44, // asa
0x0430012e: 45, // asa-TZ
0x04700000: 46, // ast
0x0470006d: 47, // ast-ES
0x05700000: 48, // az
0x0571e000: 49, // az-Cyrl
0x0571e031: 50, // az-Cyrl-AZ
0x05752000: 51, // az-Latn
0x05752031: 52, // az-Latn-AZ
0x05d00000: 53, // bas
0x05d00051: 54, // bas-CM
0x07000000: 55, // be
0x07000046: 56, // be-BY
0x07400000: 57, // bem
0x07400161: 58, // bem-ZM
0x07800000: 59, // bez
0x0780012e: 60, // bez-TZ
0x07d00000: 61, // bg
0x07d00037: 62, // bg-BG
0x08100000: 63, // bh
0x09e00000: 64, // bm
0x09e000c2: 65, // bm-ML
0x0a300000: 66, // bn
0x0a300034: 67, // bn-BD
0x0a300098: 68, // bn-IN
0x0a700000: 69, // bo
0x0a700052: 70, // bo-CN
0x0a700098: 71, // bo-IN
0x0b000000: 72, // br
0x0b000077: 73, // br-FR
0x0b300000: 74, // brx
0x0b300098: 75, // brx-IN
0x0b500000: 76, // bs
0x0b51e000: 77, // bs-Cyrl
0x0b51e032: 78, // bs-Cyrl-BA
0x0b552000: 79, // bs-Latn
0x0b552032: 80, // bs-Latn-BA
0x0d500000: 81, // ca
0x0d500021: 82, // ca-AD
0x0d50006d: 83, // ca-ES
0x0d500077: 84, // ca-FR
0x0d50009d: 85, // ca-IT
0x0da00000: 86, // ce
0x0da00105: 87, // ce-RU
0x0dd00000: 88, // cgg
0x0dd00130: 89, // cgg-UG
0x0e300000: 90, // chr
0x0e300134: 91, // chr-US
0x0e700000: 92, // ckb
0x0e70009a: 93, // ckb-IQ
0x0e70009b: 94, // ckb-IR
0x0f600000: 95, // cs
0x0f60005d: 96, // cs-CZ
0x0fa00000: 97, // cu
0x0fa00105: 98, // cu-RU
0x0fc00000: 99, // cy
0x0fc0007a: 100, // cy-GB
0x0fd00000: 101, // da
0x0fd00062: 102, // da-DK
0x0fd00081: 103, // da-GL
0x10400000: 104, // dav
0x104000a3: 105, // dav-KE
0x10900000: 106, // de
0x1090002d: 107, // de-AT
0x10900035: 108, // de-BE
0x1090004d: 109, // de-CH
0x1090005f: 110, // de-DE
0x1090009d: 111, // de-IT
0x109000b1: 112, // de-LI
0x109000b6: 113, // de-LU
0x11300000: 114, // dje
0x113000d3: 115, // dje-NE
0x11b00000: 116, // dsb
0x11b0005f: 117, // dsb-DE
0x12000000: 118, // dua
0x12000051: 119, // dua-CM
0x12400000: 120, // dv
0x12700000: 121, // dyo
0x12700113: 122, // dyo-SN
0x12900000: 123, // dz
0x12900042: 124, // dz-BT
0x12b00000: 125, // ebu
0x12b000a3: 126, // ebu-KE
0x12c00000: 127, // ee
0x12c0007f: 128, // ee-GH
0x12c00121: 129, // ee-TG
0x13100000: 130, // el
0x1310005c: 131, // el-CY
0x13100086: 132, // el-GR
0x13400000: 133, // en
0x13400001: 134, // en-001
0x1340001a: 135, // en-150
0x13400024: 136, // en-AG
0x13400025: 137, // en-AI
0x1340002c: 138, // en-AS
0x1340002d: 139, // en-AT
0x1340002e: 140, // en-AU
0x13400033: 141, // en-BB
0x13400035: 142, // en-BE
0x13400039: 143, // en-BI
0x1340003c: 144, // en-BM
0x13400041: 145, // en-BS
0x13400045: 146, // en-BW
0x13400047: 147, // en-BZ
0x13400048: 148, // en-CA
0x13400049: 149, // en-CC
0x1340004d: 150, // en-CH
0x1340004f: 151, // en-CK
0x13400051: 152, // en-CM
0x1340005b: 153, // en-CX
0x1340005c: 154, // en-CY
0x1340005f: 155, // en-DE
0x13400060: 156, // en-DG
0x13400062: 157, // en-DK
0x13400063: 158, // en-DM
0x1340006c: 159, // en-ER
0x13400071: 160, // en-FI
0x13400072: 161, // en-FJ
0x13400073: 162, // en-FK
0x13400074: 163, // en-FM
0x1340007a: 164, // en-GB
0x1340007b: 165, // en-GD
0x1340007e: 166, // en-GG
0x1340007f: 167, // en-GH
0x13400080: 168, // en-GI
0x13400082: 169, // en-GM
0x13400089: 170, // en-GU
0x1340008b: 171, // en-GY
0x1340008c: 172, // en-HK
0x13400095: 173, // en-IE
0x13400096: 174, // en-IL
0x13400097: 175, // en-IM
0x13400098: 176, // en-IN
0x13400099: 177, // en-IO
0x1340009e: 178, // en-JE
0x1340009f: 179, // en-JM
0x134000a3: 180, // en-KE
0x134000a6: 181, // en-KI
0x134000a8: 182, // en-KN
0x134000ac: 183, // en-KY
0x134000b0: 184, // en-LC
0x134000b3: 185, // en-LR
0x134000b4: 186, // en-LS
0x134000be: 187, // en-MG
0x134000bf: 188, // en-MH
0x134000c5: 189, // en-MO
0x134000c6: 190, // en-MP
0x134000c9: 191, // en-MS
0x134000ca: 192, // en-MT
0x134000cb: 193, // en-MU
0x134000cd: 194, // en-MW
0x134000cf: 195, // en-MY
0x134000d1: 196, // en-NA
0x134000d4: 197, // en-NF
0x134000d5: 198, // en-NG
0x134000d8: 199, // en-NL
0x134000dc: 200, // en-NR
0x134000de: 201, // en-NU
0x134000df: 202, // en-NZ
0x134000e5: 203, // en-PG
0x134000e6: 204, // en-PH
0x134000e7: 205, // en-PK
0x134000ea: 206, // en-PN
0x134000eb: 207, // en-PR
0x134000ef: 208, // en-PW
0x13400106: 209, // en-RW
0x13400108: 210, // en-SB
0x13400109: 211, // en-SC
0x1340010a: 212, // en-SD
0x1340010b: 213, // en-SE
0x1340010c: 214, // en-SG
0x1340010d: 215, // en-SH
0x1340010e: 216, // en-SI
0x13400111: 217, // en-SL
0x13400116: 218, // en-SS
0x1340011a: 219, // en-SX
0x1340011c: 220, // en-SZ
0x1340011e: 221, // en-TC
0x13400124: 222, // en-TK
0x13400128: 223, // en-TO
0x1340012b: 224, // en-TT
0x1340012c: 225, // en-TV
0x1340012e: 226, // en-TZ
0x13400130: 227, // en-UG
0x13400132: 228, // en-UM
0x13400134: 229, // en-US
0x13400138: 230, // en-VC
0x1340013b: 231, // en-VG
0x1340013c: 232, // en-VI
0x1340013e: 233, // en-VU
0x13400141: 234, // en-WS
0x13400160: 235, // en-ZA
0x13400161: 236, // en-ZM
0x13400163: 237, // en-ZW
0x13700000: 238, // eo
0x13700001: 239, // eo-001
0x13900000: 240, // es
0x1390001e: 241, // es-419
0x1390002b: 242, // es-AR
0x1390003e: 243, // es-BO
0x13900040: 244, // es-BR
0x13900050: 245, // es-CL
0x13900053: 246, // es-CO
0x13900055: 247, // es-CR
0x13900058: 248, // es-CU
0x13900064: 249, // es-DO
0x13900067: 250, // es-EA
0x13900068: 251, // es-EC
0x1390006d: 252, // es-ES
0x13900085: 253, // es-GQ
0x13900088: 254, // es-GT
0x1390008e: 255, // es-HN
0x13900093: 256, // es-IC
0x139000ce: 257, // es-MX
0x139000d7: 258, // es-NI
0x139000e1: 259, // es-PA
0x139000e3: 260, // es-PE
0x139000e6: 261, // es-PH
0x139000eb: 262, // es-PR
0x139000f0: 263, // es-PY
0x13900119: 264, // es-SV
0x13900134: 265, // es-US
0x13900135: 266, // es-UY
0x1390013a: 267, // es-VE
0x13b00000: 268, // et
0x13b00069: 269, // et-EE
0x14000000: 270, // eu
0x1400006d: 271, // eu-ES
0x14100000: 272, // ewo
0x14100051: 273, // ewo-CM
0x14300000: 274, // fa
0x14300023: 275, // fa-AF
0x1430009b: 276, // fa-IR
0x14900000: 277, // ff
0x14900051: 278, // ff-CM
0x14900083: 279, // ff-GN
0x149000c8: 280, // ff-MR
0x14900113: 281, // ff-SN
0x14c00000: 282, // fi
0x14c00071: 283, // fi-FI
0x14e00000: 284, // fil
0x14e000e6: 285, // fil-PH
0x15300000: 286, // fo
0x15300062: 287, // fo-DK
0x15300075: 288, // fo-FO
0x15900000: 289, // fr
0x15900035: 290, // fr-BE
0x15900036: 291, // fr-BF
0x15900039: 292, // fr-BI
0x1590003a: 293, // fr-BJ
0x1590003b: 294, // fr-BL
0x15900048: 295, // fr-CA
0x1590004a: 296, // fr-CD
0x1590004b: 297, // fr-CF
0x1590004c: 298, // fr-CG
0x1590004d: 299, // fr-CH
0x1590004e: 300, // fr-CI
0x15900051: 301, // fr-CM
0x15900061: 302, // fr-DJ
0x15900066: 303, // fr-DZ
0x15900077: 304, // fr-FR
0x15900079: 305, // fr-GA
0x1590007d: 306, // fr-GF
0x15900083: 307, // fr-GN
0x15900084: 308, // fr-GP
0x15900085: 309, // fr-GQ
0x15900090: 310, // fr-HT
0x159000a7: 311, // fr-KM
0x159000b6: 312, // fr-LU
0x159000b9: 313, // fr-MA
0x159000ba: 314, // fr-MC
0x159000bd: 315, // fr-MF
0x159000be: 316, // fr-MG
0x159000c2: 317, // fr-ML
0x159000c7: 318, // fr-MQ
0x159000c8: 319, // fr-MR
0x159000cb: 320, // fr-MU
0x159000d2: 321, // fr-NC
0x159000d3: 322, // fr-NE
0x159000e4: 323, // fr-PF
0x159000e9: 324, // fr-PM
0x15900101: 325, // fr-RE
0x15900106: 326, // fr-RW
0x15900109: 327, // fr-SC
0x15900113: 328, // fr-SN
0x1590011b: 329, // fr-SY
0x1590011f: 330, // fr-TD
0x15900121: 331, // fr-TG
0x15900127: 332, // fr-TN
0x1590013e: 333, // fr-VU
0x1590013f: 334, // fr-WF
0x1590015e: 335, // fr-YT
0x16400000: 336, // fur
0x1640009d: 337, // fur-IT
0x16800000: 338, // fy
0x168000d8: 339, // fy-NL
0x16900000: 340, // ga
0x16900095: 341, // ga-IE
0x17800000: 342, // gd
0x1780007a: 343, // gd-GB
0x18a00000: 344, // gl
0x18a0006d: 345, // gl-ES
0x19c00000: 346, // gsw
0x19c0004d: 347, // gsw-CH
0x19c00077: 348, // gsw-FR
0x19c000b1: 349, // gsw-LI
0x19d00000: 350, // gu
0x19d00098: 351, // gu-IN
0x1a200000: 352, // guw
0x1a400000: 353, // guz
0x1a4000a3: 354, // guz-KE
0x1a500000: 355, // gv
0x1a500097: 356, // gv-IM
0x1ad00000: 357, // ha
0x1ad0007f: 358, // ha-GH
0x1ad000d3: 359, // ha-NE
0x1ad000d5: 360, // ha-NG
0x1b100000: 361, // haw
0x1b100134: 362, // haw-US
0x1b500000: 363, // he
0x1b500096: 364, // he-IL
0x1b700000: 365, // hi
0x1b700098: 366, // hi-IN
0x1ca00000: 367, // hr
0x1ca00032: 368, // hr-BA
0x1ca0008f: 369, // hr-HR
0x1cb00000: 370, // hsb
0x1cb0005f: 371, // hsb-DE
0x1ce00000: 372, // hu
0x1ce00091: 373, // hu-HU
0x1d000000: 374, // hy
0x1d000027: 375, // hy-AM
0x1da00000: 376, // id
0x1da00094: 377, // id-ID
0x1df00000: 378, // ig
0x1df000d5: 379, // ig-NG
0x1e200000: 380, // ii
0x1e200052: 381, // ii-CN
0x1f000000: 382, // is
0x1f00009c: 383, // is-IS
0x1f100000: 384, // it
0x1f10004d: 385, // it-CH
0x1f10009d: 386, // it-IT
0x1f100112: 387, // it-SM
0x1f200000: 388, // iu
0x1f800000: 389, // ja
0x1f8000a1: 390, // ja-JP
0x1fb00000: 391, // jbo
0x1ff00000: 392, // jgo
0x1ff00051: 393, // jgo-CM
0x20200000: 394, // jmc
0x2020012e: 395, // jmc-TZ
0x20600000: 396, // jv
0x20800000: 397, // ka
0x2080007c: 398, // ka-GE
0x20a00000: 399, // kab
0x20a00066: 400, // kab-DZ
0x20e00000: 401, // kaj
0x20f00000: 402, // kam
0x20f000a3: 403, // kam-KE
0x21700000: 404, // kcg
0x21b00000: 405, // kde
0x21b0012e: 406, // kde-TZ
0x21f00000: 407, // kea
0x21f00059: 408, // kea-CV
0x22c00000: 409, // khq
0x22c000c2: 410, // khq-ML
0x23100000: 411, // ki
0x231000a3: 412, // ki-KE
0x23a00000: 413, // kk
0x23a000ad: 414, // kk-KZ
0x23c00000: 415, // kkj
0x23c00051: 416, // kkj-CM
0x23d00000: 417, // kl
0x23d00081: 418, // kl-GL
0x23e00000: 419, // kln
0x23e000a3: 420, // kln-KE
0x24200000: 421, // km
0x242000a5: 422, // km-KH
0x24900000: 423, // kn
0x24900098: 424, // kn-IN
0x24b00000: 425, // ko
0x24b000a9: 426, // ko-KP
0x24b000aa: 427, // ko-KR
0x24d00000: 428, // kok
0x24d00098: 429, // kok-IN
0x26100000: 430, // ks
0x26100098: 431, // ks-IN
0x26200000: 432, // ksb
0x2620012e: 433, // ksb-TZ
0x26400000: 434, // ksf
0x26400051: 435, // ksf-CM
0x26500000: 436, // ksh
0x2650005f: 437, // ksh-DE
0x26b00000: 438, // ku
0x27800000: 439, // kw
0x2780007a: 440, // kw-GB
0x28100000: 441, // ky
0x281000a4: 442, // ky-KG
0x28800000: 443, // lag
0x2880012e: 444, // lag-TZ
0x28c00000: 445, // lb
0x28c000b6: 446, // lb-LU
0x29a00000: 447, // lg
0x29a00130: 448, // lg-UG
0x2a600000: 449, // lkt
0x2a600134: 450, // lkt-US
0x2ac00000: 451, // ln
0x2ac00029: 452, // ln-AO
0x2ac0004a: 453, // ln-CD
0x2ac0004b: 454, // ln-CF
0x2ac0004c: 455, // ln-CG
0x2af00000: 456, // lo
0x2af000ae: 457, // lo-LA
0x2b600000: 458, // lrc
0x2b60009a: 459, // lrc-IQ
0x2b60009b: 460, // lrc-IR
0x2b700000: 461, // lt
0x2b7000b5: 462, // lt-LT
0x2b900000: 463, // lu
0x2b90004a: 464, // lu-CD
0x2bb00000: 465, // luo
0x2bb000a3: 466, // luo-KE
0x2bc00000: 467, // luy
0x2bc000a3: 468, // luy-KE
0x2be00000: 469, // lv
0x2be000b7: 470, // lv-LV
0x2c800000: 471, // mas
0x2c8000a3: 472, // mas-KE
0x2c80012e: 473, // mas-TZ
0x2e000000: 474, // mer
0x2e0000a3: 475, // mer-KE
0x2e400000: 476, // mfe
0x2e4000cb: 477, // mfe-MU
0x2e800000: 478, // mg
0x2e8000be: 479, // mg-MG
0x2e900000: 480, // mgh
0x2e9000d0: 481, // mgh-MZ
0x2eb00000: 482, // mgo
0x2eb00051: 483, // mgo-CM
0x2f600000: 484, // mk
0x2f6000c1: 485, // mk-MK
0x2fb00000: 486, // ml
0x2fb00098: 487, // ml-IN
0x30200000: 488, // mn
0x302000c4: 489, // mn-MN
0x31200000: 490, // mr
0x31200098: 491, // mr-IN
0x31600000: 492, // ms
0x3160003d: 493, // ms-BN
0x316000cf: 494, // ms-MY
0x3160010c: 495, // ms-SG
0x31700000: 496, // mt
0x317000ca: 497, // mt-MT
0x31c00000: 498, // mua
0x31c00051: 499, // mua-CM
0x32800000: 500, // my
0x328000c3: 501, // my-MM
0x33100000: 502, // mzn
0x3310009b: 503, // mzn-IR
0x33800000: 504, // nah
0x33c00000: 505, // naq
0x33c000d1: 506, // naq-NA
0x33e00000: 507, // nb
0x33e000d9: 508, // nb-NO
0x33e0010f: 509, // nb-SJ
0x34500000: 510, // nd
0x34500163: 511, // nd-ZW
0x34700000: 512, // nds
0x3470005f: 513, // nds-DE
0x347000d8: 514, // nds-NL
0x34800000: 515, // ne
0x34800098: 516, // ne-IN
0x348000da: 517, // ne-NP
0x35e00000: 518, // nl
0x35e0002f: 519, // nl-AW
0x35e00035: 520, // nl-BE
0x35e0003f: 521, // nl-BQ
0x35e0005a: 522, // nl-CW
0x35e000d8: 523, // nl-NL
0x35e00115: 524, // nl-SR
0x35e0011a: 525, // nl-SX
0x35f00000: 526, // nmg
0x35f00051: 527, // nmg-CM
0x36100000: 528, // nn
0x361000d9: 529, // nn-NO
0x36300000: 530, // nnh
0x36300051: 531, // nnh-CM
0x36600000: 532, // no
0x36c00000: 533, // nqo
0x36d00000: 534, // nr
0x37100000: 535, // nso
0x37700000: 536, // nus
0x37700116: 537, // nus-SS
0x37e00000: 538, // ny
0x38000000: 539, // nyn
0x38000130: 540, // nyn-UG
0x38700000: 541, // om
0x3870006e: 542, // om-ET
0x387000a3: 543, // om-KE
0x38c00000: 544, // or
0x38c00098: 545, // or-IN
0x38f00000: 546, // os
0x38f0007c: 547, // os-GE
0x38f00105: 548, // os-RU
0x39400000: 549, // pa
0x39405000: 550, // pa-Arab
0x394050e7: 551, // pa-Arab-PK
0x3942f000: 552, // pa-Guru
0x3942f098: 553, // pa-Guru-IN
0x39800000: 554, // pap
0x3aa00000: 555, // pl
0x3aa000e8: 556, // pl-PL
0x3b400000: 557, // prg
0x3b400001: 558, // prg-001
0x3b500000: 559, // ps
0x3b500023: 560, // ps-AF
0x3b700000: 561, // pt
0x3b700029: 562, // pt-AO
0x3b700040: 563, // pt-BR
0x3b70004d: 564, // pt-CH
0x3b700059: 565, // pt-CV
0x3b700085: 566, // pt-GQ
0x3b70008a: 567, // pt-GW
0x3b7000b6: 568, // pt-LU
0x3b7000c5: 569, // pt-MO
0x3b7000d0: 570, // pt-MZ
0x3b7000ed: 571, // pt-PT
0x3b700117: 572, // pt-ST
0x3b700125: 573, // pt-TL
0x3bb00000: 574, // qu
0x3bb0003e: 575, // qu-BO
0x3bb00068: 576, // qu-EC
0x3bb000e3: 577, // qu-PE
0x3cb00000: 578, // rm
0x3cb0004d: 579, // rm-CH
0x3d000000: 580, // rn
0x3d000039: 581, // rn-BI
0x3d300000: 582, // ro
0x3d3000bb: 583, // ro-MD
0x3d300103: 584, // ro-RO
0x3d500000: 585, // rof
0x3d50012e: 586, // rof-TZ
0x3d900000: 587, // ru
0x3d900046: 588, // ru-BY
0x3d9000a4: 589, // ru-KG
0x3d9000ad: 590, // ru-KZ
0x3d9000bb: 591, // ru-MD
0x3d900105: 592, // ru-RU
0x3d90012f: 593, // ru-UA
0x3dc00000: 594, // rw
0x3dc00106: 595, // rw-RW
0x3dd00000: 596, // rwk
0x3dd0012e: 597, // rwk-TZ
0x3e200000: 598, // sah
0x3e200105: 599, // sah-RU
0x3e300000: 600, // saq
0x3e3000a3: 601, // saq-KE
0x3e900000: 602, // sbp
0x3e90012e: 603, // sbp-TZ
0x3f200000: 604, // sdh
0x3f300000: 605, // se
0x3f300071: 606, // se-FI
0x3f3000d9: 607, // se-NO
0x3f30010b: 608, // se-SE
0x3f500000: 609, // seh
0x3f5000d0: 610, // seh-MZ
0x3f700000: 611, // ses
0x3f7000c2: 612, // ses-ML
0x3f800000: 613, // sg
0x3f80004b: 614, // sg-CF
0x3fe00000: 615, // shi
0x3fe52000: 616, // shi-Latn
0x3fe520b9: 617, // shi-Latn-MA
0x3fed2000: 618, // shi-Tfng
0x3fed20b9: 619, // shi-Tfng-MA
0x40200000: 620, // si
0x402000b2: 621, // si-LK
0x40800000: 622, // sk
0x40800110: 623, // sk-SK
0x40c00000: 624, // sl
0x40c0010e: 625, // sl-SI
0x41200000: 626, // sma
0x41300000: 627, // smi
0x41400000: 628, // smj
0x41500000: 629, // smn
0x41500071: 630, // smn-FI
0x41800000: 631, // sms
0x41900000: 632, // sn
0x41900163: 633, // sn-ZW
0x41f00000: 634, // so
0x41f00061: 635, // so-DJ
0x41f0006e: 636, // so-ET
0x41f000a3: 637, // so-KE
0x41f00114: 638, // so-SO
0x42700000: 639, // sq
0x42700026: 640, // sq-AL
0x427000c1: 641, // sq-MK
0x4270014c: 642, // sq-XK
0x42800000: 643, // sr
0x4281e000: 644, // sr-Cyrl
0x4281e032: 645, // sr-Cyrl-BA
0x4281e0bc: 646, // sr-Cyrl-ME
0x4281e104: 647, // sr-Cyrl-RS
0x4281e14c: 648, // sr-Cyrl-XK
0x42852000: 649, // sr-Latn
0x42852032: 650, // sr-Latn-BA
0x428520bc: 651, // sr-Latn-ME
0x42852104: 652, // sr-Latn-RS
0x4285214c: 653, // sr-Latn-XK
0x42d00000: 654, // ss
0x43000000: 655, // ssy
0x43100000: 656, // st
0x43a00000: 657, // sv
0x43a00030: 658, // sv-AX
0x43a00071: 659, // sv-FI
0x43a0010b: 660, // sv-SE
0x43b00000: 661, // sw
0x43b0004a: 662, // sw-CD
0x43b000a3: 663, // sw-KE
0x43b0012e: 664, // sw-TZ
0x43b00130: 665, // sw-UG
0x44400000: 666, // syr
0x44600000: 667, // ta
0x44600098: 668, // ta-IN
0x446000b2: 669, // ta-LK
0x446000cf: 670, // ta-MY
0x4460010c: 671, // ta-SG
0x45700000: 672, // te
0x45700098: 673, // te-IN
0x45a00000: 674, // teo
0x45a000a3: 675, // teo-KE
0x45a00130: 676, // teo-UG
0x46100000: 677, // th
0x46100122: 678, // th-TH
0x46500000: 679, // ti
0x4650006c: 680, // ti-ER
0x4650006e: 681, // ti-ET
0x46700000: 682, // tig
0x46c00000: 683, // tk
0x46c00126: 684, // tk-TM
0x47600000: 685, // tn
0x47800000: 686, // to
0x47800128: 687, // to-TO
0x48000000: 688, // tr
0x4800005c: 689, // tr-CY
0x4800012a: 690, // tr-TR
0x48400000: 691, // ts
0x49a00000: 692, // twq
0x49a000d3: 693, // twq-NE
0x49f00000: 694, // tzm
0x49f000b9: 695, // tzm-MA
0x4a200000: 696, // ug
0x4a200052: 697, // ug-CN
0x4a400000: 698, // uk
0x4a40012f: 699, // uk-UA
0x4aa00000: 700, // ur
0x4aa00098: 701, // ur-IN
0x4aa000e7: 702, // ur-PK
0x4b200000: 703, // uz
0x4b205000: 704, // uz-Arab
0x4b205023: 705, // uz-Arab-AF
0x4b21e000: 706, // uz-Cyrl
0x4b21e136: 707, // uz-Cyrl-UZ
0x4b252000: 708, // uz-Latn
0x4b252136: 709, // uz-Latn-UZ
0x4b400000: 710, // vai
0x4b452000: 711, // vai-Latn
0x4b4520b3: 712, // vai-Latn-LR
0x4b4d9000: 713, // vai-Vaii
0x4b4d90b3: 714, // vai-Vaii-LR
0x4b600000: 715, // ve
0x4b900000: 716, // vi
0x4b90013d: 717, // vi-VN
0x4bf00000: 718, // vo
0x4bf00001: 719, // vo-001
0x4c200000: 720, // vun
0x4c20012e: 721, // vun-TZ
0x4c400000: 722, // wa
0x4c500000: 723, // wae
0x4c50004d: 724, // wae-CH
0x4db00000: 725, // wo
0x4e800000: 726, // xh
0x4f100000: 727, // xog
0x4f100130: 728, // xog-UG
0x4ff00000: 729, // yav
0x4ff00051: 730, // yav-CM
0x50800000: 731, // yi
0x50800001: 732, // yi-001
0x50e00000: 733, // yo
0x50e0003a: 734, // yo-BJ
0x50e000d5: 735, // yo-NG
0x51500000: 736, // yue
0x5150008c: 737, // yue-HK
0x51e00000: 738, // zgh
0x51e000b9: 739, // zgh-MA
0x51f00000: 740, // zh
0x51f34000: 741, // zh-Hans
0x51f34052: 742, // zh-Hans-CN
0x51f3408c: 743, // zh-Hans-HK
0x51f340c5: 744, // zh-Hans-MO
0x51f3410c: 745, // zh-Hans-SG
0x51f35000: 746, // zh-Hant
0x51f3508c: 747, // zh-Hant-HK
0x51f350c5: 748, // zh-Hant-MO
0x51f3512d: 749, // zh-Hant-TW
0x52400000: 750, // zu
0x52400160: 751, // zu-ZA
}
// Total table size 4580 bytes (4KiB); checksum: A7F72A2A

File diff suppressed because it is too large Load Diff

View File

@ -1,396 +0,0 @@
// 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
import (
"bytes"
"fmt"
"sort"
"strconv"
"golang.org/x/text/internal/tag"
)
// findIndex tries to find the given tag in idx and returns a standardized error
// if it could not be found.
func findIndex(idx tag.Index, key []byte, form string) (index int, err error) {
if !tag.FixCase(form, key) {
return 0, errSyntax
}
i := idx.Index(key)
if i == -1 {
return 0, mkErrInvalid(key)
}
return i, nil
}
func searchUint(imap []uint16, key uint16) int {
return sort.Search(len(imap), func(i int) bool {
return imap[i] >= key
})
}
type langID uint16
// getLangID returns the langID of s if s is a canonical subtag
// or langUnknown if s is not a canonical subtag.
func getLangID(s []byte) (langID, error) {
if len(s) == 2 {
return getLangISO2(s)
}
return getLangISO3(s)
}
// mapLang returns the mapped langID of id according to mapping m.
func normLang(id langID) (langID, langAliasType) {
k := sort.Search(len(langAliasMap), func(i int) bool {
return langAliasMap[i].from >= uint16(id)
})
if k < len(langAliasMap) && langAliasMap[k].from == uint16(id) {
return langID(langAliasMap[k].to), langAliasTypes[k]
}
return id, langAliasTypeUnknown
}
// getLangISO2 returns the langID for the given 2-letter ISO language code
// or unknownLang if this does not exist.
func getLangISO2(s []byte) (langID, error) {
if !tag.FixCase("zz", s) {
return 0, errSyntax
}
if i := lang.Index(s); i != -1 && lang.Elem(i)[3] != 0 {
return langID(i), nil
}
return 0, mkErrInvalid(s)
}
const base = 'z' - 'a' + 1
func strToInt(s []byte) uint {
v := uint(0)
for i := 0; i < len(s); i++ {
v *= base
v += uint(s[i] - 'a')
}
return v
}
// converts the given integer to the original ASCII string passed to strToInt.
// len(s) must match the number of characters obtained.
func intToStr(v uint, s []byte) {
for i := len(s) - 1; i >= 0; i-- {
s[i] = byte(v%base) + 'a'
v /= base
}
}
// getLangISO3 returns the langID for the given 3-letter ISO language code
// or unknownLang if this does not exist.
func getLangISO3(s []byte) (langID, error) {
if tag.FixCase("und", s) {
// first try to match canonical 3-letter entries
for i := lang.Index(s[:2]); i != -1; i = lang.Next(s[:2], i) {
if e := lang.Elem(i); e[3] == 0 && e[2] == s[2] {
// We treat "und" as special and always translate it to "unspecified".
// Note that ZZ and Zzzz are private use and are not treated as
// unspecified by default.
id := langID(i)
if id == nonCanonicalUnd {
return 0, nil
}
return id, nil
}
}
if i := altLangISO3.Index(s); i != -1 {
return langID(altLangIndex[altLangISO3.Elem(i)[3]]), nil
}
n := strToInt(s)
if langNoIndex[n/8]&(1<<(n%8)) != 0 {
return langID(n) + langNoIndexOffset, nil
}
// Check for non-canonical uses of ISO3.
for i := lang.Index(s[:1]); i != -1; i = lang.Next(s[:1], i) {
if e := lang.Elem(i); e[2] == s[1] && e[3] == s[2] {
return langID(i), nil
}
}
return 0, mkErrInvalid(s)
}
return 0, errSyntax
}
// stringToBuf writes the string to b and returns the number of bytes
// written. cap(b) must be >= 3.
func (id langID) stringToBuf(b []byte) int {
if id >= langNoIndexOffset {
intToStr(uint(id)-langNoIndexOffset, b[:3])
return 3
} else if id == 0 {
return copy(b, "und")
}
l := lang[id<<2:]
if l[3] == 0 {
return copy(b, l[:3])
}
return copy(b, l[:2])
}
// String returns the BCP 47 representation of the langID.
// Use b as variable name, instead of id, to ensure the variable
// used is consistent with that of Base in which this type is embedded.
func (b langID) String() string {
if b == 0 {
return "und"
} else if b >= langNoIndexOffset {
b -= langNoIndexOffset
buf := [3]byte{}
intToStr(uint(b), buf[:])
return string(buf[:])
}
l := lang.Elem(int(b))
if l[3] == 0 {
return l[:3]
}
return l[:2]
}
// ISO3 returns the ISO 639-3 language code.
func (b langID) ISO3() string {
if b == 0 || b >= langNoIndexOffset {
return b.String()
}
l := lang.Elem(int(b))
if l[3] == 0 {
return l[:3]
} else if l[2] == 0 {
return altLangISO3.Elem(int(l[3]))[:3]
}
// This allocation will only happen for 3-letter ISO codes
// that are non-canonical BCP 47 language identifiers.
return l[0:1] + l[2:4]
}
// IsPrivateUse reports whether this language code is reserved for private use.
func (b langID) IsPrivateUse() bool {
return langPrivateStart <= b && b <= langPrivateEnd
}
type regionID uint16
// getRegionID returns the region id for s if s is a valid 2-letter region code
// or unknownRegion.
func getRegionID(s []byte) (regionID, error) {
if len(s) == 3 {
if isAlpha(s[0]) {
return getRegionISO3(s)
}
if i, err := strconv.ParseUint(string(s), 10, 10); err == nil {
return getRegionM49(int(i))
}
}
return getRegionISO2(s)
}
// getRegionISO2 returns the regionID for the given 2-letter ISO country code
// or unknownRegion if this does not exist.
func getRegionISO2(s []byte) (regionID, error) {
i, err := findIndex(regionISO, s, "ZZ")
if err != nil {
return 0, err
}
return regionID(i) + isoRegionOffset, nil
}
// getRegionISO3 returns the regionID for the given 3-letter ISO country code
// or unknownRegion if this does not exist.
func getRegionISO3(s []byte) (regionID, error) {
if tag.FixCase("ZZZ", s) {
for i := regionISO.Index(s[:1]); i != -1; i = regionISO.Next(s[:1], i) {
if e := regionISO.Elem(i); e[2] == s[1] && e[3] == s[2] {
return regionID(i) + isoRegionOffset, nil
}
}
for i := 0; i < len(altRegionISO3); i += 3 {
if tag.Compare(altRegionISO3[i:i+3], s) == 0 {
return regionID(altRegionIDs[i/3]), nil
}
}
return 0, mkErrInvalid(s)
}
return 0, errSyntax
}
func getRegionM49(n int) (regionID, error) {
if 0 < n && n <= 999 {
const (
searchBits = 7
regionBits = 9
regionMask = 1<<regionBits - 1
)
idx := n >> searchBits
buf := fromM49[m49Index[idx]:m49Index[idx+1]]
val := uint16(n) << regionBits // we rely on bits shifting out
i := sort.Search(len(buf), func(i int) bool {
return buf[i] >= val
})
if r := fromM49[int(m49Index[idx])+i]; r&^regionMask == val {
return regionID(r & regionMask), nil
}
}
var e ValueError
fmt.Fprint(bytes.NewBuffer([]byte(e.v[:])), n)
return 0, e
}
// normRegion returns a region if r is deprecated or 0 otherwise.
// TODO: consider supporting BYS (-> BLR), CSK (-> 200 or CZ), PHI (-> PHL) and AFI (-> DJ).
// TODO: consider mapping split up regions to new most populous one (like CLDR).
func normRegion(r regionID) regionID {
m := regionOldMap
k := sort.Search(len(m), func(i int) bool {
return m[i].from >= uint16(r)
})
if k < len(m) && m[k].from == uint16(r) {
return regionID(m[k].to)
}
return 0
}
const (
iso3166UserAssigned = 1 << iota
ccTLD
bcp47Region
)
func (r regionID) typ() byte {
return regionTypes[r]
}
// String returns the BCP 47 representation for the region.
// It returns "ZZ" for an unspecified region.
func (r regionID) String() string {
if r < isoRegionOffset {
if r == 0 {
return "ZZ"
}
return fmt.Sprintf("%03d", r.M49())
}
r -= isoRegionOffset
return regionISO.Elem(int(r))[:2]
}
// ISO3 returns the 3-letter ISO code of r.
// Note that not all regions have a 3-letter ISO code.
// In such cases this method returns "ZZZ".
func (r regionID) ISO3() string {
if r < isoRegionOffset {
return "ZZZ"
}
r -= isoRegionOffset
reg := regionISO.Elem(int(r))
switch reg[2] {
case 0:
return altRegionISO3[reg[3]:][:3]
case ' ':
return "ZZZ"
}
return reg[0:1] + reg[2:4]
}
// M49 returns the UN M.49 encoding of r, or 0 if this encoding
// is not defined for r.
func (r regionID) M49() int {
return int(m49[r])
}
// IsPrivateUse reports whether r has the ISO 3166 User-assigned status. This
// may include private-use tags that are assigned by CLDR and used in this
// implementation. So IsPrivateUse and IsCountry can be simultaneously true.
func (r regionID) IsPrivateUse() bool {
return r.typ()&iso3166UserAssigned != 0
}
type scriptID uint8
// getScriptID returns the script id for string s. It assumes that s
// is of the format [A-Z][a-z]{3}.
func getScriptID(idx tag.Index, s []byte) (scriptID, error) {
i, err := findIndex(idx, s, "Zzzz")
return scriptID(i), err
}
// String returns the script code in title case.
// It returns "Zzzz" for an unspecified script.
func (s scriptID) String() string {
if s == 0 {
return "Zzzz"
}
return script.Elem(int(s))
}
// IsPrivateUse reports whether this script code is reserved for private use.
func (s scriptID) IsPrivateUse() bool {
return _Qaaa <= s && s <= _Qabx
}
const (
maxAltTaglen = len("en-US-POSIX")
maxLen = maxAltTaglen
)
var (
// grandfatheredMap holds a mapping from legacy and grandfathered tags to
// their base language or index to more elaborate tag.
grandfatheredMap = map[[maxLen]byte]int16{
[maxLen]byte{'a', 'r', 't', '-', 'l', 'o', 'j', 'b', 'a', 'n'}: _jbo, // art-lojban
[maxLen]byte{'i', '-', 'a', 'm', 'i'}: _ami, // i-ami
[maxLen]byte{'i', '-', 'b', 'n', 'n'}: _bnn, // i-bnn
[maxLen]byte{'i', '-', 'h', 'a', 'k'}: _hak, // i-hak
[maxLen]byte{'i', '-', 'k', 'l', 'i', 'n', 'g', 'o', 'n'}: _tlh, // i-klingon
[maxLen]byte{'i', '-', 'l', 'u', 'x'}: _lb, // i-lux
[maxLen]byte{'i', '-', 'n', 'a', 'v', 'a', 'j', 'o'}: _nv, // i-navajo
[maxLen]byte{'i', '-', 'p', 'w', 'n'}: _pwn, // i-pwn
[maxLen]byte{'i', '-', 't', 'a', 'o'}: _tao, // i-tao
[maxLen]byte{'i', '-', 't', 'a', 'y'}: _tay, // i-tay
[maxLen]byte{'i', '-', 't', 's', 'u'}: _tsu, // i-tsu
[maxLen]byte{'n', 'o', '-', 'b', 'o', 'k'}: _nb, // no-bok
[maxLen]byte{'n', 'o', '-', 'n', 'y', 'n'}: _nn, // no-nyn
[maxLen]byte{'s', 'g', 'n', '-', 'b', 'e', '-', 'f', 'r'}: _sfb, // sgn-BE-FR
[maxLen]byte{'s', 'g', 'n', '-', 'b', 'e', '-', 'n', 'l'}: _vgt, // sgn-BE-NL
[maxLen]byte{'s', 'g', 'n', '-', 'c', 'h', '-', 'd', 'e'}: _sgg, // sgn-CH-DE
[maxLen]byte{'z', 'h', '-', 'g', 'u', 'o', 'y', 'u'}: _cmn, // zh-guoyu
[maxLen]byte{'z', 'h', '-', 'h', 'a', 'k', 'k', 'a'}: _hak, // zh-hakka
[maxLen]byte{'z', 'h', '-', 'm', 'i', 'n', '-', 'n', 'a', 'n'}: _nan, // zh-min-nan
[maxLen]byte{'z', 'h', '-', 'x', 'i', 'a', 'n', 'g'}: _hsn, // zh-xiang
// Grandfathered tags with no modern replacement will be converted as
// follows:
[maxLen]byte{'c', 'e', 'l', '-', 'g', 'a', 'u', 'l', 'i', 's', 'h'}: -1, // cel-gaulish
[maxLen]byte{'e', 'n', '-', 'g', 'b', '-', 'o', 'e', 'd'}: -2, // en-GB-oed
[maxLen]byte{'i', '-', 'd', 'e', 'f', 'a', 'u', 'l', 't'}: -3, // i-default
[maxLen]byte{'i', '-', 'e', 'n', 'o', 'c', 'h', 'i', 'a', 'n'}: -4, // i-enochian
[maxLen]byte{'i', '-', 'm', 'i', 'n', 'g', 'o'}: -5, // i-mingo
[maxLen]byte{'z', 'h', '-', 'm', 'i', 'n'}: -6, // zh-min
// CLDR-specific tag.
[maxLen]byte{'r', 'o', 'o', 't'}: 0, // root
[maxLen]byte{'e', 'n', '-', 'u', 's', '-', 'p', 'o', 's', 'i', 'x'}: -7, // en_US_POSIX"
}
altTagIndex = [...]uint8{0, 17, 31, 45, 61, 74, 86, 102}
altTags = "xtg-x-cel-gaulishen-GB-oxendicten-x-i-defaultund-x-i-enochiansee-x-i-mingonan-x-zh-minen-US-u-va-posix"
)
func grandfathered(s [maxAltTaglen]byte) (t Tag, ok bool) {
if v, ok := grandfatheredMap[s]; ok {
if v < 0 {
return Make(altTags[altTagIndex[-v-1]:altTagIndex[-v]]), true
}
t.lang = langID(v)
return t, true
}
return t, false
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,216 +5,21 @@
package language
import (
"bytes"
"errors"
"fmt"
"sort"
"strconv"
"strings"
"golang.org/x/text/internal/tag"
"golang.org/x/text/internal/language"
)
// isAlpha returns true if the byte is not a digit.
// b must be an ASCII letter or digit.
func isAlpha(b byte) bool {
return b > '9'
}
// isAlphaNum returns true if the string contains only ASCII letters or digits.
func isAlphaNum(s []byte) bool {
for _, c := range s {
if !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9') {
return false
}
}
return true
}
// errSyntax is returned by any of the parsing functions when the
// input is not well-formed, according to BCP 47.
// TODO: return the position at which the syntax error occurred?
var errSyntax = errors.New("language: tag is not well-formed")
// ValueError is returned by any of the parsing functions when the
// input is well-formed but the respective subtag is not recognized
// as a valid value.
type ValueError struct {
v [8]byte
}
type ValueError interface {
error
func mkErrInvalid(s []byte) error {
var e ValueError
copy(e.v[:], s)
return e
}
func (e ValueError) tag() []byte {
n := bytes.IndexByte(e.v[:], 0)
if n == -1 {
n = 8
}
return e.v[:n]
}
// Error implements the error interface.
func (e ValueError) Error() string {
return fmt.Sprintf("language: subtag %q is well-formed but unknown", e.tag())
}
// Subtag returns the subtag for which the error occurred.
func (e ValueError) Subtag() string {
return string(e.tag())
}
// scanner is used to scan BCP 47 tokens, which are separated by _ or -.
type scanner struct {
b []byte
bytes [max99thPercentileSize]byte
token []byte
start int // start position of the current token
end int // end position of the current token
next int // next point for scan
err error
done bool
}
func makeScannerString(s string) scanner {
scan := scanner{}
if len(s) <= len(scan.bytes) {
scan.b = scan.bytes[:copy(scan.bytes[:], s)]
} else {
scan.b = []byte(s)
}
scan.init()
return scan
}
// makeScanner returns a scanner using b as the input buffer.
// b is not copied and may be modified by the scanner routines.
func makeScanner(b []byte) scanner {
scan := scanner{b: b}
scan.init()
return scan
}
func (s *scanner) init() {
for i, c := range s.b {
if c == '_' {
s.b[i] = '-'
}
}
s.scan()
}
// restToLower converts the string between start and end to lower case.
func (s *scanner) toLower(start, end int) {
for i := start; i < end; i++ {
c := s.b[i]
if 'A' <= c && c <= 'Z' {
s.b[i] += 'a' - 'A'
}
}
}
func (s *scanner) setError(e error) {
if s.err == nil || (e == errSyntax && s.err != errSyntax) {
s.err = e
}
}
// resizeRange shrinks or grows the array at position oldStart such that
// a new string of size newSize can fit between oldStart and oldEnd.
// Sets the scan point to after the resized range.
func (s *scanner) resizeRange(oldStart, oldEnd, newSize int) {
s.start = oldStart
if end := oldStart + newSize; end != oldEnd {
diff := end - oldEnd
if end < cap(s.b) {
b := make([]byte, len(s.b)+diff)
copy(b, s.b[:oldStart])
copy(b[end:], s.b[oldEnd:])
s.b = b
} else {
s.b = append(s.b[end:], s.b[oldEnd:]...)
}
s.next = end + (s.next - s.end)
s.end = end
}
}
// replace replaces the current token with repl.
func (s *scanner) replace(repl string) {
s.resizeRange(s.start, s.end, len(repl))
copy(s.b[s.start:], repl)
}
// gobble removes the current token from the input.
// Caller must call scan after calling gobble.
func (s *scanner) gobble(e error) {
s.setError(e)
if s.start == 0 {
s.b = s.b[:+copy(s.b, s.b[s.next:])]
s.end = 0
} else {
s.b = s.b[:s.start-1+copy(s.b[s.start-1:], s.b[s.end:])]
s.end = s.start - 1
}
s.next = s.start
}
// deleteRange removes the given range from s.b before the current token.
func (s *scanner) deleteRange(start, end int) {
s.setError(errSyntax)
s.b = s.b[:start+copy(s.b[start:], s.b[end:])]
diff := end - start
s.next -= diff
s.start -= diff
s.end -= diff
}
// scan parses the next token of a BCP 47 string. Tokens that are larger
// than 8 characters or include non-alphanumeric characters result in an error
// and are gobbled and removed from the output.
// It returns the end position of the last token consumed.
func (s *scanner) scan() (end int) {
end = s.end
s.token = nil
for s.start = s.next; s.next < len(s.b); {
i := bytes.IndexByte(s.b[s.next:], '-')
if i == -1 {
s.end = len(s.b)
s.next = len(s.b)
i = s.end - s.start
} else {
s.end = s.next + i
s.next = s.end + 1
}
token := s.b[s.start:s.end]
if i < 1 || i > 8 || !isAlphaNum(token) {
s.gobble(errSyntax)
continue
}
s.token = token
return end
}
if n := len(s.b); n > 0 && s.b[n-1] == '-' {
s.setError(errSyntax)
s.b = s.b[:len(s.b)-1]
}
s.done = true
return end
}
// acceptMinSize parses multiple tokens of the given size or greater.
// It returns the end position of the last token consumed.
func (s *scanner) acceptMinSize(min int) (end int) {
end = s.end
s.scan()
for ; len(s.token) >= min; s.scan() {
end = s.end
}
return end
// Subtag returns the subtag for which the error occurred.
Subtag() string
}
// Parse parses the given BCP 47 string and returns a valid Tag. If parsing
@ -238,324 +43,15 @@ func Parse(s string) (t Tag, err error) {
// http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers.
// The resulting tag is canonicalized using the the canonicalization type c.
func (c CanonType) Parse(s string) (t Tag, err error) {
// TODO: consider supporting old-style locale key-value pairs.
if s == "" {
return und, errSyntax
tt, err := language.Parse(s)
if err != nil {
return makeTag(tt), err
}
if len(s) <= maxAltTaglen {
b := [maxAltTaglen]byte{}
for i, c := range s {
// Generating invalid UTF-8 is okay as it won't match.
if 'A' <= c && c <= 'Z' {
c += 'a' - 'A'
} else if c == '_' {
c = '-'
}
b[i] = byte(c)
}
if t, ok := grandfathered(b); ok {
return t, nil
}
}
scan := makeScannerString(s)
t, err = parse(&scan, s)
t, changed := t.canonicalize(c)
tt, changed := canonicalize(c, tt)
if changed {
t.remakeString()
tt.RemakeString()
}
return t, err
}
func parse(scan *scanner, s string) (t Tag, err error) {
t = und
var end int
if n := len(scan.token); n <= 1 {
scan.toLower(0, len(scan.b))
if n == 0 || scan.token[0] != 'x' {
return t, errSyntax
}
end = parseExtensions(scan)
} else if n >= 4 {
return und, errSyntax
} else { // the usual case
t, end = parseTag(scan)
if n := len(scan.token); n == 1 {
t.pExt = uint16(end)
end = parseExtensions(scan)
} else if end < len(scan.b) {
scan.setError(errSyntax)
scan.b = scan.b[:end]
}
}
if int(t.pVariant) < len(scan.b) {
if end < len(s) {
s = s[:end]
}
if len(s) > 0 && tag.Compare(s, scan.b) == 0 {
t.str = s
} else {
t.str = string(scan.b)
}
} else {
t.pVariant, t.pExt = 0, 0
}
return t, scan.err
}
// parseTag parses language, script, region and variants.
// It returns a Tag and the end position in the input that was parsed.
func parseTag(scan *scanner) (t Tag, end int) {
var e error
// TODO: set an error if an unknown lang, script or region is encountered.
t.lang, e = getLangID(scan.token)
scan.setError(e)
scan.replace(t.lang.String())
langStart := scan.start
end = scan.scan()
for len(scan.token) == 3 && isAlpha(scan.token[0]) {
// From http://tools.ietf.org/html/bcp47, <lang>-<extlang> tags are equivalent
// to a tag of the form <extlang>.
lang, e := getLangID(scan.token)
if lang != 0 {
t.lang = lang
copy(scan.b[langStart:], lang.String())
scan.b[langStart+3] = '-'
scan.start = langStart + 4
}
scan.gobble(e)
end = scan.scan()
}
if len(scan.token) == 4 && isAlpha(scan.token[0]) {
t.script, e = getScriptID(script, scan.token)
if t.script == 0 {
scan.gobble(e)
}
end = scan.scan()
}
if n := len(scan.token); n >= 2 && n <= 3 {
t.region, e = getRegionID(scan.token)
if t.region == 0 {
scan.gobble(e)
} else {
scan.replace(t.region.String())
}
end = scan.scan()
}
scan.toLower(scan.start, len(scan.b))
t.pVariant = byte(end)
end = parseVariants(scan, end, t)
t.pExt = uint16(end)
return t, end
}
var separator = []byte{'-'}
// parseVariants scans tokens as long as each token is a valid variant string.
// Duplicate variants are removed.
func parseVariants(scan *scanner, end int, t Tag) int {
start := scan.start
varIDBuf := [4]uint8{}
variantBuf := [4][]byte{}
varID := varIDBuf[:0]
variant := variantBuf[:0]
last := -1
needSort := false
for ; len(scan.token) >= 4; scan.scan() {
// TODO: measure the impact of needing this conversion and redesign
// the data structure if there is an issue.
v, ok := variantIndex[string(scan.token)]
if !ok {
// unknown variant
// TODO: allow user-defined variants?
scan.gobble(mkErrInvalid(scan.token))
continue
}
varID = append(varID, v)
variant = append(variant, scan.token)
if !needSort {
if last < int(v) {
last = int(v)
} else {
needSort = true
// There is no legal combinations of more than 7 variants
// (and this is by no means a useful sequence).
const maxVariants = 8
if len(varID) > maxVariants {
break
}
}
}
end = scan.end
}
if needSort {
sort.Sort(variantsSort{varID, variant})
k, l := 0, -1
for i, v := range varID {
w := int(v)
if l == w {
// Remove duplicates.
continue
}
varID[k] = varID[i]
variant[k] = variant[i]
k++
l = w
}
if str := bytes.Join(variant[:k], separator); len(str) == 0 {
end = start - 1
} else {
scan.resizeRange(start, end, len(str))
copy(scan.b[scan.start:], str)
end = scan.end
}
}
return end
}
type variantsSort struct {
i []uint8
v [][]byte
}
func (s variantsSort) Len() int {
return len(s.i)
}
func (s variantsSort) Swap(i, j int) {
s.i[i], s.i[j] = s.i[j], s.i[i]
s.v[i], s.v[j] = s.v[j], s.v[i]
}
func (s variantsSort) Less(i, j int) bool {
return s.i[i] < s.i[j]
}
type bytesSort [][]byte
func (b bytesSort) Len() int {
return len(b)
}
func (b bytesSort) Swap(i, j int) {
b[i], b[j] = b[j], b[i]
}
func (b bytesSort) Less(i, j int) bool {
return bytes.Compare(b[i], b[j]) == -1
}
// parseExtensions parses and normalizes the extensions in the buffer.
// It returns the last position of scan.b that is part of any extension.
// It also trims scan.b to remove excess parts accordingly.
func parseExtensions(scan *scanner) int {
start := scan.start
exts := [][]byte{}
private := []byte{}
end := scan.end
for len(scan.token) == 1 {
extStart := scan.start
ext := scan.token[0]
end = parseExtension(scan)
extension := scan.b[extStart:end]
if len(extension) < 3 || (ext != 'x' && len(extension) < 4) {
scan.setError(errSyntax)
end = extStart
continue
} else if start == extStart && (ext == 'x' || scan.start == len(scan.b)) {
scan.b = scan.b[:end]
return end
} else if ext == 'x' {
private = extension
break
}
exts = append(exts, extension)
}
sort.Sort(bytesSort(exts))
if len(private) > 0 {
exts = append(exts, private)
}
scan.b = scan.b[:start]
if len(exts) > 0 {
scan.b = append(scan.b, bytes.Join(exts, separator)...)
} else if start > 0 {
// Strip trailing '-'.
scan.b = scan.b[:start-1]
}
return end
}
// parseExtension parses a single extension and returns the position of
// the extension end.
func parseExtension(scan *scanner) int {
start, end := scan.start, scan.end
switch scan.token[0] {
case 'u':
attrStart := end
scan.scan()
for last := []byte{}; len(scan.token) > 2; scan.scan() {
if bytes.Compare(scan.token, last) != -1 {
// Attributes are unsorted. Start over from scratch.
p := attrStart + 1
scan.next = p
attrs := [][]byte{}
for scan.scan(); len(scan.token) > 2; scan.scan() {
attrs = append(attrs, scan.token)
end = scan.end
}
sort.Sort(bytesSort(attrs))
copy(scan.b[p:], bytes.Join(attrs, separator))
break
}
last = scan.token
end = scan.end
}
var last, key []byte
for attrEnd := end; len(scan.token) == 2; last = key {
key = scan.token
keyEnd := scan.end
end = scan.acceptMinSize(3)
// TODO: check key value validity
if keyEnd == end || bytes.Compare(key, last) != 1 {
// We have an invalid key or the keys are not sorted.
// Start scanning keys from scratch and reorder.
p := attrEnd + 1
scan.next = p
keys := [][]byte{}
for scan.scan(); len(scan.token) == 2; {
keyStart, keyEnd := scan.start, scan.end
end = scan.acceptMinSize(3)
if keyEnd != end {
keys = append(keys, scan.b[keyStart:end])
} else {
scan.setError(errSyntax)
end = keyStart
}
}
sort.Sort(bytesSort(keys))
reordered := bytes.Join(keys, separator)
if e := p + len(reordered); e < end {
scan.deleteRange(e, end)
end = e
}
copy(scan.b[p:], bytes.Join(keys, separator))
break
}
}
case 't':
scan.scan()
if n := len(scan.token); n >= 2 && n <= 3 && isAlpha(scan.token[1]) {
_, end = parseTag(scan)
scan.toLower(start, end)
}
for len(scan.token) == 2 && !isAlpha(scan.token[1]) {
end = scan.acceptMinSize(3)
}
case 'x':
end = scan.acceptMinSize(1)
default:
end = scan.acceptMinSize(2)
}
return end
return makeTag(tt), err
}
// Compose creates a Tag from individual parts, which may be of type Tag, Base,
@ -563,10 +59,11 @@ func parseExtension(scan *scanner) int {
// Base, Script or Region or slice of type Variant or Extension is passed more
// than once, the latter will overwrite the former. Variants and Extensions are
// accumulated, but if two extensions of the same type are passed, the latter
// will replace the former. A Tag overwrites all former values and typically
// only makes sense as the first argument. The resulting tag is returned after
// canonicalizing using the Default CanonType. If one or more errors are
// encountered, one of the errors is returned.
// will replace the former. For -u extensions, though, the key-type pairs are
// added, where later values overwrite older ones. A Tag overwrites all former
// values and typically only makes sense as the first argument. The resulting
// tag is returned after canonicalizing using the Default CanonType. If one or
// more errors are encountered, one of the errors is returned.
func Compose(part ...interface{}) (t Tag, err error) {
return Default.Compose(part...)
}
@ -576,196 +73,68 @@ func Compose(part ...interface{}) (t Tag, err error) {
// Base, Script or Region or slice of type Variant or Extension is passed more
// than once, the latter will overwrite the former. Variants and Extensions are
// accumulated, but if two extensions of the same type are passed, the latter
// will replace the former. A Tag overwrites all former values and typically
// only makes sense as the first argument. The resulting tag is returned after
// canonicalizing using CanonType c. If one or more errors are encountered,
// one of the errors is returned.
// will replace the former. For -u extensions, though, the key-type pairs are
// added, where later values overwrite older ones. A Tag overwrites all former
// values and typically only makes sense as the first argument. The resulting
// tag is returned after canonicalizing using CanonType c. If one or more errors
// are encountered, one of the errors is returned.
func (c CanonType) Compose(part ...interface{}) (t Tag, err error) {
var b builder
if err = b.update(part...); err != nil {
var b language.Builder
if err = update(&b, part...); err != nil {
return und, err
}
t, _ = b.tag.canonicalize(c)
if len(b.ext) > 0 || len(b.variant) > 0 {
sort.Sort(sortVariant(b.variant))
sort.Strings(b.ext)
if b.private != "" {
b.ext = append(b.ext, b.private)
}
n := maxCoreSize + tokenLen(b.variant...) + tokenLen(b.ext...)
buf := make([]byte, n)
p := t.genCoreBytes(buf)
t.pVariant = byte(p)
p += appendTokens(buf[p:], b.variant...)
t.pExt = uint16(p)
p += appendTokens(buf[p:], b.ext...)
t.str = string(buf[:p])
} else if b.private != "" {
t.str = b.private
t.remakeString()
}
return
}
type builder struct {
tag Tag
private string // the x extension
ext []string
variant []string
err error
}
func (b *builder) addExt(e string) {
if e == "" {
} else if e[0] == 'x' {
b.private = e
} else {
b.ext = append(b.ext, e)
}
b.Tag, _ = canonicalize(c, b.Tag)
return makeTag(b.Make()), err
}
var errInvalidArgument = errors.New("invalid Extension or Variant")
func (b *builder) update(part ...interface{}) (err error) {
replace := func(l *[]string, s string, eq func(a, b string) bool) bool {
if s == "" {
b.err = errInvalidArgument
return true
}
for i, v := range *l {
if eq(v, s) {
(*l)[i] = s
return true
}
}
return false
}
func update(b *language.Builder, part ...interface{}) (err error) {
for _, x := range part {
switch v := x.(type) {
case Tag:
b.tag.lang = v.lang
b.tag.region = v.region
b.tag.script = v.script
if v.str != "" {
b.variant = nil
for x, s := "", v.str[v.pVariant:v.pExt]; s != ""; {
x, s = nextToken(s)
b.variant = append(b.variant, x)
}
b.ext, b.private = nil, ""
for i, e := int(v.pExt), ""; i < len(v.str); {
i, e = getExtension(v.str, i)
b.addExt(e)
}
}
b.SetTag(v.tag())
case Base:
b.tag.lang = v.langID
b.Tag.LangID = v.langID
case Script:
b.tag.script = v.scriptID
b.Tag.ScriptID = v.scriptID
case Region:
b.tag.region = v.regionID
b.Tag.RegionID = v.regionID
case Variant:
if !replace(&b.variant, v.variant, func(a, b string) bool { return a == b }) {
b.variant = append(b.variant, v.variant)
if v.variant == "" {
err = errInvalidArgument
break
}
b.AddVariant(v.variant)
case Extension:
if !replace(&b.ext, v.s, func(a, b string) bool { return a[0] == b[0] }) {
b.addExt(v.s)
if v.s == "" {
err = errInvalidArgument
break
}
b.SetExt(v.s)
case []Variant:
b.variant = nil
for _, x := range v {
b.update(x)
b.ClearVariants()
for _, v := range v {
b.AddVariant(v.variant)
}
case []Extension:
b.ext, b.private = nil, ""
b.ClearExtensions()
for _, e := range v {
b.update(e)
b.SetExt(e.s)
}
// TODO: support parsing of raw strings based on morphology or just extensions?
case error:
err = v
}
}
return
}
func tokenLen(token ...string) (n int) {
for _, t := range token {
n += len(t) + 1
}
return
}
func appendTokens(b []byte, token ...string) int {
p := 0
for _, t := range token {
b[p] = '-'
copy(b[p+1:], t)
p += 1 + len(t)
}
return p
}
type sortVariant []string
func (s sortVariant) Len() int {
return len(s)
}
func (s sortVariant) Swap(i, j int) {
s[j], s[i] = s[i], s[j]
}
func (s sortVariant) Less(i, j int) bool {
return variantIndex[s[i]] < variantIndex[s[j]]
}
func findExt(list []string, x byte) int {
for i, e := range list {
if e[0] == x {
return i
}
}
return -1
}
// getExtension returns the name, body and end position of the extension.
func getExtension(s string, p int) (end int, ext string) {
if s[p] == '-' {
p++
}
if s[p] == 'x' {
return len(s), s[p:]
}
end = nextExtension(s, p)
return end, s[p:end]
}
// nextExtension finds the next extension within the string, searching
// for the -<char>- pattern from position p.
// In the fast majority of cases, language tags will have at most
// one extension and extensions tend to be small.
func nextExtension(s string, p int) int {
for n := len(s) - 3; p < n; {
if s[p] == '-' {
if s[p+2] == '-' {
return p
if v != nil {
err = v
}
p += 3
} else {
p++
}
}
return len(s)
return
}
var errInvalidWeight = errors.New("ParseAcceptLanguage: invalid weight")
// ParseAcceptLanguage parses the contents of a Accept-Language header as
// ParseAcceptLanguage parses the contents of an Accept-Language header as
// defined in http://www.ietf.org/rfc/rfc2616.txt and returns a list of Tags and
// a list of corresponding quality weights. It is more permissive than RFC 2616
// and may return non-nil slices even if the input is not valid.
@ -788,7 +157,7 @@ func ParseAcceptLanguage(s string) (tag []Tag, q []float32, err error) {
if !ok {
return nil, nil, err
}
t = Tag{lang: id}
t = makeTag(language.Tag{LangID: id})
}
// Scan the optional weight.
@ -832,7 +201,7 @@ func split(s string, c byte) (head, tail string) {
// Add hack mapping to deal with a small number of cases that that occur
// in Accept-Language (with reasonable frequency).
var acceptFallback = map[string]langID{
var acceptFallback = map[string]language.Language{
"english": _en,
"deutsch": _de,
"italian": _it,

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,8 @@
package language
import "golang.org/x/text/internal/language/compact"
// TODO: Various sets of commonly use tags and regions.
// MustParse is like Parse, but panics if the given BCP 47 tag cannot be parsed.
@ -61,83 +63,83 @@ var (
Und Tag = Tag{}
Afrikaans Tag = Tag{lang: _af} // af
Amharic Tag = Tag{lang: _am} // am
Arabic Tag = Tag{lang: _ar} // ar
ModernStandardArabic Tag = Tag{lang: _ar, region: _001} // ar-001
Azerbaijani Tag = Tag{lang: _az} // az
Bulgarian Tag = Tag{lang: _bg} // bg
Bengali Tag = Tag{lang: _bn} // bn
Catalan Tag = Tag{lang: _ca} // ca
Czech Tag = Tag{lang: _cs} // cs
Danish Tag = Tag{lang: _da} // da
German Tag = Tag{lang: _de} // de
Greek Tag = Tag{lang: _el} // el
English Tag = Tag{lang: _en} // en
AmericanEnglish Tag = Tag{lang: _en, region: _US} // en-US
BritishEnglish Tag = Tag{lang: _en, region: _GB} // en-GB
Spanish Tag = Tag{lang: _es} // es
EuropeanSpanish Tag = Tag{lang: _es, region: _ES} // es-ES
LatinAmericanSpanish Tag = Tag{lang: _es, region: _419} // es-419
Estonian Tag = Tag{lang: _et} // et
Persian Tag = Tag{lang: _fa} // fa
Finnish Tag = Tag{lang: _fi} // fi
Filipino Tag = Tag{lang: _fil} // fil
French Tag = Tag{lang: _fr} // fr
CanadianFrench Tag = Tag{lang: _fr, region: _CA} // fr-CA
Gujarati Tag = Tag{lang: _gu} // gu
Hebrew Tag = Tag{lang: _he} // he
Hindi Tag = Tag{lang: _hi} // hi
Croatian Tag = Tag{lang: _hr} // hr
Hungarian Tag = Tag{lang: _hu} // hu
Armenian Tag = Tag{lang: _hy} // hy
Indonesian Tag = Tag{lang: _id} // id
Icelandic Tag = Tag{lang: _is} // is
Italian Tag = Tag{lang: _it} // it
Japanese Tag = Tag{lang: _ja} // ja
Georgian Tag = Tag{lang: _ka} // ka
Kazakh Tag = Tag{lang: _kk} // kk
Khmer Tag = Tag{lang: _km} // km
Kannada Tag = Tag{lang: _kn} // kn
Korean Tag = Tag{lang: _ko} // ko
Kirghiz Tag = Tag{lang: _ky} // ky
Lao Tag = Tag{lang: _lo} // lo
Lithuanian Tag = Tag{lang: _lt} // lt
Latvian Tag = Tag{lang: _lv} // lv
Macedonian Tag = Tag{lang: _mk} // mk
Malayalam Tag = Tag{lang: _ml} // ml
Mongolian Tag = Tag{lang: _mn} // mn
Marathi Tag = Tag{lang: _mr} // mr
Malay Tag = Tag{lang: _ms} // ms
Burmese Tag = Tag{lang: _my} // my
Nepali Tag = Tag{lang: _ne} // ne
Dutch Tag = Tag{lang: _nl} // nl
Norwegian Tag = Tag{lang: _no} // no
Punjabi Tag = Tag{lang: _pa} // pa
Polish Tag = Tag{lang: _pl} // pl
Portuguese Tag = Tag{lang: _pt} // pt
BrazilianPortuguese Tag = Tag{lang: _pt, region: _BR} // pt-BR
EuropeanPortuguese Tag = Tag{lang: _pt, region: _PT} // pt-PT
Romanian Tag = Tag{lang: _ro} // ro
Russian Tag = Tag{lang: _ru} // ru
Sinhala Tag = Tag{lang: _si} // si
Slovak Tag = Tag{lang: _sk} // sk
Slovenian Tag = Tag{lang: _sl} // sl
Albanian Tag = Tag{lang: _sq} // sq
Serbian Tag = Tag{lang: _sr} // sr
SerbianLatin Tag = Tag{lang: _sr, script: _Latn} // sr-Latn
Swedish Tag = Tag{lang: _sv} // sv
Swahili Tag = Tag{lang: _sw} // sw
Tamil Tag = Tag{lang: _ta} // ta
Telugu Tag = Tag{lang: _te} // te
Thai Tag = Tag{lang: _th} // th
Turkish Tag = Tag{lang: _tr} // tr
Ukrainian Tag = Tag{lang: _uk} // uk
Urdu Tag = Tag{lang: _ur} // ur
Uzbek Tag = Tag{lang: _uz} // uz
Vietnamese Tag = Tag{lang: _vi} // vi
Chinese Tag = Tag{lang: _zh} // zh
SimplifiedChinese Tag = Tag{lang: _zh, script: _Hans} // zh-Hans
TraditionalChinese Tag = Tag{lang: _zh, script: _Hant} // zh-Hant
Zulu Tag = Tag{lang: _zu} // zu
Afrikaans Tag = Tag(compact.Afrikaans)
Amharic Tag = Tag(compact.Amharic)
Arabic Tag = Tag(compact.Arabic)
ModernStandardArabic Tag = Tag(compact.ModernStandardArabic)
Azerbaijani Tag = Tag(compact.Azerbaijani)
Bulgarian Tag = Tag(compact.Bulgarian)
Bengali Tag = Tag(compact.Bengali)
Catalan Tag = Tag(compact.Catalan)
Czech Tag = Tag(compact.Czech)
Danish Tag = Tag(compact.Danish)
German Tag = Tag(compact.German)
Greek Tag = Tag(compact.Greek)
English Tag = Tag(compact.English)
AmericanEnglish Tag = Tag(compact.AmericanEnglish)
BritishEnglish Tag = Tag(compact.BritishEnglish)
Spanish Tag = Tag(compact.Spanish)
EuropeanSpanish Tag = Tag(compact.EuropeanSpanish)
LatinAmericanSpanish Tag = Tag(compact.LatinAmericanSpanish)
Estonian Tag = Tag(compact.Estonian)
Persian Tag = Tag(compact.Persian)
Finnish Tag = Tag(compact.Finnish)
Filipino Tag = Tag(compact.Filipino)
French Tag = Tag(compact.French)
CanadianFrench Tag = Tag(compact.CanadianFrench)
Gujarati Tag = Tag(compact.Gujarati)
Hebrew Tag = Tag(compact.Hebrew)
Hindi Tag = Tag(compact.Hindi)
Croatian Tag = Tag(compact.Croatian)
Hungarian Tag = Tag(compact.Hungarian)
Armenian Tag = Tag(compact.Armenian)
Indonesian Tag = Tag(compact.Indonesian)
Icelandic Tag = Tag(compact.Icelandic)
Italian Tag = Tag(compact.Italian)
Japanese Tag = Tag(compact.Japanese)
Georgian Tag = Tag(compact.Georgian)
Kazakh Tag = Tag(compact.Kazakh)
Khmer Tag = Tag(compact.Khmer)
Kannada Tag = Tag(compact.Kannada)
Korean Tag = Tag(compact.Korean)
Kirghiz Tag = Tag(compact.Kirghiz)
Lao Tag = Tag(compact.Lao)
Lithuanian Tag = Tag(compact.Lithuanian)
Latvian Tag = Tag(compact.Latvian)
Macedonian Tag = Tag(compact.Macedonian)
Malayalam Tag = Tag(compact.Malayalam)
Mongolian Tag = Tag(compact.Mongolian)
Marathi Tag = Tag(compact.Marathi)
Malay Tag = Tag(compact.Malay)
Burmese Tag = Tag(compact.Burmese)
Nepali Tag = Tag(compact.Nepali)
Dutch Tag = Tag(compact.Dutch)
Norwegian Tag = Tag(compact.Norwegian)
Punjabi Tag = Tag(compact.Punjabi)
Polish Tag = Tag(compact.Polish)
Portuguese Tag = Tag(compact.Portuguese)
BrazilianPortuguese Tag = Tag(compact.BrazilianPortuguese)
EuropeanPortuguese Tag = Tag(compact.EuropeanPortuguese)
Romanian Tag = Tag(compact.Romanian)
Russian Tag = Tag(compact.Russian)
Sinhala Tag = Tag(compact.Sinhala)
Slovak Tag = Tag(compact.Slovak)
Slovenian Tag = Tag(compact.Slovenian)
Albanian Tag = Tag(compact.Albanian)
Serbian Tag = Tag(compact.Serbian)
SerbianLatin Tag = Tag(compact.SerbianLatin)
Swedish Tag = Tag(compact.Swedish)
Swahili Tag = Tag(compact.Swahili)
Tamil Tag = Tag(compact.Tamil)
Telugu Tag = Tag(compact.Telugu)
Thai Tag = Tag(compact.Thai)
Turkish Tag = Tag(compact.Turkish)
Ukrainian Tag = Tag(compact.Ukrainian)
Urdu Tag = Tag(compact.Urdu)
Uzbek Tag = Tag(compact.Uzbek)
Vietnamese Tag = Tag(compact.Vietnamese)
Chinese Tag = Tag(compact.Chinese)
SimplifiedChinese Tag = Tag(compact.SimplifiedChinese)
TraditionalChinese Tag = Tag(compact.TraditionalChinese)
Zulu Tag = Tag(compact.Zulu)
)