summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/text/language/display/display.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/language/display/display.go')
-rw-r--r--vendor/golang.org/x/text/language/display/display.go420
1 files changed, 420 insertions, 0 deletions
diff --git a/vendor/golang.org/x/text/language/display/display.go b/vendor/golang.org/x/text/language/display/display.go
new file mode 100644
index 0000000..eafe54a
--- /dev/null
+++ b/vendor/golang.org/x/text/language/display/display.go
@@ -0,0 +1,420 @@
+// 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.
+
+//go:generate go run maketables.go -output tables.go
+
+// Package display provides display names for languages, scripts and regions in
+// a requested language.
+//
+// The data is based on CLDR's localeDisplayNames. It includes the names of the
+// draft level "contributed" or "approved". The resulting tables are quite
+// large. The display package is designed so that users can reduce the linked-in
+// table sizes by cherry picking the languages one wishes to support. There is a
+// Dictionary defined for a selected set of common languages for this purpose.
+package display // import "golang.org/x/text/language/display"
+
+import (
+ "fmt"
+ "strings"
+
+ "golang.org/x/text/internal/format"
+ "golang.org/x/text/language"
+)
+
+/*
+TODO:
+All fairly low priority at the moment:
+ - Include alternative and variants as an option (using func options).
+ - Option for returning the empty string for undefined values.
+ - Support variants, currencies, time zones, option names and other data
+ provided in CLDR.
+ - Do various optimizations:
+ - Reduce size of offset tables.
+ - 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 {
+ // Name returns a display string for the given value. A Namer returns an
+ // empty string for values it does not support. A Namer may support naming
+ // an unspecified value. For example, when getting the name for a region for
+ // a tag that does not have a defined Region, it may return the name for an
+ // unknown region. It is up to the user to filter calls to Name for values
+ // for which one does not want to have a name string.
+ Name(x interface{}) string
+}
+
+var (
+ // Supported lists the languages for which names are defined.
+ Supported language.Coverage
+
+ // The set of all possible values for which names are defined. Note that not
+ // all Namer implementations will cover all the values of a given type.
+ // A Namer will return the empty string for unsupported values.
+ Values language.Coverage
+
+ matcher language.Matcher
+)
+
+func init() {
+ tags := make([]language.Tag, numSupported)
+ s := supported
+ for i := range tags {
+ p := strings.IndexByte(s, '|')
+ tags[i] = language.Raw.Make(s[:p])
+ s = s[p+1:]
+ }
+ matcher = language.NewMatcher(tags)
+ Supported = language.NewCoverage(tags)
+
+ Values = language.NewCoverage(langTagSet.Tags, supportedScripts, supportedRegions)
+}
+
+// Languages returns a Namer for naming languages. It returns nil if there is no
+// data for the given tag. The type passed to Name must be either language.Base
+// or language.Tag. Note that the result may differ between passing a tag or its
+// base language. For example, for English, passing "nl-BE" would return Flemish
+// whereas passing "nl" returns "Dutch".
+func Languages(t language.Tag) Namer {
+ if _, index, conf := matcher.Match(t); conf != language.No {
+ return languageNamer(index)
+ }
+ return nil
+}
+
+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)
+}
+
+// Name implements the Namer interface for language names.
+func (n languageNamer) Name(x interface{}) string {
+ return nameLanguage(n, x)
+}
+
+// nonEmptyIndex walks up the parent chain until a non-empty header is found.
+// It returns -1 if no index could be found.
+func nonEmptyIndex(h []header, index int) int {
+ for ; index != -1 && h[index].data == ""; index = int(parents[index]) {
+ }
+ return index
+}
+
+// Scripts returns a Namer for naming scripts. It returns nil if there is no
+// data for the given tag. The type passed to Name must be either a
+// language.Script or a language.Tag. It will not attempt to infer a script for
+// tags with an unspecified script.
+func Scripts(t language.Tag) Namer {
+ if _, index, conf := matcher.Match(t); conf != language.No {
+ if index = nonEmptyIndex(scriptHeaders[:], index); index != -1 {
+ return scriptNamer(index)
+ }
+ }
+ return nil
+}
+
+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)
+}
+
+// Name implements the Namer interface for script names.
+func (n scriptNamer) Name(x interface{}) string {
+ return nameScript(n, x)
+}
+
+// Regions returns a Namer for naming regions. It returns nil if there is no
+// data for the given tag. The type passed to Name must be either a
+// language.Region or a language.Tag. It will not attempt to infer a region for
+// tags with an unspecified region.
+func Regions(t language.Tag) Namer {
+ if _, index, conf := matcher.Match(t); conf != language.No {
+ if index = nonEmptyIndex(regionHeaders[:], index); index != -1 {
+ return regionNamer(index)
+ }
+ }
+ return nil
+}
+
+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)
+}
+
+// Name implements the Namer interface for region names.
+func (n regionNamer) Name(x interface{}) string {
+ return nameRegion(n, x)
+}
+
+// Tags returns a Namer for giving a full description of a tag. The names of
+// scripts and regions that are not already implied by the language name will
+// in appended within parentheses. It returns nil if there is not data for the
+// given tag. The type passed to Name must be a tag.
+func Tags(t language.Tag) Namer {
+ if _, index, conf := matcher.Match(t); conf != language.No {
+ return tagNamer(index)
+ }
+ return nil
+}
+
+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)
+}
+
+// lookup finds the name for an entry in a global table, traversing the
+// inheritance hierarchy if needed.
+func lookup(table []header, dict, want int) string {
+ for dict != -1 {
+ if s := table[dict].name(want); s != "" {
+ return s
+ }
+ dict = int(parents[dict])
+ }
+ return ""
+}
+
+// A Dictionary holds a collection of Namers for a single language. One can
+// reduce the amount of data linked in to a binary by only referencing
+// Dictionaries for the languages one needs to support instead of using the
+// generic Namer factories.
+type Dictionary struct {
+ parent *Dictionary
+ lang header
+ script header
+ region header
+}
+
+// Tags returns a Namer for giving a full description of a tag. The names of
+// scripts and regions that are not already implied by the language name will
+// in appended within parentheses. It returns nil if there is not data for the
+// given tag. The type passed to Name must be a tag.
+func (d *Dictionary) Tags() Namer {
+ return dictTags{d}
+}
+
+type dictTags struct {
+ d *Dictionary
+}
+
+// Name implements the Namer interface for tag names.
+func (n dictTags) Name(x interface{}) string {
+ return nameTag(dictLanguages{n.d}, dictScripts{n.d}, dictRegions{n.d}, x)
+}
+
+// Languages returns a Namer for naming languages. It returns nil if there is no
+// data for the given tag. The type passed to Name must be either language.Base
+// or language.Tag. Note that the result may differ between passing a tag or its
+// base language. For example, for English, passing "nl-BE" would return Flemish
+// whereas passing "nl" returns "Dutch".
+func (d *Dictionary) Languages() Namer {
+ return dictLanguages{d}
+}
+
+type dictLanguages struct {
+ d *Dictionary
+}
+
+func (n dictLanguages) name(i int) string {
+ for d := n.d; d != nil; d = d.parent {
+ if s := d.lang.name(i); s != "" {
+ return s
+ }
+ }
+ return ""
+}
+
+// Name implements the Namer interface for language names.
+func (n dictLanguages) Name(x interface{}) string {
+ return nameLanguage(n, x)
+}
+
+// Scripts returns a Namer for naming scripts. It returns nil if there is no
+// data for the given tag. The type passed to Name must be either a
+// language.Script or a language.Tag. It will not attempt to infer a script for
+// tags with an unspecified script.
+func (d *Dictionary) Scripts() Namer {
+ return dictScripts{d}
+}
+
+type dictScripts struct {
+ d *Dictionary
+}
+
+func (n dictScripts) name(i int) string {
+ for d := n.d; d != nil; d = d.parent {
+ if s := d.script.name(i); s != "" {
+ return s
+ }
+ }
+ return ""
+}
+
+// Name implements the Namer interface for script names.
+func (n dictScripts) Name(x interface{}) string {
+ return nameScript(n, x)
+}
+
+// Regions returns a Namer for naming regions. It returns nil if there is no
+// data for the given tag. The type passed to Name must be either a
+// language.Region or a language.Tag. It will not attempt to infer a region for
+// tags with an unspecified region.
+func (d *Dictionary) Regions() Namer {
+ return dictRegions{d}
+}
+
+type dictRegions struct {
+ d *Dictionary
+}
+
+func (n dictRegions) name(i int) string {
+ for d := n.d; d != nil; d = d.parent {
+ if s := d.region.name(i); s != "" {
+ return s
+ }
+ }
+ return ""
+}
+
+// Name implements the Namer interface for region names.
+func (n dictRegions) Name(x interface{}) string {
+ return nameRegion(n, x)
+}
+
+// A SelfNamer implements a Namer that returns the name of language in this same
+// language. It provides a very compact mechanism to provide a comprehensive
+// list of languages to users in their native language.
+type SelfNamer struct {
+ // Supported defines the values supported by this Namer.
+ Supported language.Coverage
+}
+
+var (
+ // Self is a shared instance of a SelfNamer.
+ Self *SelfNamer = &self
+
+ self = SelfNamer{language.NewCoverage(selfTagSet.Tags)}
+)
+
+// Name returns the name of a given language tag in the language identified by
+// this tag. It supports both the language.Base and language.Tag types.
+func (n SelfNamer) Name(x interface{}) string {
+ t, _ := language.All.Compose(x)
+ base, scr, reg := t.Raw()
+ baseScript := language.Script{}
+ if (scr == language.Script{} && reg != language.Region{}) {
+ // For looking up in the self dictionary, we need to select the
+ // maximized script. This is even the case if the script isn't
+ // specified.
+ s1, _ := t.Script()
+ if baseScript = getScript(base); baseScript != s1 {
+ scr = s1
+ }
+ }
+
+ i, scr, reg := selfTagSet.index(base, scr, reg)
+ if i == -1 {
+ return ""
+ }
+
+ // Only return the display name if the script matches the expected script.
+ if (scr != language.Script{}) {
+ if (baseScript == language.Script{}) {
+ baseScript = getScript(base)
+ }
+ if baseScript != scr {
+ return ""
+ }
+ }
+
+ return selfHeaders[0].name(i)
+}
+
+// getScript returns the maximized script for a base language.
+func getScript(b language.Base) language.Script {
+ tag, _ := language.Raw.Compose(b)
+ scr, _ := tag.Script()
+ return scr
+}