|
|
// 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.
package language
import ( "fmt" "sort"
"golang.org/x/text/internal/language" )
// The Coverage interface is used to define the level of coverage of an
// internationalization service. Note that not all types are supported by all
// services. As lists may be generated on the fly, it is recommended that users
// of a Coverage cache the results.
type Coverage interface { // Tags returns the list of supported tags.
Tags() []Tag
// BaseLanguages returns the list of supported base languages.
BaseLanguages() []Base
// Scripts returns the list of supported scripts.
Scripts() []Script
// Regions returns the list of supported regions.
Regions() []Region }
var ( // Supported defines a Coverage that lists all supported subtags. Tags
// always returns nil.
Supported Coverage = allSubtags{} )
// TODO:
// - Support Variants, numbering systems.
// - CLDR coverage levels.
// - Set of common tags defined in this package.
type allSubtags struct{}
// Regions returns the list of supported regions. As all regions are in a
// 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, language.NumRegions) for i := range reg { reg[i] = Region{language.Region(i + 1)} } return reg }
// Scripts returns the list of supported scripts. As all scripts are in a
// 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, language.NumScripts) for i := range scr { scr[i] = Script{language.Script(i + 1)} } return scr }
// BaseLanguages returns the list of all supported base languages. It generates
// the list by traversing the internal structures.
func (s allSubtags) BaseLanguages() []Base { bs := language.BaseLanguages() base := make([]Base, len(bs)) for i, b := range bs { base[i] = Base{b} } return base }
// Tags always returns nil.
func (s allSubtags) Tags() []Tag { return nil }
// coverage is used by NewCoverage which is used as a convenient way for
// creating Coverage implementations for partially defined data. Very often a
// package will only need to define a subset of slices. coverage provides a
// convenient way to do this. Moreover, packages using NewCoverage, instead of
// their own implementation, will not break if later new slice types are added.
type coverage struct { tags func() []Tag bases func() []Base scripts func() []Script regions func() []Region }
func (s *coverage) Tags() []Tag { if s.tags == nil { return nil } return s.tags() }
// bases implements sort.Interface and is used to sort base languages.
type bases []Base
func (b bases) Len() int { return len(b) }
func (b bases) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
func (b bases) Less(i, j int) bool { return b[i].langID < b[j].langID }
// BaseLanguages returns the result from calling s.bases if it is specified or
// otherwise derives the set of supported base languages from tags.
func (s *coverage) BaseLanguages() []Base { if s.bases == nil { tags := s.Tags() if len(tags) == 0 { return nil } a := make([]Base, len(tags)) for i, t := range tags { a[i] = Base{language.Language(t.lang())} } sort.Sort(bases(a)) k := 0 for i := 1; i < len(a); i++ { if a[k] != a[i] { k++ a[k] = a[i] } } return a[:k+1] } return s.bases() }
func (s *coverage) Scripts() []Script { if s.scripts == nil { return nil } return s.scripts() }
func (s *coverage) Regions() []Region { if s.regions == nil { return nil } return s.regions() }
// NewCoverage returns a Coverage for the given lists. It is typically used by
// packages providing internationalization services to define their level of
// coverage. A list may be of type []T or func() []T, where T is either Tag,
// Base, Script or Region. The returned Coverage derives the value for Bases
// from Tags if no func or slice for []Base is specified. For other unspecified
// types the returned Coverage will return nil for the respective methods.
func NewCoverage(list ...interface{}) Coverage { s := &coverage{} for _, x := range list { switch v := x.(type) { case func() []Base: s.bases = v case func() []Script: s.scripts = v case func() []Region: s.regions = v case func() []Tag: s.tags = v case []Base: s.bases = func() []Base { return v } case []Script: s.scripts = func() []Script { return v } case []Region: s.regions = func() []Region { return v } case []Tag: s.tags = func() []Tag { return v } default: panic(fmt.Sprintf("language: unsupported set type %T", v)) } } return s }
|