Update dependencies to K8s 1.8
This commit is contained in:
parent
ba6c89672d
commit
6a59f4c9a2
1114 changed files with 160955 additions and 262845 deletions
2
vendor/golang.org/x/text/language/common.go
generated
vendored
2
vendor/golang.org/x/text/language/common.go
generated
vendored
|
|
@ -1,4 +1,4 @@
|
|||
// This file was generated by go generate; DO NOT EDIT
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package language
|
||||
|
||||
|
|
|
|||
206
vendor/golang.org/x/text/language/maketables.go → vendor/golang.org/x/text/language/gen.go
generated
vendored
206
vendor/golang.org/x/text/language/maketables.go → vendor/golang.org/x/text/language/gen.go
generated
vendored
|
|
@ -678,6 +678,8 @@ func (b *builder) parseIndices() {
|
|||
b.locale.parse(meta.DefaultContent.Locales)
|
||||
}
|
||||
|
||||
// TODO: region inclusion data will probably not be use used in future matchers.
|
||||
|
||||
func (b *builder) computeRegionGroups() {
|
||||
b.groups = make(map[int]index)
|
||||
|
||||
|
|
@ -686,6 +688,11 @@ func (b *builder) computeRegionGroups() {
|
|||
b.groups[i] = index(len(b.groups))
|
||||
}
|
||||
for _, g := range b.supp.TerritoryContainment.Group {
|
||||
// Skip UN and EURO zone as they are flattening the containment
|
||||
// relationship.
|
||||
if g.Type == "EZ" || g.Type == "UN" {
|
||||
continue
|
||||
}
|
||||
group := b.region.index(g.Type)
|
||||
if _, ok := b.groups[group]; !ok {
|
||||
b.groups[group] = index(len(b.groups))
|
||||
|
|
@ -782,6 +789,7 @@ func (b *builder) writeLanguage() {
|
|||
lang.updateLater("tw", "twi")
|
||||
lang.updateLater("nb", "nob")
|
||||
lang.updateLater("ak", "aka")
|
||||
lang.updateLater("bh", "bih")
|
||||
|
||||
// Ensure that each 2-letter code is matched with a 3-letter code.
|
||||
for _, v := range lang.s[1:] {
|
||||
|
|
@ -798,10 +806,10 @@ func (b *builder) writeLanguage() {
|
|||
}
|
||||
}
|
||||
|
||||
// Complete canonialized language tags.
|
||||
// Complete canonicalized language tags.
|
||||
lang.freeze()
|
||||
for i, v := range lang.s {
|
||||
// We can avoid these manual entries by using the IANI registry directly.
|
||||
// We can avoid these manual entries by using the IANA registry directly.
|
||||
// Seems easier to update the list manually, as changes are rare.
|
||||
// The panic in this loop will trigger if we miss an entry.
|
||||
add := ""
|
||||
|
|
@ -908,7 +916,7 @@ func (b *builder) writeRegion() {
|
|||
i := b.region.index(s)
|
||||
for _, d := range e.description {
|
||||
if strings.Contains(d, "Private use") {
|
||||
regionTypes[i] = iso3166UserAssgined
|
||||
regionTypes[i] = iso3166UserAssigned
|
||||
}
|
||||
}
|
||||
regionTypes[i] |= bcp47Region
|
||||
|
|
@ -1065,7 +1073,7 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
iso3166UserAssgined = 1 << iota
|
||||
iso3166UserAssigned = 1 << iota
|
||||
ccTLD
|
||||
bcp47Region
|
||||
)
|
||||
|
|
@ -1355,42 +1363,23 @@ func (b *builder) writeLikelyData() {
|
|||
|
||||
type mutualIntelligibility struct {
|
||||
want, have uint16
|
||||
conf uint8
|
||||
distance uint8
|
||||
oneway bool
|
||||
}
|
||||
|
||||
type scriptIntelligibility struct {
|
||||
lang uint16 // langID or 0 if *
|
||||
want, have uint8
|
||||
conf uint8
|
||||
wantLang, haveLang uint16
|
||||
wantScript, haveScript uint8
|
||||
distance uint8
|
||||
// Always oneway
|
||||
}
|
||||
|
||||
type sortByConf []mutualIntelligibility
|
||||
|
||||
func (l sortByConf) Less(a, b int) bool {
|
||||
return l[a].conf > l[b].conf
|
||||
}
|
||||
|
||||
func (l sortByConf) Swap(a, b int) {
|
||||
l[a], l[b] = l[b], l[a]
|
||||
}
|
||||
|
||||
func (l sortByConf) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
// toConf converts a percentage value [0, 100] to a confidence class.
|
||||
func toConf(pct uint8) uint8 {
|
||||
switch {
|
||||
case pct == 100:
|
||||
return 3 // Exact
|
||||
case pct >= 90:
|
||||
return 2 // High
|
||||
case pct > 50:
|
||||
return 1 // Low
|
||||
default:
|
||||
return 0 // No
|
||||
}
|
||||
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
|
||||
|
|
@ -1400,13 +1389,50 @@ func toConf(pct uint8) uint8 {
|
|||
// 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, len(b.region.s))
|
||||
|
||||
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.region.index(r)] |= 1 << uint8(i)
|
||||
todo = append(todo, regionHierarchy[r]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
b.writeSlice("regionToGroups", regionToGroups)
|
||||
|
||||
b.writeType(mutualIntelligibility{})
|
||||
b.writeType(scriptIntelligibility{})
|
||||
lm := b.supp.LanguageMatching.LanguageMatches
|
||||
cldr.MakeSlice(&lm).SelectAnyOf("type", "written")
|
||||
b.writeType(regionIntelligibility{})
|
||||
|
||||
matchLang := []mutualIntelligibility{}
|
||||
matchLang := []mutualIntelligibility{{
|
||||
// TODO: remove once CLDR is fixed.
|
||||
want: uint16(b.langIndex("sr")),
|
||||
have: uint16(b.langIndex("hr")),
|
||||
distance: uint8(5),
|
||||
}, {
|
||||
want: uint16(b.langIndex("sr")),
|
||||
have: uint16(b.langIndex("bs")),
|
||||
distance: uint8(5),
|
||||
}}
|
||||
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.
|
||||
|
|
@ -1414,33 +1440,38 @@ func (b *builder) writeMatchData() {
|
|||
supported := strings.Replace(m.Supported, "-", "_", -1)
|
||||
d := strings.Split(desired, "_")
|
||||
s := strings.Split(supported, "_")
|
||||
if len(d) != len(s) || len(d) > 2 {
|
||||
// Skip all entries with regions and work around CLDR bug.
|
||||
if len(d) != len(s) {
|
||||
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
|
||||
continue
|
||||
}
|
||||
pct, _ := strconv.ParseInt(m.Percent, 10, 8)
|
||||
if len(d) == 2 && d[0] == s[0] && len(d[1]) == 4 {
|
||||
// language-script pair.
|
||||
lang := uint16(0)
|
||||
if d[0] != "*" {
|
||||
lang = uint16(b.langIndex(d[0]))
|
||||
distance, _ := strconv.ParseInt(m.Distance, 10, 8)
|
||||
switch len(d) {
|
||||
case 2:
|
||||
if desired == supported && desired == "*_*" {
|
||||
continue
|
||||
}
|
||||
// language-script pair.
|
||||
matchScript = append(matchScript, scriptIntelligibility{
|
||||
lang: lang,
|
||||
want: uint8(b.script.index(d[1])),
|
||||
have: uint8(b.script.index(s[1])),
|
||||
conf: toConf(uint8(pct)),
|
||||
wantLang: uint16(b.langIndex(d[0])),
|
||||
haveLang: uint16(b.langIndex(s[0])),
|
||||
wantScript: uint8(b.script.index(d[1])),
|
||||
haveScript: uint8(b.script.index(s[1])),
|
||||
distance: uint8(distance),
|
||||
})
|
||||
if m.Oneway != "true" {
|
||||
matchScript = append(matchScript, scriptIntelligibility{
|
||||
lang: lang,
|
||||
want: uint8(b.script.index(s[1])),
|
||||
have: uint8(b.script.index(d[1])),
|
||||
conf: toConf(uint8(pct)),
|
||||
wantLang: uint16(b.langIndex(s[0])),
|
||||
haveLang: uint16(b.langIndex(d[0])),
|
||||
wantScript: uint8(b.script.index(s[1])),
|
||||
haveScript: uint8(b.script.index(d[1])),
|
||||
distance: uint8(distance),
|
||||
})
|
||||
}
|
||||
} else if len(d) == 1 && d[0] != "*" {
|
||||
if pct == 100 {
|
||||
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" {
|
||||
|
|
@ -1448,28 +1479,57 @@ func (b *builder) writeMatchData() {
|
|||
}
|
||||
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])),
|
||||
conf: uint8(pct),
|
||||
oneway: m.Oneway == "true",
|
||||
want: uint16(b.langIndex(d[0])),
|
||||
have: uint16(b.langIndex(s[0])),
|
||||
distance: uint8(distance),
|
||||
oneway: m.Oneway == "true",
|
||||
})
|
||||
} else {
|
||||
// TODO: Handle other mappings.
|
||||
a := []string{"*;*", "*_*;*_*", "es_MX;es_419"}
|
||||
s := strings.Join([]string{desired, supported}, ";")
|
||||
if i := sort.SearchStrings(a, s); i == len(a) || a[i] != s {
|
||||
log.Printf("%q not handled", s)
|
||||
case 3:
|
||||
if desired == supported && desired == "*_*_*" {
|
||||
continue
|
||||
}
|
||||
if desired != supported { // (Weird but correct.)
|
||||
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.script.index(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.Stable(sortByConf(matchLang))
|
||||
// collapse percentage into confidence classes
|
||||
for i, m := range matchLang {
|
||||
matchLang[i].conf = toConf(m.conf)
|
||||
}
|
||||
sort.SliceStable(matchLang, func(i, j int) bool {
|
||||
return matchLang[i].distance < matchLang[j].distance
|
||||
})
|
||||
b.writeSlice("matchLang", matchLang)
|
||||
|
||||
sort.SliceStable(matchScript, func(i, j int) bool {
|
||||
return matchScript[i].distance < matchScript[j].distance
|
||||
})
|
||||
b.writeSlice("matchScript", matchScript)
|
||||
|
||||
sort.SliceStable(matchRegion, func(i, j int) bool {
|
||||
return matchRegion[i].distance < matchRegion[j].distance
|
||||
})
|
||||
b.writeSlice("matchRegion", matchRegion)
|
||||
}
|
||||
|
||||
func (b *builder) writeRegionInclusionData() {
|
||||
|
|
@ -1482,6 +1542,11 @@ func (b *builder) writeRegionInclusionData() {
|
|||
containment = make(map[index][]index)
|
||||
)
|
||||
for _, g := range b.supp.TerritoryContainment.Group {
|
||||
// Skip UN and EURO zone as they are flattening the containment
|
||||
// relationship.
|
||||
if g.Type == "EZ" || g.Type == "UN" {
|
||||
continue
|
||||
}
|
||||
group := b.region.index(g.Type)
|
||||
groupIdx := b.groups[group]
|
||||
for _, mem := range strings.Split(g.Contains, " ") {
|
||||
|
|
@ -1508,7 +1573,6 @@ func (b *builder) writeRegionInclusionData() {
|
|||
for _, v := range l {
|
||||
regionContainment[g] |= 1 << v
|
||||
}
|
||||
// log.Printf("%d: %X", g, regionContainment[g])
|
||||
}
|
||||
b.writeSlice("regionContainment", regionContainment)
|
||||
|
||||
1505
vendor/golang.org/x/text/language/index.go
generated
vendored
1505
vendor/golang.org/x/text/language/index.go
generated
vendored
File diff suppressed because it is too large
Load diff
15
vendor/golang.org/x/text/language/language.go
generated
vendored
15
vendor/golang.org/x/text/language/language.go
generated
vendored
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run maketables.go gen_common.go -output tables.go
|
||||
//go:generate go run gen.go gen_common.go -output tables.go
|
||||
//go:generate go run gen_index.go
|
||||
|
||||
// Package language implements BCP 47 language tags and related functionality.
|
||||
|
|
@ -129,8 +129,15 @@ const (
|
|||
// specific language or locale. All language tag values are guaranteed to be
|
||||
// well-formed.
|
||||
type Tag struct {
|
||||
lang langID
|
||||
region regionID
|
||||
lang langID
|
||||
region regionID
|
||||
// TODO: we will soon run out of positions for script. Idea: instead of
|
||||
// storing lang, region, and script codes, store only the compact index and
|
||||
// have a lookup table from this code to its expansion. This greatly speeds
|
||||
// up table lookup, speed up common variant cases.
|
||||
// This will also immediately free up 3 extra bytes. Also, the pVariant
|
||||
// field can now be moved to the lookup table, as the compact index uniquely
|
||||
// determines the offset of a possible variant.
|
||||
script scriptID
|
||||
pVariant byte // offset in str, includes preceding '-'
|
||||
pExt uint16 // offset of first extension, includes preceding '-'
|
||||
|
|
@ -593,7 +600,7 @@ func (t Tag) Extension(x byte) (ext Extension, ok bool) {
|
|||
return Extension{ext}, true
|
||||
}
|
||||
}
|
||||
return Extension{string(x)}, false
|
||||
return Extension{}, false
|
||||
}
|
||||
|
||||
// Extensions returns all extensions of t.
|
||||
|
|
|
|||
177
vendor/golang.org/x/text/language/match.go
generated
vendored
177
vendor/golang.org/x/text/language/match.go
generated
vendored
|
|
@ -6,6 +6,16 @@ package language
|
|||
|
||||
import "errors"
|
||||
|
||||
// A MatchOption configures a Matcher.
|
||||
type MatchOption func(*matcher)
|
||||
|
||||
// PreferSameScript will, in the absence of a match, result in the first
|
||||
// preferred tag with the same script as a supported tag to match this supported
|
||||
// tag. The default is currently true, but this may change in the future.
|
||||
func PreferSameScript(preferSame bool) MatchOption {
|
||||
return func(m *matcher) { m.preferSameScript = preferSame }
|
||||
}
|
||||
|
||||
// Matcher is the interface that wraps the Match method.
|
||||
//
|
||||
// Match returns the best match for any of the given tags, along with
|
||||
|
|
@ -36,23 +46,44 @@ func Comprehends(speaker, alternative Tag) Confidence {
|
|||
// matched tag in t, but is augmented with the Unicode extension ('u')of the
|
||||
// corresponding preferred tag. This allows user locale options to be passed
|
||||
// transparently.
|
||||
func NewMatcher(t []Tag) Matcher {
|
||||
return newMatcher(t)
|
||||
func NewMatcher(t []Tag, options ...MatchOption) Matcher {
|
||||
return newMatcher(t, options)
|
||||
}
|
||||
|
||||
func (m *matcher) Match(want ...Tag) (t Tag, index int, c Confidence) {
|
||||
match, w, c := m.getBest(want...)
|
||||
if match == nil {
|
||||
t = m.default_.tag
|
||||
} else {
|
||||
if match != nil {
|
||||
t, index = match.tag, match.index
|
||||
} else {
|
||||
// TODO: this should be an option
|
||||
t = m.default_.tag
|
||||
if m.preferSameScript {
|
||||
outer:
|
||||
for _, w := range want {
|
||||
script, _ := w.Script()
|
||||
if script.scriptID == 0 {
|
||||
// Don't do anything if there is no script, such as with
|
||||
// private subtags.
|
||||
continue
|
||||
}
|
||||
for i, h := range m.supported {
|
||||
if script.scriptID == h.maxScript {
|
||||
t, index = h.tag, i
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: select first language tag based on script.
|
||||
}
|
||||
if w.region != 0 && t.region != 0 && t.region.contains(w.region) {
|
||||
t, _ = Raw.Compose(t, Region{w.region})
|
||||
}
|
||||
// Copy options from the user-provided tag into the result tag. This is hard
|
||||
// to do after the fact, so we do it here.
|
||||
// TODO: consider also adding in variants that are compatible with the
|
||||
// matched language.
|
||||
// TODO: Add back region if it is non-ambiguous? Or create another tag to
|
||||
// preserve the region?
|
||||
// TODO: add in alternative variants to -u-va-.
|
||||
// TODO: add preferred region to -u-rg-.
|
||||
// TODO: add other extensions. Merge with existing extensions.
|
||||
if u, ok := w.Extension('u'); ok {
|
||||
t, _ = Raw.Compose(t, u)
|
||||
}
|
||||
|
|
@ -388,16 +419,18 @@ func minimizeTags(t Tag) (Tag, error) {
|
|||
|
||||
// matcher keeps a set of supported language tags, indexed by language.
|
||||
type matcher struct {
|
||||
default_ *haveTag
|
||||
index map[langID]*matchHeader
|
||||
passSettings bool
|
||||
default_ *haveTag
|
||||
supported []*haveTag
|
||||
index map[langID]*matchHeader
|
||||
passSettings bool
|
||||
preferSameScript bool
|
||||
}
|
||||
|
||||
// matchHeader has the lists of tags for exact matches and matches based on
|
||||
// maximized and canonicalized tags for a given language.
|
||||
type matchHeader struct {
|
||||
exact []haveTag
|
||||
max []haveTag
|
||||
exact []*haveTag
|
||||
max []*haveTag
|
||||
}
|
||||
|
||||
// haveTag holds a supported Tag and its maximized script and region. The maximized
|
||||
|
|
@ -440,8 +473,10 @@ func makeHaveTag(tag Tag, index int) (haveTag, langID) {
|
|||
// script to map to another and we rely on this to keep the code simple.
|
||||
func altScript(l langID, s scriptID) scriptID {
|
||||
for _, alt := range matchScript {
|
||||
if (alt.lang == 0 || langID(alt.lang) == l) && scriptID(alt.have) == s {
|
||||
return scriptID(alt.want)
|
||||
// TODO: also match cases where language is not the same.
|
||||
if (langID(alt.wantLang) == l || langID(alt.haveLang) == l) &&
|
||||
scriptID(alt.haveScript) == s {
|
||||
return scriptID(alt.wantScript)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
|
|
@ -457,7 +492,7 @@ func (h *matchHeader) addIfNew(n haveTag, exact bool) {
|
|||
}
|
||||
}
|
||||
if exact {
|
||||
h.exact = append(h.exact, n)
|
||||
h.exact = append(h.exact, &n)
|
||||
}
|
||||
// Allow duplicate maximized tags, but create a linked list to allow quickly
|
||||
// comparing the equivalents and bail out.
|
||||
|
|
@ -472,7 +507,7 @@ func (h *matchHeader) addIfNew(n haveTag, exact bool) {
|
|||
break
|
||||
}
|
||||
}
|
||||
h.max = append(h.max, n)
|
||||
h.max = append(h.max, &n)
|
||||
}
|
||||
|
||||
// header returns the matchHeader for the given language. It creates one if
|
||||
|
|
@ -486,12 +521,26 @@ func (m *matcher) header(l langID) *matchHeader {
|
|||
return h
|
||||
}
|
||||
|
||||
func toConf(d uint8) Confidence {
|
||||
if d <= 10 {
|
||||
return High
|
||||
}
|
||||
if d < 30 {
|
||||
return Low
|
||||
}
|
||||
return No
|
||||
}
|
||||
|
||||
// newMatcher builds an index for the given supported tags and returns it as
|
||||
// a matcher. It also expands the index by considering various equivalence classes
|
||||
// for a given tag.
|
||||
func newMatcher(supported []Tag) *matcher {
|
||||
func newMatcher(supported []Tag, options []MatchOption) *matcher {
|
||||
m := &matcher{
|
||||
index: make(map[langID]*matchHeader),
|
||||
index: make(map[langID]*matchHeader),
|
||||
preferSameScript: true,
|
||||
}
|
||||
for _, o := range options {
|
||||
o(m)
|
||||
}
|
||||
if len(supported) == 0 {
|
||||
m.default_ = &haveTag{}
|
||||
|
|
@ -502,8 +551,9 @@ func newMatcher(supported []Tag) *matcher {
|
|||
for i, tag := range supported {
|
||||
pair, _ := makeHaveTag(tag, i)
|
||||
m.header(tag.lang).addIfNew(pair, true)
|
||||
m.supported = append(m.supported, &pair)
|
||||
}
|
||||
m.default_ = &m.header(supported[0].lang).exact[0]
|
||||
m.default_ = m.header(supported[0].lang).exact[0]
|
||||
for i, tag := range supported {
|
||||
pair, max := makeHaveTag(tag, i)
|
||||
if max != tag.lang {
|
||||
|
|
@ -511,6 +561,9 @@ func newMatcher(supported []Tag) *matcher {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: include alt script.
|
||||
// - don't replace regions, but allow regions to be made more specific.
|
||||
|
||||
// update is used to add indexes in the map for equivalent languages.
|
||||
// If force is true, the update will also apply to derived entries. To
|
||||
// avoid applying a "transitive closure", use false.
|
||||
|
|
@ -520,7 +573,8 @@ func newMatcher(supported []Tag) *matcher {
|
|||
return
|
||||
}
|
||||
hw := m.header(langID(want))
|
||||
for _, v := range hh.max {
|
||||
for _, ht := range hh.max {
|
||||
v := *ht
|
||||
if conf < v.conf {
|
||||
v.conf = conf
|
||||
}
|
||||
|
|
@ -536,9 +590,9 @@ func newMatcher(supported []Tag) *matcher {
|
|||
// Add entries for languages with mutual intelligibility as defined by CLDR's
|
||||
// languageMatch data.
|
||||
for _, ml := range matchLang {
|
||||
update(ml.want, ml.have, Confidence(ml.conf), false)
|
||||
update(ml.want, ml.have, toConf(ml.distance), false)
|
||||
if !ml.oneway {
|
||||
update(ml.have, ml.want, Confidence(ml.conf), false)
|
||||
update(ml.have, ml.want, toConf(ml.distance), false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -580,7 +634,7 @@ func (m *matcher) getBest(want ...Tag) (got *haveTag, orig Tag, c Confidence) {
|
|||
continue
|
||||
}
|
||||
for i := range h.exact {
|
||||
have := &h.exact[i]
|
||||
have := h.exact[i]
|
||||
if have.tag.equalsRest(w) {
|
||||
return have, w, Exact
|
||||
}
|
||||
|
|
@ -591,7 +645,7 @@ func (m *matcher) getBest(want ...Tag) (got *haveTag, orig Tag, c Confidence) {
|
|||
// Base language is not defined.
|
||||
if h != nil {
|
||||
for i := range h.exact {
|
||||
have := &h.exact[i]
|
||||
have := h.exact[i]
|
||||
if have.tag.equalsRest(w) {
|
||||
return have, w, Exact
|
||||
}
|
||||
|
|
@ -609,11 +663,11 @@ func (m *matcher) getBest(want ...Tag) (got *haveTag, orig Tag, c Confidence) {
|
|||
}
|
||||
// Check for match based on maximized tag.
|
||||
for i := range h.max {
|
||||
have := &h.max[i]
|
||||
have := h.max[i]
|
||||
best.update(have, w, max.script, max.region)
|
||||
if best.conf == Exact {
|
||||
for have.nextMax != 0 {
|
||||
have = &h.max[have.nextMax]
|
||||
have = h.max[have.nextMax]
|
||||
best.update(have, w, max.script, max.region)
|
||||
}
|
||||
return best.have, best.want, High
|
||||
|
|
@ -635,11 +689,12 @@ type bestMatch struct {
|
|||
want Tag
|
||||
conf Confidence
|
||||
// Cached results from applying tie-breaking rules.
|
||||
origLang bool
|
||||
origReg bool
|
||||
regDist uint8
|
||||
origScript bool
|
||||
parentDist uint8 // 255 if have is not an ancestor of want tag.
|
||||
origLang bool
|
||||
origReg bool
|
||||
regGroupDist uint8
|
||||
regDist uint8
|
||||
origScript bool
|
||||
parentDist uint8 // 255 if have is not an ancestor of want tag.
|
||||
}
|
||||
|
||||
// update updates the existing best match if the new pair is considered to be a
|
||||
|
|
@ -693,6 +748,14 @@ func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion
|
|||
beaten = true
|
||||
}
|
||||
|
||||
regGroupDist := regionGroupDist(have.maxRegion, maxRegion, maxScript, tag.lang)
|
||||
if !beaten && m.regGroupDist != regGroupDist {
|
||||
if regGroupDist > m.regGroupDist {
|
||||
return
|
||||
}
|
||||
beaten = true
|
||||
}
|
||||
|
||||
// We prefer if the pre-maximized region was specified and identical.
|
||||
origReg := have.tag.region == tag.region && tag.region != 0
|
||||
if !beaten && m.origReg != origReg {
|
||||
|
|
@ -702,8 +765,22 @@ func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion
|
|||
beaten = true
|
||||
}
|
||||
|
||||
// Next we prefer smaller distances between regions, as defined by regionDist.
|
||||
regDist := regionDist(have.maxRegion, maxRegion, tag.lang)
|
||||
// TODO: remove the region distance rule. Region distance has been replaced
|
||||
// by the region grouping rule. For now we leave it as it still seems to
|
||||
// have a net positive effect when applied after the grouping rule.
|
||||
// Possible solutions:
|
||||
// - apply the primary locale rule first to effectively disable region
|
||||
// region distance if groups are defined.
|
||||
// - express the following errors in terms of grouping (if possible)
|
||||
// - find another method of handling the following cases.
|
||||
// maximization of legacy: find mo in
|
||||
// "sr-Cyrl, sr-Latn, ro, ro-MD": have ro; want ro-MD (High)
|
||||
// region distance French: find fr-US in
|
||||
// "en, fr, fr-CA, fr-CH": have fr; want fr-CA (High)
|
||||
|
||||
// Next we prefer smaller distances between regions, as defined by
|
||||
// regionDist.
|
||||
regDist := uint8(regionDistance(have.maxRegion, maxRegion))
|
||||
if !beaten && m.regDist != regDist {
|
||||
if regDist > m.regDist {
|
||||
return
|
||||
|
|
@ -721,6 +798,9 @@ func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion
|
|||
}
|
||||
|
||||
// Finally we prefer tags which have a closer parent relationship.
|
||||
// TODO: the parent relationship no longer seems necessary. It doesn't hurt
|
||||
// to leave it in as the final tie-breaker, though, especially until the
|
||||
// grouping data has further matured.
|
||||
parentDist := parentDistance(have.tag.region, tag)
|
||||
if !beaten && m.parentDist != parentDist {
|
||||
if parentDist > m.parentDist {
|
||||
|
|
@ -737,6 +817,7 @@ func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion
|
|||
m.origLang = origLang
|
||||
m.origReg = origReg
|
||||
m.origScript = origScript
|
||||
m.regGroupDist = regGroupDist
|
||||
m.regDist = regDist
|
||||
m.parentDist = parentDist
|
||||
}
|
||||
|
|
@ -759,15 +840,27 @@ func parentDistance(haveRegion regionID, tag Tag) uint8 {
|
|||
return d
|
||||
}
|
||||
|
||||
// regionDist wraps regionDistance with some exceptions to the algorithmic distance.
|
||||
func regionDist(a, b regionID, lang langID) uint8 {
|
||||
if lang == _en {
|
||||
// Two variants of non-US English are close to each other, regardless of distance.
|
||||
if a != _US && b != _US {
|
||||
return 2
|
||||
// regionGroupDist computes the distance between two regions based on their
|
||||
// CLDR grouping.
|
||||
func regionGroupDist(a, b regionID, script scriptID, lang langID) uint8 {
|
||||
aGroup := uint(regionToGroups[a]) << 1
|
||||
bGroup := uint(regionToGroups[b]) << 1
|
||||
for _, ri := range matchRegion {
|
||||
if langID(ri.lang) == lang && (ri.script == 0 || scriptID(ri.script) == script) {
|
||||
group := uint(1 << (ri.group &^ 0x80))
|
||||
if 0x80&ri.group == 0 {
|
||||
if aGroup&bGroup&group != 0 { // Both regions are in the group.
|
||||
return ri.distance
|
||||
}
|
||||
} else {
|
||||
if (aGroup|bGroup)&group == 0 { // Both regions are not in the group.
|
||||
return ri.distance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return uint8(regionDistance(a, b))
|
||||
const defaultDistance = 4
|
||||
return defaultDistance
|
||||
}
|
||||
|
||||
// regionDistance computes the distance between two regions based on the
|
||||
|
|
|
|||
5241
vendor/golang.org/x/text/language/tables.go
generated
vendored
5241
vendor/golang.org/x/text/language/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue