This commit is contained in:
arraykeys
2019-08-08 17:13:34 +08:00
parent e8e5966a8c
commit f0bf2d5fec
2885 changed files with 1195993 additions and 12 deletions
+105
View File
@@ -0,0 +1,105 @@
// Copyright 2013 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 cldr
import (
"encoding/xml"
"regexp"
"strconv"
)
// Elem is implemented by every XML element.
type Elem interface {
setEnclosing(Elem)
setName(string)
enclosing() Elem
GetCommon() *Common
}
type hidden struct {
CharData string `xml:",chardata"`
Alias *struct {
Common
Source string `xml:"source,attr"`
Path string `xml:"path,attr"`
} `xml:"alias"`
Def *struct {
Common
Choice string `xml:"choice,attr,omitempty"`
Type string `xml:"type,attr,omitempty"`
} `xml:"default"`
}
// Common holds several of the most common attributes and sub elements
// of an XML element.
type Common struct {
XMLName xml.Name
name string
enclElem Elem
Type string `xml:"type,attr,omitempty"`
Reference string `xml:"reference,attr,omitempty"`
Alt string `xml:"alt,attr,omitempty"`
ValidSubLocales string `xml:"validSubLocales,attr,omitempty"`
Draft string `xml:"draft,attr,omitempty"`
hidden
}
// Default returns the default type to select from the enclosed list
// or "" if no default value is specified.
func (e *Common) Default() string {
if e.Def == nil {
return ""
}
if e.Def.Choice != "" {
return e.Def.Choice
} else if e.Def.Type != "" {
// Type is still used by the default element in collation.
return e.Def.Type
}
return ""
}
// Element returns the XML element name.
func (e *Common) Element() string {
return e.name
}
// GetCommon returns e. It is provided such that Common implements Elem.
func (e *Common) GetCommon() *Common {
return e
}
// Data returns the character data accumulated for this element.
func (e *Common) Data() string {
e.CharData = charRe.ReplaceAllStringFunc(e.CharData, replaceUnicode)
return e.CharData
}
func (e *Common) setName(s string) {
e.name = s
}
func (e *Common) enclosing() Elem {
return e.enclElem
}
func (e *Common) setEnclosing(en Elem) {
e.enclElem = en
}
// Escape characters that can be escaped without further escaping the string.
var charRe = regexp.MustCompile(`&#x[0-9a-fA-F]*;|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|\\x[0-9a-fA-F]{2}|\\[0-7]{3}|\\[abtnvfr]`)
// replaceUnicode converts hexadecimal Unicode codepoint notations to a one-rune string.
// It assumes the input string is correctly formatted.
func replaceUnicode(s string) string {
if s[1] == '#' {
r, _ := strconv.ParseInt(s[3:len(s)-1], 16, 32)
return string(r)
}
r, _, _, _ := strconv.UnquoteChar(s, 0)
return string(r)
}
+137
View File
@@ -0,0 +1,137 @@
// Copyright 2013 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 makexml.go -output xml.go
// Package cldr provides a parser for LDML and related XML formats.
//
// This package is intended to be used by the table generation tools for the
// various packages in x/text and is not internal for historical reasons.
//
// As the XML types are generated from the CLDR DTD, and as the CLDR standard is
// periodically amended, this package may change considerably over time. This
// mostly means that data may appear and disappear between versions. That is,
// old code should keep compiling for newer versions, but data may have moved or
// changed. CLDR version 22 is the first version supported by this package.
// Older versions may not work.
package cldr // import "golang.org/x/text/unicode/cldr"
import (
"fmt"
"sort"
)
// CLDR provides access to parsed data of the Unicode Common Locale Data Repository.
type CLDR struct {
parent map[string][]string
locale map[string]*LDML
resolved map[string]*LDML
bcp47 *LDMLBCP47
supp *SupplementalData
}
func makeCLDR() *CLDR {
return &CLDR{
parent: make(map[string][]string),
locale: make(map[string]*LDML),
resolved: make(map[string]*LDML),
bcp47: &LDMLBCP47{},
supp: &SupplementalData{},
}
}
// BCP47 returns the parsed BCP47 LDML data. If no such data was parsed, nil is returned.
func (cldr *CLDR) BCP47() *LDMLBCP47 {
return nil
}
// Draft indicates the draft level of an element.
type Draft int
const (
Approved Draft = iota
Contributed
Provisional
Unconfirmed
)
var drafts = []string{"unconfirmed", "provisional", "contributed", "approved", ""}
// ParseDraft returns the Draft value corresponding to the given string. The
// empty string corresponds to Approved.
func ParseDraft(level string) (Draft, error) {
if level == "" {
return Approved, nil
}
for i, s := range drafts {
if level == s {
return Unconfirmed - Draft(i), nil
}
}
return Approved, fmt.Errorf("cldr: unknown draft level %q", level)
}
func (d Draft) String() string {
return drafts[len(drafts)-1-int(d)]
}
// SetDraftLevel sets which draft levels to include in the evaluated LDML.
// Any draft element for which the draft level is higher than lev will be excluded.
// If multiple draft levels are available for a single element, the one with the
// lowest draft level will be selected, unless preferDraft is true, in which case
// the highest draft will be chosen.
// It is assumed that the underlying LDML is canonicalized.
func (cldr *CLDR) SetDraftLevel(lev Draft, preferDraft bool) {
// TODO: implement
cldr.resolved = make(map[string]*LDML)
}
// RawLDML returns the LDML XML for id in unresolved form.
// id must be one of the strings returned by Locales.
func (cldr *CLDR) RawLDML(loc string) *LDML {
return cldr.locale[loc]
}
// LDML returns the fully resolved LDML XML for loc, which must be one of
// the strings returned by Locales.
//
// Deprecated: Use RawLDML and implement inheritance manually or using the
// internal cldrtree package.
// Inheritance has changed quite a bit since the onset of this package and in
// practice data often represented in a way where knowledge of how it was
// inherited is relevant.
func (cldr *CLDR) LDML(loc string) (*LDML, error) {
return cldr.resolve(loc)
}
// Supplemental returns the parsed supplemental data. If no such data was parsed,
// nil is returned.
func (cldr *CLDR) Supplemental() *SupplementalData {
return cldr.supp
}
// Locales returns the locales for which there exist files.
// Valid sublocales for which there is no file are not included.
// The root locale is always sorted first.
func (cldr *CLDR) Locales() []string {
loc := []string{"root"}
hasRoot := false
for l, _ := range cldr.locale {
if l == "root" {
hasRoot = true
continue
}
loc = append(loc, l)
}
sort.Strings(loc[1:])
if !hasRoot {
return loc[1:]
}
return loc
}
// Get fills in the fields of x based on the XPath path.
func Get(e Elem, path string) (res Elem, err error) {
return walkXPath(e, path)
}
+359
View File
@@ -0,0 +1,359 @@
// Copyright 2013 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 cldr
import (
"bufio"
"encoding/xml"
"errors"
"fmt"
"strconv"
"strings"
"unicode"
"unicode/utf8"
)
// RuleProcessor can be passed to Collator's Process method, which
// parses the rules and calls the respective method for each rule found.
type RuleProcessor interface {
Reset(anchor string, before int) error
Insert(level int, str, context, extend string) error
Index(id string)
}
const (
// cldrIndex is a Unicode-reserved sentinel value used to mark the start
// of a grouping within an index.
// We ignore any rule that starts with this rune.
// See https://unicode.org/reports/tr35/#Collation_Elements for details.
cldrIndex = "\uFDD0"
// specialAnchor is the format in which to represent logical reset positions,
// such as "first tertiary ignorable".
specialAnchor = "<%s/>"
)
// Process parses the rules for the tailorings of this collation
// and calls the respective methods of p for each rule found.
func (c Collation) Process(p RuleProcessor) (err error) {
if len(c.Cr) > 0 {
if len(c.Cr) > 1 {
return fmt.Errorf("multiple cr elements, want 0 or 1")
}
return processRules(p, c.Cr[0].Data())
}
if c.Rules.Any != nil {
return c.processXML(p)
}
return errors.New("no tailoring data")
}
// processRules parses rules in the Collation Rule Syntax defined in
// https://www.unicode.org/reports/tr35/tr35-collation.html#Collation_Tailorings.
func processRules(p RuleProcessor, s string) (err error) {
chk := func(s string, e error) string {
if err == nil {
err = e
}
return s
}
i := 0 // Save the line number for use after the loop.
scanner := bufio.NewScanner(strings.NewReader(s))
for ; scanner.Scan() && err == nil; i++ {
for s := skipSpace(scanner.Text()); s != "" && s[0] != '#'; s = skipSpace(s) {
level := 5
var ch byte
switch ch, s = s[0], s[1:]; ch {
case '&': // followed by <anchor> or '[' <key> ']'
if s = skipSpace(s); consume(&s, '[') {
s = chk(parseSpecialAnchor(p, s))
} else {
s = chk(parseAnchor(p, 0, s))
}
case '<': // sort relation '<'{1,4}, optionally followed by '*'.
for level = 1; consume(&s, '<'); level++ {
}
if level > 4 {
err = fmt.Errorf("level %d > 4", level)
}
fallthrough
case '=': // identity relation, optionally followed by *.
if consume(&s, '*') {
s = chk(parseSequence(p, level, s))
} else {
s = chk(parseOrder(p, level, s))
}
default:
chk("", fmt.Errorf("illegal operator %q", ch))
break
}
}
}
if chk("", scanner.Err()); err != nil {
return fmt.Errorf("%d: %v", i, err)
}
return nil
}
// parseSpecialAnchor parses the anchor syntax which is either of the form
// ['before' <level>] <anchor>
// or
// [<label>]
// The starting should already be consumed.
func parseSpecialAnchor(p RuleProcessor, s string) (tail string, err error) {
i := strings.IndexByte(s, ']')
if i == -1 {
return "", errors.New("unmatched bracket")
}
a := strings.TrimSpace(s[:i])
s = s[i+1:]
if strings.HasPrefix(a, "before ") {
l, err := strconv.ParseUint(skipSpace(a[len("before "):]), 10, 3)
if err != nil {
return s, err
}
return parseAnchor(p, int(l), s)
}
return s, p.Reset(fmt.Sprintf(specialAnchor, a), 0)
}
func parseAnchor(p RuleProcessor, level int, s string) (tail string, err error) {
anchor, s, err := scanString(s)
if err != nil {
return s, err
}
return s, p.Reset(anchor, level)
}
func parseOrder(p RuleProcessor, level int, s string) (tail string, err error) {
var value, context, extend string
if value, s, err = scanString(s); err != nil {
return s, err
}
if strings.HasPrefix(value, cldrIndex) {
p.Index(value[len(cldrIndex):])
return
}
if consume(&s, '|') {
if context, s, err = scanString(s); err != nil {
return s, errors.New("missing string after context")
}
}
if consume(&s, '/') {
if extend, s, err = scanString(s); err != nil {
return s, errors.New("missing string after extension")
}
}
return s, p.Insert(level, value, context, extend)
}
// scanString scans a single input string.
func scanString(s string) (str, tail string, err error) {
if s = skipSpace(s); s == "" {
return s, s, errors.New("missing string")
}
buf := [16]byte{} // small but enough to hold most cases.
value := buf[:0]
for s != "" {
if consume(&s, '\'') {
i := strings.IndexByte(s, '\'')
if i == -1 {
return "", "", errors.New(`unmatched single quote`)
}
if i == 0 {
value = append(value, '\'')
} else {
value = append(value, s[:i]...)
}
s = s[i+1:]
continue
}
r, sz := utf8.DecodeRuneInString(s)
if unicode.IsSpace(r) || strings.ContainsRune("&<=#", r) {
break
}
value = append(value, s[:sz]...)
s = s[sz:]
}
return string(value), skipSpace(s), nil
}
func parseSequence(p RuleProcessor, level int, s string) (tail string, err error) {
if s = skipSpace(s); s == "" {
return s, errors.New("empty sequence")
}
last := rune(0)
for s != "" {
r, sz := utf8.DecodeRuneInString(s)
s = s[sz:]
if r == '-' {
// We have a range. The first element was already written.
if last == 0 {
return s, errors.New("range without starter value")
}
r, sz = utf8.DecodeRuneInString(s)
s = s[sz:]
if r == utf8.RuneError || r < last {
return s, fmt.Errorf("invalid range %q-%q", last, r)
}
for i := last + 1; i <= r; i++ {
if err := p.Insert(level, string(i), "", ""); err != nil {
return s, err
}
}
last = 0
continue
}
if unicode.IsSpace(r) || unicode.IsPunct(r) {
break
}
// normal case
if err := p.Insert(level, string(r), "", ""); err != nil {
return s, err
}
last = r
}
return s, nil
}
func skipSpace(s string) string {
return strings.TrimLeftFunc(s, unicode.IsSpace)
}
// consumes returns whether the next byte is ch. If so, it gobbles it by
// updating s.
func consume(s *string, ch byte) (ok bool) {
if *s == "" || (*s)[0] != ch {
return false
}
*s = (*s)[1:]
return true
}
// The following code parses Collation rules of CLDR version 24 and before.
var lmap = map[byte]int{
'p': 1,
's': 2,
't': 3,
'i': 5,
}
type rulesElem struct {
Rules struct {
Common
Any []*struct {
XMLName xml.Name
rule
} `xml:",any"`
} `xml:"rules"`
}
type rule struct {
Value string `xml:",chardata"`
Before string `xml:"before,attr"`
Any []*struct {
XMLName xml.Name
rule
} `xml:",any"`
}
var emptyValueError = errors.New("cldr: empty rule value")
func (r *rule) value() (string, error) {
// Convert hexadecimal Unicode codepoint notation to a string.
s := charRe.ReplaceAllStringFunc(r.Value, replaceUnicode)
r.Value = s
if s == "" {
if len(r.Any) != 1 {
return "", emptyValueError
}
r.Value = fmt.Sprintf(specialAnchor, r.Any[0].XMLName.Local)
r.Any = nil
} else if len(r.Any) != 0 {
return "", fmt.Errorf("cldr: XML elements found in collation rule: %v", r.Any)
}
return r.Value, nil
}
func (r rule) process(p RuleProcessor, name, context, extend string) error {
v, err := r.value()
if err != nil {
return err
}
switch name {
case "p", "s", "t", "i":
if strings.HasPrefix(v, cldrIndex) {
p.Index(v[len(cldrIndex):])
return nil
}
if err := p.Insert(lmap[name[0]], v, context, extend); err != nil {
return err
}
case "pc", "sc", "tc", "ic":
level := lmap[name[0]]
for _, s := range v {
if err := p.Insert(level, string(s), context, extend); err != nil {
return err
}
}
default:
return fmt.Errorf("cldr: unsupported tag: %q", name)
}
return nil
}
// processXML parses the format of CLDR versions 24 and older.
func (c Collation) processXML(p RuleProcessor) (err error) {
// Collation is generated and defined in xml.go.
var v string
for _, r := range c.Rules.Any {
switch r.XMLName.Local {
case "reset":
level := 0
switch r.Before {
case "primary", "1":
level = 1
case "secondary", "2":
level = 2
case "tertiary", "3":
level = 3
case "":
default:
return fmt.Errorf("cldr: unknown level %q", r.Before)
}
v, err = r.value()
if err == nil {
err = p.Reset(v, level)
}
case "x":
var context, extend string
for _, r1 := range r.Any {
v, err = r1.value()
switch r1.XMLName.Local {
case "context":
context = v
case "extend":
extend = v
}
}
for _, r1 := range r.Any {
if t := r1.XMLName.Local; t == "context" || t == "extend" {
continue
}
r1.rule.process(p, r1.XMLName.Local, context, extend)
}
default:
err = r.rule.process(p, r.XMLName.Local, "", "")
}
if err != nil {
return err
}
}
return nil
}
+172
View File
@@ -0,0 +1,172 @@
// Copyright 2013 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 cldr
import (
"archive/zip"
"bytes"
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"regexp"
)
// A Decoder loads an archive of CLDR data.
type Decoder struct {
dirFilter []string
sectionFilter []string
loader Loader
cldr *CLDR
curLocale string
}
// SetSectionFilter takes a list top-level LDML element names to which
// evaluation of LDML should be limited. It automatically calls SetDirFilter.
func (d *Decoder) SetSectionFilter(filter ...string) {
d.sectionFilter = filter
// TODO: automatically set dir filter
}
// SetDirFilter limits the loading of LDML XML files of the specied directories.
// Note that sections may be split across directories differently for different CLDR versions.
// For more robust code, use SetSectionFilter.
func (d *Decoder) SetDirFilter(dir ...string) {
d.dirFilter = dir
}
// A Loader provides access to the files of a CLDR archive.
type Loader interface {
Len() int
Path(i int) string
Reader(i int) (io.ReadCloser, error)
}
var fileRe = regexp.MustCompile(`.*[/\\](.*)[/\\](.*)\.xml`)
// Decode loads and decodes the files represented by l.
func (d *Decoder) Decode(l Loader) (cldr *CLDR, err error) {
d.cldr = makeCLDR()
for i := 0; i < l.Len(); i++ {
fname := l.Path(i)
if m := fileRe.FindStringSubmatch(fname); m != nil {
if len(d.dirFilter) > 0 && !in(d.dirFilter, m[1]) {
continue
}
var r io.ReadCloser
if r, err = l.Reader(i); err == nil {
err = d.decode(m[1], m[2], r)
r.Close()
}
if err != nil {
return nil, err
}
}
}
d.cldr.finalize(d.sectionFilter)
return d.cldr, nil
}
func (d *Decoder) decode(dir, id string, r io.Reader) error {
var v interface{}
var l *LDML
cldr := d.cldr
switch {
case dir == "supplemental":
v = cldr.supp
case dir == "transforms":
return nil
case dir == "bcp47":
v = cldr.bcp47
case dir == "validity":
return nil
default:
ok := false
if v, ok = cldr.locale[id]; !ok {
l = &LDML{}
v, cldr.locale[id] = l, l
}
}
x := xml.NewDecoder(r)
if err := x.Decode(v); err != nil {
log.Printf("%s/%s: %v", dir, id, err)
return err
}
if l != nil {
if l.Identity == nil {
return fmt.Errorf("%s/%s: missing identity element", dir, id)
}
// TODO: verify when CLDR bug https://unicode.org/cldr/trac/ticket/8970
// is resolved.
// path := strings.Split(id, "_")
// if lang := l.Identity.Language.Type; lang != path[0] {
// return fmt.Errorf("%s/%s: language was %s; want %s", dir, id, lang, path[0])
// }
}
return nil
}
type pathLoader []string
func makePathLoader(path string) (pl pathLoader, err error) {
err = filepath.Walk(path, func(path string, _ os.FileInfo, err error) error {
pl = append(pl, path)
return err
})
return pl, err
}
func (pl pathLoader) Len() int {
return len(pl)
}
func (pl pathLoader) Path(i int) string {
return pl[i]
}
func (pl pathLoader) Reader(i int) (io.ReadCloser, error) {
return os.Open(pl[i])
}
// DecodePath loads CLDR data from the given path.
func (d *Decoder) DecodePath(path string) (cldr *CLDR, err error) {
loader, err := makePathLoader(path)
if err != nil {
return nil, err
}
return d.Decode(loader)
}
type zipLoader struct {
r *zip.Reader
}
func (zl zipLoader) Len() int {
return len(zl.r.File)
}
func (zl zipLoader) Path(i int) string {
return zl.r.File[i].Name
}
func (zl zipLoader) Reader(i int) (io.ReadCloser, error) {
return zl.r.File[i].Open()
}
// DecodeZip loads CLDR data from the zip archive for which r is the source.
func (d *Decoder) DecodeZip(r io.Reader) (cldr *CLDR, err error) {
buffer, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
archive, err := zip.NewReader(bytes.NewReader(buffer), int64(len(buffer)))
if err != nil {
return nil, err
}
return d.Decode(zipLoader{archive})
}
+400
View File
@@ -0,0 +1,400 @@
// Copyright 2013 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.
// +build ignore
// This tool generates types for the various XML formats of CLDR.
package main
import (
"archive/zip"
"bytes"
"encoding/xml"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"regexp"
"strings"
"golang.org/x/text/internal/gen"
)
var outputFile = flag.String("output", "xml.go", "output file name")
func main() {
flag.Parse()
r := gen.OpenCLDRCoreZip()
buffer, err := ioutil.ReadAll(r)
if err != nil {
log.Fatal("Could not read zip file")
}
r.Close()
z, err := zip.NewReader(bytes.NewReader(buffer), int64(len(buffer)))
if err != nil {
log.Fatalf("Could not read zip archive: %v", err)
}
var buf bytes.Buffer
version := gen.CLDRVersion()
for _, dtd := range files {
for _, f := range z.File {
if strings.HasSuffix(f.Name, dtd.file+".dtd") {
r, err := f.Open()
failOnError(err)
b := makeBuilder(&buf, dtd)
b.parseDTD(r)
b.resolve(b.index[dtd.top[0]])
b.write()
if b.version != "" && version != b.version {
println(f.Name)
log.Fatalf("main: inconsistent versions: found %s; want %s", b.version, version)
}
break
}
}
}
fmt.Fprintln(&buf, "// Version is the version of CLDR from which the XML definitions are generated.")
fmt.Fprintf(&buf, "const Version = %q\n", version)
gen.WriteGoFile(*outputFile, "cldr", buf.Bytes())
}
func failOnError(err error) {
if err != nil {
log.New(os.Stderr, "", log.Lshortfile).Output(2, err.Error())
os.Exit(1)
}
}
// configuration data per DTD type
type dtd struct {
file string // base file name
root string // Go name of the root XML element
top []string // create a different type for this section
skipElem []string // hard-coded or deprecated elements
skipAttr []string // attributes to exclude
predefined []string // hard-coded elements exist of the form <name>Elem
forceRepeat []string // elements to make slices despite DTD
}
var files = []dtd{
{
file: "ldmlBCP47",
root: "LDMLBCP47",
top: []string{"ldmlBCP47"},
skipElem: []string{
"cldrVersion", // deprecated, not used
},
},
{
file: "ldmlSupplemental",
root: "SupplementalData",
top: []string{"supplementalData"},
skipElem: []string{
"cldrVersion", // deprecated, not used
},
forceRepeat: []string{
"plurals", // data defined in plurals.xml and ordinals.xml
},
},
{
file: "ldml",
root: "LDML",
top: []string{
"ldml", "collation", "calendar", "timeZoneNames", "localeDisplayNames", "numbers",
},
skipElem: []string{
"cp", // not used anywhere
"special", // not used anywhere
"fallback", // deprecated, not used
"alias", // in Common
"default", // in Common
},
skipAttr: []string{
"hiraganaQuarternary", // typo in DTD, correct version included as well
},
predefined: []string{"rules"},
},
}
var comments = map[string]string{
"ldmlBCP47": `
// LDMLBCP47 holds information on allowable values for various variables in LDML.
`,
"supplementalData": `
// SupplementalData holds information relevant for internationalization
// and proper use of CLDR, but that is not contained in the locale hierarchy.
`,
"ldml": `
// LDML is the top-level type for locale-specific data.
`,
"collation": `
// Collation contains rules that specify a certain sort-order,
// as a tailoring of the root order.
// The parsed rules are obtained by passing a RuleProcessor to Collation's
// Process method.
`,
"calendar": `
// Calendar specifies the fields used for formatting and parsing dates and times.
// The month and quarter names are identified numerically, starting at 1.
// The day (of the week) names are identified with short strings, since there is
// no universally-accepted numeric designation.
`,
"dates": `
// Dates contains information regarding the format and parsing of dates and times.
`,
"localeDisplayNames": `
// LocaleDisplayNames specifies localized display names for scripts, languages,
// countries, currencies, and variants.
`,
"numbers": `
// Numbers supplies information for formatting and parsing numbers and currencies.
`,
}
type element struct {
name string // XML element name
category string // elements contained by this element
signature string // category + attrKey*
attr []*attribute // attributes supported by this element.
sub []struct { // parsed and evaluated sub elements of this element.
e *element
repeat bool // true if the element needs to be a slice
}
resolved bool // prevent multiple resolutions of this element.
}
type attribute struct {
name string
key string
list []string
tag string // Go tag
}
var (
reHead = regexp.MustCompile(` *(\w+) +([\w\-]+)`)
reAttr = regexp.MustCompile(` *(\w+) *(?:(\w+)|\(([\w\- \|]+)\)) *(?:#([A-Z]*) *(?:\"([\.\d+])\")?)? *("[\w\-:]*")?`)
reElem = regexp.MustCompile(`^ *(EMPTY|ANY|\(.*\)[\*\+\?]?) *$`)
reToken = regexp.MustCompile(`\w\-`)
)
// builder is used to read in the DTD files from CLDR and generate Go code
// to be used with the encoding/xml package.
type builder struct {
w io.Writer
index map[string]*element
elem []*element
info dtd
version string
}
func makeBuilder(w io.Writer, d dtd) builder {
return builder{
w: w,
index: make(map[string]*element),
elem: []*element{},
info: d,
}
}
// parseDTD parses a DTD file.
func (b *builder) parseDTD(r io.Reader) {
for d := xml.NewDecoder(r); ; {
t, err := d.Token()
if t == nil {
break
}
failOnError(err)
dir, ok := t.(xml.Directive)
if !ok {
continue
}
m := reHead.FindSubmatch(dir)
dir = dir[len(m[0]):]
ename := string(m[2])
el, elementFound := b.index[ename]
switch string(m[1]) {
case "ELEMENT":
if elementFound {
log.Fatal("parseDTD: duplicate entry for element %q", ename)
}
m := reElem.FindSubmatch(dir)
if m == nil {
log.Fatalf("parseDTD: invalid element %q", string(dir))
}
if len(m[0]) != len(dir) {
log.Fatal("parseDTD: invalid element %q", string(dir), len(dir), len(m[0]), string(m[0]))
}
s := string(m[1])
el = &element{
name: ename,
category: s,
}
b.index[ename] = el
case "ATTLIST":
if !elementFound {
log.Fatalf("parseDTD: unknown element %q", ename)
}
s := string(dir)
m := reAttr.FindStringSubmatch(s)
if m == nil {
log.Fatal(fmt.Errorf("parseDTD: invalid attribute %q", string(dir)))
}
if m[4] == "FIXED" {
b.version = m[5]
} else {
switch m[1] {
case "draft", "references", "alt", "validSubLocales", "standard" /* in Common */ :
case "type", "choice":
default:
el.attr = append(el.attr, &attribute{
name: m[1],
key: s,
list: reToken.FindAllString(m[3], -1),
})
el.signature = fmt.Sprintf("%s=%s+%s", el.signature, m[1], m[2])
}
}
}
}
}
var reCat = regexp.MustCompile(`[ ,\|]*(?:(\(|\)|\#?[\w_-]+)([\*\+\?]?))?`)
// resolve takes a parsed element and converts it into structured data
// that can be used to generate the XML code.
func (b *builder) resolve(e *element) {
if e.resolved {
return
}
b.elem = append(b.elem, e)
e.resolved = true
s := e.category
found := make(map[string]bool)
sequenceStart := []int{}
for len(s) > 0 {
m := reCat.FindStringSubmatch(s)
if m == nil {
log.Fatalf("%s: invalid category string %q", e.name, s)
}
repeat := m[2] == "*" || m[2] == "+" || in(b.info.forceRepeat, m[1])
switch m[1] {
case "":
case "(":
sequenceStart = append(sequenceStart, len(e.sub))
case ")":
if len(sequenceStart) == 0 {
log.Fatalf("%s: unmatched closing parenthesis", e.name)
}
for i := sequenceStart[len(sequenceStart)-1]; i < len(e.sub); i++ {
e.sub[i].repeat = e.sub[i].repeat || repeat
}
sequenceStart = sequenceStart[:len(sequenceStart)-1]
default:
if in(b.info.skipElem, m[1]) {
} else if sub, ok := b.index[m[1]]; ok {
if !found[sub.name] {
e.sub = append(e.sub, struct {
e *element
repeat bool
}{sub, repeat})
found[sub.name] = true
b.resolve(sub)
}
} else if m[1] == "#PCDATA" || m[1] == "ANY" {
} else if m[1] != "EMPTY" {
log.Fatalf("resolve:%s: element %q not found", e.name, m[1])
}
}
s = s[len(m[0]):]
}
}
// return true if s is contained in set.
func in(set []string, s string) bool {
for _, v := range set {
if v == s {
return true
}
}
return false
}
var repl = strings.NewReplacer("-", " ", "_", " ")
// title puts the first character or each character following '_' in title case and
// removes all occurrences of '_'.
func title(s string) string {
return strings.Replace(strings.Title(repl.Replace(s)), " ", "", -1)
}
// writeElem generates Go code for a single element, recursively.
func (b *builder) writeElem(tab int, e *element) {
p := func(f string, x ...interface{}) {
f = strings.Replace(f, "\n", "\n"+strings.Repeat("\t", tab), -1)
fmt.Fprintf(b.w, f, x...)
}
if len(e.sub) == 0 && len(e.attr) == 0 {
p("Common")
return
}
p("struct {")
tab++
p("\nCommon")
for _, attr := range e.attr {
if !in(b.info.skipAttr, attr.name) {
p("\n%s string `xml:\"%s,attr\"`", title(attr.name), attr.name)
}
}
for _, sub := range e.sub {
if in(b.info.predefined, sub.e.name) {
p("\n%sElem", sub.e.name)
continue
}
if in(b.info.skipElem, sub.e.name) {
continue
}
p("\n%s ", title(sub.e.name))
if sub.repeat {
p("[]")
}
p("*")
if in(b.info.top, sub.e.name) {
p(title(sub.e.name))
} else {
b.writeElem(tab, sub.e)
}
p(" `xml:\"%s\"`", sub.e.name)
}
tab--
p("\n}")
}
// write generates the Go XML code.
func (b *builder) write() {
for i, name := range b.info.top {
e := b.index[name]
if e != nil {
fmt.Fprintf(b.w, comments[name])
name := title(e.name)
if i == 0 {
name = b.info.root
}
fmt.Fprintf(b.w, "type %s ", name)
b.writeElem(0, e)
fmt.Fprint(b.w, "\n")
}
}
}
+602
View File
@@ -0,0 +1,602 @@
// Copyright 2013 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 cldr
// This file implements the various inheritance constructs defined by LDML.
// See https://www.unicode.org/reports/tr35/#Inheritance_and_Validity
// for more details.
import (
"fmt"
"log"
"reflect"
"regexp"
"sort"
"strings"
)
// fieldIter iterates over fields in a struct. It includes
// fields of embedded structs.
type fieldIter struct {
v reflect.Value
index, n []int
}
func iter(v reflect.Value) fieldIter {
if v.Kind() != reflect.Struct {
log.Panicf("value %v must be a struct", v)
}
i := fieldIter{
v: v,
index: []int{0},
n: []int{v.NumField()},
}
i.descent()
return i
}
func (i *fieldIter) descent() {
for f := i.field(); f.Anonymous && f.Type.NumField() > 0; f = i.field() {
i.index = append(i.index, 0)
i.n = append(i.n, f.Type.NumField())
}
}
func (i *fieldIter) done() bool {
return len(i.index) == 1 && i.index[0] >= i.n[0]
}
func skip(f reflect.StructField) bool {
return !f.Anonymous && (f.Name[0] < 'A' || f.Name[0] > 'Z')
}
func (i *fieldIter) next() {
for {
k := len(i.index) - 1
i.index[k]++
if i.index[k] < i.n[k] {
if !skip(i.field()) {
break
}
} else {
if k == 0 {
return
}
i.index = i.index[:k]
i.n = i.n[:k]
}
}
i.descent()
}
func (i *fieldIter) value() reflect.Value {
return i.v.FieldByIndex(i.index)
}
func (i *fieldIter) field() reflect.StructField {
return i.v.Type().FieldByIndex(i.index)
}
type visitor func(v reflect.Value) error
var stopDescent = fmt.Errorf("do not recurse")
func (f visitor) visit(x interface{}) error {
return f.visitRec(reflect.ValueOf(x))
}
// visit recursively calls f on all nodes in v.
func (f visitor) visitRec(v reflect.Value) error {
if v.Kind() == reflect.Ptr {
if v.IsNil() {
return nil
}
return f.visitRec(v.Elem())
}
if err := f(v); err != nil {
if err == stopDescent {
return nil
}
return err
}
switch v.Kind() {
case reflect.Struct:
for i := iter(v); !i.done(); i.next() {
if err := f.visitRec(i.value()); err != nil {
return err
}
}
case reflect.Slice:
for i := 0; i < v.Len(); i++ {
if err := f.visitRec(v.Index(i)); err != nil {
return err
}
}
}
return nil
}
// getPath is used for error reporting purposes only.
func getPath(e Elem) string {
if e == nil {
return "<nil>"
}
if e.enclosing() == nil {
return e.GetCommon().name
}
if e.GetCommon().Type == "" {
return fmt.Sprintf("%s.%s", getPath(e.enclosing()), e.GetCommon().name)
}
return fmt.Sprintf("%s.%s[type=%s]", getPath(e.enclosing()), e.GetCommon().name, e.GetCommon().Type)
}
// xmlName returns the xml name of the element or attribute
func xmlName(f reflect.StructField) (name string, attr bool) {
tags := strings.Split(f.Tag.Get("xml"), ",")
for _, s := range tags {
attr = attr || s == "attr"
}
return tags[0], attr
}
func findField(v reflect.Value, key string) (reflect.Value, error) {
v = reflect.Indirect(v)
for i := iter(v); !i.done(); i.next() {
if n, _ := xmlName(i.field()); n == key {
return i.value(), nil
}
}
return reflect.Value{}, fmt.Errorf("cldr: no field %q in element %#v", key, v.Interface())
}
var xpathPart = regexp.MustCompile(`(\pL+)(?:\[@(\pL+)='([\w-]+)'\])?`)
func walkXPath(e Elem, path string) (res Elem, err error) {
for _, c := range strings.Split(path, "/") {
if c == ".." {
if e = e.enclosing(); e == nil {
panic("path ..")
return nil, fmt.Errorf(`cldr: ".." moves past root in path %q`, path)
}
continue
} else if c == "" {
continue
}
m := xpathPart.FindStringSubmatch(c)
if len(m) == 0 || len(m[0]) != len(c) {
return nil, fmt.Errorf("cldr: syntax error in path component %q", c)
}
v, err := findField(reflect.ValueOf(e), m[1])
if err != nil {
return nil, err
}
switch v.Kind() {
case reflect.Slice:
i := 0
if m[2] != "" || v.Len() > 1 {
if m[2] == "" {
m[2] = "type"
if m[3] = e.GetCommon().Default(); m[3] == "" {
return nil, fmt.Errorf("cldr: type selector or default value needed for element %s", m[1])
}
}
for ; i < v.Len(); i++ {
vi := v.Index(i)
key, err := findField(vi.Elem(), m[2])
if err != nil {
return nil, err
}
key = reflect.Indirect(key)
if key.Kind() == reflect.String && key.String() == m[3] {
break
}
}
}
if i == v.Len() || v.Index(i).IsNil() {
return nil, fmt.Errorf("no %s found with %s==%s", m[1], m[2], m[3])
}
e = v.Index(i).Interface().(Elem)
case reflect.Ptr:
if v.IsNil() {
return nil, fmt.Errorf("cldr: element %q not found within element %q", m[1], e.GetCommon().name)
}
var ok bool
if e, ok = v.Interface().(Elem); !ok {
return nil, fmt.Errorf("cldr: %q is not an XML element", m[1])
} else if m[2] != "" || m[3] != "" {
return nil, fmt.Errorf("cldr: no type selector allowed for element %s", m[1])
}
default:
return nil, fmt.Errorf("cldr: %q is not an XML element", m[1])
}
}
return e, nil
}
const absPrefix = "//ldml/"
func (cldr *CLDR) resolveAlias(e Elem, src, path string) (res Elem, err error) {
if src != "locale" {
if !strings.HasPrefix(path, absPrefix) {
return nil, fmt.Errorf("cldr: expected absolute path, found %q", path)
}
path = path[len(absPrefix):]
if e, err = cldr.resolve(src); err != nil {
return nil, err
}
}
return walkXPath(e, path)
}
func (cldr *CLDR) resolveAndMergeAlias(e Elem) error {
alias := e.GetCommon().Alias
if alias == nil {
return nil
}
a, err := cldr.resolveAlias(e, alias.Source, alias.Path)
if err != nil {
return fmt.Errorf("%v: error evaluating path %q: %v", getPath(e), alias.Path, err)
}
// Ensure alias node was already evaluated. TODO: avoid double evaluation.
err = cldr.resolveAndMergeAlias(a)
v := reflect.ValueOf(e).Elem()
for i := iter(reflect.ValueOf(a).Elem()); !i.done(); i.next() {
if vv := i.value(); vv.Kind() != reflect.Ptr || !vv.IsNil() {
if _, attr := xmlName(i.field()); !attr {
v.FieldByIndex(i.index).Set(vv)
}
}
}
return err
}
func (cldr *CLDR) aliasResolver() visitor {
return func(v reflect.Value) (err error) {
if e, ok := v.Addr().Interface().(Elem); ok {
err = cldr.resolveAndMergeAlias(e)
if err == nil && blocking[e.GetCommon().name] {
return stopDescent
}
}
return err
}
}
// elements within blocking elements do not inherit.
// Taken from CLDR's supplementalMetaData.xml.
var blocking = map[string]bool{
"identity": true,
"supplementalData": true,
"cldrTest": true,
"collation": true,
"transform": true,
}
// Distinguishing attributes affect inheritance; two elements with different
// distinguishing attributes are treated as different for purposes of inheritance,
// except when such attributes occur in the indicated elements.
// Taken from CLDR's supplementalMetaData.xml.
var distinguishing = map[string][]string{
"key": nil,
"request_id": nil,
"id": nil,
"registry": nil,
"alt": nil,
"iso4217": nil,
"iso3166": nil,
"mzone": nil,
"from": nil,
"to": nil,
"type": []string{
"abbreviationFallback",
"default",
"mapping",
"measurementSystem",
"preferenceOrdering",
},
"numberSystem": nil,
}
func in(set []string, s string) bool {
for _, v := range set {
if v == s {
return true
}
}
return false
}
// attrKey computes a key based on the distinguishable attributes of
// an element and its values.
func attrKey(v reflect.Value, exclude ...string) string {
parts := []string{}
ename := v.Interface().(Elem).GetCommon().name
v = v.Elem()
for i := iter(v); !i.done(); i.next() {
if name, attr := xmlName(i.field()); attr {
if except, ok := distinguishing[name]; ok && !in(exclude, name) && !in(except, ename) {
v := i.value()
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.IsValid() {
parts = append(parts, fmt.Sprintf("%s=%s", name, v.String()))
}
}
}
}
sort.Strings(parts)
return strings.Join(parts, ";")
}
// Key returns a key for e derived from all distinguishing attributes
// except those specified by exclude.
func Key(e Elem, exclude ...string) string {
return attrKey(reflect.ValueOf(e), exclude...)
}
// linkEnclosing sets the enclosing element as well as the name
// for all sub-elements of child, recursively.
func linkEnclosing(parent, child Elem) {
child.setEnclosing(parent)
v := reflect.ValueOf(child).Elem()
for i := iter(v); !i.done(); i.next() {
vf := i.value()
if vf.Kind() == reflect.Slice {
for j := 0; j < vf.Len(); j++ {
linkEnclosing(child, vf.Index(j).Interface().(Elem))
}
} else if vf.Kind() == reflect.Ptr && !vf.IsNil() && vf.Elem().Kind() == reflect.Struct {
linkEnclosing(child, vf.Interface().(Elem))
}
}
}
func setNames(e Elem, name string) {
e.setName(name)
v := reflect.ValueOf(e).Elem()
for i := iter(v); !i.done(); i.next() {
vf := i.value()
name, _ = xmlName(i.field())
if vf.Kind() == reflect.Slice {
for j := 0; j < vf.Len(); j++ {
setNames(vf.Index(j).Interface().(Elem), name)
}
} else if vf.Kind() == reflect.Ptr && !vf.IsNil() && vf.Elem().Kind() == reflect.Struct {
setNames(vf.Interface().(Elem), name)
}
}
}
// deepCopy copies elements of v recursively. All elements of v that may
// be modified by inheritance are explicitly copied.
func deepCopy(v reflect.Value) reflect.Value {
switch v.Kind() {
case reflect.Ptr:
if v.IsNil() || v.Elem().Kind() != reflect.Struct {
return v
}
nv := reflect.New(v.Elem().Type())
nv.Elem().Set(v.Elem())
deepCopyRec(nv.Elem(), v.Elem())
return nv
case reflect.Slice:
nv := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
for i := 0; i < v.Len(); i++ {
deepCopyRec(nv.Index(i), v.Index(i))
}
return nv
}
panic("deepCopy: must be called with pointer or slice")
}
// deepCopyRec is only called by deepCopy.
func deepCopyRec(nv, v reflect.Value) {
if v.Kind() == reflect.Struct {
t := v.Type()
for i := 0; i < v.NumField(); i++ {
if name, attr := xmlName(t.Field(i)); name != "" && !attr {
deepCopyRec(nv.Field(i), v.Field(i))
}
}
} else {
nv.Set(deepCopy(v))
}
}
// newNode is used to insert a missing node during inheritance.
func (cldr *CLDR) newNode(v, enc reflect.Value) reflect.Value {
n := reflect.New(v.Type())
for i := iter(v); !i.done(); i.next() {
if name, attr := xmlName(i.field()); name == "" || attr {
n.Elem().FieldByIndex(i.index).Set(i.value())
}
}
n.Interface().(Elem).GetCommon().setEnclosing(enc.Addr().Interface().(Elem))
return n
}
// v, parent must be pointers to struct
func (cldr *CLDR) inheritFields(v, parent reflect.Value) (res reflect.Value, err error) {
t := v.Type()
nv := reflect.New(t)
nv.Elem().Set(v)
for i := iter(v); !i.done(); i.next() {
vf := i.value()
f := i.field()
name, attr := xmlName(f)
if name == "" || attr {
continue
}
pf := parent.FieldByIndex(i.index)
if blocking[name] {
if vf.IsNil() {
vf = pf
}
nv.Elem().FieldByIndex(i.index).Set(deepCopy(vf))
continue
}
switch f.Type.Kind() {
case reflect.Ptr:
if f.Type.Elem().Kind() == reflect.Struct {
if !vf.IsNil() {
if vf, err = cldr.inheritStructPtr(vf, pf); err != nil {
return reflect.Value{}, err
}
vf.Interface().(Elem).setEnclosing(nv.Interface().(Elem))
nv.Elem().FieldByIndex(i.index).Set(vf)
} else if !pf.IsNil() {
n := cldr.newNode(pf.Elem(), v)
if vf, err = cldr.inheritStructPtr(n, pf); err != nil {
return reflect.Value{}, err
}
vf.Interface().(Elem).setEnclosing(nv.Interface().(Elem))
nv.Elem().FieldByIndex(i.index).Set(vf)
}
}
case reflect.Slice:
vf, err := cldr.inheritSlice(nv.Elem(), vf, pf)
if err != nil {
return reflect.Zero(t), err
}
nv.Elem().FieldByIndex(i.index).Set(vf)
}
}
return nv, nil
}
func root(e Elem) *LDML {
for ; e.enclosing() != nil; e = e.enclosing() {
}
return e.(*LDML)
}
// inheritStructPtr first merges possible aliases in with v and then inherits
// any underspecified elements from parent.
func (cldr *CLDR) inheritStructPtr(v, parent reflect.Value) (r reflect.Value, err error) {
if !v.IsNil() {
e := v.Interface().(Elem).GetCommon()
alias := e.Alias
if alias == nil && !parent.IsNil() {
alias = parent.Interface().(Elem).GetCommon().Alias
}
if alias != nil {
a, err := cldr.resolveAlias(v.Interface().(Elem), alias.Source, alias.Path)
if a != nil {
if v, err = cldr.inheritFields(v.Elem(), reflect.ValueOf(a).Elem()); err != nil {
return reflect.Value{}, err
}
}
}
if !parent.IsNil() {
return cldr.inheritFields(v.Elem(), parent.Elem())
}
} else if parent.IsNil() {
panic("should not reach here")
}
return v, nil
}
// Must be slice of struct pointers.
func (cldr *CLDR) inheritSlice(enc, v, parent reflect.Value) (res reflect.Value, err error) {
t := v.Type()
index := make(map[string]reflect.Value)
if !v.IsNil() {
for i := 0; i < v.Len(); i++ {
vi := v.Index(i)
key := attrKey(vi)
index[key] = vi
}
}
if !parent.IsNil() {
for i := 0; i < parent.Len(); i++ {
vi := parent.Index(i)
key := attrKey(vi)
if w, ok := index[key]; ok {
index[key], err = cldr.inheritStructPtr(w, vi)
} else {
n := cldr.newNode(vi.Elem(), enc)
index[key], err = cldr.inheritStructPtr(n, vi)
}
index[key].Interface().(Elem).setEnclosing(enc.Addr().Interface().(Elem))
if err != nil {
return v, err
}
}
}
keys := make([]string, 0, len(index))
for k, _ := range index {
keys = append(keys, k)
}
sort.Strings(keys)
sl := reflect.MakeSlice(t, len(index), len(index))
for i, k := range keys {
sl.Index(i).Set(index[k])
}
return sl, nil
}
func parentLocale(loc string) string {
parts := strings.Split(loc, "_")
if len(parts) == 1 {
return "root"
}
parts = parts[:len(parts)-1]
key := strings.Join(parts, "_")
return key
}
func (cldr *CLDR) resolve(loc string) (res *LDML, err error) {
if r := cldr.resolved[loc]; r != nil {
return r, nil
}
x := cldr.RawLDML(loc)
if x == nil {
return nil, fmt.Errorf("cldr: unknown locale %q", loc)
}
var v reflect.Value
if loc == "root" {
x = deepCopy(reflect.ValueOf(x)).Interface().(*LDML)
linkEnclosing(nil, x)
err = cldr.aliasResolver().visit(x)
} else {
key := parentLocale(loc)
var parent *LDML
for ; cldr.locale[key] == nil; key = parentLocale(key) {
}
if parent, err = cldr.resolve(key); err != nil {
return nil, err
}
v, err = cldr.inheritFields(reflect.ValueOf(x).Elem(), reflect.ValueOf(parent).Elem())
x = v.Interface().(*LDML)
linkEnclosing(nil, x)
}
if err != nil {
return nil, err
}
cldr.resolved[loc] = x
return x, err
}
// finalize finalizes the initialization of the raw LDML structs. It also
// removed unwanted fields, as specified by filter, so that they will not
// be unnecessarily evaluated.
func (cldr *CLDR) finalize(filter []string) {
for _, x := range cldr.locale {
if filter != nil {
v := reflect.ValueOf(x).Elem()
t := v.Type()
for i := 0; i < v.NumField(); i++ {
f := t.Field(i)
name, _ := xmlName(f)
if name != "" && name != "identity" && !in(filter, name) {
v.Field(i).Set(reflect.Zero(f.Type))
}
}
}
linkEnclosing(nil, x) // for resolving aliases and paths
setNames(x, "ldml")
}
}
+144
View File
@@ -0,0 +1,144 @@
// Copyright 2013 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 cldr
import (
"fmt"
"reflect"
"sort"
)
// Slice provides utilities for modifying slices of elements.
// It can be wrapped around any slice of which the element type implements
// interface Elem.
type Slice struct {
ptr reflect.Value
typ reflect.Type
}
// Value returns the reflect.Value of the underlying slice.
func (s *Slice) Value() reflect.Value {
return s.ptr.Elem()
}
// MakeSlice wraps a pointer to a slice of Elems.
// It replaces the array pointed to by the slice so that subsequent modifications
// do not alter the data in a CLDR type.
// It panics if an incorrect type is passed.
func MakeSlice(slicePtr interface{}) Slice {
ptr := reflect.ValueOf(slicePtr)
if ptr.Kind() != reflect.Ptr {
panic(fmt.Sprintf("MakeSlice: argument must be pointer to slice, found %v", ptr.Type()))
}
sl := ptr.Elem()
if sl.Kind() != reflect.Slice {
panic(fmt.Sprintf("MakeSlice: argument must point to a slice, found %v", sl.Type()))
}
intf := reflect.TypeOf((*Elem)(nil)).Elem()
if !sl.Type().Elem().Implements(intf) {
panic(fmt.Sprintf("MakeSlice: element type of slice (%v) does not implement Elem", sl.Type().Elem()))
}
nsl := reflect.MakeSlice(sl.Type(), sl.Len(), sl.Len())
reflect.Copy(nsl, sl)
sl.Set(nsl)
return Slice{
ptr: ptr,
typ: sl.Type().Elem().Elem(),
}
}
func (s Slice) indexForAttr(a string) []int {
for i := iter(reflect.Zero(s.typ)); !i.done(); i.next() {
if n, _ := xmlName(i.field()); n == a {
return i.index
}
}
panic(fmt.Sprintf("MakeSlice: no attribute %q for type %v", a, s.typ))
}
// Filter filters s to only include elements for which fn returns true.
func (s Slice) Filter(fn func(e Elem) bool) {
k := 0
sl := s.Value()
for i := 0; i < sl.Len(); i++ {
vi := sl.Index(i)
if fn(vi.Interface().(Elem)) {
sl.Index(k).Set(vi)
k++
}
}
sl.Set(sl.Slice(0, k))
}
// Group finds elements in s for which fn returns the same value and groups
// them in a new Slice.
func (s Slice) Group(fn func(e Elem) string) []Slice {
m := make(map[string][]reflect.Value)
sl := s.Value()
for i := 0; i < sl.Len(); i++ {
vi := sl.Index(i)
key := fn(vi.Interface().(Elem))
m[key] = append(m[key], vi)
}
keys := []string{}
for k, _ := range m {
keys = append(keys, k)
}
sort.Strings(keys)
res := []Slice{}
for _, k := range keys {
nsl := reflect.New(sl.Type())
nsl.Elem().Set(reflect.Append(nsl.Elem(), m[k]...))
res = append(res, MakeSlice(nsl.Interface()))
}
return res
}
// SelectAnyOf filters s to contain only elements for which attr matches
// any of the values.
func (s Slice) SelectAnyOf(attr string, values ...string) {
index := s.indexForAttr(attr)
s.Filter(func(e Elem) bool {
vf := reflect.ValueOf(e).Elem().FieldByIndex(index)
return in(values, vf.String())
})
}
// SelectOnePerGroup filters s to include at most one element e per group of
// elements matching Key(attr), where e has an attribute a that matches any
// the values in v.
// If more than one element in a group matches a value in v preference
// is given to the element that matches the first value in v.
func (s Slice) SelectOnePerGroup(a string, v []string) {
index := s.indexForAttr(a)
grouped := s.Group(func(e Elem) string { return Key(e, a) })
sl := s.Value()
sl.Set(sl.Slice(0, 0))
for _, g := range grouped {
e := reflect.Value{}
found := len(v)
gsl := g.Value()
for i := 0; i < gsl.Len(); i++ {
vi := gsl.Index(i).Elem().FieldByIndex(index)
j := 0
for ; j < len(v) && v[j] != vi.String(); j++ {
}
if j < found {
found = j
e = gsl.Index(i)
}
}
if found < len(v) {
sl.Set(reflect.Append(sl, e))
}
}
}
// SelectDraft drops all elements from the list with a draft level smaller than d
// and selects the highest draft level of the remaining.
// This method assumes that the input CLDR is canonicalized.
func (s Slice) SelectDraft(d Draft) {
s.SelectOnePerGroup("draft", drafts[len(drafts)-2-int(d):])
}
+1494
View File
@@ -0,0 +1,1494 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package cldr
// LDMLBCP47 holds information on allowable values for various variables in LDML.
type LDMLBCP47 struct {
Common
Version *struct {
Common
Number string `xml:"number,attr"`
} `xml:"version"`
Generation *struct {
Common
Date string `xml:"date,attr"`
} `xml:"generation"`
Keyword []*struct {
Common
Key []*struct {
Common
Extension string `xml:"extension,attr"`
Name string `xml:"name,attr"`
Description string `xml:"description,attr"`
Deprecated string `xml:"deprecated,attr"`
Preferred string `xml:"preferred,attr"`
Alias string `xml:"alias,attr"`
ValueType string `xml:"valueType,attr"`
Since string `xml:"since,attr"`
Type []*struct {
Common
Name string `xml:"name,attr"`
Description string `xml:"description,attr"`
Deprecated string `xml:"deprecated,attr"`
Preferred string `xml:"preferred,attr"`
Alias string `xml:"alias,attr"`
Since string `xml:"since,attr"`
} `xml:"type"`
} `xml:"key"`
} `xml:"keyword"`
Attribute []*struct {
Common
Name string `xml:"name,attr"`
Description string `xml:"description,attr"`
Deprecated string `xml:"deprecated,attr"`
Preferred string `xml:"preferred,attr"`
Since string `xml:"since,attr"`
} `xml:"attribute"`
}
// SupplementalData holds information relevant for internationalization
// and proper use of CLDR, but that is not contained in the locale hierarchy.
type SupplementalData struct {
Common
Version *struct {
Common
Number string `xml:"number,attr"`
} `xml:"version"`
Generation *struct {
Common
Date string `xml:"date,attr"`
} `xml:"generation"`
CurrencyData *struct {
Common
Fractions []*struct {
Common
Info []*struct {
Common
Iso4217 string `xml:"iso4217,attr"`
Digits string `xml:"digits,attr"`
Rounding string `xml:"rounding,attr"`
CashDigits string `xml:"cashDigits,attr"`
CashRounding string `xml:"cashRounding,attr"`
} `xml:"info"`
} `xml:"fractions"`
Region []*struct {
Common
Iso3166 string `xml:"iso3166,attr"`
Currency []*struct {
Common
Before string `xml:"before,attr"`
From string `xml:"from,attr"`
To string `xml:"to,attr"`
Iso4217 string `xml:"iso4217,attr"`
Digits string `xml:"digits,attr"`
Rounding string `xml:"rounding,attr"`
CashRounding string `xml:"cashRounding,attr"`
Tender string `xml:"tender,attr"`
Alternate []*struct {
Common
Iso4217 string `xml:"iso4217,attr"`
} `xml:"alternate"`
} `xml:"currency"`
} `xml:"region"`
} `xml:"currencyData"`
TerritoryContainment *struct {
Common
Group []*struct {
Common
Contains string `xml:"contains,attr"`
Grouping string `xml:"grouping,attr"`
Status string `xml:"status,attr"`
} `xml:"group"`
} `xml:"territoryContainment"`
SubdivisionContainment *struct {
Common
Subgroup []*struct {
Common
Subtype string `xml:"subtype,attr"`
Contains string `xml:"contains,attr"`
} `xml:"subgroup"`
} `xml:"subdivisionContainment"`
LanguageData *struct {
Common
Language []*struct {
Common
Scripts string `xml:"scripts,attr"`
Territories string `xml:"territories,attr"`
Variants string `xml:"variants,attr"`
} `xml:"language"`
} `xml:"languageData"`
TerritoryInfo *struct {
Common
Territory []*struct {
Common
Gdp string `xml:"gdp,attr"`
LiteracyPercent string `xml:"literacyPercent,attr"`
Population string `xml:"population,attr"`
LanguagePopulation []*struct {
Common
LiteracyPercent string `xml:"literacyPercent,attr"`
WritingPercent string `xml:"writingPercent,attr"`
PopulationPercent string `xml:"populationPercent,attr"`
OfficialStatus string `xml:"officialStatus,attr"`
} `xml:"languagePopulation"`
} `xml:"territory"`
} `xml:"territoryInfo"`
PostalCodeData *struct {
Common
PostCodeRegex []*struct {
Common
TerritoryId string `xml:"territoryId,attr"`
} `xml:"postCodeRegex"`
} `xml:"postalCodeData"`
CalendarData *struct {
Common
Calendar []*struct {
Common
Territories string `xml:"territories,attr"`
CalendarSystem *Common `xml:"calendarSystem"`
Eras *struct {
Common
Era []*struct {
Common
Start string `xml:"start,attr"`
End string `xml:"end,attr"`
} `xml:"era"`
} `xml:"eras"`
} `xml:"calendar"`
} `xml:"calendarData"`
CalendarPreferenceData *struct {
Common
CalendarPreference []*struct {
Common
Territories string `xml:"territories,attr"`
Ordering string `xml:"ordering,attr"`
} `xml:"calendarPreference"`
} `xml:"calendarPreferenceData"`
WeekData *struct {
Common
MinDays []*struct {
Common
Count string `xml:"count,attr"`
Territories string `xml:"territories,attr"`
} `xml:"minDays"`
FirstDay []*struct {
Common
Day string `xml:"day,attr"`
Territories string `xml:"territories,attr"`
} `xml:"firstDay"`
WeekendStart []*struct {
Common
Day string `xml:"day,attr"`
Territories string `xml:"territories,attr"`
} `xml:"weekendStart"`
WeekendEnd []*struct {
Common
Day string `xml:"day,attr"`
Territories string `xml:"territories,attr"`
} `xml:"weekendEnd"`
WeekOfPreference []*struct {
Common
Locales string `xml:"locales,attr"`
Ordering string `xml:"ordering,attr"`
} `xml:"weekOfPreference"`
} `xml:"weekData"`
TimeData *struct {
Common
Hours []*struct {
Common
Allowed string `xml:"allowed,attr"`
Preferred string `xml:"preferred,attr"`
Regions string `xml:"regions,attr"`
} `xml:"hours"`
} `xml:"timeData"`
MeasurementData *struct {
Common
MeasurementSystem []*struct {
Common
Category string `xml:"category,attr"`
Territories string `xml:"territories,attr"`
} `xml:"measurementSystem"`
PaperSize []*struct {
Common
Territories string `xml:"territories,attr"`
} `xml:"paperSize"`
} `xml:"measurementData"`
UnitPreferenceData *struct {
Common
UnitPreferences []*struct {
Common
Category string `xml:"category,attr"`
Usage string `xml:"usage,attr"`
Scope string `xml:"scope,attr"`
UnitPreference []*struct {
Common
Regions string `xml:"regions,attr"`
} `xml:"unitPreference"`
} `xml:"unitPreferences"`
} `xml:"unitPreferenceData"`
TimezoneData *struct {
Common
MapTimezones []*struct {
Common
OtherVersion string `xml:"otherVersion,attr"`
TypeVersion string `xml:"typeVersion,attr"`
MapZone []*struct {
Common
Other string `xml:"other,attr"`
Territory string `xml:"territory,attr"`
} `xml:"mapZone"`
} `xml:"mapTimezones"`
ZoneFormatting []*struct {
Common
Multizone string `xml:"multizone,attr"`
TzidVersion string `xml:"tzidVersion,attr"`
ZoneItem []*struct {
Common
Territory string `xml:"territory,attr"`
Aliases string `xml:"aliases,attr"`
} `xml:"zoneItem"`
} `xml:"zoneFormatting"`
} `xml:"timezoneData"`
Characters *struct {
Common
CharacterFallback []*struct {
Common
Character []*struct {
Common
Value string `xml:"value,attr"`
Substitute []*Common `xml:"substitute"`
} `xml:"character"`
} `xml:"character-fallback"`
} `xml:"characters"`
Transforms *struct {
Common
Transform []*struct {
Common
Source string `xml:"source,attr"`
Target string `xml:"target,attr"`
Variant string `xml:"variant,attr"`
Direction string `xml:"direction,attr"`
Alias string `xml:"alias,attr"`
BackwardAlias string `xml:"backwardAlias,attr"`
Visibility string `xml:"visibility,attr"`
Comment []*Common `xml:"comment"`
TRule []*Common `xml:"tRule"`
} `xml:"transform"`
} `xml:"transforms"`
Metadata *struct {
Common
AttributeOrder *Common `xml:"attributeOrder"`
ElementOrder *Common `xml:"elementOrder"`
SerialElements *Common `xml:"serialElements"`
Suppress *struct {
Common
Attributes []*struct {
Common
Element string `xml:"element,attr"`
Attribute string `xml:"attribute,attr"`
AttributeValue string `xml:"attributeValue,attr"`
} `xml:"attributes"`
} `xml:"suppress"`
Validity *struct {
Common
Variable []*struct {
Common
Id string `xml:"id,attr"`
} `xml:"variable"`
AttributeValues []*struct {
Common
Dtds string `xml:"dtds,attr"`
Elements string `xml:"elements,attr"`
Attributes string `xml:"attributes,attr"`
Order string `xml:"order,attr"`
} `xml:"attributeValues"`
} `xml:"validity"`
Alias *struct {
Common
LanguageAlias []*struct {
Common
Replacement string `xml:"replacement,attr"`
Reason string `xml:"reason,attr"`
} `xml:"languageAlias"`
ScriptAlias []*struct {
Common
Replacement string `xml:"replacement,attr"`
Reason string `xml:"reason,attr"`
} `xml:"scriptAlias"`
TerritoryAlias []*struct {
Common
Replacement string `xml:"replacement,attr"`
Reason string `xml:"reason,attr"`
} `xml:"territoryAlias"`
SubdivisionAlias []*struct {
Common
Replacement string `xml:"replacement,attr"`
Reason string `xml:"reason,attr"`
} `xml:"subdivisionAlias"`
VariantAlias []*struct {
Common
Replacement string `xml:"replacement,attr"`
Reason string `xml:"reason,attr"`
} `xml:"variantAlias"`
ZoneAlias []*struct {
Common
Replacement string `xml:"replacement,attr"`
Reason string `xml:"reason,attr"`
} `xml:"zoneAlias"`
} `xml:"alias"`
Deprecated *struct {
Common
DeprecatedItems []*struct {
Common
Elements string `xml:"elements,attr"`
Attributes string `xml:"attributes,attr"`
Values string `xml:"values,attr"`
} `xml:"deprecatedItems"`
} `xml:"deprecated"`
Distinguishing *struct {
Common
DistinguishingItems []*struct {
Common
Exclude string `xml:"exclude,attr"`
Elements string `xml:"elements,attr"`
Attributes string `xml:"attributes,attr"`
} `xml:"distinguishingItems"`
} `xml:"distinguishing"`
Blocking *struct {
Common
BlockingItems []*struct {
Common
Elements string `xml:"elements,attr"`
} `xml:"blockingItems"`
} `xml:"blocking"`
CoverageAdditions *struct {
Common
LanguageCoverage []*struct {
Common
Values string `xml:"values,attr"`
} `xml:"languageCoverage"`
ScriptCoverage []*struct {
Common
Values string `xml:"values,attr"`
} `xml:"scriptCoverage"`
TerritoryCoverage []*struct {
Common
Values string `xml:"values,attr"`
} `xml:"territoryCoverage"`
CurrencyCoverage []*struct {
Common
Values string `xml:"values,attr"`
} `xml:"currencyCoverage"`
TimezoneCoverage []*struct {
Common
Values string `xml:"values,attr"`
} `xml:"timezoneCoverage"`
} `xml:"coverageAdditions"`
SkipDefaultLocale *struct {
Common
Services string `xml:"services,attr"`
} `xml:"skipDefaultLocale"`
DefaultContent *struct {
Common
Locales string `xml:"locales,attr"`
} `xml:"defaultContent"`
} `xml:"metadata"`
CodeMappings *struct {
Common
LanguageCodes []*struct {
Common
Alpha3 string `xml:"alpha3,attr"`
} `xml:"languageCodes"`
TerritoryCodes []*struct {
Common
Numeric string `xml:"numeric,attr"`
Alpha3 string `xml:"alpha3,attr"`
Fips10 string `xml:"fips10,attr"`
Internet string `xml:"internet,attr"`
} `xml:"territoryCodes"`
CurrencyCodes []*struct {
Common
Numeric string `xml:"numeric,attr"`
} `xml:"currencyCodes"`
} `xml:"codeMappings"`
ParentLocales *struct {
Common
ParentLocale []*struct {
Common
Parent string `xml:"parent,attr"`
Locales string `xml:"locales,attr"`
} `xml:"parentLocale"`
} `xml:"parentLocales"`
LikelySubtags *struct {
Common
LikelySubtag []*struct {
Common
From string `xml:"from,attr"`
To string `xml:"to,attr"`
} `xml:"likelySubtag"`
} `xml:"likelySubtags"`
MetazoneInfo *struct {
Common
Timezone []*struct {
Common
UsesMetazone []*struct {
Common
From string `xml:"from,attr"`
To string `xml:"to,attr"`
Mzone string `xml:"mzone,attr"`
} `xml:"usesMetazone"`
} `xml:"timezone"`
} `xml:"metazoneInfo"`
Plurals []*struct {
Common
PluralRules []*struct {
Common
Locales string `xml:"locales,attr"`
PluralRule []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"pluralRule"`
} `xml:"pluralRules"`
PluralRanges []*struct {
Common
Locales string `xml:"locales,attr"`
PluralRange []*struct {
Common
Start string `xml:"start,attr"`
End string `xml:"end,attr"`
Result string `xml:"result,attr"`
} `xml:"pluralRange"`
} `xml:"pluralRanges"`
} `xml:"plurals"`
TelephoneCodeData *struct {
Common
CodesByTerritory []*struct {
Common
Territory string `xml:"territory,attr"`
TelephoneCountryCode []*struct {
Common
Code string `xml:"code,attr"`
From string `xml:"from,attr"`
To string `xml:"to,attr"`
} `xml:"telephoneCountryCode"`
} `xml:"codesByTerritory"`
} `xml:"telephoneCodeData"`
NumberingSystems *struct {
Common
NumberingSystem []*struct {
Common
Id string `xml:"id,attr"`
Radix string `xml:"radix,attr"`
Digits string `xml:"digits,attr"`
Rules string `xml:"rules,attr"`
} `xml:"numberingSystem"`
} `xml:"numberingSystems"`
Bcp47KeywordMappings *struct {
Common
MapKeys *struct {
Common
KeyMap []*struct {
Common
Bcp47 string `xml:"bcp47,attr"`
} `xml:"keyMap"`
} `xml:"mapKeys"`
MapTypes []*struct {
Common
TypeMap []*struct {
Common
Bcp47 string `xml:"bcp47,attr"`
} `xml:"typeMap"`
} `xml:"mapTypes"`
} `xml:"bcp47KeywordMappings"`
Gender *struct {
Common
PersonList []*struct {
Common
Locales string `xml:"locales,attr"`
} `xml:"personList"`
} `xml:"gender"`
References *struct {
Common
Reference []*struct {
Common
Uri string `xml:"uri,attr"`
} `xml:"reference"`
} `xml:"references"`
LanguageMatching *struct {
Common
LanguageMatches []*struct {
Common
ParadigmLocales []*struct {
Common
Locales string `xml:"locales,attr"`
} `xml:"paradigmLocales"`
MatchVariable []*struct {
Common
Id string `xml:"id,attr"`
Value string `xml:"value,attr"`
} `xml:"matchVariable"`
LanguageMatch []*struct {
Common
Desired string `xml:"desired,attr"`
Supported string `xml:"supported,attr"`
Percent string `xml:"percent,attr"`
Distance string `xml:"distance,attr"`
Oneway string `xml:"oneway,attr"`
} `xml:"languageMatch"`
} `xml:"languageMatches"`
} `xml:"languageMatching"`
DayPeriodRuleSet []*struct {
Common
DayPeriodRules []*struct {
Common
Locales string `xml:"locales,attr"`
DayPeriodRule []*struct {
Common
At string `xml:"at,attr"`
After string `xml:"after,attr"`
Before string `xml:"before,attr"`
From string `xml:"from,attr"`
To string `xml:"to,attr"`
} `xml:"dayPeriodRule"`
} `xml:"dayPeriodRules"`
} `xml:"dayPeriodRuleSet"`
MetaZones *struct {
Common
MetazoneInfo *struct {
Common
Timezone []*struct {
Common
UsesMetazone []*struct {
Common
From string `xml:"from,attr"`
To string `xml:"to,attr"`
Mzone string `xml:"mzone,attr"`
} `xml:"usesMetazone"`
} `xml:"timezone"`
} `xml:"metazoneInfo"`
MapTimezones *struct {
Common
OtherVersion string `xml:"otherVersion,attr"`
TypeVersion string `xml:"typeVersion,attr"`
MapZone []*struct {
Common
Other string `xml:"other,attr"`
Territory string `xml:"territory,attr"`
} `xml:"mapZone"`
} `xml:"mapTimezones"`
} `xml:"metaZones"`
PrimaryZones *struct {
Common
PrimaryZone []*struct {
Common
Iso3166 string `xml:"iso3166,attr"`
} `xml:"primaryZone"`
} `xml:"primaryZones"`
WindowsZones *struct {
Common
MapTimezones *struct {
Common
OtherVersion string `xml:"otherVersion,attr"`
TypeVersion string `xml:"typeVersion,attr"`
MapZone []*struct {
Common
Other string `xml:"other,attr"`
Territory string `xml:"territory,attr"`
} `xml:"mapZone"`
} `xml:"mapTimezones"`
} `xml:"windowsZones"`
CoverageLevels *struct {
Common
ApprovalRequirements *struct {
Common
ApprovalRequirement []*struct {
Common
Votes string `xml:"votes,attr"`
Locales string `xml:"locales,attr"`
Paths string `xml:"paths,attr"`
} `xml:"approvalRequirement"`
} `xml:"approvalRequirements"`
CoverageVariable []*struct {
Common
Key string `xml:"key,attr"`
Value string `xml:"value,attr"`
} `xml:"coverageVariable"`
CoverageLevel []*struct {
Common
InLanguage string `xml:"inLanguage,attr"`
InScript string `xml:"inScript,attr"`
InTerritory string `xml:"inTerritory,attr"`
Value string `xml:"value,attr"`
Match string `xml:"match,attr"`
} `xml:"coverageLevel"`
} `xml:"coverageLevels"`
IdValidity *struct {
Common
Id []*struct {
Common
IdStatus string `xml:"idStatus,attr"`
} `xml:"id"`
} `xml:"idValidity"`
RgScope *struct {
Common
RgPath []*struct {
Common
Path string `xml:"path,attr"`
} `xml:"rgPath"`
} `xml:"rgScope"`
LanguageGroups *struct {
Common
LanguageGroup []*struct {
Common
Parent string `xml:"parent,attr"`
} `xml:"languageGroup"`
} `xml:"languageGroups"`
}
// LDML is the top-level type for locale-specific data.
type LDML struct {
Common
Version string `xml:"version,attr"`
Identity *struct {
Common
Version *struct {
Common
Number string `xml:"number,attr"`
} `xml:"version"`
Generation *struct {
Common
Date string `xml:"date,attr"`
} `xml:"generation"`
Language *Common `xml:"language"`
Script *Common `xml:"script"`
Territory *Common `xml:"territory"`
Variant *Common `xml:"variant"`
} `xml:"identity"`
LocaleDisplayNames *LocaleDisplayNames `xml:"localeDisplayNames"`
Layout *struct {
Common
Orientation []*struct {
Common
Characters string `xml:"characters,attr"`
Lines string `xml:"lines,attr"`
CharacterOrder []*Common `xml:"characterOrder"`
LineOrder []*Common `xml:"lineOrder"`
} `xml:"orientation"`
InList []*struct {
Common
Casing string `xml:"casing,attr"`
} `xml:"inList"`
InText []*Common `xml:"inText"`
} `xml:"layout"`
ContextTransforms *struct {
Common
ContextTransformUsage []*struct {
Common
ContextTransform []*Common `xml:"contextTransform"`
} `xml:"contextTransformUsage"`
} `xml:"contextTransforms"`
Characters *struct {
Common
ExemplarCharacters []*Common `xml:"exemplarCharacters"`
Ellipsis []*Common `xml:"ellipsis"`
MoreInformation []*Common `xml:"moreInformation"`
Stopwords []*struct {
Common
StopwordList []*Common `xml:"stopwordList"`
} `xml:"stopwords"`
IndexLabels []*struct {
Common
IndexSeparator []*Common `xml:"indexSeparator"`
CompressedIndexSeparator []*Common `xml:"compressedIndexSeparator"`
IndexRangePattern []*Common `xml:"indexRangePattern"`
IndexLabelBefore []*Common `xml:"indexLabelBefore"`
IndexLabelAfter []*Common `xml:"indexLabelAfter"`
IndexLabel []*struct {
Common
IndexSource string `xml:"indexSource,attr"`
Priority string `xml:"priority,attr"`
} `xml:"indexLabel"`
} `xml:"indexLabels"`
Mapping []*struct {
Common
Registry string `xml:"registry,attr"`
} `xml:"mapping"`
ParseLenients []*struct {
Common
Scope string `xml:"scope,attr"`
Level string `xml:"level,attr"`
ParseLenient []*struct {
Common
Sample string `xml:"sample,attr"`
} `xml:"parseLenient"`
} `xml:"parseLenients"`
} `xml:"characters"`
Delimiters *struct {
Common
QuotationStart []*Common `xml:"quotationStart"`
QuotationEnd []*Common `xml:"quotationEnd"`
AlternateQuotationStart []*Common `xml:"alternateQuotationStart"`
AlternateQuotationEnd []*Common `xml:"alternateQuotationEnd"`
} `xml:"delimiters"`
Measurement *struct {
Common
MeasurementSystem []*Common `xml:"measurementSystem"`
PaperSize []*struct {
Common
Height []*Common `xml:"height"`
Width []*Common `xml:"width"`
} `xml:"paperSize"`
} `xml:"measurement"`
Dates *struct {
Common
LocalizedPatternChars []*Common `xml:"localizedPatternChars"`
DateRangePattern []*Common `xml:"dateRangePattern"`
Calendars *struct {
Common
Calendar []*Calendar `xml:"calendar"`
} `xml:"calendars"`
Fields *struct {
Common
Field []*struct {
Common
DisplayName []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"displayName"`
Relative []*Common `xml:"relative"`
RelativeTime []*struct {
Common
RelativeTimePattern []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"relativeTimePattern"`
} `xml:"relativeTime"`
RelativePeriod []*Common `xml:"relativePeriod"`
} `xml:"field"`
} `xml:"fields"`
TimeZoneNames *TimeZoneNames `xml:"timeZoneNames"`
} `xml:"dates"`
Numbers *Numbers `xml:"numbers"`
Units *struct {
Common
Unit []*struct {
Common
DisplayName []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"displayName"`
UnitPattern []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"unitPattern"`
PerUnitPattern []*Common `xml:"perUnitPattern"`
} `xml:"unit"`
UnitLength []*struct {
Common
CompoundUnit []*struct {
Common
CompoundUnitPattern []*Common `xml:"compoundUnitPattern"`
} `xml:"compoundUnit"`
Unit []*struct {
Common
DisplayName []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"displayName"`
UnitPattern []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"unitPattern"`
PerUnitPattern []*Common `xml:"perUnitPattern"`
} `xml:"unit"`
CoordinateUnit []*struct {
Common
CoordinateUnitPattern []*Common `xml:"coordinateUnitPattern"`
} `xml:"coordinateUnit"`
} `xml:"unitLength"`
DurationUnit []*struct {
Common
DurationUnitPattern []*Common `xml:"durationUnitPattern"`
} `xml:"durationUnit"`
} `xml:"units"`
ListPatterns *struct {
Common
ListPattern []*struct {
Common
ListPatternPart []*Common `xml:"listPatternPart"`
} `xml:"listPattern"`
} `xml:"listPatterns"`
Collations *struct {
Common
Version string `xml:"version,attr"`
DefaultCollation *Common `xml:"defaultCollation"`
Collation []*Collation `xml:"collation"`
} `xml:"collations"`
Posix *struct {
Common
Messages []*struct {
Common
Yesstr []*Common `xml:"yesstr"`
Nostr []*Common `xml:"nostr"`
Yesexpr []*Common `xml:"yesexpr"`
Noexpr []*Common `xml:"noexpr"`
} `xml:"messages"`
} `xml:"posix"`
CharacterLabels *struct {
Common
CharacterLabelPattern []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"characterLabelPattern"`
CharacterLabel []*Common `xml:"characterLabel"`
} `xml:"characterLabels"`
Segmentations *struct {
Common
Segmentation []*struct {
Common
Variables *struct {
Common
Variable []*struct {
Common
Id string `xml:"id,attr"`
} `xml:"variable"`
} `xml:"variables"`
SegmentRules *struct {
Common
Rule []*struct {
Common
Id string `xml:"id,attr"`
} `xml:"rule"`
} `xml:"segmentRules"`
Exceptions *struct {
Common
Exception []*Common `xml:"exception"`
} `xml:"exceptions"`
Suppressions *struct {
Common
Suppression []*Common `xml:"suppression"`
} `xml:"suppressions"`
} `xml:"segmentation"`
} `xml:"segmentations"`
Rbnf *struct {
Common
RulesetGrouping []*struct {
Common
Ruleset []*struct {
Common
Access string `xml:"access,attr"`
AllowsParsing string `xml:"allowsParsing,attr"`
Rbnfrule []*struct {
Common
Value string `xml:"value,attr"`
Radix string `xml:"radix,attr"`
Decexp string `xml:"decexp,attr"`
} `xml:"rbnfrule"`
} `xml:"ruleset"`
} `xml:"rulesetGrouping"`
} `xml:"rbnf"`
Annotations *struct {
Common
Annotation []*struct {
Common
Cp string `xml:"cp,attr"`
Tts string `xml:"tts,attr"`
} `xml:"annotation"`
} `xml:"annotations"`
Metadata *struct {
Common
CasingData *struct {
Common
CasingItem []*struct {
Common
Override string `xml:"override,attr"`
ForceError string `xml:"forceError,attr"`
} `xml:"casingItem"`
} `xml:"casingData"`
} `xml:"metadata"`
References *struct {
Common
Reference []*struct {
Common
Uri string `xml:"uri,attr"`
} `xml:"reference"`
} `xml:"references"`
}
// Collation contains rules that specify a certain sort-order,
// as a tailoring of the root order.
// The parsed rules are obtained by passing a RuleProcessor to Collation's
// Process method.
type Collation struct {
Common
Visibility string `xml:"visibility,attr"`
Base *Common `xml:"base"`
Import []*struct {
Common
Source string `xml:"source,attr"`
} `xml:"import"`
Settings *struct {
Common
Strength string `xml:"strength,attr"`
Alternate string `xml:"alternate,attr"`
Backwards string `xml:"backwards,attr"`
Normalization string `xml:"normalization,attr"`
CaseLevel string `xml:"caseLevel,attr"`
CaseFirst string `xml:"caseFirst,attr"`
HiraganaQuaternary string `xml:"hiraganaQuaternary,attr"`
MaxVariable string `xml:"maxVariable,attr"`
Numeric string `xml:"numeric,attr"`
Private string `xml:"private,attr"`
VariableTop string `xml:"variableTop,attr"`
Reorder string `xml:"reorder,attr"`
} `xml:"settings"`
SuppressContractions *Common `xml:"suppress_contractions"`
Optimize *Common `xml:"optimize"`
Cr []*Common `xml:"cr"`
rulesElem
}
// Calendar specifies the fields used for formatting and parsing dates and times.
// The month and quarter names are identified numerically, starting at 1.
// The day (of the week) names are identified with short strings, since there is
// no universally-accepted numeric designation.
type Calendar struct {
Common
Months *struct {
Common
MonthContext []*struct {
Common
MonthWidth []*struct {
Common
Month []*struct {
Common
Yeartype string `xml:"yeartype,attr"`
} `xml:"month"`
} `xml:"monthWidth"`
} `xml:"monthContext"`
} `xml:"months"`
MonthNames *struct {
Common
Month []*struct {
Common
Yeartype string `xml:"yeartype,attr"`
} `xml:"month"`
} `xml:"monthNames"`
MonthAbbr *struct {
Common
Month []*struct {
Common
Yeartype string `xml:"yeartype,attr"`
} `xml:"month"`
} `xml:"monthAbbr"`
MonthPatterns *struct {
Common
MonthPatternContext []*struct {
Common
MonthPatternWidth []*struct {
Common
MonthPattern []*Common `xml:"monthPattern"`
} `xml:"monthPatternWidth"`
} `xml:"monthPatternContext"`
} `xml:"monthPatterns"`
Days *struct {
Common
DayContext []*struct {
Common
DayWidth []*struct {
Common
Day []*Common `xml:"day"`
} `xml:"dayWidth"`
} `xml:"dayContext"`
} `xml:"days"`
DayNames *struct {
Common
Day []*Common `xml:"day"`
} `xml:"dayNames"`
DayAbbr *struct {
Common
Day []*Common `xml:"day"`
} `xml:"dayAbbr"`
Quarters *struct {
Common
QuarterContext []*struct {
Common
QuarterWidth []*struct {
Common
Quarter []*Common `xml:"quarter"`
} `xml:"quarterWidth"`
} `xml:"quarterContext"`
} `xml:"quarters"`
Week *struct {
Common
MinDays []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"minDays"`
FirstDay []*struct {
Common
Day string `xml:"day,attr"`
} `xml:"firstDay"`
WeekendStart []*struct {
Common
Day string `xml:"day,attr"`
Time string `xml:"time,attr"`
} `xml:"weekendStart"`
WeekendEnd []*struct {
Common
Day string `xml:"day,attr"`
Time string `xml:"time,attr"`
} `xml:"weekendEnd"`
} `xml:"week"`
Am []*Common `xml:"am"`
Pm []*Common `xml:"pm"`
DayPeriods *struct {
Common
DayPeriodContext []*struct {
Common
DayPeriodWidth []*struct {
Common
DayPeriod []*Common `xml:"dayPeriod"`
} `xml:"dayPeriodWidth"`
} `xml:"dayPeriodContext"`
} `xml:"dayPeriods"`
Eras *struct {
Common
EraNames *struct {
Common
Era []*Common `xml:"era"`
} `xml:"eraNames"`
EraAbbr *struct {
Common
Era []*Common `xml:"era"`
} `xml:"eraAbbr"`
EraNarrow *struct {
Common
Era []*Common `xml:"era"`
} `xml:"eraNarrow"`
} `xml:"eras"`
CyclicNameSets *struct {
Common
CyclicNameSet []*struct {
Common
CyclicNameContext []*struct {
Common
CyclicNameWidth []*struct {
Common
CyclicName []*Common `xml:"cyclicName"`
} `xml:"cyclicNameWidth"`
} `xml:"cyclicNameContext"`
} `xml:"cyclicNameSet"`
} `xml:"cyclicNameSets"`
DateFormats *struct {
Common
DateFormatLength []*struct {
Common
DateFormat []*struct {
Common
Pattern []*struct {
Common
Numbers string `xml:"numbers,attr"`
Count string `xml:"count,attr"`
} `xml:"pattern"`
DisplayName []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"displayName"`
} `xml:"dateFormat"`
} `xml:"dateFormatLength"`
} `xml:"dateFormats"`
TimeFormats *struct {
Common
TimeFormatLength []*struct {
Common
TimeFormat []*struct {
Common
Pattern []*struct {
Common
Numbers string `xml:"numbers,attr"`
Count string `xml:"count,attr"`
} `xml:"pattern"`
DisplayName []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"displayName"`
} `xml:"timeFormat"`
} `xml:"timeFormatLength"`
} `xml:"timeFormats"`
DateTimeFormats *struct {
Common
DateTimeFormatLength []*struct {
Common
DateTimeFormat []*struct {
Common
Pattern []*struct {
Common
Numbers string `xml:"numbers,attr"`
Count string `xml:"count,attr"`
} `xml:"pattern"`
DisplayName []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"displayName"`
} `xml:"dateTimeFormat"`
} `xml:"dateTimeFormatLength"`
AvailableFormats []*struct {
Common
DateFormatItem []*struct {
Common
Id string `xml:"id,attr"`
Count string `xml:"count,attr"`
} `xml:"dateFormatItem"`
} `xml:"availableFormats"`
AppendItems []*struct {
Common
AppendItem []*struct {
Common
Request string `xml:"request,attr"`
} `xml:"appendItem"`
} `xml:"appendItems"`
IntervalFormats []*struct {
Common
IntervalFormatFallback []*Common `xml:"intervalFormatFallback"`
IntervalFormatItem []*struct {
Common
Id string `xml:"id,attr"`
GreatestDifference []*struct {
Common
Id string `xml:"id,attr"`
} `xml:"greatestDifference"`
} `xml:"intervalFormatItem"`
} `xml:"intervalFormats"`
} `xml:"dateTimeFormats"`
Fields []*struct {
Common
Field []*struct {
Common
DisplayName []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"displayName"`
Relative []*Common `xml:"relative"`
RelativeTime []*struct {
Common
RelativeTimePattern []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"relativeTimePattern"`
} `xml:"relativeTime"`
RelativePeriod []*Common `xml:"relativePeriod"`
} `xml:"field"`
} `xml:"fields"`
}
type TimeZoneNames struct {
Common
HourFormat []*Common `xml:"hourFormat"`
HoursFormat []*Common `xml:"hoursFormat"`
GmtFormat []*Common `xml:"gmtFormat"`
GmtZeroFormat []*Common `xml:"gmtZeroFormat"`
RegionFormat []*Common `xml:"regionFormat"`
FallbackFormat []*Common `xml:"fallbackFormat"`
FallbackRegionFormat []*Common `xml:"fallbackRegionFormat"`
AbbreviationFallback []*Common `xml:"abbreviationFallback"`
PreferenceOrdering []*Common `xml:"preferenceOrdering"`
SingleCountries []*struct {
Common
List string `xml:"list,attr"`
} `xml:"singleCountries"`
Zone []*struct {
Common
Long []*struct {
Common
Generic []*Common `xml:"generic"`
Standard []*Common `xml:"standard"`
Daylight []*Common `xml:"daylight"`
} `xml:"long"`
Short []*struct {
Common
Generic []*Common `xml:"generic"`
Standard []*Common `xml:"standard"`
Daylight []*Common `xml:"daylight"`
} `xml:"short"`
CommonlyUsed []*struct {
Common
Used string `xml:"used,attr"`
} `xml:"commonlyUsed"`
ExemplarCity []*Common `xml:"exemplarCity"`
} `xml:"zone"`
Metazone []*struct {
Common
Long []*struct {
Common
Generic []*Common `xml:"generic"`
Standard []*Common `xml:"standard"`
Daylight []*Common `xml:"daylight"`
} `xml:"long"`
Short []*struct {
Common
Generic []*Common `xml:"generic"`
Standard []*Common `xml:"standard"`
Daylight []*Common `xml:"daylight"`
} `xml:"short"`
CommonlyUsed []*struct {
Common
Used string `xml:"used,attr"`
} `xml:"commonlyUsed"`
} `xml:"metazone"`
}
// LocaleDisplayNames specifies localized display names for scripts, languages,
// countries, currencies, and variants.
type LocaleDisplayNames struct {
Common
LocaleDisplayPattern *struct {
Common
LocalePattern []*Common `xml:"localePattern"`
LocaleSeparator []*Common `xml:"localeSeparator"`
LocaleKeyTypePattern []*Common `xml:"localeKeyTypePattern"`
} `xml:"localeDisplayPattern"`
Languages *struct {
Common
Language []*Common `xml:"language"`
} `xml:"languages"`
Scripts *struct {
Common
Script []*Common `xml:"script"`
} `xml:"scripts"`
Territories *struct {
Common
Territory []*Common `xml:"territory"`
} `xml:"territories"`
Subdivisions *struct {
Common
Subdivision []*Common `xml:"subdivision"`
} `xml:"subdivisions"`
Variants *struct {
Common
Variant []*Common `xml:"variant"`
} `xml:"variants"`
Keys *struct {
Common
Key []*Common `xml:"key"`
} `xml:"keys"`
Types *struct {
Common
Type []*struct {
Common
Key string `xml:"key,attr"`
} `xml:"type"`
} `xml:"types"`
TransformNames *struct {
Common
TransformName []*Common `xml:"transformName"`
} `xml:"transformNames"`
MeasurementSystemNames *struct {
Common
MeasurementSystemName []*Common `xml:"measurementSystemName"`
} `xml:"measurementSystemNames"`
CodePatterns *struct {
Common
CodePattern []*Common `xml:"codePattern"`
} `xml:"codePatterns"`
}
// Numbers supplies information for formatting and parsing numbers and currencies.
type Numbers struct {
Common
DefaultNumberingSystem []*Common `xml:"defaultNumberingSystem"`
OtherNumberingSystems []*struct {
Common
Native []*Common `xml:"native"`
Traditional []*Common `xml:"traditional"`
Finance []*Common `xml:"finance"`
} `xml:"otherNumberingSystems"`
MinimumGroupingDigits []*Common `xml:"minimumGroupingDigits"`
Symbols []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
Decimal []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"decimal"`
Group []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"group"`
List []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"list"`
PercentSign []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"percentSign"`
NativeZeroDigit []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"nativeZeroDigit"`
PatternDigit []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"patternDigit"`
PlusSign []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"plusSign"`
MinusSign []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"minusSign"`
Exponential []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"exponential"`
SuperscriptingExponent []*Common `xml:"superscriptingExponent"`
PerMille []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"perMille"`
Infinity []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"infinity"`
Nan []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"nan"`
CurrencyDecimal []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"currencyDecimal"`
CurrencyGroup []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"currencyGroup"`
TimeSeparator []*Common `xml:"timeSeparator"`
} `xml:"symbols"`
DecimalFormats []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
DecimalFormatLength []*struct {
Common
DecimalFormat []*struct {
Common
Pattern []*struct {
Common
Numbers string `xml:"numbers,attr"`
Count string `xml:"count,attr"`
} `xml:"pattern"`
} `xml:"decimalFormat"`
} `xml:"decimalFormatLength"`
} `xml:"decimalFormats"`
ScientificFormats []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
ScientificFormatLength []*struct {
Common
ScientificFormat []*struct {
Common
Pattern []*struct {
Common
Numbers string `xml:"numbers,attr"`
Count string `xml:"count,attr"`
} `xml:"pattern"`
} `xml:"scientificFormat"`
} `xml:"scientificFormatLength"`
} `xml:"scientificFormats"`
PercentFormats []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
PercentFormatLength []*struct {
Common
PercentFormat []*struct {
Common
Pattern []*struct {
Common
Numbers string `xml:"numbers,attr"`
Count string `xml:"count,attr"`
} `xml:"pattern"`
} `xml:"percentFormat"`
} `xml:"percentFormatLength"`
} `xml:"percentFormats"`
CurrencyFormats []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
CurrencySpacing []*struct {
Common
BeforeCurrency []*struct {
Common
CurrencyMatch []*Common `xml:"currencyMatch"`
SurroundingMatch []*Common `xml:"surroundingMatch"`
InsertBetween []*Common `xml:"insertBetween"`
} `xml:"beforeCurrency"`
AfterCurrency []*struct {
Common
CurrencyMatch []*Common `xml:"currencyMatch"`
SurroundingMatch []*Common `xml:"surroundingMatch"`
InsertBetween []*Common `xml:"insertBetween"`
} `xml:"afterCurrency"`
} `xml:"currencySpacing"`
CurrencyFormatLength []*struct {
Common
CurrencyFormat []*struct {
Common
Pattern []*struct {
Common
Numbers string `xml:"numbers,attr"`
Count string `xml:"count,attr"`
} `xml:"pattern"`
} `xml:"currencyFormat"`
} `xml:"currencyFormatLength"`
UnitPattern []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"unitPattern"`
} `xml:"currencyFormats"`
Currencies *struct {
Common
Currency []*struct {
Common
Pattern []*struct {
Common
Numbers string `xml:"numbers,attr"`
Count string `xml:"count,attr"`
} `xml:"pattern"`
DisplayName []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"displayName"`
Symbol []*Common `xml:"symbol"`
Decimal []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"decimal"`
Group []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
} `xml:"group"`
} `xml:"currency"`
} `xml:"currencies"`
MiscPatterns []*struct {
Common
NumberSystem string `xml:"numberSystem,attr"`
Pattern []*struct {
Common
Numbers string `xml:"numbers,attr"`
Count string `xml:"count,attr"`
} `xml:"pattern"`
} `xml:"miscPatterns"`
MinimalPairs []*struct {
Common
PluralMinimalPairs []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"pluralMinimalPairs"`
OrdinalMinimalPairs []*struct {
Common
Ordinal string `xml:"ordinal,attr"`
} `xml:"ordinalMinimalPairs"`
} `xml:"minimalPairs"`
}
// Version is the version of CLDR from which the XML definitions are generated.
const Version = "32"