1 // Copyright 2014 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.
12 // The Coverage interface is used to define the level of coverage of an
13 // internationalization service. Note that not all types are supported by all
14 // services. As lists may be generated on the fly, it is recommended that users
15 // of a Coverage cache the results.
16 type Coverage interface {
17 // Tags returns the list of supported tags.
20 // BaseLanguages returns the list of supported base languages.
21 BaseLanguages() []Base
23 // Scripts returns the list of supported scripts.
26 // Regions returns the list of supported regions.
31 // Supported defines a Coverage that lists all supported subtags. Tags
32 // always returns nil.
33 Supported Coverage = allSubtags{}
37 // - Support Variants, numbering systems.
38 // - CLDR coverage levels.
39 // - Set of common tags defined in this package.
41 type allSubtags struct{}
43 // Regions returns the list of supported regions. As all regions are in a
44 // consecutive range, it simply returns a slice of numbers in increasing order.
45 // The "undefined" region is not returned.
46 func (s allSubtags) Regions() []Region {
47 reg := make([]Region, numRegions)
49 reg[i] = Region{regionID(i + 1)}
54 // Scripts returns the list of supported scripts. As all scripts are in a
55 // consecutive range, it simply returns a slice of numbers in increasing order.
56 // The "undefined" script is not returned.
57 func (s allSubtags) Scripts() []Script {
58 scr := make([]Script, numScripts)
60 scr[i] = Script{scriptID(i + 1)}
65 // BaseLanguages returns the list of all supported base languages. It generates
66 // the list by traversing the internal structures.
67 func (s allSubtags) BaseLanguages() []Base {
68 base := make([]Base, 0, numLanguages)
69 for i := 0; i < langNoIndexOffset; i++ {
70 // We included "und" already for the value 0.
71 if i != nonCanonicalUnd {
72 base = append(base, Base{langID(i)})
75 i := langNoIndexOffset
76 for _, v := range langNoIndex {
77 for k := 0; k < 8; k++ {
79 base = append(base, Base{langID(i)})
88 // Tags always returns nil.
89 func (s allSubtags) Tags() []Tag {
93 // coverage is used used by NewCoverage which is used as a convenient way for
94 // creating Coverage implementations for partially defined data. Very often a
95 // package will only need to define a subset of slices. coverage provides a
96 // convenient way to do this. Moreover, packages using NewCoverage, instead of
97 // their own implementation, will not break if later new slice types are added.
98 type coverage struct {
101 scripts func() []Script
102 regions func() []Region
105 func (s *coverage) Tags() []Tag {
112 // bases implements sort.Interface and is used to sort base languages.
115 func (b bases) Len() int {
119 func (b bases) Swap(i, j int) {
120 b[i], b[j] = b[j], b[i]
123 func (b bases) Less(i, j int) bool {
124 return b[i].langID < b[j].langID
127 // BaseLanguages returns the result from calling s.bases if it is specified or
128 // otherwise derives the set of supported base languages from tags.
129 func (s *coverage) BaseLanguages() []Base {
135 a := make([]Base, len(tags))
136 for i, t := range tags {
137 a[i] = Base{langID(t.lang)}
141 for i := 1; i < len(a); i++ {
152 func (s *coverage) Scripts() []Script {
153 if s.scripts == nil {
159 func (s *coverage) Regions() []Region {
160 if s.regions == nil {
166 // NewCoverage returns a Coverage for the given lists. It is typically used by
167 // packages providing internationalization services to define their level of
168 // coverage. A list may be of type []T or func() []T, where T is either Tag,
169 // Base, Script or Region. The returned Coverage derives the value for Bases
170 // from Tags if no func or slice for []Base is specified. For other unspecified
171 // types the returned Coverage will return nil for the respective methods.
172 func NewCoverage(list ...interface{}) Coverage {
174 for _, x := range list {
175 switch v := x.(type) {
178 case func() []Script:
180 case func() []Region:
185 s.bases = func() []Base { return v }
187 s.scripts = func() []Script { return v }
189 s.regions = func() []Region { return v }
191 s.tags = func() []Tag { return v }
193 panic(fmt.Sprintf("language: unsupported set type %T", v))