github.com/go-xe2/third@v1.0.3/golang.org/x/text/internal/colltab/colltab.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package colltab contains functionality related to collation tables.
     6  // It is only to be used by the collate and search packages.
     7  package colltab // import "github.com/go-xe2/third/golang.org/x/text/internal/colltab"
     8  
     9  import (
    10  	"sort"
    11  
    12  	"github.com/go-xe2/third/golang.org/x/text/language"
    13  )
    14  
    15  // MatchLang finds the index of t in tags, using a matching algorithm used for
    16  // collation and search. tags[0] must be language.Und, the remaining tags should
    17  // be sorted alphabetically.
    18  //
    19  // Language matching for collation and search is different from the matching
    20  // defined by language.Matcher: the (inferred) base language must be an exact
    21  // match for the relevant fields. For example, "gsw" should not match "de".
    22  // Also the parent relation is different, as a parent may have a different
    23  // script. So usually the parent of zh-Hant is und, whereas for MatchLang it is
    24  // zh.
    25  func MatchLang(t language.Tag, tags []language.Tag) int {
    26  	// Canonicalize the values, including collapsing macro languages.
    27  	t, _ = language.All.Canonicalize(t)
    28  
    29  	base, conf := t.Base()
    30  	// Estimate the base language, but only use high-confidence values.
    31  	if conf < language.High {
    32  		// The root locale supports "search" and "standard". We assume that any
    33  		// implementation will only use one of both.
    34  		return 0
    35  	}
    36  
    37  	// Maximize base and script and normalize the tag.
    38  	if _, s, r := t.Raw(); (r != language.Region{}) {
    39  		p, _ := language.Raw.Compose(base, s, r)
    40  		// Taking the parent forces the script to be maximized.
    41  		p = p.Parent()
    42  		// Add back region and extensions.
    43  		t, _ = language.Raw.Compose(p, r, t.Extensions())
    44  	} else {
    45  		// Set the maximized base language.
    46  		t, _ = language.Raw.Compose(base, s, t.Extensions())
    47  	}
    48  
    49  	// Find start index of the language tag.
    50  	start := 1 + sort.Search(len(tags)-1, func(i int) bool {
    51  		b, _, _ := tags[i+1].Raw()
    52  		return base.String() <= b.String()
    53  	})
    54  	if start < len(tags) {
    55  		if b, _, _ := tags[start].Raw(); b != base {
    56  			return 0
    57  		}
    58  	}
    59  
    60  	// Besides the base language, script and region, only the collation type and
    61  	// the custom variant defined in the 'u' extension are used to distinguish a
    62  	// locale.
    63  	// Strip all variants and extensions and add back the custom variant.
    64  	tdef, _ := language.Raw.Compose(t.Raw())
    65  	tdef, _ = tdef.SetTypeForKey("va", t.TypeForKey("va"))
    66  
    67  	// First search for a specialized collation type, if present.
    68  	try := []language.Tag{tdef}
    69  	if co := t.TypeForKey("co"); co != "" {
    70  		tco, _ := tdef.SetTypeForKey("co", co)
    71  		try = []language.Tag{tco, tdef}
    72  	}
    73  
    74  	for _, tx := range try {
    75  		for ; tx != language.Und; tx = parent(tx) {
    76  			for i, t := range tags[start:] {
    77  				if b, _, _ := t.Raw(); b != base {
    78  					break
    79  				}
    80  				if tx == t {
    81  					return start + i
    82  				}
    83  			}
    84  		}
    85  	}
    86  	return 0
    87  }
    88  
    89  // parent computes the structural parent. This means inheritance may change
    90  // script. So, unlike the CLDR parent, parent(zh-Hant) == zh.
    91  func parent(t language.Tag) language.Tag {
    92  	if t.TypeForKey("va") != "" {
    93  		t, _ = t.SetTypeForKey("va", "")
    94  		return t
    95  	}
    96  	result := language.Und
    97  	if b, s, r := t.Raw(); (r != language.Region{}) {
    98  		result, _ = language.Raw.Compose(b, s, t.Extensions())
    99  	} else if (s != language.Script{}) {
   100  		result, _ = language.Raw.Compose(b, t.Extensions())
   101  	} else if (b != language.Base{}) {
   102  		result, _ = language.Raw.Compose(t.Extensions())
   103  	}
   104  	return result
   105  }