summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-08-07 00:21:12 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-08-07 00:21:12 +0200
commit351c15d28e0444fd8a78c510a0c4d62ed433c758 (patch)
treeb97aae6ec45c1b341075da147fb9e333246c19f7
Genesis commit
-rw-r--r--.gitignore2
-rw-r--r--Makefile14
-rw-r--r--go.mod7
-rw-r--r--go.sum6
-rw-r--r--i18n/catalog.go79
-rw-r--r--i18n/locales/en-GB/messages.gotext.json96
-rw-r--r--i18n/locales/nl-NL/messages.gotext.json70
-rw-r--r--i18n/translations.go181
-rw-r--r--main.go71
-rw-r--r--middleware/i18n.go41
-rw-r--r--static/style.css2472
-rw-r--r--templates/base.go8
-rw-r--r--templates/navbar.templ237
-rw-r--r--templates/navbar_templ.go202
-rw-r--r--templates/root.templ101
-rw-r--r--templates/root_templ.go414
-rw-r--r--vendor/github.com/a-h/templ/.dockerignore3
-rw-r--r--vendor/github.com/a-h/templ/.gitignore28
-rw-r--r--vendor/github.com/a-h/templ/.goreleaser.yaml72
-rw-r--r--vendor/github.com/a-h/templ/.ignore7
-rw-r--r--vendor/github.com/a-h/templ/.version1
-rw-r--r--vendor/github.com/a-h/templ/CODE_OF_CONDUCT.md128
-rw-r--r--vendor/github.com/a-h/templ/CONTRIBUTING.md244
-rw-r--r--vendor/github.com/a-h/templ/LICENSE21
-rw-r--r--vendor/github.com/a-h/templ/README.md171
-rw-r--r--vendor/github.com/a-h/templ/SECURITY.md9
-rw-r--r--vendor/github.com/a-h/templ/cosign.pub4
-rw-r--r--vendor/github.com/a-h/templ/flake.lock140
-rw-r--r--vendor/github.com/a-h/templ/flake.nix93
-rw-r--r--vendor/github.com/a-h/templ/flush.go36
-rw-r--r--vendor/github.com/a-h/templ/gomod2nix.toml90
-rw-r--r--vendor/github.com/a-h/templ/handler.go102
-rw-r--r--vendor/github.com/a-h/templ/ide-demo.gifbin0 -> 544148 bytes
-rw-r--r--vendor/github.com/a-h/templ/jsonscript.go85
-rw-r--r--vendor/github.com/a-h/templ/jsonstring.go14
-rw-r--r--vendor/github.com/a-h/templ/once.go64
-rw-r--r--vendor/github.com/a-h/templ/push-tag.sh14
-rw-r--r--vendor/github.com/a-h/templ/runtime.go855
-rw-r--r--vendor/github.com/a-h/templ/runtime/buffer.go62
-rw-r--r--vendor/github.com/a-h/templ/runtime/bufferpool.go38
-rw-r--r--vendor/github.com/a-h/templ/runtime/builder.go8
-rw-r--r--vendor/github.com/a-h/templ/runtime/runtime.go21
-rw-r--r--vendor/github.com/a-h/templ/safehtml/style.go168
-rw-r--r--vendor/github.com/a-h/templ/templ.pngbin0 -> 15528 bytes
-rw-r--r--vendor/github.com/a-h/templ/url.go20
-rw-r--r--vendor/github.com/a-h/templ/version.go10
-rw-r--r--vendor/golang.org/x/text/LICENSE27
-rw-r--r--vendor/golang.org/x/text/PATENTS22
-rw-r--r--vendor/golang.org/x/text/feature/plural/common.go70
-rw-r--r--vendor/golang.org/x/text/feature/plural/message.go244
-rw-r--r--vendor/golang.org/x/text/feature/plural/plural.go262
-rw-r--r--vendor/golang.org/x/text/feature/plural/tables.go552
-rw-r--r--vendor/golang.org/x/text/internal/catmsg/catmsg.go417
-rw-r--r--vendor/golang.org/x/text/internal/catmsg/codec.go407
-rw-r--r--vendor/golang.org/x/text/internal/catmsg/varint.go62
-rw-r--r--vendor/golang.org/x/text/internal/format/format.go41
-rw-r--r--vendor/golang.org/x/text/internal/format/parser.go358
-rw-r--r--vendor/golang.org/x/text/internal/internal.go49
-rw-r--r--vendor/golang.org/x/text/internal/language/common.go16
-rw-r--r--vendor/golang.org/x/text/internal/language/compact.go29
-rw-r--r--vendor/golang.org/x/text/internal/language/compact/compact.go61
-rw-r--r--vendor/golang.org/x/text/internal/language/compact/language.go260
-rw-r--r--vendor/golang.org/x/text/internal/language/compact/parents.go120
-rw-r--r--vendor/golang.org/x/text/internal/language/compact/tables.go1015
-rw-r--r--vendor/golang.org/x/text/internal/language/compact/tags.go91
-rw-r--r--vendor/golang.org/x/text/internal/language/compose.go167
-rw-r--r--vendor/golang.org/x/text/internal/language/coverage.go28
-rw-r--r--vendor/golang.org/x/text/internal/language/language.go627
-rw-r--r--vendor/golang.org/x/text/internal/language/lookup.go412
-rw-r--r--vendor/golang.org/x/text/internal/language/match.go226
-rw-r--r--vendor/golang.org/x/text/internal/language/parse.go608
-rw-r--r--vendor/golang.org/x/text/internal/language/tables.go3494
-rw-r--r--vendor/golang.org/x/text/internal/language/tags.go48
-rw-r--r--vendor/golang.org/x/text/internal/match.go67
-rw-r--r--vendor/golang.org/x/text/internal/number/common.go55
-rw-r--r--vendor/golang.org/x/text/internal/number/decimal.go500
-rw-r--r--vendor/golang.org/x/text/internal/number/format.go535
-rw-r--r--vendor/golang.org/x/text/internal/number/number.go152
-rw-r--r--vendor/golang.org/x/text/internal/number/pattern.go485
-rw-r--r--vendor/golang.org/x/text/internal/number/roundingmode_string.go30
-rw-r--r--vendor/golang.org/x/text/internal/number/tables.go1219
-rw-r--r--vendor/golang.org/x/text/internal/stringset/set.go86
-rw-r--r--vendor/golang.org/x/text/internal/tag/tag.go100
-rw-r--r--vendor/golang.org/x/text/language/coverage.go187
-rw-r--r--vendor/golang.org/x/text/language/doc.go98
-rw-r--r--vendor/golang.org/x/text/language/language.go605
-rw-r--r--vendor/golang.org/x/text/language/match.go735
-rw-r--r--vendor/golang.org/x/text/language/parse.go256
-rw-r--r--vendor/golang.org/x/text/language/tables.go298
-rw-r--r--vendor/golang.org/x/text/language/tags.go145
-rw-r--r--vendor/golang.org/x/text/message/catalog.go36
-rw-r--r--vendor/golang.org/x/text/message/catalog/catalog.go365
-rw-r--r--vendor/golang.org/x/text/message/catalog/dict.go129
-rw-r--r--vendor/golang.org/x/text/message/catalog/go19.go15
-rw-r--r--vendor/golang.org/x/text/message/catalog/gopre19.go23
-rw-r--r--vendor/golang.org/x/text/message/doc.go99
-rw-r--r--vendor/golang.org/x/text/message/format.go510
-rw-r--r--vendor/golang.org/x/text/message/message.go192
-rw-r--r--vendor/golang.org/x/text/message/print.go984
-rw-r--r--vendor/modules.txt19
100 files changed, 24147 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..736fed5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+euro-cash.eu
+out.gotext.json
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c3a9e05
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+# Generating translations is rather slow; so don’t do that by default
+all:
+ TEMPL_EXPERIMENT=rawgo go generate ./templates
+ go build
+
+all-i18n:
+ TEMPL_EXPERIMENT=rawgo go generate ./templates ./i18n
+ find . -name out.gotext.json | mcp -b sed s/out/messages/
+ go build
+
+watch:
+ ls euro-cash.eu | entr -r ./euro-cash.eu
+
+.PHONY: watch
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..54ef251
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,7 @@
+module git.thomasvoss.com/euro-cash.eu
+
+go 1.22.5
+
+require golang.org/x/text v0.17.0
+
+require github.com/a-h/templ v0.2.747
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..336985b
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,6 @@
+github.com/a-h/templ v0.2.747 h1:D0dQ2lxC3W7Dxl6fxQ/1zZHBQslSkTSvl5FxP/CfdKg=
+github.com/a-h/templ v0.2.747/go.mod h1:69ObQIbrcuwPCU32ohNaWce3Cb7qM5GMiqN1K+2yop4=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
+golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
diff --git a/i18n/catalog.go b/i18n/catalog.go
new file mode 100644
index 0000000..f01b375
--- /dev/null
+++ b/i18n/catalog.go
@@ -0,0 +1,79 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package i18n
+
+import (
+ "golang.org/x/text/language"
+ "golang.org/x/text/message"
+ "golang.org/x/text/message/catalog"
+)
+
+type dictionary struct {
+ index []uint32
+ data string
+}
+
+func (d *dictionary) Lookup(key string) (data string, ok bool) {
+ p, ok := messageKeyToIndex[key]
+ if !ok {
+ return "", false
+ }
+ start, end := d.index[p], d.index[p+1]
+ if start == end {
+ return "", false
+ }
+ return d.data[start:end], true
+}
+
+func init() {
+ dict := map[string]catalog.Dictionary{
+ "en_GB": &dictionary{index: en_GBIndex, data: en_GBData},
+ "nl_NL": &dictionary{index: nl_NLIndex, data: nl_NLData},
+ }
+ fallback := language.MustParse("en-GB")
+ cat, err := catalog.NewFromMap(dict, catalog.Fallback(fallback))
+ if err != nil {
+ panic(err)
+ }
+ message.DefaultCatalog = cat
+}
+
+var messageKeyToIndex = map[string]int{
+ "Banknotes": 4,
+ "Coin Collecting": 2,
+ "Coins": 3,
+ "Discord": 6,
+ "Eurozone Languages": 11,
+ "Feel free to contact us!": 8,
+ "Found a mistake or want to contribute missing information?": 7,
+ "Home": 0,
+ "Jargon": 5,
+ "News": 1,
+ "Other Languages": 12,
+ "Select Your Language": 9,
+ "Select your preferred language to use on the site.": 10,
+}
+
+var en_GBIndex = []uint32{ // 14 elements
+ 0x00000000, 0x00000005, 0x0000000a, 0x0000001a,
+ 0x00000020, 0x0000002a, 0x00000031, 0x00000039,
+ 0x00000074, 0x0000008d, 0x000000a2, 0x000000d5,
+ 0x000000e8, 0x000000f8,
+} // Size: 80 bytes
+
+const en_GBData string = "" + // Size: 248 bytes
+ "\x02Home\x02News\x02Coin Collecting\x02Coins\x02Banknotes\x02Jargon\x02D" +
+ "iscord\x02Found a mistake or want to contribute missing information?\x02" +
+ "Feel free to contact us!\x02Select Your Language\x02Select your preferre" +
+ "d language to use on the site.\x02Eurozone Languages\x02Other Languages"
+
+var nl_NLIndex = []uint32{ // 14 elements
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000,
+} // Size: 80 bytes
+
+const nl_NLData string = ""
+
+// Total table size 408 bytes (0KiB); checksum: E5CA15
diff --git a/i18n/locales/en-GB/messages.gotext.json b/i18n/locales/en-GB/messages.gotext.json
new file mode 100644
index 0000000..64c1a2a
--- /dev/null
+++ b/i18n/locales/en-GB/messages.gotext.json
@@ -0,0 +1,96 @@
+{
+ "language": "en-GB",
+ "messages": [
+ {
+ "id": "Home",
+ "message": "Home",
+ "translation": "Home",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "News",
+ "message": "News",
+ "translation": "News",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Coin Collecting",
+ "message": "Coin Collecting",
+ "translation": "Coin Collecting",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Coins",
+ "message": "Coins",
+ "translation": "Coins",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Banknotes",
+ "message": "Banknotes",
+ "translation": "Banknotes",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Jargon",
+ "message": "Jargon",
+ "translation": "Jargon",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Discord",
+ "message": "Discord",
+ "translation": "Discord",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Found a mistake or want to contribute missing information?",
+ "message": "Found a mistake or want to contribute missing information?",
+ "translation": "Found a mistake or want to contribute missing information?",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Feel free to contact us!",
+ "message": "Feel free to contact us!",
+ "translation": "Feel free to contact us!",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Select Your Language",
+ "message": "Select Your Language",
+ "translation": "Select Your Language",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Select your preferred language to use on the site.",
+ "message": "Select your preferred language to use on the site.",
+ "translation": "Select your preferred language to use on the site.",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Eurozone Languages",
+ "message": "Eurozone Languages",
+ "translation": "Eurozone Languages",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ },
+ {
+ "id": "Other Languages",
+ "message": "Other Languages",
+ "translation": "Other Languages",
+ "translatorComment": "Copied from source.",
+ "fuzzy": true
+ }
+ ]
+} \ No newline at end of file
diff --git a/i18n/locales/nl-NL/messages.gotext.json b/i18n/locales/nl-NL/messages.gotext.json
new file mode 100644
index 0000000..d1cd455
--- /dev/null
+++ b/i18n/locales/nl-NL/messages.gotext.json
@@ -0,0 +1,70 @@
+{
+ "language": "nl-NL",
+ "messages": [
+ {
+ "id": "Home",
+ "message": "Home",
+ "translation": ""
+ },
+ {
+ "id": "News",
+ "message": "News",
+ "translation": ""
+ },
+ {
+ "id": "Coin Collecting",
+ "message": "Coin Collecting",
+ "translation": ""
+ },
+ {
+ "id": "Coins",
+ "message": "Coins",
+ "translation": ""
+ },
+ {
+ "id": "Banknotes",
+ "message": "Banknotes",
+ "translation": ""
+ },
+ {
+ "id": "Jargon",
+ "message": "Jargon",
+ "translation": ""
+ },
+ {
+ "id": "Discord",
+ "message": "Discord",
+ "translation": ""
+ },
+ {
+ "id": "Found a mistake or want to contribute missing information?",
+ "message": "Found a mistake or want to contribute missing information?",
+ "translation": ""
+ },
+ {
+ "id": "Feel free to contact us!",
+ "message": "Feel free to contact us!",
+ "translation": ""
+ },
+ {
+ "id": "Select Your Language",
+ "message": "Select Your Language",
+ "translation": ""
+ },
+ {
+ "id": "Select your preferred language to use on the site.",
+ "message": "Select your preferred language to use on the site.",
+ "translation": ""
+ },
+ {
+ "id": "Eurozone Languages",
+ "message": "Eurozone Languages",
+ "translation": ""
+ },
+ {
+ "id": "Other Languages",
+ "message": "Other Languages",
+ "translation": ""
+ }
+ ]
+} \ No newline at end of file
diff --git a/i18n/translations.go b/i18n/translations.go
new file mode 100644
index 0000000..1d35f98
--- /dev/null
+++ b/i18n/translations.go
@@ -0,0 +1,181 @@
+package i18n
+
+import (
+ "strings"
+
+ "golang.org/x/text/language"
+ "golang.org/x/text/message"
+)
+
+//go:generate gotext -srclang=en-GB update -out=catalog.go -lang=en-GB,nl-NL git.thomasvoss.com/euro-cash.eu
+
+type Printer struct {
+ Lang string
+ printer *message.Printer
+}
+
+type Locale struct {
+ Code string
+ Name string
+ Eurozone bool
+ Enabled bool
+}
+
+var (
+ Locales = [...]Locale{
+ Locale{
+ Code: "ca-AD",
+ Name: "català",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "de-DE",
+ Name: "Deutsch",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "el-GR",
+ Name: "ελληνικά",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "en-GB",
+ Name: "English",
+ Eurozone: true,
+ Enabled: true,
+ },
+ Locale{
+ Code: "es-ES",
+ Name: "español",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "et-EE",
+ Name: "eesti",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "fi-FI",
+ Name: "suomi",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "fr-FR",
+ Name: "français",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "ga-IE",
+ Name: "Gaeilge",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "hr-HR",
+ Name: "hrvatski",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "it-IT",
+ Name: "italiano",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "lt-LT",
+ Name: "lietuvių",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "lv-LV",
+ Name: "latviešu",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "mt-MT",
+ Name: "Malti",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "nl-NL",
+ Name: "Nederlands",
+ Eurozone: true,
+ Enabled: true,
+ },
+ Locale{
+ Code: "pt-PT",
+ Name: "português",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "sk-SK",
+ Name: "slovenčina",
+ Eurozone: true,
+ Enabled: false,
+ },
+ Locale{
+ Code: "sl-SI",
+ Name: "slovenščina",
+ Eurozone: true,
+ Enabled: false,
+ },
+
+ /* Non-Eurozone locales */
+ Locale{
+ Code: "bg-BG",
+ Name: "български",
+ Eurozone: false,
+ Enabled: false,
+ },
+ Locale{
+ Code: "en-US",
+ Name: "English (US)",
+ Eurozone: false,
+ Enabled: false,
+ },
+ Locale{
+ Code: "ro-RO",
+ Name: "română",
+ Eurozone: false,
+ Enabled: false,
+ },
+ }
+ /* Map of language codes to printers. We do this instead of just
+ using language.MustParse() directly so that we can easily see if a
+ language is supported or not. */
+ Printers map[string]Printer = make(map[string]Printer, len(Locales))
+ DefaultPrinter Printer
+)
+
+func InitPrinters() {
+ for _, loc := range Locales {
+ if loc.Enabled {
+ lang := language.MustParse(loc.Code)
+ Printers[strings.ToLower(loc.Code)] = Printer{
+ Lang: loc.Code,
+ printer: message.NewPrinter(lang),
+ }
+ }
+ }
+ DefaultPrinter = Printers["en-gb"]
+}
+
+func (p Printer) T(fmt string, args ...any) string {
+ return p.printer.Sprintf(fmt, args...)
+}
+
+func (l Locale) Language() string {
+ return l.Code[:2]
+}
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..0624665
--- /dev/null
+++ b/main.go
@@ -0,0 +1,71 @@
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "log"
+ "math"
+ "net/http"
+ "strconv"
+ "strings"
+
+ "git.thomasvoss.com/euro-cash.eu/i18n"
+ "git.thomasvoss.com/euro-cash.eu/middleware"
+ "git.thomasvoss.com/euro-cash.eu/templates"
+ "github.com/a-h/templ"
+)
+
+var components = map[string]templ.Component{
+ "/": templates.Index(),
+ "/language": templates.SetLanguage(),
+}
+
+func main() {
+ i18n.InitPrinters()
+
+ port := flag.Int("port", 8080, "port number")
+ flag.Parse()
+
+ mux := http.NewServeMux()
+ mux.Handle("GET /style.css", http.FileServer(http.Dir("static")))
+ mux.Handle("GET /", middleware.I18n(http.HandlerFunc(finalHandler)))
+ mux.Handle("POST /language", http.HandlerFunc(setUserLanguage))
+
+ portStr := ":" + strconv.Itoa(*port)
+ log.Println("Listening on", portStr)
+ log.Fatal(http.ListenAndServe(portStr, mux))
+}
+
+func finalHandler(w http.ResponseWriter, r *http.Request) {
+ p := r.Context().Value(middleware.PrinterKey).(i18n.Printer)
+ ctx := context.WithValue(context.Background(), templates.PrinterKey, p)
+
+ path := r.URL.Path
+ if path != "/" && path[len(path)-1] == '/' {
+ path = path[:len(path)-1]
+ }
+
+ if c, ok := components[path]; !ok {
+ w.WriteHeader(http.StatusNotFound)
+ fmt.Fprintln(w, p.T("Page not found"))
+ } else {
+ w.WriteHeader(http.StatusOK)
+ templates.Root(nil, c).Render(ctx, w)
+ }
+}
+
+func setUserLanguage(w http.ResponseWriter, r *http.Request) {
+ loc := r.FormValue(templates.LocaleKey)
+ _, ok := i18n.Printers[strings.ToLower(loc)]
+ if !ok {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "Locale ‘%s’ is invalid or unsupported", loc)
+ return
+ }
+ http.SetCookie(w, &http.Cookie{
+ Name: "lang",
+ Value: loc,
+ MaxAge: math.MaxInt32,
+ })
+}
diff --git a/middleware/i18n.go b/middleware/i18n.go
new file mode 100644
index 0000000..5e33636
--- /dev/null
+++ b/middleware/i18n.go
@@ -0,0 +1,41 @@
+package middleware
+
+import (
+ "cmp"
+ "context"
+ "errors"
+ "log"
+ "net/http"
+ "strings"
+
+ "git.thomasvoss.com/euro-cash.eu/i18n"
+ "git.thomasvoss.com/euro-cash.eu/templates"
+)
+
+const PrinterKey = "printer"
+
+func I18n(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ var p, pZero i18n.Printer
+
+ if c, err := r.Cookie("lang"); errors.Is(err, http.ErrNoCookie) {
+ log.Println("Language cookie not set")
+ } else {
+ var ok bool
+ p, ok = i18n.Printers[strings.ToLower(c.Value)]
+ if !ok {
+ log.Printf("Language ‘%s’ is unsupported\n", c.Value)
+ }
+ }
+
+ used := cmp.Or(p, i18n.DefaultPrinter)
+ ctx := context.WithValue(r.Context(), PrinterKey, used)
+
+ if p == pZero {
+ templates.Root(nil, templates.SetLanguage()).Render(ctx, w)
+ /* TODO: Redirect the user back to where they came from */
+ } else {
+ next.ServeHTTP(w, r.WithContext(ctx))
+ }
+ })
+}
diff --git a/static/style.css b/static/style.css
new file mode 100644
index 0000000..daf1a42
--- /dev/null
+++ b/static/style.css
@@ -0,0 +1,2472 @@
+/* TODO: Remove shit I don’t need! */
+
+@charset "UTF-8";
+
+:root {
+ --pico-line-height: 1.5;
+ --pico-font-weight: 400;
+ --pico-font-size: 100%;
+ --pico-text-underline-offset: 0.1rem;
+ --pico-border-radius: 0.25rem;
+ --pico-border-width: 0.0625rem;
+ --pico-outline-width: 0.125rem;
+ --pico-transition: 0.2s ease-in-out;
+ --pico-spacing: 1rem;
+ --pico-typography-spacing-vertical: 1rem;
+ --pico-block-spacing-vertical: var(--pico-spacing);
+ --pico-block-spacing-horizontal: var(--pico-spacing);
+ --pico-form-element-spacing-vertical: 0.75rem;
+ --pico-form-element-spacing-horizontal: 1rem;
+ --pico-group-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);
+ --pico-group-box-shadow-focus-with-input: 0 0 0 0.0625rem var(--pico-form-element-border-color);
+ --pico-modal-overlay-backdrop-filter: blur(0.375rem);
+ --pico-nav-element-spacing-vertical: 1rem;
+ --pico-nav-element-spacing-horizontal: 0.5rem;
+ --pico-nav-link-spacing-vertical: 0.5rem;
+ --pico-nav-link-spacing-horizontal: 0.5rem;
+ --pico-nav-breadcrumb-divider: ">";
+ --pico-icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ --pico-icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
+ --pico-icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --pico-icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
+ --pico-icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
+ --pico-icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
+ --pico-icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
+ --pico-icon-loading: url("data:image/svg+xml,%3Csvg fill='none' height='24' width='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' %3E%3Cstyle%3E g %7B animation: rotate 2s linear infinite; transform-origin: center center; %7D circle %7B stroke-dasharray: 75,100; stroke-dashoffset: -5; animation: dash 1.5s ease-in-out infinite; stroke-linecap: round; %7D @keyframes rotate %7B 0%25 %7B transform: rotate(0deg); %7D 100%25 %7B transform: rotate(360deg); %7D %7D @keyframes dash %7B 0%25 %7B stroke-dasharray: 1,100; stroke-dashoffset: 0; %7D 50%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -17.5; %7D 100%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -62; %7D %7D %3C/style%3E%3Cg%3E%3Ccircle cx='12' cy='12' r='10' fill='none' stroke='rgb(136, 145, 164)' stroke-width='4' /%3E%3C/g%3E%3C/svg%3E");
+}
+@media (min-width: 576px) {
+ :root {
+ --pico-font-size: 106.25%;
+ }
+}
+@media (min-width: 768px) {
+ :root {
+ --pico-font-size: 112.5%;
+ }
+}
+@media (min-width: 1024px) {
+ :root {
+ --pico-font-size: 118.75%;
+ }
+}
+@media (min-width: 1280px) {
+ :root {
+ --pico-font-size: 125%;
+ }
+}
+
+a {
+ --pico-text-decoration: underline;
+}
+
+small {
+ --pico-font-size: 0.875em;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ --pico-font-weight: 700;
+}
+
+h1 {
+ --pico-font-size: 2rem;
+ --pico-line-height: 1.125;
+ --pico-typography-spacing-top: 3rem;
+}
+
+h2 {
+ --pico-font-size: 1.75rem;
+ --pico-line-height: 1.15;
+ --pico-typography-spacing-top: 2.625rem;
+}
+
+h3 {
+ --pico-font-size: 1.5rem;
+ --pico-line-height: 1.175;
+ --pico-typography-spacing-top: 2.25rem;
+}
+
+h4 {
+ --pico-font-size: 1.25rem;
+ --pico-line-height: 1.2;
+ --pico-typography-spacing-top: 1.874rem;
+}
+
+h5 {
+ --pico-font-size: 1.125rem;
+ --pico-line-height: 1.225;
+ --pico-typography-spacing-top: 1.6875rem;
+}
+
+h6 {
+ --pico-font-size: 1rem;
+ --pico-line-height: 1.25;
+ --pico-typography-spacing-top: 1.5rem;
+}
+
+thead th,
+thead td,
+tfoot th,
+tfoot td {
+ --pico-font-weight: 600;
+ --pico-border-width: 0.1875rem;
+}
+
+kbd {
+ --pico-font-weight: bolder;
+}
+
+input:not([type=submit],
+[type=button],
+[type=reset],
+[type=checkbox],
+[type=radio],
+[type=file]),
+:where(select, textarea) {
+ --pico-outline-width: 0.0625rem;
+}
+
+[type=search] {
+ --pico-border-radius: 5rem;
+}
+
+[type=checkbox],
+[type=radio] {
+ --pico-border-width: 0.125rem;
+}
+
+[type=checkbox][role=switch] {
+ --pico-border-width: 0.1875rem;
+}
+
+[role=search] {
+ --pico-border-radius: 5rem;
+}
+
+[role=search] button,
+[role=search] [type=submit],
+[role=search] [type=button],
+[role=search] [role=button],
+[role=group] button,
+[role=group] [type=submit],
+[role=group] [type=button],
+[role=group] [role=button] {
+ --pico-form-element-spacing-horizontal: 2rem;
+}
+
+details summary[role=button]::after {
+ filter: brightness(0) invert(1);
+}
+
+[aria-busy=true]:not(input, select, textarea):is(button, [type=submit], [type=button], [type=reset], [role=button])::before {
+ filter: brightness(0) invert(1);
+}
+
+/**
+ * Color schemes
+ */
+[data-theme=light],
+:root:not([data-theme=dark]) {
+ --pico-background-color: #fff;
+ --pico-color: #373c44;
+ --pico-text-selection-color: rgba(2, 154, 232, 0.25);
+ --pico-muted-color: #646b79;
+ --pico-muted-border-color: #e7eaf0;
+ --pico-primary: #0172ad;
+ --pico-primary-background: #0172ad;
+ --pico-primary-border: var(--pico-primary-background);
+ --pico-primary-underline: rgba(1, 114, 173, 0.5);
+ --pico-primary-hover: #015887;
+ --pico-primary-hover-background: #02659a;
+ --pico-primary-hover-border: var(--pico-primary-hover-background);
+ --pico-primary-hover-underline: var(--pico-primary-hover);
+ --pico-primary-focus: rgba(2, 154, 232, 0.5);
+ --pico-primary-inverse: #fff;
+ --pico-secondary: #5d6b89;
+ --pico-secondary-background: #525f7a;
+ --pico-secondary-border: var(--pico-secondary-background);
+ --pico-secondary-underline: rgba(93, 107, 137, 0.5);
+ --pico-secondary-hover: #48536b;
+ --pico-secondary-hover-background: #48536b;
+ --pico-secondary-hover-border: var(--pico-secondary-hover-background);
+ --pico-secondary-hover-underline: var(--pico-secondary-hover);
+ --pico-secondary-focus: rgba(93, 107, 137, 0.25);
+ --pico-secondary-inverse: #fff;
+ --pico-contrast: #181c25;
+ --pico-contrast-background: #181c25;
+ --pico-contrast-border: var(--pico-contrast-background);
+ --pico-contrast-underline: rgba(24, 28, 37, 0.5);
+ --pico-contrast-hover: #000;
+ --pico-contrast-hover-background: #000;
+ --pico-contrast-hover-border: var(--pico-contrast-hover-background);
+ --pico-contrast-hover-underline: var(--pico-secondary-hover);
+ --pico-contrast-focus: rgba(93, 107, 137, 0.25);
+ --pico-contrast-inverse: #fff;
+ --pico-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(129, 145, 181, 0.01698), 0.0335rem 0.067rem 0.402rem rgba(129, 145, 181, 0.024), 0.0625rem 0.125rem 0.75rem rgba(129, 145, 181, 0.03), 0.1125rem 0.225rem 1.35rem rgba(129, 145, 181, 0.036), 0.2085rem 0.417rem 2.502rem rgba(129, 145, 181, 0.04302), 0.5rem 1rem 6rem rgba(129, 145, 181, 0.06), 0 0 0 0.0625rem rgba(129, 145, 181, 0.015);
+ --pico-h1-color: #2d3138;
+ --pico-h2-color: #373c44;
+ --pico-h3-color: #424751;
+ --pico-h4-color: #4d535e;
+ --pico-h5-color: #5c6370;
+ --pico-h6-color: #646b79;
+ --pico-mark-background-color: #fde7c0;
+ --pico-mark-color: #0f1114;
+ --pico-blockquote-border-color: var(--pico-muted-border-color);
+ --pico-blockquote-footer-color: var(--pico-muted-color);
+ --pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --pico-table-border-color: var(--pico-muted-border-color);
+ --pico-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375);
+ --pico-code-background-color: #f3f5f7;
+ --pico-code-color: #646b79;
+ --pico-code-kbd-background-color: var(--pico-color);
+ --pico-code-kbd-color: var(--pico-background-color);
+ --pico-form-element-background-color: #fbfcfc;
+ --pico-form-element-selected-background-color: #dfe3eb;
+ --pico-form-element-border-color: #cfd5e2;
+ --pico-form-element-color: #23262c;
+ --pico-form-element-placeholder-color: var(--pico-muted-color);
+ --pico-form-element-active-background-color: #fff;
+ --pico-form-element-active-border-color: var(--pico-primary-border);
+ --pico-form-element-focus-color: var(--pico-primary-border);
+ --pico-form-element-disabled-opacity: 0.5;
+ --pico-form-element-invalid-border-color: #b86a6b;
+ --pico-form-element-invalid-active-border-color: #c84f48;
+ --pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);
+ --pico-form-element-valid-border-color: #4c9b8a;
+ --pico-form-element-valid-active-border-color: #279977;
+ --pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);
+ --pico-switch-background-color: #bfc7d9;
+ --pico-switch-checked-background-color: var(--pico-primary-background);
+ --pico-switch-color: #fff;
+ --pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --pico-range-border-color: #dfe3eb;
+ --pico-range-active-border-color: #bfc7d9;
+ --pico-range-thumb-border-color: var(--pico-background-color);
+ --pico-range-thumb-color: var(--pico-secondary-background);
+ --pico-range-thumb-active-color: var(--pico-primary-background);
+ --pico-accordion-border-color: var(--pico-muted-border-color);
+ --pico-accordion-active-summary-color: var(--pico-primary-hover);
+ --pico-accordion-close-summary-color: var(--pico-color);
+ --pico-accordion-open-summary-color: var(--pico-muted-color);
+ --pico-card-background-color: var(--pico-background-color);
+ --pico-card-border-color: var(--pico-muted-border-color);
+ --pico-card-box-shadow: var(--pico-box-shadow);
+ --pico-card-sectioning-background-color: #fbfcfc;
+ --pico-loading-spinner-opacity: 0.5;
+ --pico-modal-overlay-background-color: rgba(232, 234, 237, 0.75);
+ --pico-progress-background-color: #dfe3eb;
+ --pico-progress-color: var(--pico-primary-background);
+ --pico-tooltip-background-color: var(--pico-contrast-background);
+ --pico-tooltip-color: var(--pico-contrast-inverse);
+ --pico-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(76, 155, 138)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ --pico-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(200, 79, 72)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
+ color-scheme: light;
+}
+[data-theme=light] input:is([type=submit],
+[type=button],
+[type=reset],
+[type=checkbox],
+[type=radio],
+[type=file]),
+:root:not([data-theme=dark]) input:is([type=submit],
+[type=button],
+[type=reset],
+[type=checkbox],
+[type=radio],
+[type=file]) {
+ --pico-form-element-focus-color: var(--pico-primary-focus);
+}
+
+@media only screen and (prefers-color-scheme: dark) {
+ :root:not([data-theme]) {
+ --pico-background-color: #13171f;
+ --pico-color: #c2c7d0;
+ --pico-text-selection-color: rgba(1, 170, 255, 0.1875);
+ --pico-muted-color: #7b8495;
+ --pico-muted-border-color: #202632;
+ --pico-primary: #01aaff;
+ --pico-primary-background: #0172ad;
+ --pico-primary-border: var(--pico-primary-background);
+ --pico-primary-underline: rgba(1, 170, 255, 0.5);
+ --pico-primary-hover: #79c0ff;
+ --pico-primary-hover-background: #017fc0;
+ --pico-primary-hover-border: var(--pico-primary-hover-background);
+ --pico-primary-hover-underline: var(--pico-primary-hover);
+ --pico-primary-focus: rgba(1, 170, 255, 0.375);
+ --pico-primary-inverse: #fff;
+ --pico-secondary: #969eaf;
+ --pico-secondary-background: #525f7a;
+ --pico-secondary-border: var(--pico-secondary-background);
+ --pico-secondary-underline: rgba(150, 158, 175, 0.5);
+ --pico-secondary-hover: #b3b9c5;
+ --pico-secondary-hover-background: #5d6b89;
+ --pico-secondary-hover-border: var(--pico-secondary-hover-background);
+ --pico-secondary-hover-underline: var(--pico-secondary-hover);
+ --pico-secondary-focus: rgba(144, 158, 190, 0.25);
+ --pico-secondary-inverse: #fff;
+ --pico-contrast: #dfe3eb;
+ --pico-contrast-background: #eff1f4;
+ --pico-contrast-border: var(--pico-contrast-background);
+ --pico-contrast-underline: rgba(223, 227, 235, 0.5);
+ --pico-contrast-hover: #fff;
+ --pico-contrast-hover-background: #fff;
+ --pico-contrast-hover-border: var(--pico-contrast-hover-background);
+ --pico-contrast-hover-underline: var(--pico-contrast-hover);
+ --pico-contrast-focus: rgba(207, 213, 226, 0.25);
+ --pico-contrast-inverse: #000;
+ --pico-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(7, 9, 12, 0.01698), 0.0335rem 0.067rem 0.402rem rgba(7, 9, 12, 0.024), 0.0625rem 0.125rem 0.75rem rgba(7, 9, 12, 0.03), 0.1125rem 0.225rem 1.35rem rgba(7, 9, 12, 0.036), 0.2085rem 0.417rem 2.502rem rgba(7, 9, 12, 0.04302), 0.5rem 1rem 6rem rgba(7, 9, 12, 0.06), 0 0 0 0.0625rem rgba(7, 9, 12, 0.015);
+ --pico-h1-color: #f0f1f3;
+ --pico-h2-color: #e0e3e7;
+ --pico-h3-color: #c2c7d0;
+ --pico-h4-color: #b3b9c5;
+ --pico-h5-color: #a4acba;
+ --pico-h6-color: #8891a4;
+ --pico-mark-background-color: #014063;
+ --pico-mark-color: #fff;
+ --pico-blockquote-border-color: var(--pico-muted-border-color);
+ --pico-blockquote-footer-color: var(--pico-muted-color);
+ --pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --pico-table-border-color: var(--pico-muted-border-color);
+ --pico-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375);
+ --pico-code-background-color: #1a1f28;
+ --pico-code-color: #8891a4;
+ --pico-code-kbd-background-color: var(--pico-color);
+ --pico-code-kbd-color: var(--pico-background-color);
+ --pico-form-element-background-color: #1c212c;
+ --pico-form-element-selected-background-color: #2a3140;
+ --pico-form-element-border-color: #2a3140;
+ --pico-form-element-color: #e0e3e7;
+ --pico-form-element-placeholder-color: #8891a4;
+ --pico-form-element-active-background-color: #1a1f28;
+ --pico-form-element-active-border-color: var(--pico-primary-border);
+ --pico-form-element-focus-color: var(--pico-primary-border);
+ --pico-form-element-disabled-opacity: 0.5;
+ --pico-form-element-invalid-border-color: #964a50;
+ --pico-form-element-invalid-active-border-color: #b7403b;
+ --pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);
+ --pico-form-element-valid-border-color: #2a7b6f;
+ --pico-form-element-valid-active-border-color: #16896a;
+ --pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);
+ --pico-switch-background-color: #333c4e;
+ --pico-switch-checked-background-color: var(--pico-primary-background);
+ --pico-switch-color: #fff;
+ --pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --pico-range-border-color: #202632;
+ --pico-range-active-border-color: #2a3140;
+ --pico-range-thumb-border-color: var(--pico-background-color);
+ --pico-range-thumb-color: var(--pico-secondary-background);
+ --pico-range-thumb-active-color: var(--pico-primary-background);
+ --pico-accordion-border-color: var(--pico-muted-border-color);
+ --pico-accordion-active-summary-color: var(--pico-primary-hover);
+ --pico-accordion-close-summary-color: var(--pico-color);
+ --pico-accordion-open-summary-color: var(--pico-muted-color);
+ --pico-card-background-color: #181c25;
+ --pico-card-border-color: var(--pico-card-background-color);
+ --pico-card-box-shadow: var(--pico-box-shadow);
+ --pico-card-sectioning-background-color: #1a1f28;
+ --pico-loading-spinner-opacity: 0.5;
+ --pico-modal-overlay-background-color: rgba(8, 9, 10, 0.75);
+ --pico-progress-background-color: #202632;
+ --pico-progress-color: var(--pico-primary-background);
+ --pico-tooltip-background-color: var(--pico-contrast-background);
+ --pico-tooltip-color: var(--pico-contrast-inverse);
+ --pico-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ --pico-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(150, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
+ color-scheme: dark;
+ }
+ :root:not([data-theme]) input:is([type=submit],
+ [type=button],
+ [type=reset],
+ [type=checkbox],
+ [type=radio],
+ [type=file]) {
+ --pico-form-element-focus-color: var(--pico-primary-focus);
+ }
+}
+[data-theme=dark] {
+ --pico-background-color: #13171f;
+ --pico-color: #c2c7d0;
+ --pico-text-selection-color: rgba(1, 170, 255, 0.1875);
+ --pico-muted-color: #7b8495;
+ --pico-muted-border-color: #202632;
+ --pico-primary: #01aaff;
+ --pico-primary-background: #0172ad;
+ --pico-primary-border: var(--pico-primary-background);
+ --pico-primary-underline: rgba(1, 170, 255, 0.5);
+ --pico-primary-hover: #79c0ff;
+ --pico-primary-hover-background: #017fc0;
+ --pico-primary-hover-border: var(--pico-primary-hover-background);
+ --pico-primary-hover-underline: var(--pico-primary-hover);
+ --pico-primary-focus: rgba(1, 170, 255, 0.375);
+ --pico-primary-inverse: #fff;
+ --pico-secondary: #969eaf;
+ --pico-secondary-background: #525f7a;
+ --pico-secondary-border: var(--pico-secondary-background);
+ --pico-secondary-underline: rgba(150, 158, 175, 0.5);
+ --pico-secondary-hover: #b3b9c5;
+ --pico-secondary-hover-background: #5d6b89;
+ --pico-secondary-hover-border: var(--pico-secondary-hover-background);
+ --pico-secondary-hover-underline: var(--pico-secondary-hover);
+ --pico-secondary-focus: rgba(144, 158, 190, 0.25);
+ --pico-secondary-inverse: #fff;
+ --pico-contrast: #dfe3eb;
+ --pico-contrast-background: #eff1f4;
+ --pico-contrast-border: var(--pico-contrast-background);
+ --pico-contrast-underline: rgba(223, 227, 235, 0.5);
+ --pico-contrast-hover: #fff;
+ --pico-contrast-hover-background: #fff;
+ --pico-contrast-hover-border: var(--pico-contrast-hover-background);
+ --pico-contrast-hover-underline: var(--pico-contrast-hover);
+ --pico-contrast-focus: rgba(207, 213, 226, 0.25);
+ --pico-contrast-inverse: #000;
+ --pico-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(7, 9, 12, 0.01698), 0.0335rem 0.067rem 0.402rem rgba(7, 9, 12, 0.024), 0.0625rem 0.125rem 0.75rem rgba(7, 9, 12, 0.03), 0.1125rem 0.225rem 1.35rem rgba(7, 9, 12, 0.036), 0.2085rem 0.417rem 2.502rem rgba(7, 9, 12, 0.04302), 0.5rem 1rem 6rem rgba(7, 9, 12, 0.06), 0 0 0 0.0625rem rgba(7, 9, 12, 0.015);
+ --pico-h1-color: #f0f1f3;
+ --pico-h2-color: #e0e3e7;
+ --pico-h3-color: #c2c7d0;
+ --pico-h4-color: #b3b9c5;
+ --pico-h5-color: #a4acba;
+ --pico-h6-color: #8891a4;
+ --pico-mark-background-color: #014063;
+ --pico-mark-color: #fff;
+ --pico-blockquote-border-color: var(--pico-muted-border-color);
+ --pico-blockquote-footer-color: var(--pico-muted-color);
+ --pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --pico-table-border-color: var(--pico-muted-border-color);
+ --pico-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375);
+ --pico-code-background-color: #1a1f28;
+ --pico-code-color: #8891a4;
+ --pico-code-kbd-background-color: var(--pico-color);
+ --pico-code-kbd-color: var(--pico-background-color);
+ --pico-form-element-background-color: #1c212c;
+ --pico-form-element-selected-background-color: #2a3140;
+ --pico-form-element-border-color: #2a3140;
+ --pico-form-element-color: #e0e3e7;
+ --pico-form-element-placeholder-color: #8891a4;
+ --pico-form-element-active-background-color: #1a1f28;
+ --pico-form-element-active-border-color: var(--pico-primary-border);
+ --pico-form-element-focus-color: var(--pico-primary-border);
+ --pico-form-element-disabled-opacity: 0.5;
+ --pico-form-element-invalid-border-color: #964a50;
+ --pico-form-element-invalid-active-border-color: #b7403b;
+ --pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);
+ --pico-form-element-valid-border-color: #2a7b6f;
+ --pico-form-element-valid-active-border-color: #16896a;
+ --pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);
+ --pico-switch-background-color: #333c4e;
+ --pico-switch-checked-background-color: var(--pico-primary-background);
+ --pico-switch-color: #fff;
+ --pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --pico-range-border-color: #202632;
+ --pico-range-active-border-color: #2a3140;
+ --pico-range-thumb-border-color: var(--pico-background-color);
+ --pico-range-thumb-color: var(--pico-secondary-background);
+ --pico-range-thumb-active-color: var(--pico-primary-background);
+ --pico-accordion-border-color: var(--pico-muted-border-color);
+ --pico-accordion-active-summary-color: var(--pico-primary-hover);
+ --pico-accordion-close-summary-color: var(--pico-color);
+ --pico-accordion-open-summary-color: var(--pico-muted-color);
+ --pico-card-background-color: #181c25;
+ --pico-card-border-color: var(--pico-card-background-color);
+ --pico-card-box-shadow: var(--pico-box-shadow);
+ --pico-card-sectioning-background-color: #1a1f28;
+ --pico-loading-spinner-opacity: 0.5;
+ --pico-modal-overlay-background-color: rgba(8, 9, 10, 0.75);
+ --pico-progress-background-color: #202632;
+ --pico-progress-color: var(--pico-primary-background);
+ --pico-tooltip-background-color: var(--pico-contrast-background);
+ --pico-tooltip-color: var(--pico-contrast-inverse);
+ --pico-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ --pico-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(150, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
+ color-scheme: dark;
+}
+[data-theme=dark] input:is([type=submit],
+[type=button],
+[type=reset],
+[type=checkbox],
+[type=radio],
+[type=file]) {
+ --pico-form-element-focus-color: var(--pico-primary-focus);
+}
+
+progress,
+[type=checkbox],
+[type=radio],
+[type=range] {
+ accent-color: var(--pico-primary);
+}
+
+/**
+ * Document
+ * Content-box & Responsive typography
+ */
+*,
+ *::before,
+ *::after {
+ box-sizing: border-box;
+ background-repeat: no-repeat;
+ }
+
+ ::before,
+ ::after {
+ text-decoration: inherit;
+ vertical-align: inherit;
+ }
+
+ :where(:root) {
+ -webkit-tap-highlight-color: transparent;
+ -webkit-text-size-adjust: 100%;
+ -moz-text-size-adjust: 100%;
+ text-size-adjust: 100%;
+ background-color: var(--pico-background-color);
+ color: var(--pico-color);
+ font-weight: var(--pico-font-weight);
+ font-size: var(--pico-font-size);
+ line-height: var(--pico-line-height);
+ text-underline-offset: var(--pico-text-underline-offset);
+ text-rendering: optimizeLegibility;
+ overflow-wrap: break-word;
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+ }
+
+ /**
+ * Landmarks
+ */
+body {
+ width: 100%;
+ margin: 0;
+}
+
+main {
+ display: block;
+}
+
+body > header,
+body > main,
+body > footer {
+ width: 100%;
+ margin-right: auto;
+ margin-left: auto;
+ padding: var(--pico-block-spacing-vertical) var(--pico-block-spacing-horizontal);
+}
+@media (min-width: 576px) {
+ body > header,
+ body > main,
+ body > footer {
+ max-width: 510px;
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+@media (min-width: 768px) {
+ body > header,
+ body > main,
+ body > footer {
+ max-width: 700px;
+ }
+}
+@media (min-width: 1024px) {
+ body > header,
+ body > main,
+ body > footer {
+ max-width: 950px;
+ }
+}
+@media (min-width: 1200px) {
+ body > header,
+ body > main,
+ body > footer {
+ max-width: 1130px;
+ }
+}
+
+/**
+ * Section
+ */
+section {
+ margin-bottom: var(--pico-block-spacing-vertical);
+}
+
+/**
+ * Typography
+ */
+b,
+strong {
+ font-weight: bolder;
+}
+
+sub,
+sup {
+ position: relative;
+ font-size: 0.75em;
+ line-height: 0;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+address,
+blockquote,
+dl,
+ol,
+p,
+pre,
+table,
+ul {
+ margin-top: 0;
+ margin-bottom: var(--pico-typography-spacing-vertical);
+ color: var(--pico-color);
+ font-style: normal;
+ font-weight: var(--pico-font-weight);
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ margin-top: 0;
+ margin-bottom: var(--pico-typography-spacing-vertical);
+ color: var(--pico-color);
+ font-weight: var(--pico-font-weight);
+ font-size: var(--pico-font-size);
+ line-height: var(--pico-line-height);
+}
+
+h1 {
+ --pico-color: var(--pico-h1-color);
+}
+
+h2 {
+ --pico-color: var(--pico-h2-color);
+}
+
+h3 {
+ --pico-color: var(--pico-h3-color);
+}
+
+h4 {
+ --pico-color: var(--pico-h4-color);
+}
+
+h5 {
+ --pico-color: var(--pico-h5-color);
+}
+
+h6 {
+ --pico-color: var(--pico-h6-color);
+}
+
+:where(article, address, blockquote, dl, figure, form, ol, p, pre, table, ul) ~ :is(h1, h2, h3, h4, h5, h6) {
+ margin-top: var(--pico-typography-spacing-top);
+}
+
+p {
+ margin-bottom: var(--pico-typography-spacing-vertical);
+}
+
+hgroup {
+ margin-bottom: var(--pico-typography-spacing-vertical);
+}
+hgroup > * {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+hgroup > *:not(:first-child):last-child {
+ --pico-color: var(--pico-muted-color);
+ --pico-font-weight: unset;
+ font-size: 1rem;
+}
+
+:where(ol, ul) li {
+ margin-bottom: calc(var(--pico-typography-spacing-vertical) * 0.25);
+}
+
+:where(dl, ol, ul) :where(dl, ol, ul) {
+ margin: 0;
+ margin-top: calc(var(--pico-typography-spacing-vertical) * 0.25);
+}
+
+ul li {
+ list-style: square;
+}
+
+mark {
+ padding: 0.125rem 0.25rem;
+ background-color: var(--pico-mark-background-color);
+ color: var(--pico-mark-color);
+ vertical-align: baseline;
+}
+
+blockquote {
+ display: block;
+ margin: var(--pico-typography-spacing-vertical) 0;
+ padding: var(--pico-spacing);
+ border-right: none;
+ border-left: 0.25rem solid var(--pico-blockquote-border-color);
+ border-inline-start: 0.25rem solid var(--pico-blockquote-border-color);
+ border-inline-end: none;
+}
+blockquote footer {
+ margin-top: calc(var(--pico-typography-spacing-vertical) * 0.5);
+ color: var(--pico-blockquote-footer-color);
+}
+
+abbr[title] {
+ border-bottom: 1px dotted;
+ text-decoration: none;
+ cursor: help;
+}
+
+ins {
+ color: green;
+ text-decoration: none;
+}
+
+del {
+ color: red;
+}
+
+::-moz-selection {
+ background-color: var(--pico-text-selection-color);
+}
+
+::selection {
+ background-color: var(--pico-text-selection-color);
+}
+
+/**
+ * Link
+ */
+:where(a:not([role=button])),
+[role=link] {
+ --pico-color: var(--pico-primary);
+ --pico-background-color: transparent;
+ --pico-underline: var(--pico-primary-underline);
+ outline: none;
+ background-color: var(--pico-background-color);
+ color: var(--pico-color);
+ -webkit-text-decoration: var(--pico-text-decoration);
+ text-decoration: var(--pico-text-decoration);
+ text-decoration-color: var(--pico-underline);
+ text-underline-offset: 0.125em;
+ transition: background-color var(--pico-transition), color var(--pico-transition), box-shadow var(--pico-transition), -webkit-text-decoration var(--pico-transition);
+ transition: background-color var(--pico-transition), color var(--pico-transition), text-decoration var(--pico-transition), box-shadow var(--pico-transition);
+ transition: background-color var(--pico-transition), color var(--pico-transition), text-decoration var(--pico-transition), box-shadow var(--pico-transition), -webkit-text-decoration var(--pico-transition);
+}
+:where(a:not([role=button])):is([aria-current]:not([aria-current=false]), :hover, :active, :focus),
+[role=link]:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
+ --pico-color: var(--pico-primary-hover);
+ --pico-underline: var(--pico-primary-hover-underline);
+ --pico-text-decoration: underline;
+}
+:where(a:not([role=button])):focus-visible,
+[role=link]:focus-visible {
+ box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);
+}
+
+a[role=button] {
+ display: inline-block;
+}
+
+/**
+ * Button
+ */
+button {
+ margin: 0;
+ overflow: visible;
+ text-transform: none;
+}
+
+button,
+[type=submit],
+[type=reset],
+[type=button] {
+ -webkit-appearance: button;
+}
+
+button,
+[type=submit],
+[type=reset],
+[type=button],
+[type=file]::file-selector-button,
+[role=button] {
+ --pico-background-color: var(--pico-primary-background);
+ --pico-border-color: var(--pico-primary-border);
+ --pico-color: var(--pico-primary-inverse);
+ --pico-box-shadow: var(--pico-button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
+ padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);
+ border: var(--pico-border-width) solid var(--pico-border-color);
+ border-radius: var(--pico-border-radius);
+ outline: none;
+ background-color: var(--pico-background-color);
+ box-shadow: var(--pico-box-shadow);
+ color: var(--pico-color);
+ font-weight: var(--pico-font-weight);
+ font-size: 1rem;
+ line-height: var(--pico-line-height);
+ text-align: center;
+ text-decoration: none;
+ cursor: pointer;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+ transition: background-color var(--pico-transition), border-color var(--pico-transition), color var(--pico-transition), box-shadow var(--pico-transition);
+}
+button:is([aria-current]:not([aria-current=false])), button:is(:hover, :active, :focus),
+[type=submit]:is([aria-current]:not([aria-current=false])),
+[type=submit]:is(:hover, :active, :focus),
+[type=reset]:is([aria-current]:not([aria-current=false])),
+[type=reset]:is(:hover, :active, :focus),
+[type=button]:is([aria-current]:not([aria-current=false])),
+[type=button]:is(:hover, :active, :focus),
+[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])),
+[type=file]::file-selector-button:is(:hover, :active, :focus),
+[role=button]:is([aria-current]:not([aria-current=false])),
+[role=button]:is(:hover, :active, :focus) {
+ --pico-background-color: var(--pico-primary-hover-background);
+ --pico-border-color: var(--pico-primary-hover-border);
+ --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
+ --pico-color: var(--pico-primary-inverse);
+}
+button:focus, button:is([aria-current]:not([aria-current=false])):focus,
+[type=submit]:focus,
+[type=submit]:is([aria-current]:not([aria-current=false])):focus,
+[type=reset]:focus,
+[type=reset]:is([aria-current]:not([aria-current=false])):focus,
+[type=button]:focus,
+[type=button]:is([aria-current]:not([aria-current=false])):focus,
+[type=file]::file-selector-button:focus,
+[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])):focus,
+[role=button]:focus,
+[role=button]:is([aria-current]:not([aria-current=false])):focus {
+ --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);
+}
+
+[type=submit],
+[type=reset],
+[type=button] {
+ margin-bottom: var(--pico-spacing);
+}
+
+[type=reset],
+[type=file]::file-selector-button {
+ --pico-background-color: var(--pico-secondary-background);
+ --pico-border-color: var(--pico-secondary-border);
+ --pico-color: var(--pico-secondary-inverse);
+ cursor: pointer;
+}
+[type=reset]:is([aria-current]:not([aria-current=false]), :hover, :active, :focus),
+[type=file]::file-selector-button:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
+ --pico-background-color: var(--pico-secondary-hover-background);
+ --pico-border-color: var(--pico-secondary-hover-border);
+ --pico-color: var(--pico-secondary-inverse);
+}
+[type=reset]:focus,
+[type=file]::file-selector-button:focus {
+ --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus);
+}
+
+:where(button, [type=submit], [type=reset], [type=button], [role=button])[disabled],
+:where(fieldset[disabled]) :is(button, [type=submit], [type=button], [type=reset], [role=button]) {
+ opacity: 0.5;
+ pointer-events: none;
+}
+
+/**
+ * Table
+ */
+:where(table) {
+ width: 100%;
+ border-collapse: collapse;
+ border-spacing: 0;
+ text-indent: 0;
+}
+
+th,
+td {
+ padding: calc(var(--pico-spacing) / 2) var(--pico-spacing);
+ border-bottom: var(--pico-border-width) solid var(--pico-table-border-color);
+ background-color: var(--pico-background-color);
+ color: var(--pico-color);
+ font-weight: var(--pico-font-weight);
+ text-align: left;
+ text-align: start;
+}
+
+tfoot th,
+tfoot td {
+ border-top: var(--pico-border-width) solid var(--pico-table-border-color);
+ border-bottom: 0;
+}
+
+table.striped tbody tr:nth-child(odd) th,
+table.striped tbody tr:nth-child(odd) td {
+ background-color: var(--pico-table-row-stripped-background-color);
+}
+
+/**
+ * Embedded content
+ */
+:where(audio, canvas, iframe, img, svg, video) {
+ vertical-align: middle;
+}
+
+audio,
+video {
+ display: inline-block;
+}
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+:where(iframe) {
+ border-style: none;
+}
+
+img {
+ max-width: 100%;
+ height: auto;
+ border-style: none;
+}
+
+:where(svg:not([fill])) {
+ fill: currentColor;
+}
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/**
+ * Code
+ */
+pre,
+code,
+kbd,
+samp {
+ font-size: 0.875em;
+}
+
+pre code {
+ font-size: inherit;
+}
+
+pre {
+ -ms-overflow-style: scrollbar;
+ overflow: auto;
+}
+
+pre,
+code,
+kbd {
+ border-radius: var(--pico-border-radius);
+ background: var(--pico-code-background-color);
+ color: var(--pico-code-color);
+ font-weight: var(--pico-font-weight);
+ line-height: initial;
+}
+
+code,
+kbd {
+ display: inline-block;
+ padding: 0.375rem;
+}
+
+pre {
+ display: block;
+ margin-bottom: var(--pico-spacing);
+ overflow-x: auto;
+}
+pre > code {
+ display: block;
+ padding: var(--pico-spacing);
+ background: none;
+ line-height: var(--pico-line-height);
+}
+
+kbd {
+ background-color: var(--pico-code-kbd-background-color);
+ color: var(--pico-code-kbd-color);
+ vertical-align: baseline;
+}
+
+/**
+ * Figure
+ */
+figure {
+ display: block;
+ margin: 0;
+ padding: 0;
+}
+figure figcaption {
+ padding: calc(var(--pico-spacing) * 0.5) 0;
+ color: var(--pico-muted-color);
+}
+
+/**
+ * Miscs
+ */
+hr {
+ height: 0;
+ margin: var(--pico-typography-spacing-vertical) 0;
+ border: 0;
+ border-top: 1px solid var(--pico-muted-border-color);
+ color: inherit;
+}
+
+[hidden],
+template {
+ display: none !important;
+}
+
+canvas {
+ display: inline-block;
+}
+
+/**
+ * Basics form elements
+ */
+input,
+optgroup,
+select,
+textarea {
+ margin: 0;
+ font-size: 1rem;
+ line-height: var(--pico-line-height);
+ letter-spacing: inherit;
+}
+
+input {
+ overflow: visible;
+}
+
+select {
+ text-transform: none;
+}
+
+legend {
+ max-width: 100%;
+ padding: 0;
+ color: inherit;
+ white-space: normal;
+}
+
+textarea {
+ overflow: auto;
+}
+
+[type=checkbox],
+[type=radio] {
+ padding: 0;
+}
+
+::-webkit-inner-spin-button,
+::-webkit-outer-spin-button {
+ height: auto;
+}
+
+[type=search] {
+ -webkit-appearance: textfield;
+ outline-offset: -2px;
+}
+
+[type=search]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button;
+ font: inherit;
+}
+
+::-moz-focus-inner {
+ padding: 0;
+ border-style: none;
+}
+
+:-moz-focusring {
+ outline: none;
+}
+
+:-moz-ui-invalid {
+ box-shadow: none;
+}
+
+::-ms-expand {
+ display: none;
+}
+
+[type=file],
+[type=range] {
+ padding: 0;
+ border-width: 0;
+}
+
+input:not([type=checkbox], [type=radio], [type=range]) {
+ height: calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2);
+}
+
+fieldset {
+ width: 100%;
+ margin: 0;
+ margin-bottom: var(--pico-spacing);
+ padding: 0;
+ border: 0;
+}
+
+label,
+fieldset legend {
+ display: block;
+ margin-bottom: calc(var(--pico-spacing) * 0.375);
+ color: var(--pico-color);
+ font-weight: var(--pico-form-label-font-weight, var(--pico-font-weight));
+}
+
+fieldset legend {
+ margin-bottom: calc(var(--pico-spacing) * 0.5);
+}
+
+input:not([type=checkbox], [type=radio]),
+button[type=submit],
+select,
+textarea {
+ width: 100%;
+}
+
+input:not([type=checkbox], [type=radio], [type=range], [type=file]),
+select,
+textarea {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);
+}
+
+input,
+select,
+textarea {
+ --pico-background-color: var(--pico-form-element-background-color);
+ --pico-border-color: var(--pico-form-element-border-color);
+ --pico-color: var(--pico-form-element-color);
+ --pico-box-shadow: none;
+ border: var(--pico-border-width) solid var(--pico-border-color);
+ border-radius: var(--pico-border-radius);
+ outline: none;
+ background-color: var(--pico-background-color);
+ box-shadow: var(--pico-box-shadow);
+ color: var(--pico-color);
+ font-weight: var(--pico-font-weight);
+ transition: background-color var(--pico-transition), border-color var(--pico-transition), color var(--pico-transition), box-shadow var(--pico-transition);
+}
+
+input:not([type=submit],
+[type=button],
+[type=reset],
+[type=checkbox],
+[type=radio],
+[readonly]):is(:active, :focus),
+:where(select, textarea):not([readonly]):is(:active, :focus) {
+ --pico-background-color: var(--pico-form-element-active-background-color);
+}
+
+input:not([type=submit], [type=button], [type=reset], [role=switch], [readonly]):is(:active, :focus),
+:where(select, textarea):not([readonly]):is(:active, :focus) {
+ --pico-border-color: var(--pico-form-element-active-border-color);
+}
+
+input:not([type=submit],
+[type=button],
+[type=reset],
+[type=range],
+[type=file],
+[readonly]):focus,
+:where(select, textarea):not([readonly]):focus {
+ --pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-focus-color);
+}
+
+input:not([type=submit], [type=button], [type=reset])[disabled],
+select[disabled],
+textarea[disabled],
+label[aria-disabled=true],
+:where(fieldset[disabled]) :is(input:not([type=submit], [type=button], [type=reset]), select, textarea) {
+ opacity: var(--pico-form-element-disabled-opacity);
+ pointer-events: none;
+}
+
+label[aria-disabled=true] input[disabled] {
+ opacity: 1;
+}
+
+:where(input, select, textarea):not([type=checkbox],
+[type=radio],
+[type=date],
+[type=datetime-local],
+[type=month],
+[type=time],
+[type=week],
+[type=range])[aria-invalid] {
+ padding-right: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem) !important;
+ padding-left: var(--pico-form-element-spacing-horizontal);
+ padding-inline-start: var(--pico-form-element-spacing-horizontal) !important;
+ padding-inline-end: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem) !important;
+ background-position: center right 0.75rem;
+ background-size: 1rem auto;
+ background-repeat: no-repeat;
+}
+:where(input, select, textarea):not([type=checkbox],
+[type=radio],
+[type=date],
+[type=datetime-local],
+[type=month],
+[type=time],
+[type=week],
+[type=range])[aria-invalid=false]:not(select) {
+ background-image: var(--pico-icon-valid);
+}
+:where(input, select, textarea):not([type=checkbox],
+[type=radio],
+[type=date],
+[type=datetime-local],
+[type=month],
+[type=time],
+[type=week],
+[type=range])[aria-invalid=true]:not(select) {
+ background-image: var(--pico-icon-invalid);
+}
+:where(input, select, textarea)[aria-invalid=false] {
+ --pico-border-color: var(--pico-form-element-valid-border-color);
+}
+:where(input, select, textarea)[aria-invalid=false]:is(:active, :focus) {
+ --pico-border-color: var(--pico-form-element-valid-active-border-color) !important;
+}
+:where(input, select, textarea)[aria-invalid=false]:is(:active, :focus):not([type=checkbox], [type=radio]) {
+ --pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-valid-focus-color) !important;
+}
+:where(input, select, textarea)[aria-invalid=true] {
+ --pico-border-color: var(--pico-form-element-invalid-border-color);
+}
+:where(input, select, textarea)[aria-invalid=true]:is(:active, :focus) {
+ --pico-border-color: var(--pico-form-element-invalid-active-border-color) !important;
+}
+:where(input, select, textarea)[aria-invalid=true]:is(:active, :focus):not([type=checkbox], [type=radio]) {
+ --pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-invalid-focus-color) !important;
+}
+
+[dir=rtl] :where(input, select, textarea):not([type=checkbox], [type=radio]):is([aria-invalid], [aria-invalid=true], [aria-invalid=false]) {
+ background-position: center left 0.75rem;
+}
+
+input::placeholder,
+input::-webkit-input-placeholder,
+textarea::placeholder,
+textarea::-webkit-input-placeholder,
+select:invalid {
+ color: var(--pico-form-element-placeholder-color);
+ opacity: 1;
+}
+
+input:not([type=checkbox], [type=radio]),
+select,
+textarea {
+ margin-bottom: var(--pico-spacing);
+}
+
+select::-ms-expand {
+ border: 0;
+ background-color: transparent;
+}
+select:not([multiple], [size]) {
+ padding-right: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem);
+ padding-left: var(--pico-form-element-spacing-horizontal);
+ padding-inline-start: var(--pico-form-element-spacing-horizontal);
+ padding-inline-end: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem);
+ background-image: var(--pico-icon-chevron);
+ background-position: center right 0.75rem;
+ background-size: 1rem auto;
+ background-repeat: no-repeat;
+}
+select[multiple] option:checked {
+ background: var(--pico-form-element-selected-background-color);
+ color: var(--pico-form-element-color);
+}
+
+[dir=rtl] select:not([multiple], [size]) {
+ background-position: center left 0.75rem;
+}
+
+textarea {
+ display: block;
+ resize: vertical;
+}
+textarea[aria-invalid] {
+ --pico-icon-height: calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2);
+ background-position: top right 0.75rem !important;
+ background-size: 1rem var(--pico-icon-height) !important;
+}
+
+:where(input, select, textarea, fieldset) + small {
+ display: block;
+ width: 100%;
+ margin-top: calc(var(--pico-spacing) * -0.75);
+ margin-bottom: var(--pico-spacing);
+ color: var(--pico-muted-color);
+}
+:where(input, select, textarea, fieldset)[aria-invalid=false] + small {
+ color: green;
+}
+:where(input, select, textarea, fieldset)[aria-invalid=true] + small {
+ color: red;
+}
+
+label > :where(input, select, textarea) {
+ margin-top: calc(var(--pico-spacing) * 0.25);
+}
+
+/**
+ * Checkboxes, Radios and Switches
+ */
+label:has([type=checkbox], [type=radio]) {
+ width: -moz-fit-content;
+ width: fit-content;
+ cursor: pointer;
+}
+
+[type=checkbox],
+[type=radio] {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ width: 1.25em;
+ height: 1.25em;
+ margin-top: -0.125em;
+ margin-inline-end: 0.5em;
+ border-width: var(--pico-border-width);
+ vertical-align: middle;
+ cursor: pointer;
+}
+[type=checkbox]::-ms-check,
+[type=radio]::-ms-check {
+ display: none;
+}
+[type=checkbox]:checked, [type=checkbox]:checked:active, [type=checkbox]:checked:focus,
+[type=radio]:checked,
+[type=radio]:checked:active,
+[type=radio]:checked:focus {
+ --pico-background-color: var(--pico-primary-background);
+ --pico-border-color: var(--pico-primary-border);
+ background-image: var(--pico-icon-checkbox);
+ background-position: center;
+ background-size: 0.75em auto;
+ background-repeat: no-repeat;
+}
+[type=checkbox] ~ label,
+[type=radio] ~ label {
+ display: inline-block;
+ margin-bottom: 0;
+ cursor: pointer;
+}
+[type=checkbox] ~ label:not(:last-of-type),
+[type=radio] ~ label:not(:last-of-type) {
+ margin-inline-end: 1em;
+}
+
+[type=checkbox]:indeterminate {
+ --pico-background-color: var(--pico-primary-background);
+ --pico-border-color: var(--pico-primary-border);
+ background-image: var(--pico-icon-minus);
+ background-position: center;
+ background-size: 0.75em auto;
+ background-repeat: no-repeat;
+}
+
+[type=radio] {
+ border-radius: 50%;
+}
+[type=radio]:checked, [type=radio]:checked:active, [type=radio]:checked:focus {
+ --pico-background-color: var(--pico-primary-inverse);
+ border-width: 0.35em;
+ background-image: none;
+}
+
+[type=checkbox][role=switch] {
+ --pico-background-color: var(--pico-switch-background-color);
+ --pico-color: var(--pico-switch-color);
+ width: 2.25em;
+ height: 1.25em;
+ border: var(--pico-border-width) solid var(--pico-border-color);
+ border-radius: 1.25em;
+ background-color: var(--pico-background-color);
+ line-height: 1.25em;
+}
+[type=checkbox][role=switch]:not([aria-invalid]) {
+ --pico-border-color: var(--pico-switch-background-color);
+}
+[type=checkbox][role=switch]:before {
+ display: block;
+ aspect-ratio: 1;
+ height: 100%;
+ border-radius: 50%;
+ background-color: var(--pico-color);
+ box-shadow: var(--pico-switch-thumb-box-shadow);
+ content: "";
+ transition: margin 0.1s ease-in-out;
+}
+[type=checkbox][role=switch]:focus {
+ --pico-background-color: var(--pico-switch-background-color);
+ --pico-border-color: var(--pico-switch-background-color);
+}
+[type=checkbox][role=switch]:checked {
+ --pico-background-color: var(--pico-switch-checked-background-color);
+ --pico-border-color: var(--pico-switch-checked-background-color);
+ background-image: none;
+}
+[type=checkbox][role=switch]:checked::before {
+ margin-inline-start: calc(2.25em - 1.25em);
+}
+[type=checkbox][role=switch][disabled] {
+ --pico-background-color: var(--pico-border-color);
+}
+
+[type=checkbox][aria-invalid=false]:checked, [type=checkbox][aria-invalid=false]:checked:active, [type=checkbox][aria-invalid=false]:checked:focus,
+[type=checkbox][role=switch][aria-invalid=false]:checked,
+[type=checkbox][role=switch][aria-invalid=false]:checked:active,
+[type=checkbox][role=switch][aria-invalid=false]:checked:focus {
+ --pico-background-color: var(--pico-form-element-valid-border-color);
+}
+[type=checkbox]:checked[aria-invalid=true], [type=checkbox]:checked:active[aria-invalid=true], [type=checkbox]:checked:focus[aria-invalid=true],
+[type=checkbox][role=switch]:checked[aria-invalid=true],
+[type=checkbox][role=switch]:checked:active[aria-invalid=true],
+[type=checkbox][role=switch]:checked:focus[aria-invalid=true] {
+ --pico-background-color: var(--pico-form-element-invalid-border-color);
+}
+
+[type=checkbox][aria-invalid=false]:checked, [type=checkbox][aria-invalid=false]:checked:active, [type=checkbox][aria-invalid=false]:checked:focus,
+[type=radio][aria-invalid=false]:checked,
+[type=radio][aria-invalid=false]:checked:active,
+[type=radio][aria-invalid=false]:checked:focus,
+[type=checkbox][role=switch][aria-invalid=false]:checked,
+[type=checkbox][role=switch][aria-invalid=false]:checked:active,
+[type=checkbox][role=switch][aria-invalid=false]:checked:focus {
+ --pico-border-color: var(--pico-form-element-valid-border-color);
+}
+[type=checkbox]:checked[aria-invalid=true], [type=checkbox]:checked:active[aria-invalid=true], [type=checkbox]:checked:focus[aria-invalid=true],
+[type=radio]:checked[aria-invalid=true],
+[type=radio]:checked:active[aria-invalid=true],
+[type=radio]:checked:focus[aria-invalid=true],
+[type=checkbox][role=switch]:checked[aria-invalid=true],
+[type=checkbox][role=switch]:checked:active[aria-invalid=true],
+[type=checkbox][role=switch]:checked:focus[aria-invalid=true] {
+ --pico-border-color: var(--pico-form-element-invalid-border-color);
+}
+
+/**
+ * Input type color
+ */
+[type=color]::-webkit-color-swatch-wrapper {
+ padding: 0;
+}
+[type=color]::-moz-focus-inner {
+ padding: 0;
+}
+[type=color]::-webkit-color-swatch {
+ border: 0;
+ border-radius: calc(var(--pico-border-radius) * 0.5);
+}
+[type=color]::-moz-color-swatch {
+ border: 0;
+ border-radius: calc(var(--pico-border-radius) * 0.5);
+}
+
+/**
+ * Input type datetime
+ */
+input:not([type=checkbox], [type=radio], [type=range], [type=file]):is([type=date], [type=datetime-local], [type=month], [type=time], [type=week]) {
+ --pico-icon-position: 0.75rem;
+ --pico-icon-width: 1rem;
+ padding-right: calc(var(--pico-icon-width) + var(--pico-icon-position));
+ background-image: var(--pico-icon-date);
+ background-position: center right var(--pico-icon-position);
+ background-size: var(--pico-icon-width) auto;
+ background-repeat: no-repeat;
+}
+input:not([type=checkbox], [type=radio], [type=range], [type=file])[type=time] {
+ background-image: var(--pico-icon-time);
+}
+
+[type=date]::-webkit-calendar-picker-indicator,
+[type=datetime-local]::-webkit-calendar-picker-indicator,
+[type=month]::-webkit-calendar-picker-indicator,
+[type=time]::-webkit-calendar-picker-indicator,
+[type=week]::-webkit-calendar-picker-indicator {
+ width: var(--pico-icon-width);
+ margin-right: calc(var(--pico-icon-width) * -1);
+ margin-left: var(--pico-icon-position);
+ opacity: 0;
+}
+
+@-moz-document url-prefix() {
+ [type=date],
+ [type=datetime-local],
+ [type=month],
+ [type=time],
+ [type=week] {
+ padding-right: var(--pico-form-element-spacing-horizontal) !important;
+ background-image: none !important;
+ }
+}
+[dir=rtl] :is([type=date], [type=datetime-local], [type=month], [type=time], [type=week]) {
+ text-align: right;
+}
+
+/**
+ * Input type file
+ */
+[type=file] {
+ --pico-color: var(--pico-muted-color);
+ margin-left: calc(var(--pico-outline-width) * -1);
+ padding: calc(var(--pico-form-element-spacing-vertical) * 0.5) 0;
+ padding-left: var(--pico-outline-width);
+ border: 0;
+ border-radius: 0;
+ background: none;
+}
+[type=file]::file-selector-button {
+ margin-right: calc(var(--pico-spacing) / 2);
+ padding: calc(var(--pico-form-element-spacing-vertical) * 0.5) var(--pico-form-element-spacing-horizontal);
+}
+[type=file]:is(:hover, :active, :focus)::file-selector-button {
+ --pico-background-color: var(--pico-secondary-hover-background);
+ --pico-border-color: var(--pico-secondary-hover-border);
+}
+[type=file]:focus::file-selector-button {
+ --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus);
+}
+
+/**
+ * Input type range
+ */
+[type=range] {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ width: 100%;
+ height: 1.25rem;
+ background: none;
+}
+[type=range]::-webkit-slider-runnable-track {
+ width: 100%;
+ height: 0.375rem;
+ border-radius: var(--pico-border-radius);
+ background-color: var(--pico-range-border-color);
+ -webkit-transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
+ transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
+}
+[type=range]::-moz-range-track {
+ width: 100%;
+ height: 0.375rem;
+ border-radius: var(--pico-border-radius);
+ background-color: var(--pico-range-border-color);
+ -moz-transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
+ transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
+}
+[type=range]::-ms-track {
+ width: 100%;
+ height: 0.375rem;
+ border-radius: var(--pico-border-radius);
+ background-color: var(--pico-range-border-color);
+ -ms-transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
+ transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
+}
+[type=range]::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-top: -0.4375rem;
+ border: 2px solid var(--pico-range-thumb-border-color);
+ border-radius: 50%;
+ background-color: var(--pico-range-thumb-color);
+ cursor: pointer;
+ -webkit-transition: background-color var(--pico-transition), transform var(--pico-transition);
+ transition: background-color var(--pico-transition), transform var(--pico-transition);
+}
+[type=range]::-moz-range-thumb {
+ -webkit-appearance: none;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-top: -0.4375rem;
+ border: 2px solid var(--pico-range-thumb-border-color);
+ border-radius: 50%;
+ background-color: var(--pico-range-thumb-color);
+ cursor: pointer;
+ -moz-transition: background-color var(--pico-transition), transform var(--pico-transition);
+ transition: background-color var(--pico-transition), transform var(--pico-transition);
+}
+[type=range]::-ms-thumb {
+ -webkit-appearance: none;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-top: -0.4375rem;
+ border: 2px solid var(--pico-range-thumb-border-color);
+ border-radius: 50%;
+ background-color: var(--pico-range-thumb-color);
+ cursor: pointer;
+ -ms-transition: background-color var(--pico-transition), transform var(--pico-transition);
+ transition: background-color var(--pico-transition), transform var(--pico-transition);
+}
+[type=range]:active, [type=range]:focus-within {
+ --pico-range-border-color: var(--pico-range-active-border-color);
+ --pico-range-thumb-color: var(--pico-range-thumb-active-color);
+}
+[type=range]:active::-webkit-slider-thumb {
+ transform: scale(1.25);
+}
+[type=range]:active::-moz-range-thumb {
+ transform: scale(1.25);
+}
+[type=range]:active::-ms-thumb {
+ transform: scale(1.25);
+}
+
+/**
+ * Input type search
+ */
+input:not([type=checkbox], [type=radio], [type=range], [type=file])[type=search] {
+ padding-inline-start: calc(var(--pico-form-element-spacing-horizontal) + 1.75rem);
+ background-image: var(--pico-icon-search);
+ background-position: center left calc(var(--pico-form-element-spacing-horizontal) + 0.125rem);
+ background-size: 1rem auto;
+ background-repeat: no-repeat;
+}
+input:not([type=checkbox], [type=radio], [type=range], [type=file])[type=search][aria-invalid] {
+ padding-inline-start: calc(var(--pico-form-element-spacing-horizontal) + 1.75rem) !important;
+ background-position: center left 1.125rem, center right 0.75rem;
+}
+input:not([type=checkbox], [type=radio], [type=range], [type=file])[type=search][aria-invalid=false] {
+ background-image: var(--pico-icon-search), var(--pico-icon-valid);
+}
+input:not([type=checkbox], [type=radio], [type=range], [type=file])[type=search][aria-invalid=true] {
+ background-image: var(--pico-icon-search), var(--pico-icon-invalid);
+}
+
+[dir=rtl] :where(input):not([type=checkbox], [type=radio], [type=range], [type=file])[type=search] {
+ background-position: center right 1.125rem;
+}
+[dir=rtl] :where(input):not([type=checkbox], [type=radio], [type=range], [type=file])[type=search][aria-invalid] {
+ background-position: center right 1.125rem, center left 0.75rem;
+}
+
+/**
+ * Accordion (<details>)
+ */
+details {
+ display: block;
+ margin-bottom: var(--pico-spacing);
+}
+details summary {
+ line-height: 1rem;
+ list-style-type: none;
+ cursor: pointer;
+ transition: color var(--pico-transition);
+}
+details summary:not([role]) {
+ color: var(--pico-accordion-close-summary-color);
+}
+details summary::-webkit-details-marker {
+ display: none;
+}
+details summary::marker {
+ display: none;
+}
+details summary::-moz-list-bullet {
+ list-style-type: none;
+}
+details summary::after {
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ margin-inline-start: calc(var(--pico-spacing, 1rem) * 0.5);
+ float: right;
+ transform: rotate(-90deg);
+ background-image: var(--pico-icon-chevron);
+ background-position: right center;
+ background-size: 1rem auto;
+ background-repeat: no-repeat;
+ content: "";
+ transition: transform var(--pico-transition);
+}
+details summary:focus {
+ outline: none;
+}
+details summary:focus:not([role]) {
+ color: var(--pico-accordion-active-summary-color);
+}
+details summary:focus-visible:not([role]) {
+ outline: var(--pico-outline-width) solid var(--pico-primary-focus);
+ outline-offset: calc(var(--pico-spacing, 1rem) * 0.5);
+ color: var(--pico-primary);
+}
+details summary[role=button] {
+ width: 100%;
+ text-align: left;
+}
+details summary[role=button]::after {
+ height: calc(1rem * var(--pico-line-height, 1.5));
+}
+details[open] > summary {
+ margin-bottom: var(--pico-spacing);
+}
+details[open] > summary:not([role]):not(:focus) {
+ color: var(--pico-accordion-open-summary-color);
+}
+details[open] > summary::after {
+ transform: rotate(0);
+}
+
+[dir=rtl] details summary {
+ text-align: right;
+}
+[dir=rtl] details summary::after {
+ float: left;
+ background-position: left center;
+}
+
+/**
+ * Card (<article>)
+ */
+article {
+ margin-bottom: var(--pico-block-spacing-vertical);
+ padding: var(--pico-block-spacing-vertical) var(--pico-block-spacing-horizontal);
+ border-radius: var(--pico-border-radius);
+ background: var(--pico-card-background-color);
+ box-shadow: var(--pico-card-box-shadow);
+}
+article > header,
+article > footer {
+ margin-right: calc(var(--pico-block-spacing-horizontal) * -1);
+ margin-left: calc(var(--pico-block-spacing-horizontal) * -1);
+ padding: calc(var(--pico-block-spacing-vertical) * 0.66) var(--pico-block-spacing-horizontal);
+ background-color: var(--pico-card-sectioning-background-color);
+}
+article > header {
+ margin-top: calc(var(--pico-block-spacing-vertical) * -1);
+ margin-bottom: var(--pico-block-spacing-vertical);
+ border-bottom: var(--pico-border-width) solid var(--pico-card-border-color);
+ border-top-right-radius: var(--pico-border-radius);
+ border-top-left-radius: var(--pico-border-radius);
+}
+article > footer {
+ margin-top: var(--pico-block-spacing-vertical);
+ margin-bottom: calc(var(--pico-block-spacing-vertical) * -1);
+ border-top: var(--pico-border-width) solid var(--pico-card-border-color);
+ border-bottom-right-radius: var(--pico-border-radius);
+ border-bottom-left-radius: var(--pico-border-radius);
+}
+
+/**
+ * Group ([role="group"], [role="search"])
+ */
+[role=search],
+[role=group] {
+ display: inline-flex;
+ position: relative;
+ width: 100%;
+ margin-bottom: var(--pico-spacing);
+ border-radius: var(--pico-border-radius);
+ box-shadow: var(--pico-group-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
+ vertical-align: middle;
+ transition: box-shadow var(--pico-transition);
+}
+[role=search] > *,
+[role=search] input:not([type=checkbox], [type=radio]),
+[role=search] select,
+[role=group] > *,
+[role=group] input:not([type=checkbox], [type=radio]),
+[role=group] select {
+ position: relative;
+ flex: 1 1 auto;
+ margin-bottom: 0;
+}
+[role=search] > *:not(:first-child),
+[role=search] input:not([type=checkbox], [type=radio]):not(:first-child),
+[role=search] select:not(:first-child),
+[role=group] > *:not(:first-child),
+[role=group] input:not([type=checkbox], [type=radio]):not(:first-child),
+[role=group] select:not(:first-child) {
+ margin-left: 0;
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+[role=search] > *:not(:last-child),
+[role=search] input:not([type=checkbox], [type=radio]):not(:last-child),
+[role=search] select:not(:last-child),
+[role=group] > *:not(:last-child),
+[role=group] input:not([type=checkbox], [type=radio]):not(:last-child),
+[role=group] select:not(:last-child) {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+[role=search] > *:focus,
+[role=search] input:not([type=checkbox], [type=radio]):focus,
+[role=search] select:focus,
+[role=group] > *:focus,
+[role=group] input:not([type=checkbox], [type=radio]):focus,
+[role=group] select:focus {
+ z-index: 2;
+}
+[role=search] button:not(:first-child),
+[role=search] [type=submit]:not(:first-child),
+[role=search] [type=reset]:not(:first-child),
+[role=search] [type=button]:not(:first-child),
+[role=search] [role=button]:not(:first-child),
+[role=search] input:not([type=checkbox], [type=radio]):not(:first-child),
+[role=search] select:not(:first-child),
+[role=group] button:not(:first-child),
+[role=group] [type=submit]:not(:first-child),
+[role=group] [type=reset]:not(:first-child),
+[role=group] [type=button]:not(:first-child),
+[role=group] [role=button]:not(:first-child),
+[role=group] input:not([type=checkbox], [type=radio]):not(:first-child),
+[role=group] select:not(:first-child) {
+ margin-left: calc(var(--pico-border-width) * -1);
+}
+[role=search] button,
+[role=search] [type=submit],
+[role=search] [type=reset],
+[role=search] [type=button],
+[role=search] [role=button],
+[role=group] button,
+[role=group] [type=submit],
+[role=group] [type=reset],
+[role=group] [type=button],
+[role=group] [role=button] {
+ width: auto;
+}
+@supports selector(:has(*)) {
+ [role=search]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus),
+ [role=group]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus) {
+ --pico-group-box-shadow: var(--pico-group-box-shadow-focus-with-button);
+ }
+ [role=search]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus) input:not([type=checkbox], [type=radio]),
+ [role=search]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus) select,
+ [role=group]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus) input:not([type=checkbox], [type=radio]),
+ [role=group]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus) select {
+ border-color: transparent;
+ }
+ [role=search]:has(input:not([type=submit], [type=button]):focus, select:focus),
+ [role=group]:has(input:not([type=submit], [type=button]):focus, select:focus) {
+ --pico-group-box-shadow: var(--pico-group-box-shadow-focus-with-input);
+ }
+ [role=search]:has(input:not([type=submit], [type=button]):focus, select:focus) button,
+ [role=search]:has(input:not([type=submit], [type=button]):focus, select:focus) [type=submit],
+ [role=search]:has(input:not([type=submit], [type=button]):focus, select:focus) [type=button],
+ [role=search]:has(input:not([type=submit], [type=button]):focus, select:focus) [role=button],
+ [role=group]:has(input:not([type=submit], [type=button]):focus, select:focus) button,
+ [role=group]:has(input:not([type=submit], [type=button]):focus, select:focus) [type=submit],
+ [role=group]:has(input:not([type=submit], [type=button]):focus, select:focus) [type=button],
+ [role=group]:has(input:not([type=submit], [type=button]):focus, select:focus) [role=button] {
+ --pico-button-box-shadow: 0 0 0 var(--pico-border-width) var(--pico-primary-border);
+ --pico-button-hover-box-shadow: 0 0 0 var(--pico-border-width) var(--pico-primary-hover-border);
+ }
+ [role=search] button:focus,
+ [role=search] [type=submit]:focus,
+ [role=search] [type=reset]:focus,
+ [role=search] [type=button]:focus,
+ [role=search] [role=button]:focus,
+ [role=group] button:focus,
+ [role=group] [type=submit]:focus,
+ [role=group] [type=reset]:focus,
+ [role=group] [type=button]:focus,
+ [role=group] [role=button]:focus {
+ box-shadow: none;
+ }
+}
+
+[role=search] > *:first-child {
+ border-top-left-radius: 5rem;
+ border-bottom-left-radius: 5rem;
+}
+[role=search] > *:last-child {
+ border-top-right-radius: 5rem;
+ border-bottom-right-radius: 5rem;
+}
+
+/**
+ * Loading ([aria-busy=true])
+ */
+[aria-busy=true]:not(input, select, textarea, html) {
+ white-space: nowrap;
+}
+[aria-busy=true]:not(input, select, textarea, html)::before {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ background-image: var(--pico-icon-loading);
+ background-size: 1em auto;
+ background-repeat: no-repeat;
+ content: "";
+ vertical-align: -0.125em;
+}
+[aria-busy=true]:not(input, select, textarea, html):not(:empty)::before {
+ margin-inline-end: calc(var(--pico-spacing) * 0.5);
+}
+[aria-busy=true]:not(input, select, textarea, html):empty {
+ text-align: center;
+}
+
+button[aria-busy=true],
+[type=submit][aria-busy=true],
+[type=button][aria-busy=true],
+[type=reset][aria-busy=true],
+[role=button][aria-busy=true],
+a[aria-busy=true] {
+ pointer-events: none;
+}
+
+/**
+ * Modal (<dialog>)
+ */
+:root {
+ --pico-scrollbar-width: 0px;
+}
+
+dialog {
+ display: flex;
+ z-index: 999;
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ align-items: center;
+ justify-content: center;
+ width: inherit;
+ min-width: 100%;
+ height: inherit;
+ min-height: 100%;
+ padding: 0;
+ border: 0;
+ -webkit-backdrop-filter: var(--pico-modal-overlay-backdrop-filter);
+ backdrop-filter: var(--pico-modal-overlay-backdrop-filter);
+ background-color: var(--pico-modal-overlay-background-color);
+ color: var(--pico-color);
+}
+dialog article {
+ width: 100%;
+ max-height: calc(100vh - var(--pico-spacing) * 2);
+ margin: var(--pico-spacing);
+ overflow: auto;
+}
+@media (min-width: 576px) {
+ dialog article {
+ max-width: 510px;
+ }
+}
+@media (min-width: 768px) {
+ dialog article {
+ max-width: 700px;
+ }
+}
+dialog article > header > * {
+ margin-bottom: 0;
+}
+dialog article > header :is(a, button)[rel=prev] {
+ margin: 0;
+ margin-left: var(--pico-spacing);
+ padding: 0;
+ float: right;
+}
+dialog article > footer {
+ text-align: right;
+}
+dialog article > footer button,
+dialog article > footer [role=button] {
+ margin-bottom: 0;
+}
+dialog article > footer button:not(:first-of-type),
+dialog article > footer [role=button]:not(:first-of-type) {
+ margin-left: calc(var(--pico-spacing) * 0.5);
+}
+dialog article :is(a, button)[rel=prev] {
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ margin-top: calc(var(--pico-spacing) * -1);
+ margin-bottom: var(--pico-spacing);
+ margin-left: auto;
+ border: none;
+ background-image: var(--pico-icon-close);
+ background-position: center;
+ background-size: auto 1rem;
+ background-repeat: no-repeat;
+ background-color: transparent;
+ opacity: 0.5;
+ transition: opacity var(--pico-transition);
+}
+dialog article :is(a, button)[rel=prev]:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
+ opacity: 1;
+}
+dialog:not([open]), dialog[open=false] {
+ display: none;
+}
+
+/**
+ * Nav
+ */
+:where(nav li)::before {
+ float: left;
+ content: "​";
+}
+
+nav,
+nav ul {
+ display: flex;
+}
+
+nav {
+ justify-content: space-between;
+ overflow: visible;
+}
+nav ol,
+nav ul {
+ align-items: center;
+ margin-bottom: 0;
+ padding: 0;
+ list-style: none;
+}
+nav ol:first-of-type,
+nav ul:first-of-type {
+ margin-left: calc(var(--pico-nav-element-spacing-horizontal) * -1);
+}
+nav ol:last-of-type,
+nav ul:last-of-type {
+ margin-right: calc(var(--pico-nav-element-spacing-horizontal) * -1);
+}
+nav li {
+ display: inline-block;
+ margin: 0;
+ padding: var(--pico-nav-element-spacing-vertical) var(--pico-nav-element-spacing-horizontal);
+}
+nav li :where(a, [role=link]) {
+ display: inline-block;
+ margin: calc(var(--pico-nav-link-spacing-vertical) * -1) calc(var(--pico-nav-link-spacing-horizontal) * -1);
+ padding: var(--pico-nav-link-spacing-vertical) var(--pico-nav-link-spacing-horizontal);
+ border-radius: var(--pico-border-radius);
+}
+nav li :where(a, [role=link]):not(:hover) {
+ text-decoration: none;
+}
+nav li button,
+nav li [role=button],
+nav li [type=button],
+nav li input:not([type=checkbox], [type=radio], [type=range], [type=file]),
+nav li select {
+ height: auto;
+ margin-right: inherit;
+ margin-bottom: 0;
+ margin-left: inherit;
+}
+nav[aria-label=breadcrumb] {
+ align-items: center;
+ justify-content: start;
+}
+nav[aria-label=breadcrumb] ul li:not(:first-child) {
+ margin-inline-start: var(--pico-nav-link-spacing-horizontal);
+}
+nav[aria-label=breadcrumb] ul li a {
+ margin: calc(var(--pico-nav-link-spacing-vertical) * -1) 0;
+ margin-inline-start: calc(var(--pico-nav-link-spacing-horizontal) * -1);
+}
+nav[aria-label=breadcrumb] ul li:not(:last-child)::after {
+ display: inline-block;
+ position: absolute;
+ width: calc(var(--pico-nav-link-spacing-horizontal) * 4);
+ margin: 0 calc(var(--pico-nav-link-spacing-horizontal) * -1);
+ content: var(--pico-nav-breadcrumb-divider);
+ color: var(--pico-muted-color);
+ text-align: center;
+ text-decoration: none;
+ white-space: nowrap;
+}
+nav[aria-label=breadcrumb] a[aria-current]:not([aria-current=false]) {
+ background-color: transparent;
+ color: inherit;
+ text-decoration: none;
+ pointer-events: none;
+}
+
+aside nav,
+aside ol,
+aside ul,
+aside li {
+ display: block;
+}
+aside li {
+ padding: calc(var(--pico-nav-element-spacing-vertical) * 0.5) var(--pico-nav-element-spacing-horizontal);
+}
+aside li a {
+ display: block;
+}
+aside li [role=button] {
+ margin: inherit;
+}
+
+[dir=rtl] nav[aria-label=breadcrumb] ul li:not(:last-child) ::after {
+ content: "\\";
+}
+
+/**
+ * Progress
+ */
+progress {
+ display: inline-block;
+ vertical-align: baseline;
+}
+
+progress {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ display: inline-block;
+ appearance: none;
+ width: 100%;
+ height: 0.5rem;
+ margin-bottom: calc(var(--pico-spacing) * 0.5);
+ overflow: hidden;
+ border: 0;
+ border-radius: var(--pico-border-radius);
+ background-color: var(--pico-progress-background-color);
+ color: var(--pico-progress-color);
+}
+progress::-webkit-progress-bar {
+ border-radius: var(--pico-border-radius);
+ background: none;
+}
+progress[value]::-webkit-progress-value {
+ background-color: var(--pico-progress-color);
+ -webkit-transition: inline-size var(--pico-transition);
+ transition: inline-size var(--pico-transition);
+}
+progress::-moz-progress-bar {
+ background-color: var(--pico-progress-color);
+}
+@media (prefers-reduced-motion: no-preference) {
+ progress:indeterminate {
+ background: var(--pico-progress-background-color) linear-gradient(to right, var(--pico-progress-color) 30%, var(--pico-progress-background-color) 30%) top left/150% 150% no-repeat;
+ animation: progress-indeterminate 1s linear infinite;
+ }
+ progress:indeterminate[value]::-webkit-progress-value {
+ background-color: transparent;
+ }
+ progress:indeterminate::-moz-progress-bar {
+ background-color: transparent;
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ [dir=rtl] progress:indeterminate {
+ animation-direction: reverse;
+ }
+}
+
+@keyframes progress-indeterminate {
+ 0% {
+ background-position: 200% 0;
+ }
+ 100% {
+ background-position: -200% 0;
+ }
+}
+/**
+ * Tooltip ([data-tooltip])
+ */
+[data-tooltip] {
+ position: relative;
+}
+[data-tooltip]:not(a, button, input) {
+ border-bottom: 1px dotted;
+ text-decoration: none;
+ cursor: help;
+}
+[data-tooltip][data-placement=top]::before, [data-tooltip][data-placement=top]::after, [data-tooltip]::before, [data-tooltip]::after {
+ display: block;
+ z-index: 99;
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ padding: 0.25rem 0.5rem;
+ overflow: hidden;
+ transform: translate(-50%, -0.25rem);
+ border-radius: var(--pico-border-radius);
+ background: var(--pico-tooltip-background-color);
+ content: attr(data-tooltip);
+ color: var(--pico-tooltip-color);
+ font-style: normal;
+ font-weight: var(--pico-font-weight);
+ font-size: 0.875rem;
+ text-decoration: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ opacity: 0;
+ pointer-events: none;
+}
+[data-tooltip][data-placement=top]::after, [data-tooltip]::after {
+ padding: 0;
+ transform: translate(-50%, 0rem);
+ border-top: 0.3rem solid;
+ border-right: 0.3rem solid transparent;
+ border-left: 0.3rem solid transparent;
+ border-radius: 0;
+ background-color: transparent;
+ content: "";
+ color: var(--pico-tooltip-background-color);
+}
+[data-tooltip][data-placement=bottom]::before, [data-tooltip][data-placement=bottom]::after {
+ top: 100%;
+ bottom: auto;
+ transform: translate(-50%, 0.25rem);
+}
+[data-tooltip][data-placement=bottom]:after {
+ transform: translate(-50%, -0.3rem);
+ border: 0.3rem solid transparent;
+ border-bottom: 0.3rem solid;
+}
+[data-tooltip][data-placement=left]::before, [data-tooltip][data-placement=left]::after {
+ top: 50%;
+ right: 100%;
+ bottom: auto;
+ left: auto;
+ transform: translate(-0.25rem, -50%);
+}
+[data-tooltip][data-placement=left]:after {
+ transform: translate(0.3rem, -50%);
+ border: 0.3rem solid transparent;
+ border-left: 0.3rem solid;
+}
+[data-tooltip][data-placement=right]::before, [data-tooltip][data-placement=right]::after {
+ top: 50%;
+ right: auto;
+ bottom: auto;
+ left: 100%;
+ transform: translate(0.25rem, -50%);
+}
+[data-tooltip][data-placement=right]:after {
+ transform: translate(-0.3rem, -50%);
+ border: 0.3rem solid transparent;
+ border-right: 0.3rem solid;
+}
+[data-tooltip]:focus::before, [data-tooltip]:focus::after, [data-tooltip]:hover::before, [data-tooltip]:hover::after {
+ opacity: 1;
+}
+@media (hover: hover) and (pointer: fine) {
+ [data-tooltip]:focus::before, [data-tooltip]:focus::after, [data-tooltip]:hover::before, [data-tooltip]:hover::after {
+ --pico-tooltip-slide-to: translate(-50%, -0.25rem);
+ transform: translate(-50%, 0.75rem);
+ animation-duration: 0.2s;
+ animation-fill-mode: forwards;
+ animation-name: tooltip-slide;
+ opacity: 0;
+ }
+ [data-tooltip]:focus::after, [data-tooltip]:hover::after {
+ --pico-tooltip-caret-slide-to: translate(-50%, 0rem);
+ transform: translate(-50%, -0.25rem);
+ animation-name: tooltip-caret-slide;
+ }
+ [data-tooltip][data-placement=bottom]:focus::before, [data-tooltip][data-placement=bottom]:focus::after, [data-tooltip][data-placement=bottom]:hover::before, [data-tooltip][data-placement=bottom]:hover::after {
+ --pico-tooltip-slide-to: translate(-50%, 0.25rem);
+ transform: translate(-50%, -0.75rem);
+ animation-name: tooltip-slide;
+ }
+ [data-tooltip][data-placement=bottom]:focus::after, [data-tooltip][data-placement=bottom]:hover::after {
+ --pico-tooltip-caret-slide-to: translate(-50%, -0.3rem);
+ transform: translate(-50%, -0.5rem);
+ animation-name: tooltip-caret-slide;
+ }
+ [data-tooltip][data-placement=left]:focus::before, [data-tooltip][data-placement=left]:focus::after, [data-tooltip][data-placement=left]:hover::before, [data-tooltip][data-placement=left]:hover::after {
+ --pico-tooltip-slide-to: translate(-0.25rem, -50%);
+ transform: translate(0.75rem, -50%);
+ animation-name: tooltip-slide;
+ }
+ [data-tooltip][data-placement=left]:focus::after, [data-tooltip][data-placement=left]:hover::after {
+ --pico-tooltip-caret-slide-to: translate(0.3rem, -50%);
+ transform: translate(0.05rem, -50%);
+ animation-name: tooltip-caret-slide;
+ }
+ [data-tooltip][data-placement=right]:focus::before, [data-tooltip][data-placement=right]:focus::after, [data-tooltip][data-placement=right]:hover::before, [data-tooltip][data-placement=right]:hover::after {
+ --pico-tooltip-slide-to: translate(0.25rem, -50%);
+ transform: translate(-0.75rem, -50%);
+ animation-name: tooltip-slide;
+ }
+ [data-tooltip][data-placement=right]:focus::after, [data-tooltip][data-placement=right]:hover::after {
+ --pico-tooltip-caret-slide-to: translate(-0.3rem, -50%);
+ transform: translate(-0.05rem, -50%);
+ animation-name: tooltip-caret-slide;
+ }
+}
+@keyframes tooltip-slide {
+ to {
+ transform: var(--pico-tooltip-slide-to);
+ opacity: 1;
+ }
+}
+@keyframes tooltip-caret-slide {
+ 50% {
+ opacity: 0;
+ }
+ to {
+ transform: var(--pico-tooltip-caret-slide-to);
+ opacity: 1;
+ }
+}
+
+/**
+ * Accessibility & User interaction
+ */
+[aria-controls] {
+ cursor: pointer;
+}
+
+[aria-disabled=true],
+[disabled] {
+ cursor: not-allowed;
+}
+
+[aria-hidden=false][hidden] {
+ display: initial;
+}
+
+[aria-hidden=false][hidden]:not(:focus) {
+ clip: rect(0, 0, 0, 0);
+ position: absolute;
+}
+
+a,
+area,
+button,
+input,
+label,
+select,
+summary,
+textarea,
+[tabindex] {
+ -ms-touch-action: manipulation;
+}
+
+[dir=rtl] {
+ direction: rtl;
+}
+
+/**
+ * Reduce Motion Features
+ */
+@media (prefers-reduced-motion: reduce) {
+ *:not([aria-busy=true]),
+ :not([aria-busy=true])::before,
+ :not([aria-busy=true])::after {
+ background-attachment: initial !important;
+ animation-duration: 1ms !important;
+ animation-delay: -1ms !important;
+ animation-iteration-count: 1 !important;
+ scroll-behavior: auto !important;
+ transition-delay: 0s !important;
+ transition-duration: 0s !important;
+ }
+}
+
+/* PICO CSS END */
+
+:root {
+ font-family: 'Ysabeau';
+
+ --x-grid-spacing-horizontal: var(--pico-spacing);
+}
+
+body > header {
+ padding-top: 0;
+}
+
+nav menu {
+ display: flex;
+ align-items: center;
+ margin-block: 0;
+ padding: 0;
+ list-style: none;
+ white-space: nowrap;
+}
+
+nav menu:first-of-type li:first-child a {
+ padding-inline-start: 0;
+}
+
+nav menu:last-of-type li:last-child a {
+ padding-inline-end: 0;
+}
+
+#nav-icon-lang a {
+ display: flex;
+ align-items: center;
+ gap: .5ch;
+}
+
+#nav-icon-lang svg {
+ stroke: var(--pico-color);
+ height: 1rem;
+}
+
+#nav-icon-theme button {
+ background-color: unset;
+ margin: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 1.5rem;
+}
+
+#nav-icon-theme svg {
+ --size: 1.2rem;
+ stroke: var(--pico-primary);
+ stroke-width: .1;
+ height: var(--size);
+ width: var(--size);
+}
+
+[data-theme="light"] #nav-icon-theme svg {
+ fill: var(--pico-primary);
+}
+
+.lang-grid {
+ display: grid;
+ grid-template-columns: repeat(
+ auto-fit,
+ minmax(min(180px, 100%), 1fr)
+ );
+ column-gap: var(--x-grid-spacing-horizontal);
+}
+
+.lang-grid button {
+ text-align: left;
+}
+
+.lang-grid span::before {
+ display: inline-block;
+ content: attr(data-code);
+ font-weight: bold;
+ width: 3ch;
+}
diff --git a/templates/base.go b/templates/base.go
new file mode 100644
index 0000000..f0b288b
--- /dev/null
+++ b/templates/base.go
@@ -0,0 +1,8 @@
+package templates
+
+const (
+ PrinterKey = "printer"
+ LocaleKey = "locale"
+)
+
+//go:generate templ generate -log-level warn
diff --git a/templates/navbar.templ b/templates/navbar.templ
new file mode 100644
index 0000000..95e8563
--- /dev/null
+++ b/templates/navbar.templ
@@ -0,0 +1,237 @@
+package templates
+
+import "git.thomasvoss.com/euro-cash.eu/i18n"
+
+templ navbar() {
+ {{ p := ctx.Value(PrinterKey).(i18n.Printer) }}
+
+ <nav>
+ <menu>
+ <li><a href="/">{ p.T("Home") }</a></li>
+ <li><a href="#TODO">{ p.T("News") }</a></li>
+ <li><a href="#TODO">{ p.T("Coin Collecting") }</a></li>
+ <li><a href="#TODO">{ p.T("Coins") }</a></li>
+ <li><a href="#TODO">{ p.T("Banknotes") }</a></li>
+ <li><a href="#TODO">{ p.T("Jargon") }</a></li>
+ </menu>
+
+ <menu>
+ <li>
+ <a
+ href="https://discord.gg/DCaXfRcy9C"
+ target="_blank"
+ >
+ { p.T("Discord") }
+ </a>
+ </li>
+ <li><a href="#TODO">{ p.T("About") }</a></li>
+ <li id="nav-icon-lang">
+ <a href="/language">
+ <svg
+ version="1.1"
+ width="19"
+ height="19"
+ viewBox="0 0 19 19"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <circle
+ cx="9.5" cy="9.5" r="9"
+ stroke-linejoin="round"
+ />
+ <path
+ d="M 9.5 .5
+ C 9.5 .5
+ 6.0 3.5
+ 6.0 9.5
+ C 6.0 15.5
+ 9.5 18.5
+ 9.5 18.5"
+ stroke-linejoin="round"
+ />
+ <path
+ d="M 9.5 .5
+ C 9.5 .5
+ 13.0 3.5
+ 13.0 9.5
+ C 13.0 15.5
+ 9.5 18.5
+ 9.5 18.5"
+ stroke-linejoin="round"
+ />
+ <path d="M .5 9.5 H 18.5" stroke-linejoin="round" />
+ <path d="M 17.0 5.0 H 2.0" stroke-linejoin="round" />
+ <path d="M 17.0 14.0 H 2.0" stroke-linejoin="round" />
+ </svg>
+ { p.T("Language") }
+ </a>
+ </li>
+ <li id="nav-icon-theme">
+ <form class={ noMargin() } action="#TODO" method="POST">
+ <button>
+ <svg
+ version="1.1"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <!-- TODO: if theme == dark -->
+ if true {
+ <path
+ d="M 7.28451 10.3333
+ C 7.10026 10.8546
+ 7 11.4156
+ 7 12
+ C 7 14.7614
+ 9.23858 17
+ 12 17
+ C 14.7614 17
+ 17 14.7614
+ 17 12
+ C 17 9.23858
+ 14.7614 7
+ 12 7
+ C 11.4156 7
+ 10.8546 7.10026
+ 10.3333 7.28451"
+ stroke-width="1.5"
+ stroke-linecap="round"
+ />
+
+ <path
+ d="M 12 2 V 4"
+ stroke-width="1.5"
+ stroke-linecap="round"
+ />
+ <path
+ d="M 12 20 V 22"
+ stroke-width="1.5"
+ stroke-linecap="round"
+ />
+ <path
+ d="M 4 12 L 2 12"
+ stroke-width="1.5"
+ stroke-linecap="round"
+ />
+ <path
+ d="M 22 12 L 20 12"
+ stroke-width="1.5"
+ stroke-linecap="round"
+ />
+
+ <path
+ d="M 19.7778 4.22266 L 17.5558 6.25424"
+ stroke-width="1.5"
+ stroke-linecap="round"
+ />
+ <path
+ d="M 4.22217 4.22266 L 6.44418 6.25424"
+ stroke-width="1.5"
+ stroke-linecap="round"
+ />
+ <path
+ d="M 6.44434 17.5557 L 4.22211 19.7779"
+ stroke-width="1.5"
+ stroke-linecap="round"
+ />
+ <path
+ d="M 19.7778 19.7773 L 17.5558 17.5551"
+ stroke-width="1.5"
+ stroke-linecap="round"
+ />
+ } else {
+ <path d="M 21.0672 11.8568
+ L 20.4253 11.469
+ L 21.0672 11.8568
+ Z
+ M 12.1432 2.93276
+ L 11.7553 2.29085
+ V 2.29085
+ L 12.1432 2.93276
+ Z
+ M 7.37554 20.013
+ C 7.017 19.8056 6.5582 19.9281 6.3508 20.2866
+ C 6.14339 20.6452 6.26591 21.104 6.62446 21.3114
+ L 7.37554 20.013
+ Z
+ M 2.68862 17.3755
+ C 2.89602 17.7341 3.35482 17.8566 3.71337 17.6492
+ C 4.07191 17.4418 4.19443 16.983 3.98703 16.6245
+ L 2.68862 17.3755
+ Z
+ M 21.25 12
+ C 21.25 17.1086 17.1086 21.25 12 21.25
+ V 22.75
+ C 17.9371 22.75 22.75 17.9371 22.75 12
+ H 21.25
+ Z
+ M 2.75 12
+ C 2.75 6.89137 6.89137 2.75 12 2.75
+ V 1.25
+ C 6.06294 1.25 1.25 6.06294 1.25 12
+ H 2.75
+ Z
+ M 15.5 14.25
+ C 12.3244 14.25 9.75 11.6756 9.75 8.5
+ H 8.25
+ C 8.25 12.5041 11.4959 15.75 15.5 15.75
+ V 14.25
+ Z
+ M 20.4253 11.469
+ C 19.4172 13.1373 17.5882 14.25 15.5 14.25
+ V 15.75
+ C 18.1349 15.75 20.4407 14.3439 21.7092 12.2447
+ L 20.4253 11.469
+ Z
+ M 9.75 8.5
+ C 9.75 6.41182 10.8627 4.5828 12.531 3.57467
+ L 11.7553 2.29085
+ C 9.65609 3.5593 8.25 5.86509 8.25 8.5
+ H 9.75
+ Z
+ M 12 2.75
+ C 11.9115 2.75 11.8077 2.71008 11.7324 2.63168
+ C 11.6686 2.56527 11.6538 2.50244 11.6503 2.47703
+ C 11.6461 2.44587 11.6482 2.35557 11.7553 2.29085
+ L 12.531 3.57467
+ C 13.0342 3.27065 13.196 2.71398 13.1368 2.27627
+ C 13.0754 1.82126 12.7166 1.25 12 1.25
+ V 2.75
+ Z
+ M 21.7092 12.2447
+ C 21.6444 12.3518 21.5541 12.3539 21.523 12.3497
+ C 21.4976 12.3462 21.4347 12.3314 21.3683 12.2676
+ C 21.2899 12.1923 21.25 12.0885 21.25 12
+ H 22.75
+ C 22.75 11.2834 22.1787 10.9246 21.7237 10.8632
+ C 21.286 10.804 20.7293 10.9658 20.4253 11.469
+ L 21.7092 12.2447
+ Z
+ M 12 21.25
+ C 10.3139 21.25 8.73533 20.7996 7.37554 20.013
+ L 6.62446 21.3114
+ C 8.2064 22.2265 10.0432 22.75 12 22.75
+ V 21.25
+ Z
+ M 3.98703 16.6245
+ C 3.20043 15.2647 2.75 13.6861 2.75 12
+ H 1.25
+ C 1.25 13.9568 1.77351 15.7936 2.68862 17.3755
+ L 3.98703 16.6245
+ Z
+ "
+ />
+ }
+ </svg>
+ </button>
+ </form>
+ </li>
+ </menu>
+ </nav>
+}
+
+css noMargin() {
+ margin: 0;
+}
diff --git a/templates/navbar_templ.go b/templates/navbar_templ.go
new file mode 100644
index 0000000..90fa955
--- /dev/null
+++ b/templates/navbar_templ.go
@@ -0,0 +1,202 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.2.747
+package templates
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+import "git.thomasvoss.com/euro-cash.eu/i18n"
+
+func navbar() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var1 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var1 == nil {
+ templ_7745c5c3_Var1 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ p := ctx.Value(PrinterKey).(i18n.Printer)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<nav><menu><li><a href=\"/\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var2 string
+ templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Home"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar.templ`, Line: 10, Col: 32}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><li><a href=\"#TODO\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var3 string
+ templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("News"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar.templ`, Line: 11, Col: 36}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><li><a href=\"#TODO\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var4 string
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Coin Collecting"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar.templ`, Line: 12, Col: 47}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><li><a href=\"#TODO\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var5 string
+ templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Coins"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar.templ`, Line: 13, Col: 37}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><li><a href=\"#TODO\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var6 string
+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Banknotes"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar.templ`, Line: 14, Col: 41}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><li><a href=\"#TODO\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var7 string
+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Jargon"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar.templ`, Line: 15, Col: 38}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li></menu> <menu><li><a href=\"https://discord.gg/DCaXfRcy9C\" target=\"_blank\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var8 string
+ templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Discord"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar.templ`, Line: 24, Col: 21}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><li><a href=\"#TODO\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var9 string
+ templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("About"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar.templ`, Line: 27, Col: 37}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><li id=\"nav-icon-lang\"><a href=\"/language\"><svg version=\"1.1\" width=\"19\" height=\"19\" viewBox=\"0 0 19 19\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"9.5\" cy=\"9.5\" r=\"9\" stroke-linejoin=\"round\"></circle> <path d=\"M 9.5 .5\n\t\t\t\t\t\t\t C 9.5 .5\n\t\t\t\t\t\t\t\t 6.0 3.5\n\t\t\t\t\t\t\t\t 6.0 9.5\n\t\t\t\t\t\t\t C 6.0 15.5\n\t\t\t\t\t\t\t\t 9.5 18.5\n\t\t\t\t\t\t\t\t 9.5 18.5\" stroke-linejoin=\"round\"></path> <path d=\"M 9.5 .5\n\t\t\t\t\t\t\t C 9.5 .5\n\t\t\t\t\t\t\t\t 13.0 3.5\n\t\t\t\t\t\t\t\t 13.0 9.5\n\t\t\t\t\t\t\t C 13.0 15.5\n\t\t\t\t\t\t\t\t 9.5 18.5\n\t\t\t\t\t\t\t\t 9.5 18.5\" stroke-linejoin=\"round\"></path> <path d=\"M .5 9.5 H 18.5\" stroke-linejoin=\"round\"></path> <path d=\"M 17.0 5.0 H 2.0\" stroke-linejoin=\"round\"></path> <path d=\"M 17.0 14.0 H 2.0\" stroke-linejoin=\"round\"></path></svg> ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var10 string
+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Language"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar.templ`, Line: 66, Col: 22}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><li id=\"nav-icon-theme\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var11 = []any{noMargin()}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form class=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var12 string
+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var11).String())
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar.templ`, Line: 1, Col: 0}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" action=\"#TODO\" method=\"POST\"><button><svg version=\"1.1\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><!-- TODO: if theme == dark -->")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if true {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<path d=\"M 7.28451 10.3333\n\t\t\t\t\t\t\t\t\t C 7.10026 10.8546\n\t\t\t\t\t\t\t\t\t\t 7 11.4156\n\t\t\t\t\t\t\t\t\t\t 7 12\n\t\t\t\t\t\t\t\t\t C 7 14.7614\n\t\t\t\t\t\t\t\t\t\t 9.23858 17\n\t\t\t\t\t\t\t\t\t\t 12 17\n\t\t\t\t\t\t\t\t\t C 14.7614 17\n\t\t\t\t\t\t\t\t\t\t 17 14.7614\n\t\t\t\t\t\t\t\t\t\t 17 12\n\t\t\t\t\t\t\t\t\t C 17 9.23858\n\t\t\t\t\t\t\t\t\t\t 14.7614 7\n\t\t\t\t\t\t\t\t\t\t 12 7\n\t\t\t\t\t\t\t\t\t C 11.4156 7\n\t\t\t\t\t\t\t\t\t\t 10.8546 7.10026\n\t\t\t\t\t\t\t\t\t\t 10.3333 7.28451\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path> <path d=\"M 12 2 V 4\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path> <path d=\"M 12 20 V 22\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path> <path d=\"M 4 12 L 2 12\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path> <path d=\"M 22 12 L 20 12\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path> <path d=\"M 19.7778 4.22266 L 17.5558 6.25424\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path> <path d=\"M 4.22217 4.22266 L 6.44418 6.25424\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path> <path d=\"M 6.44434 17.5557 L 4.22211 19.7779\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path> <path d=\"M 19.7778 19.7773 L 17.5558 17.5551\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<path d=\"M 21.0672 11.8568\n\t\t\t\t\t\t\t\t\t\t L 20.4253 11.469\n\t\t\t\t\t\t\t\t\t\t L 21.0672 11.8568\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 12.1432 2.93276\n\t\t\t\t\t\t\t\t\t\t L 11.7553 2.29085\n\t\t\t\t\t\t\t\t\t\t V 2.29085\n\t\t\t\t\t\t\t\t\t\t L 12.1432 2.93276\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 7.37554 20.013\n\t\t\t\t\t\t\t\t\t\t C 7.017 19.8056 6.5582 19.9281 6.3508 20.2866\n\t\t\t\t\t\t\t\t\t\t C 6.14339 20.6452 6.26591 21.104 6.62446 21.3114\n\t\t\t\t\t\t\t\t\t\t L 7.37554 20.013\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 2.68862 17.3755\n\t\t\t\t\t\t\t\t\t\t C 2.89602 17.7341 3.35482 17.8566 3.71337 17.6492\n\t\t\t\t\t\t\t\t\t\t C 4.07191 17.4418 4.19443 16.983 3.98703 16.6245\n\t\t\t\t\t\t\t\t\t\t L 2.68862 17.3755\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 21.25 12\n\t\t\t\t\t\t\t\t\t\t C 21.25 17.1086 17.1086 21.25 12 21.25\n\t\t\t\t\t\t\t\t\t\t V 22.75\n\t\t\t\t\t\t\t\t\t\t C 17.9371 22.75 22.75 17.9371 22.75 12\n\t\t\t\t\t\t\t\t\t\t H 21.25\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 2.75 12\n\t\t\t\t\t\t\t\t\t\t C 2.75 6.89137 6.89137 2.75 12 2.75\n\t\t\t\t\t\t\t\t\t\t V 1.25\n\t\t\t\t\t\t\t\t\t\t C 6.06294 1.25 1.25 6.06294 1.25 12\n\t\t\t\t\t\t\t\t\t\t H 2.75\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 15.5 14.25\n\t\t\t\t\t\t\t\t\t\t C 12.3244 14.25 9.75 11.6756 9.75 8.5\n\t\t\t\t\t\t\t\t\t\t H 8.25\n\t\t\t\t\t\t\t\t\t\t C 8.25 12.5041 11.4959 15.75 15.5 15.75\n\t\t\t\t\t\t\t\t\t\t V 14.25\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 20.4253 11.469\n\t\t\t\t\t\t\t\t\t\t C 19.4172 13.1373 17.5882 14.25 15.5 14.25\n\t\t\t\t\t\t\t\t\t\t V 15.75\n\t\t\t\t\t\t\t\t\t\t C 18.1349 15.75 20.4407 14.3439 21.7092 12.2447\n\t\t\t\t\t\t\t\t\t\t L 20.4253 11.469\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 9.75 8.5\n\t\t\t\t\t\t\t\t\t\t C 9.75 6.41182 10.8627 4.5828 12.531 3.57467\n\t\t\t\t\t\t\t\t\t\t L 11.7553 2.29085\n\t\t\t\t\t\t\t\t\t\t C 9.65609 3.5593 8.25 5.86509 8.25 8.5\n\t\t\t\t\t\t\t\t\t\t H 9.75\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 12 2.75\n\t\t\t\t\t\t\t\t\t\t C 11.9115 2.75 11.8077 2.71008 11.7324 2.63168\n\t\t\t\t\t\t\t\t\t\t C 11.6686 2.56527 11.6538 2.50244 11.6503 2.47703\n\t\t\t\t\t\t\t\t\t\t C 11.6461 2.44587 11.6482 2.35557 11.7553 2.29085\n\t\t\t\t\t\t\t\t\t\t L 12.531 3.57467\n\t\t\t\t\t\t\t\t\t\t C 13.0342 3.27065 13.196 2.71398 13.1368 2.27627\n\t\t\t\t\t\t\t\t\t\t C 13.0754 1.82126 12.7166 1.25 12 1.25\n\t\t\t\t\t\t\t\t\t\t V 2.75\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 21.7092 12.2447\n\t\t\t\t\t\t\t\t\t\t C 21.6444 12.3518 21.5541 12.3539 21.523 12.3497\n\t\t\t\t\t\t\t\t\t\t C 21.4976 12.3462 21.4347 12.3314 21.3683 12.2676\n\t\t\t\t\t\t\t\t\t\t C 21.2899 12.1923 21.25 12.0885 21.25 12\n\t\t\t\t\t\t\t\t\t\t H 22.75\n\t\t\t\t\t\t\t\t\t\t C 22.75 11.2834 22.1787 10.9246 21.7237 10.8632\n\t\t\t\t\t\t\t\t\t\t C 21.286 10.804 20.7293 10.9658 20.4253 11.469\n\t\t\t\t\t\t\t\t\t\t L 21.7092 12.2447\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 12 21.25\n\t\t\t\t\t\t\t\t\t\t C 10.3139 21.25 8.73533 20.7996 7.37554 20.013\n\t\t\t\t\t\t\t\t\t\t L 6.62446 21.3114\n\t\t\t\t\t\t\t\t\t\t C 8.2064 22.2265 10.0432 22.75 12 22.75\n\t\t\t\t\t\t\t\t\t\t V 21.25\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t\t M 3.98703 16.6245\n\t\t\t\t\t\t\t\t\t\t C 3.20043 15.2647 2.75 13.6861 2.75 12\n\t\t\t\t\t\t\t\t\t\t H 1.25\n\t\t\t\t\t\t\t\t\t\t C 1.25 13.9568 1.77351 15.7936 2.68862 17.3755\n\t\t\t\t\t\t\t\t\t\t L 3.98703 16.6245\n\t\t\t\t\t\t\t\t\t\t Z\n\t\t\t\t\t\t\t\t\t \"></path>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</svg></button></form></li></menu></nav>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func noMargin() templ.CSSClass {
+ templ_7745c5c3_CSSBuilder := templruntime.GetBuilder()
+ templ_7745c5c3_CSSBuilder.WriteString(`margin:0;`)
+ templ_7745c5c3_CSSID := templ.CSSID(`noMargin`, templ_7745c5c3_CSSBuilder.String())
+ return templ.ComponentCSSClass{
+ ID: templ_7745c5c3_CSSID,
+ Class: templ.SafeCSS(`.` + templ_7745c5c3_CSSID + `{` + templ_7745c5c3_CSSBuilder.String() + `}`),
+ }
+}
diff --git a/templates/root.templ b/templates/root.templ
new file mode 100644
index 0000000..d372766
--- /dev/null
+++ b/templates/root.templ
@@ -0,0 +1,101 @@
+package templates
+
+import "strings"
+import "git.thomasvoss.com/euro-cash.eu/i18n"
+
+templ Root(head, body templ.Component) {
+ {{ p := ctx.Value(PrinterKey).(i18n.Printer) }}
+
+ <!DOCTYPE html>
+ <html lang={ p.Lang } data-theme="dark">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <title>Euro Cash</title>
+ if head != nil {
+ @head
+ }
+ </head>
+ <body>
+ if body != nil {
+ @body
+ }
+ <footer>
+ <p>
+ <small>
+ { p.T("Found a mistake or want to contribute missing information?") }
+ <a href="/">{ p.T("Feel free to contact us!") }</a>
+ </small>
+ </p>
+ </footer>
+ </body>
+ </html>
+}
+
+templ Index() {
+ {{ p := ctx.Value(PrinterKey).(i18n.Printer) }}
+
+ <header>
+ @navbar()
+ <h1>{ p.T("The Euro Cash Compendium") }</h1>
+ <p>
+ { p.T("United in") }
+ <del>{ p.T("diversity") }</del>
+ <ins>{ p.T("cash") }</ins>
+ </p>
+ <p>{ p.T("Växjö has %d people", 70_489) }</p>
+ </header>
+}
+
+templ SetLanguage() {
+ {{ p := ctx.Value(PrinterKey).(i18n.Printer) }}
+
+ <header>
+ @navbar()
+ <h1>{ p.T("Select Your Language") }</h1>
+ </header>
+
+ <main>
+ <p>
+ { p.T("Select your preferred language to use on the site.") }
+ </p>
+ <p>
+ If you are an American user, it’s suggested that you select
+ American English instead of British English. This will ensure that
+ dates will be formatted with the month before the day.
+ </p>
+
+ <hr />
+
+ <h2>{ p.T("Eurozone Languages") }</h2>
+ @languageGrid(true)
+
+ <h2>{ p.T("Other Languages") }</h2>
+ @languageGrid(false)
+ </main>
+}
+
+templ languageGrid(eurozone bool) {
+ <form action="/language" method="POST">
+ <div class="lang-grid">
+ for _, loc := range i18n.Locales {
+ if loc.Eurozone == eurozone {
+ <button
+ type="submit"
+ name={ LocaleKey }
+ value={ loc.Code }
+ disabled?={ !loc.Enabled }
+ >
+ <span
+ lang={ loc.Code }
+ data-code={ strings.ToUpper(loc.Language()) }
+ >
+ { loc.Name }
+ </span>
+ </button>
+ }
+ }
+ </div>
+ </form>
+}
diff --git a/templates/root_templ.go b/templates/root_templ.go
new file mode 100644
index 0000000..d35ddd2
--- /dev/null
+++ b/templates/root_templ.go
@@ -0,0 +1,414 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.2.747
+package templates
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+import "strings"
+import "git.thomasvoss.com/euro-cash.eu/i18n"
+
+func Root(head, body templ.Component) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var1 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var1 == nil {
+ templ_7745c5c3_Var1 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ p := ctx.Value(PrinterKey).(i18n.Printer)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html lang=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var2 string
+ templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(p.Lang)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 10, Col: 20}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-theme=\"dark\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\"><title>Euro Cash</title>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if head != nil {
+ templ_7745c5c3_Err = head.Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</head><body>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if body != nil {
+ templ_7745c5c3_Err = body.Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<footer><p><small>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var3 string
+ templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Found a mistake or want to contribute missing information?"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 27, Col: 73}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <a href=\"/\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var4 string
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Feel free to contact us!"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 28, Col: 51}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></small></p></footer></body></html>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func Index() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var5 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var5 == nil {
+ templ_7745c5c3_Var5 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ p := ctx.Value(PrinterKey).(i18n.Printer)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<header>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = navbar().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var6 string
+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("The Euro Cash Compendium"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 41, Col: 39}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1><p>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var7 string
+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("United in"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 43, Col: 21}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <del>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var8 string
+ templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("diversity"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 44, Col: 26}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</del> <ins>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var9 string
+ templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("cash"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 45, Col: 21}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ins></p><p>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var10 string
+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Växjö has %d people", 70_489))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 47, Col: 43}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p></header>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func SetLanguage() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var11 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var11 == nil {
+ templ_7745c5c3_Var11 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ p := ctx.Value(PrinterKey).(i18n.Printer)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<header>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = navbar().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var12 string
+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Select Your Language"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 56, Col: 35}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1></header><main><p>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var13 string
+ templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Select your preferred language to use on the site."))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 61, Col: 62}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><p>If you are an American user, it’s suggested that you select American English instead of British English. This will ensure that dates will be formatted with the month before the day. </p><hr><h2>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var14 string
+ templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Eurozone Languages"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 71, Col: 33}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h2>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = languageGrid(true).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h2>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var15 string
+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(p.T("Other Languages"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 74, Col: 30}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h2>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = languageGrid(false).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</main>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func languageGrid(eurozone bool) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var16 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var16 == nil {
+ templ_7745c5c3_Var16 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form action=\"/language\" method=\"POST\"><div class=\"lang-grid\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, loc := range i18n.Locales {
+ if loc.Eurozone == eurozone {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button type=\"submit\" name=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var17 string
+ templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(LocaleKey)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 86, Col: 22}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" value=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var18 string
+ templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(loc.Code)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 87, Col: 22}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if !loc.Enabled {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" disabled")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("><span lang=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var19 string
+ templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(loc.Code)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 91, Col: 22}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-code=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var20 string
+ templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(strings.ToUpper(loc.Language()))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 92, Col: 50}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var21 string
+ templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(loc.Name)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `root.templ`, Line: 94, Col: 17}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span></button>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></form>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
diff --git a/vendor/github.com/a-h/templ/.dockerignore b/vendor/github.com/a-h/templ/.dockerignore
new file mode 100644
index 0000000..17896fe
--- /dev/null
+++ b/vendor/github.com/a-h/templ/.dockerignore
@@ -0,0 +1,3 @@
+.git
+Dockerfile
+.dockerignore
diff --git a/vendor/github.com/a-h/templ/.gitignore b/vendor/github.com/a-h/templ/.gitignore
new file mode 100644
index 0000000..0338eda
--- /dev/null
+++ b/vendor/github.com/a-h/templ/.gitignore
@@ -0,0 +1,28 @@
+# Output.
+cmd/templ/templ
+
+# Logs.
+cmd/templ/lspcmd/*log.txt
+
+# Go code coverage.
+coverage.out
+coverage
+
+# Mac filesystem jank.
+.DS_Store
+
+# Docusaurus.
+docs/build/
+docs/resources/_gen/
+node_modules/
+dist/
+
+# Nix artifacts.
+result
+
+# Editors
+## nvim
+.null-ls*
+
+# Go workspace.
+go.work
diff --git a/vendor/github.com/a-h/templ/.goreleaser.yaml b/vendor/github.com/a-h/templ/.goreleaser.yaml
new file mode 100644
index 0000000..456187c
--- /dev/null
+++ b/vendor/github.com/a-h/templ/.goreleaser.yaml
@@ -0,0 +1,72 @@
+builds:
+ - env:
+ - CGO_ENABLED=0
+ dir: cmd/templ
+ mod_timestamp: '{{ .CommitTimestamp }}'
+ flags:
+ - -trimpath
+ ldflags:
+ - -s -w
+ goos:
+ - linux
+ - windows
+ - darwin
+
+checksum:
+ name_template: 'checksums.txt'
+
+signs:
+ - id: checksums
+ cmd: cosign
+ stdin: '{{ .Env.COSIGN_PASSWORD }}'
+ output: true
+ artifacts: checksum
+ args:
+ - sign-blob
+ - --yes
+ - --key
+ - env://COSIGN_PRIVATE_KEY
+ - '--output-certificate=${certificate}'
+ - '--output-signature=${signature}'
+ - '${artifact}'
+
+archives:
+ - format: tar.gz
+ name_template: >-
+ {{ .ProjectName }}_
+ {{- title .Os }}_
+ {{- if eq .Arch "amd64" }}x86_64
+ {{- else if eq .Arch "386" }}i386
+ {{- else }}{{ .Arch }}{{ end }}
+ {{- if .Arm }}v{{ .Arm }}{{ end }}
+
+kos:
+ - repository: ghcr.io/a-h/templ
+ platforms:
+ - linux/amd64
+ - linux/arm64
+ tags:
+ - latest
+ - '{{.Tag}}'
+ bare: true
+
+docker_signs:
+ - cmd: cosign
+ artifacts: all
+ output: true
+ args:
+ - sign
+ - --yes
+ - --key
+ - env://COSIGN_PRIVATE_KEY
+ - '${artifact}'
+
+snapshot:
+ name_template: "{{ incpatch .Version }}-next"
+
+changelog:
+ sort: asc
+ filters:
+ exclude:
+ - '^docs:'
+ - '^test:'
diff --git a/vendor/github.com/a-h/templ/.ignore b/vendor/github.com/a-h/templ/.ignore
new file mode 100644
index 0000000..21cb25e
--- /dev/null
+++ b/vendor/github.com/a-h/templ/.ignore
@@ -0,0 +1,7 @@
+*_templ.go
+examples/integration-ct/static/index.js
+examples/counter/assets/css/bulma.*
+examples/counter/assets/js/htmx.min.js
+examples/counter-basic/assets/css/bulma.*
+examples/typescript/assets/index.js
+package-lock.json
diff --git a/vendor/github.com/a-h/templ/.version b/vendor/github.com/a-h/templ/.version
new file mode 100644
index 0000000..baee64f
--- /dev/null
+++ b/vendor/github.com/a-h/templ/.version
@@ -0,0 +1 @@
+0.2.747 \ No newline at end of file
diff --git a/vendor/github.com/a-h/templ/CODE_OF_CONDUCT.md b/vendor/github.com/a-h/templ/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..08340d3
--- /dev/null
+++ b/vendor/github.com/a-h/templ/CODE_OF_CONDUCT.md
@@ -0,0 +1,128 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+ overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+ advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+ address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+adrianhesketh@hushail.com.
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.0, available at
+https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct
+enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
+https://www.contributor-covenant.org/translations.
diff --git a/vendor/github.com/a-h/templ/CONTRIBUTING.md b/vendor/github.com/a-h/templ/CONTRIBUTING.md
new file mode 100644
index 0000000..e98d31f
--- /dev/null
+++ b/vendor/github.com/a-h/templ/CONTRIBUTING.md
@@ -0,0 +1,244 @@
+# Contributing to templ
+
+## Vision
+
+Enable Go developers to build strongly typed, component-based HTML user interfaces with first-class developer tooling, and a short learning curve.
+
+## Come up with a design and share it
+
+Before starting work on any major pull requests or code changes, start a discussion at https://github.com/a-h/templ/discussions or raise an issue.
+
+We don't want you to spend time on a PR or feature that ultimately doesn't get merged because it doesn't fit with the project goals, or the design doesn't work for some reason.
+
+For issues, it really helps if you provide a reproduction repo, or can create a failing unit test to describe the behaviour.
+
+In designs, we need to consider:
+
+* Backwards compatibility - Not changing the public API between releases, introducing gradual deprecation - don't break people's code.
+* Correctness over time - How can we reduce the risk of defects both now, and in future releases?
+* Threat model - How could each change be used to inject vulnerabilities into web pages?
+* Go version - We target the oldest supported version of Go as per https://go.dev/doc/devel/release
+* Automatic migration - If we need to force through a change.
+* Compile time vs runtime errors - Prefer compile time.
+* Documentation - New features are only useful if people can understand the new feature, what would the documentation look like?
+* Examples - How will we demonstrate the feature?
+
+## Project structure
+
+templ is structured into a few areas:
+
+### Parser `./parser`
+
+The parser directory currently contains both v1 and v2 parsers.
+
+The v1 parser is not maintained, it's only used to migrate v1 code over to the v2 syntax.
+
+The parser is responsible for parsing templ files into an object model. The types that make up the object model are in `types.go`. Automatic formatting of the types is tested in `types_test.go`.
+
+A templ file is parsed into the `TemplateFile` struct object model.
+
+```go
+type TemplateFile struct {
+ // Header contains comments or whitespace at the top of the file.
+ Header []GoExpression
+ // Package expression.
+ Package Package
+ // Nodes in the file.
+ Nodes []TemplateFileNode
+}
+```
+
+Parsers are individually tested using two types of unit test.
+
+One test covers the successful parsing of text into an object. For example, the `HTMLCommentParser` test checks for successful patterns.
+
+```go
+func TestHTMLCommentParser(t *testing.T) {
+ var tests = []struct {
+ name string
+ input string
+ expected HTMLComment
+ }{
+ {
+ name: "comment - single line",
+ input: `<!-- single line comment -->`,
+ expected: HTMLComment{
+ Contents: " single line comment ",
+ },
+ },
+ {
+ name: "comment - no whitespace",
+ input: `<!--no whitespace between sequence open and close-->`,
+ expected: HTMLComment{
+ Contents: "no whitespace between sequence open and close",
+ },
+ },
+ {
+ name: "comment - multiline",
+ input: `<!-- multiline
+ comment
+ -->`,
+ expected: HTMLComment{
+ Contents: ` multiline
+ comment
+ `,
+ },
+ },
+ {
+ name: "comment - with tag",
+ input: `<!-- <p class="test">tag</p> -->`,
+ expected: HTMLComment{
+ Contents: ` <p class="test">tag</p> `,
+ },
+ },
+ {
+ name: "comments can contain tags",
+ input: `<!-- <div> hello world </div> -->`,
+ expected: HTMLComment{
+ Contents: ` <div> hello world </div> `,
+ },
+ },
+ }
+ for _, tt := range tests {
+ tt := tt
+ t.Run(tt.name, func(t *testing.T) {
+ input := parse.NewInput(tt.input)
+ result, ok, err := htmlComment.Parse(input)
+ if err != nil {
+ t.Fatalf("parser error: %v", err)
+ }
+ if !ok {
+ t.Fatalf("failed to parse at %d", input.Index())
+ }
+ if diff := cmp.Diff(tt.expected, result); diff != "" {
+ t.Errorf(diff)
+ }
+ })
+ }
+}
+```
+
+Alongside each success test, is a similar test to check that invalid syntax is detected.
+
+```go
+func TestHTMLCommentParserErrors(t *testing.T) {
+ var tests = []struct {
+ name string
+ input string
+ expected error
+ }{
+ {
+ name: "unclosed HTML comment",
+ input: `<!-- unclosed HTML comment`,
+ expected: parse.Error("expected end comment literal '-->' not found",
+ parse.Position{
+ Index: 26,
+ Line: 0,
+ Col: 26,
+ }),
+ },
+ {
+ name: "comment in comment",
+ input: `<!-- <-- other --> -->`,
+ expected: parse.Error("comment contains invalid sequence '--'", parse.Position{
+ Index: 8,
+ Line: 0,
+ Col: 8,
+ }),
+ },
+ }
+ for _, tt := range tests {
+ tt := tt
+ t.Run(tt.name, func(t *testing.T) {
+ input := parse.NewInput(tt.input)
+ _, _, err := htmlComment.Parse(input)
+ if diff := cmp.Diff(tt.expected, err); diff != "" {
+ t.Error(diff)
+ }
+ })
+ }
+}
+```
+
+### Generator
+
+The generator takes the object model and writes out Go code that produces the expected output. Any changes to Go code output by templ are made in this area.
+
+Testing of the generator is carried out by creating a templ file, and a matching expected output file.
+
+For example, `./generator/test-a-href` contains a templ file of:
+
+```templ
+package testahref
+
+templ render() {
+ <a href="javascript:alert(&#39;unaffected&#39;);">Ignored</a>
+ <a href={ templ.URL("javascript:alert('should be sanitized')") }>Sanitized</a>
+ <a href={ templ.SafeURL("javascript:alert('should not be sanitized')") }>Unsanitized</a>
+}
+```
+
+It also contains an expected output file.
+
+```html
+<a href="javascript:alert(&#39;unaffected&#39;);">Ignored</a>
+<a href="about:invalid#TemplFailedSanitizationURL">Sanitized</a>
+<a href="javascript:alert(&#39;should not be sanitized&#39;)">Unsanitized</a>
+```
+
+These tests contribute towards the code coverage metrics by building an instrumented test CLI program. See the `test-cover` task in the `README.md` file.
+
+### CLI
+
+The command line interface for templ is used to generate Go code from templ files, format templ files, and run the LSP.
+
+The code for this is at `./cmd/templ`.
+
+Testing of the templ command line is done with unit tests to check the argument parsing.
+
+The `templ generate` command is tested by generating templ files in the project, and testing that the expected output HTML is present.
+
+### Runtime
+
+The runtime is used by generated code, and by template authors, to serve template content over HTTP, and to carry out various operations.
+
+It is in the root directory of the project at `./runtime.go`. The runtime is unit tested, as well as being tested as part of the `generate` tests.
+
+### LSP
+
+The LSP is structured within the command line interface, and proxies commands through to the `gopls` LSP.
+
+### Docs
+
+The docs are a Docusaurus project at `./docs`.
+
+## Coding
+
+### Build tasks
+
+templ uses the `xc` task runner - https://github.com/joerdav/xc
+
+If you run `xc` you can get see a list of the development tasks that can be run, or you can read the `README.md` file and see the `Tasks` section.
+
+The most useful tasks for local development are:
+
+* `install-snapshot` - this builds the templ CLI and installs it into `~/bin`. Ensure that this is in your path.
+* `test` - this regenerates all templates, and runs the unit tests.
+* `fmt` - run the `gofmt` tool to format all Go code.
+* `lint` - run the same linting as run in the CI process.
+* `docs-run` - run the Docusaurus documentation site.
+
+### Commit messages
+
+The project using https://www.conventionalcommits.org/en/v1.0.0/
+
+Examples:
+
+* `feat: support Go comments in templates, fixes #234"`
+
+### Coding style
+
+* Reduce nesting - i.e. prefer early returns over an `else` block, as per https://danp.net/posts/reducing-go-nesting/ or https://go.dev/doc/effective_go#if
+* Use line breaks to separate "paragraphs" of code - don't use line breaks in between lines, or at the start/end of functions etc.
+* Use the `fmt` and `lint` build tasks to format and lint your code before submitting a PR.
+
diff --git a/vendor/github.com/a-h/templ/LICENSE b/vendor/github.com/a-h/templ/LICENSE
new file mode 100644
index 0000000..15e6fb8
--- /dev/null
+++ b/vendor/github.com/a-h/templ/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Adrian Hesketh
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/a-h/templ/README.md b/vendor/github.com/a-h/templ/README.md
new file mode 100644
index 0000000..e3087f0
--- /dev/null
+++ b/vendor/github.com/a-h/templ/README.md
@@ -0,0 +1,171 @@
+![templ](https://github.com/a-h/templ/raw/main/templ.png)
+
+## An HTML templating language for Go that has great developer tooling.
+
+![templ](ide-demo.gif)
+
+
+## Documentation
+
+See user documentation at https://templ.guide
+
+<p align="center">
+<a href="https://pkg.go.dev/github.com/a-h/templ"><img src="https://pkg.go.dev/badge/github.com/a-h/templ.svg" alt="Go Reference" /></a>
+<a href="https://xcfile.dev"><img src="https://xcfile.dev/badge.svg" alt="xc compatible" /></a>
+<a href="https://raw.githack.com/wiki/a-h/templ/coverage.html"><img src="https://github.com/a-h/templ/wiki/coverage.svg" alt="Go Coverage" /></a>
+<a href="https://goreportcard.com/report/github.com/a-h/templ"><img src="https://goreportcard.com/badge/github.com/a-h/templ" alt="Go Report Card" /></a<
+</p>
+
+## Tasks
+
+### build
+
+Build a local version.
+
+```sh
+go run ./get-version > .version
+cd cmd/templ
+go build
+```
+
+### nix-update-gomod2nix
+
+```sh
+gomod2nix
+```
+
+### install-snapshot
+
+Build and install current version.
+
+```sh
+# Remove templ from the non-standard ~/bin/templ path
+# that this command previously used.
+rm -f ~/bin/templ
+# Clear LSP logs.
+rm -f cmd/templ/lspcmd/*.txt
+# Update version.
+go run ./get-version > .version
+# Install to $GOPATH/bin or $HOME/go/bin
+cd cmd/templ && go install
+```
+
+### build-snapshot
+
+Use goreleaser to build the command line binary using goreleaser.
+
+```sh
+goreleaser build --snapshot --clean
+```
+
+### generate
+
+Run templ generate using local version.
+
+```sh
+go run ./cmd/templ generate -include-version=false
+```
+
+### test
+
+Run Go tests.
+
+```sh
+go run ./get-version > .version
+go run ./cmd/templ generate -include-version=false
+go test ./...
+```
+
+### test-short
+
+Run Go tests.
+
+```sh
+go run ./get-version > .version
+go run ./cmd/templ generate -include-version=false
+go test ./... -short
+```
+
+### test-cover
+
+Run Go tests.
+
+```sh
+# Create test profile directories.
+mkdir -p coverage/fmt
+mkdir -p coverage/generate
+mkdir -p coverage/version
+mkdir -p coverage/unit
+# Build the test binary.
+go build -cover -o ./coverage/templ-cover ./cmd/templ
+# Run the covered generate command.
+GOCOVERDIR=coverage/fmt ./coverage/templ-cover fmt .
+GOCOVERDIR=coverage/generate ./coverage/templ-cover generate -include-version=false
+GOCOVERDIR=coverage/version ./coverage/templ-cover version
+# Run the unit tests.
+go test -cover ./... -coverpkg ./... -args -test.gocoverdir="$PWD/coverage/unit"
+# Display the combined percentage.
+go tool covdata percent -i=./coverage/fmt,./coverage/generate,./coverage/version,./coverage/unit
+# Generate a text coverage profile for tooling to use.
+go tool covdata textfmt -i=./coverage/fmt,./coverage/generate,./coverage/version,./coverage/unit -o coverage.out
+# Print total
+go tool cover -func coverage.out | grep total
+```
+
+### test-cover-watch
+
+```sh
+gotestsum --watch -- -coverprofile=coverage.out
+```
+
+### benchmark
+
+Run benchmarks.
+
+```sh
+go run ./cmd/templ generate -include-version=false && go test ./... -bench=. -benchmem
+```
+
+### fmt
+
+Format all Go and templ code.
+
+```sh
+gofmt -s -w .
+go run ./cmd/templ fmt .
+```
+
+### lint
+
+```sh
+golangci-lint run --verbose
+```
+
+### push-release-tag
+
+Push a semantic version number to Github to trigger the release process.
+
+```sh
+./push-tag.sh
+```
+
+### docs-run
+
+Run the development server.
+
+Directory: docs
+
+```sh
+npm run start
+```
+
+### docs-build
+
+Build production docs site.
+
+Directory: docs
+
+```sh
+npm run build
+```
+
diff --git a/vendor/github.com/a-h/templ/SECURITY.md b/vendor/github.com/a-h/templ/SECURITY.md
new file mode 100644
index 0000000..8241f55
--- /dev/null
+++ b/vendor/github.com/a-h/templ/SECURITY.md
@@ -0,0 +1,9 @@
+# Security Policy
+
+## Supported Versions
+
+The latest version of templ is supported.
+
+## Reporting a Vulnerability
+
+Use the "Security" tab in Github and fill out the "Report a vulnerability" form.
diff --git a/vendor/github.com/a-h/templ/cosign.pub b/vendor/github.com/a-h/templ/cosign.pub
new file mode 100644
index 0000000..9d7967b
--- /dev/null
+++ b/vendor/github.com/a-h/templ/cosign.pub
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqHp75uAj8XqKrLO2YvY0M2EddckH
+evQnNAj+0GmBptqdf3NJcUCjL6w4z2Ikh/Zb8lh6b13akAwO/dJQaMLoMA==
+-----END PUBLIC KEY-----
diff --git a/vendor/github.com/a-h/templ/flake.lock b/vendor/github.com/a-h/templ/flake.lock
new file mode 100644
index 0000000..af4e370
--- /dev/null
+++ b/vendor/github.com/a-h/templ/flake.lock
@@ -0,0 +1,140 @@
+{
+ "nodes": {
+ "flake-utils": {
+ "inputs": {
+ "systems": "systems"
+ },
+ "locked": {
+ "lastModified": 1694529238,
+ "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "flake-utils_2": {
+ "locked": {
+ "lastModified": 1667395993,
+ "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "gitignore": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1709087332,
+ "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+ "owner": "hercules-ci",
+ "repo": "gitignore.nix",
+ "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "gitignore.nix",
+ "type": "github"
+ }
+ },
+ "gomod2nix": {
+ "inputs": {
+ "flake-utils": "flake-utils",
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1717050755,
+ "narHash": "sha256-C9IEHABulv2zEDFA+Bf0E1nmfN4y6MIUe5eM2RCrDC0=",
+ "owner": "nix-community",
+ "repo": "gomod2nix",
+ "rev": "31b6d2e40b36456e792cd6cf50d5a8ddd2fa59a1",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "gomod2nix",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1720096762,
+ "narHash": "sha256-KvpJIWxTNuaSpN2L/9TmTlEhlwxEnzJ1vCpEcfK/4mQ=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "638369f687471823770f6d3093f1721dc7b8c897",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "release-24.05",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "gitignore": "gitignore",
+ "gomod2nix": "gomod2nix",
+ "nixpkgs": "nixpkgs",
+ "xc": "xc"
+ }
+ },
+ "systems": {
+ "locked": {
+ "lastModified": 1681028828,
+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+ "owner": "nix-systems",
+ "repo": "default",
+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-systems",
+ "repo": "default",
+ "type": "github"
+ }
+ },
+ "xc": {
+ "inputs": {
+ "flake-utils": "flake-utils_2",
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1717601811,
+ "narHash": "sha256-+XQvDRXpzjBdZI3JGKP6SAOYXM+JSEbWL5kqtCwRJXE=",
+ "owner": "joerdav",
+ "repo": "xc",
+ "rev": "f8e8e658978d6c9fe49c27b684ca7375a74deef1",
+ "type": "github"
+ },
+ "original": {
+ "owner": "joerdav",
+ "repo": "xc",
+ "type": "github"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/vendor/github.com/a-h/templ/flake.nix b/vendor/github.com/a-h/templ/flake.nix
new file mode 100644
index 0000000..fd8a238
--- /dev/null
+++ b/vendor/github.com/a-h/templ/flake.nix
@@ -0,0 +1,93 @@
+{
+ description = "templ";
+
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/release-24.05";
+ gomod2nix = {
+ url = "github:nix-community/gomod2nix";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+ gitignore = {
+ url = "github:hercules-ci/gitignore.nix";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+ xc = {
+ url = "github:joerdav/xc";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+ };
+
+ outputs = { self, nixpkgs, gomod2nix, gitignore, xc }:
+ let
+ allSystems = [
+ "x86_64-linux" # 64-bit Intel/AMD Linux
+ "aarch64-linux" # 64-bit ARM Linux
+ "x86_64-darwin" # 64-bit Intel macOS
+ "aarch64-darwin" # 64-bit ARM macOS
+ ];
+ forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f {
+ inherit system;
+ pkgs = import nixpkgs { inherit system; };
+ });
+ in
+ {
+ packages = forAllSystems ({ system, pkgs, ... }:
+ let
+ buildGoApplication = gomod2nix.legacyPackages.${system}.buildGoApplication;
+ in
+ rec {
+ default = templ;
+
+ templ = buildGoApplication {
+ name = "templ";
+ src = gitignore.lib.gitignoreSource ./.;
+ # Update to latest Go version when https://nixpk.gs/pr-tracker.html?pr=324123 is backported to release-24.05.
+ go = pkgs.go;
+ # Must be added due to bug https://github.com/nix-community/gomod2nix/issues/120
+ pwd = ./.;
+ subPackages = [ "cmd/templ" ];
+ CGO_ENABLED = 0;
+ flags = [
+ "-trimpath"
+ ];
+ ldflags = [
+ "-s"
+ "-w"
+ "-extldflags -static"
+ ];
+ };
+ });
+
+ # `nix develop` provides a shell containing development tools.
+ devShell = forAllSystems ({ system, pkgs }:
+ pkgs.mkShell {
+ buildInputs = with pkgs; [
+ (golangci-lint.override { buildGoModule = buildGo121Module; })
+ cosign # Used to sign container images.
+ esbuild # Used to package JS examples.
+ go_1_21
+ gomod2nix.legacyPackages.${system}.gomod2nix
+ gopls
+ goreleaser
+ gotestsum
+ ko # Used to build Docker images.
+ nodejs # Used to build templ-docs.
+ xc.packages.${system}.xc
+ ];
+ });
+
+ # This flake outputs an overlay that can be used to add templ and
+ # templ-docs to nixpkgs as per https://templ.guide/quick-start/installation/#nix
+ #
+ # Example usage:
+ #
+ # nixpkgs.overlays = [
+ # inputs.templ.overlays.default
+ # ];
+ overlays.default = final: prev: {
+ templ = self.packages.${final.stdenv.system}.templ;
+ templ-docs = self.packages.${final.stdenv.system}.templ-docs;
+ };
+ };
+}
+
diff --git a/vendor/github.com/a-h/templ/flush.go b/vendor/github.com/a-h/templ/flush.go
new file mode 100644
index 0000000..56d7d3a
--- /dev/null
+++ b/vendor/github.com/a-h/templ/flush.go
@@ -0,0 +1,36 @@
+package templ
+
+import (
+ "context"
+ "io"
+)
+
+// Flush flushes the output buffer after all its child components have been rendered.
+func Flush() FlushComponent {
+ return FlushComponent{}
+}
+
+type FlushComponent struct {
+}
+
+type flusherError interface {
+ Flush() error
+}
+
+type flusher interface {
+ Flush()
+}
+
+func (f FlushComponent) Render(ctx context.Context, w io.Writer) (err error) {
+ if err = GetChildren(ctx).Render(ctx, w); err != nil {
+ return err
+ }
+ switch w := w.(type) {
+ case flusher:
+ w.Flush()
+ return nil
+ case flusherError:
+ return w.Flush()
+ }
+ return nil
+}
diff --git a/vendor/github.com/a-h/templ/gomod2nix.toml b/vendor/github.com/a-h/templ/gomod2nix.toml
new file mode 100644
index 0000000..d572a5f
--- /dev/null
+++ b/vendor/github.com/a-h/templ/gomod2nix.toml
@@ -0,0 +1,90 @@
+schema = 3
+
+[mod]
+ [mod."github.com/PuerkitoBio/goquery"]
+ version = "v1.8.1"
+ hash = "sha256-z2RaB8PVPEzSJdMUfkfNjT616yXWTjW2gkhNOh989ZU="
+ [mod."github.com/a-h/htmlformat"]
+ version = "v0.0.0-20231108124658-5bd994fe268e"
+ hash = "sha256-YSl9GsXhc0L2oKGZLwwjUtpe5W6ra6kk74zvQdsDCMU="
+ [mod."github.com/a-h/parse"]
+ version = "v0.0.0-20240121214402-3caf7543159a"
+ hash = "sha256-ee/g6xwwhtF7vVt3griUSh96Kz4z0hM5/tpXxHW6PZk="
+ [mod."github.com/a-h/pathvars"]
+ version = "v0.0.14"
+ hash = "sha256-2NytUpcO0zbzE5XunCLcK3jDqxYzmyb3WqtYDEudAYg="
+ [mod."github.com/a-h/protocol"]
+ version = "v0.0.0-20240704131721-1e461c188041"
+ hash = "sha256-KSw8m+kVIubEi+nuS3dMdBw2ZZTlmcKD/hGbVRFaE5Q="
+ [mod."github.com/andybalholm/brotli"]
+ version = "v1.1.0"
+ hash = "sha256-njLViV4v++ZdgOWGWzlvkefuFvA/nkugl3Ta/h1nu/0="
+ [mod."github.com/andybalholm/cascadia"]
+ version = "v1.3.1"
+ hash = "sha256-M0u22DXSeXUaYtl1KoW1qWL46niFpycFkraCEQ/luYA="
+ [mod."github.com/cenkalti/backoff/v4"]
+ version = "v4.3.0"
+ hash = "sha256-wfVjNZsGG1WoNC5aL+kdcy6QXPgZo4THAevZ1787md8="
+ [mod."github.com/cli/browser"]
+ version = "v1.3.0"
+ hash = "sha256-06hcvQeOEm31clxkTuZ8ts8ZtdNKY575EsM1osRVpLg="
+ [mod."github.com/fatih/color"]
+ version = "v1.16.0"
+ hash = "sha256-Aq/SM28aPJVzvapllQ64R/DM4aZ5CHPewcm/AUJPyJQ="
+ [mod."github.com/fsnotify/fsnotify"]
+ version = "v1.7.0"
+ hash = "sha256-MdT2rQyQHspPJcx6n9ozkLbsktIOJutOqDuKpNAtoZY="
+ [mod."github.com/google/go-cmp"]
+ version = "v0.6.0"
+ hash = "sha256-qgra5jze4iPGP0JSTVeY5qV5AvEnEu39LYAuUCIkMtg="
+ [mod."github.com/mattn/go-colorable"]
+ version = "v0.1.13"
+ hash = "sha256-qb3Qbo0CELGRIzvw7NVM1g/aayaz4Tguppk9MD2/OI8="
+ [mod."github.com/mattn/go-isatty"]
+ version = "v0.0.20"
+ hash = "sha256-qhw9hWtU5wnyFyuMbKx+7RB8ckQaFQ8D+8GKPkN3HHQ="
+ [mod."github.com/natefinch/atomic"]
+ version = "v1.0.1"
+ hash = "sha256-fbOVHCwRNI8PFjC4o0YXpKZO0JU2aWTfH5c7WXXKMHg="
+ [mod."github.com/rs/cors"]
+ version = "v1.11.0"
+ hash = "sha256-hF25bVehtWCQsxiOfLuL4Hv8NKVunEqLPk/Vcuheha0="
+ [mod."github.com/segmentio/asm"]
+ version = "v1.2.0"
+ hash = "sha256-zbNuKxNrUDUc6IlmRQNuJQzVe5Ol/mqp7srDg9IMMqs="
+ [mod."github.com/segmentio/encoding"]
+ version = "v0.4.0"
+ hash = "sha256-4pWI9eTZRRDP9kO8rG6vbLCtBVVRLtbCJKd0Z2+8JoU="
+ [mod."github.com/stretchr/testify"]
+ version = "v1.8.4"
+ hash = "sha256-MoOmRzbz9QgiJ+OOBo5h5/LbilhJfRUryvzHJmXAWjo="
+ [mod."go.lsp.dev/jsonrpc2"]
+ version = "v0.10.0"
+ hash = "sha256-RbRsMYVBLR7ZDHHGMooycrkdbIauMXkQjVOGP7ggSgM="
+ [mod."go.lsp.dev/pkg"]
+ version = "v0.0.0-20210717090340-384b27a52fb2"
+ hash = "sha256-TxS0Iqe1wbIaFe7MWZJRQdgqhKE8i8CggaGSV9zU1Vg="
+ [mod."go.lsp.dev/uri"]
+ version = "v0.3.0"
+ hash = "sha256-jGP0N7Gf+bql5oJraUo33sXqWg7AKOTj0D8b4paV4dc="
+ [mod."go.uber.org/multierr"]
+ version = "v1.11.0"
+ hash = "sha256-Lb6rHHfR62Ozg2j2JZy3MKOMKdsfzd1IYTR57r3Mhp0="
+ [mod."go.uber.org/zap"]
+ version = "v1.27.0"
+ hash = "sha256-8655KDrulc4Das3VRduO9MjCn8ZYD5WkULjCvruaYsU="
+ [mod."golang.org/x/mod"]
+ version = "v0.17.0"
+ hash = "sha256-CLaPeF6uTFuRDv4oHwOQE6MCMvrzkUjWN3NuyywZjKU="
+ [mod."golang.org/x/net"]
+ version = "v0.24.0"
+ hash = "sha256-w1c21ljta5wNIyel9CSIn/crPzwOCRofNKhqmfs4aEQ="
+ [mod."golang.org/x/sync"]
+ version = "v0.3.0"
+ hash = "sha256-bCJKLvwExhYacH2ZrWlZ38lr1d6oNenNt2m1QqDCs0o="
+ [mod."golang.org/x/sys"]
+ version = "v0.21.0"
+ hash = "sha256-gapzPWuEqY36V6W2YhIDYR49sEvjJRd7bSuf9K1f4JY="
+ [mod."golang.org/x/tools"]
+ version = "v0.13.0"
+ hash = "sha256-OCgLOwia8fNHxfdogXVApf0/qK6jE2ukegOx7lkOzfo="
diff --git a/vendor/github.com/a-h/templ/handler.go b/vendor/github.com/a-h/templ/handler.go
new file mode 100644
index 0000000..a28d561
--- /dev/null
+++ b/vendor/github.com/a-h/templ/handler.go
@@ -0,0 +1,102 @@
+package templ
+
+import "net/http"
+
+// ComponentHandler is a http.Handler that renders components.
+type ComponentHandler struct {
+ Component Component
+ Status int
+ ContentType string
+ ErrorHandler func(r *http.Request, err error) http.Handler
+ StreamResponse bool
+}
+
+const componentHandlerErrorMessage = "templ: failed to render template"
+
+func (ch *ComponentHandler) ServeHTTPBuffered(w http.ResponseWriter, r *http.Request) {
+ // Since the component may error, write to a buffer first.
+ // This prevents partial responses from being written to the client.
+ buf := GetBuffer()
+ defer ReleaseBuffer(buf)
+ err := ch.Component.Render(r.Context(), buf)
+ if err != nil {
+ if ch.ErrorHandler != nil {
+ w.Header().Set("Content-Type", ch.ContentType)
+ ch.ErrorHandler(r, err).ServeHTTP(w, r)
+ return
+ }
+ http.Error(w, componentHandlerErrorMessage, http.StatusInternalServerError)
+ return
+ }
+ w.Header().Set("Content-Type", ch.ContentType)
+ if ch.Status != 0 {
+ w.WriteHeader(ch.Status)
+ }
+ // Ignore write error like http.Error() does, because there is
+ // no way to recover at this point.
+ _, _ = w.Write(buf.Bytes())
+}
+
+func (ch *ComponentHandler) ServeHTTPStreamed(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", ch.ContentType)
+ if ch.Status != 0 {
+ w.WriteHeader(ch.Status)
+ }
+ if err := ch.Component.Render(r.Context(), w); err != nil {
+ if ch.ErrorHandler != nil {
+ w.Header().Set("Content-Type", ch.ContentType)
+ ch.ErrorHandler(r, err).ServeHTTP(w, r)
+ return
+ }
+ http.Error(w, componentHandlerErrorMessage, http.StatusInternalServerError)
+ }
+}
+
+// ServeHTTP implements the http.Handler interface.
+func (ch ComponentHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if ch.StreamResponse {
+ ch.ServeHTTPStreamed(w, r)
+ return
+ }
+ ch.ServeHTTPBuffered(w, r)
+}
+
+// Handler creates a http.Handler that renders the template.
+func Handler(c Component, options ...func(*ComponentHandler)) *ComponentHandler {
+ ch := &ComponentHandler{
+ Component: c,
+ ContentType: "text/html; charset=utf-8",
+ }
+ for _, o := range options {
+ o(ch)
+ }
+ return ch
+}
+
+// WithStatus sets the HTTP status code returned by the ComponentHandler.
+func WithStatus(status int) func(*ComponentHandler) {
+ return func(ch *ComponentHandler) {
+ ch.Status = status
+ }
+}
+
+// WithContentType sets the Content-Type header returned by the ComponentHandler.
+func WithContentType(contentType string) func(*ComponentHandler) {
+ return func(ch *ComponentHandler) {
+ ch.ContentType = contentType
+ }
+}
+
+// WithErrorHandler sets the error handler used if rendering fails.
+func WithErrorHandler(eh func(r *http.Request, err error) http.Handler) func(*ComponentHandler) {
+ return func(ch *ComponentHandler) {
+ ch.ErrorHandler = eh
+ }
+}
+
+// WithStreaming sets the ComponentHandler to stream the response instead of buffering it.
+func WithStreaming() func(*ComponentHandler) {
+ return func(ch *ComponentHandler) {
+ ch.StreamResponse = true
+ }
+}
diff --git a/vendor/github.com/a-h/templ/ide-demo.gif b/vendor/github.com/a-h/templ/ide-demo.gif
new file mode 100644
index 0000000..e35fd68
--- /dev/null
+++ b/vendor/github.com/a-h/templ/ide-demo.gif
Binary files differ
diff --git a/vendor/github.com/a-h/templ/jsonscript.go b/vendor/github.com/a-h/templ/jsonscript.go
new file mode 100644
index 0000000..6e88174
--- /dev/null
+++ b/vendor/github.com/a-h/templ/jsonscript.go
@@ -0,0 +1,85 @@
+package templ
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+)
+
+var _ Component = JSONScriptElement{}
+
+// JSONScript renders a JSON object inside a script element.
+// e.g. <script type="application/json">{"foo":"bar"}</script>
+func JSONScript(id string, data any) JSONScriptElement {
+ return JSONScriptElement{
+ ID: id,
+ Type: "application/json",
+ Data: data,
+ Nonce: GetNonce,
+ }
+}
+
+// WithType sets the value of the type attribute of the script element.
+func (j JSONScriptElement) WithType(t string) JSONScriptElement {
+ j.Type = t
+ return j
+}
+
+// WithNonceFromString sets the value of the nonce attribute of the script element to the given string.
+func (j JSONScriptElement) WithNonceFromString(nonce string) JSONScriptElement {
+ j.Nonce = func(context.Context) string {
+ return nonce
+ }
+ return j
+}
+
+// WithNonceFrom sets the value of the nonce attribute of the script element to the value returned by the given function.
+func (j JSONScriptElement) WithNonceFrom(f func(context.Context) string) JSONScriptElement {
+ j.Nonce = f
+ return j
+}
+
+type JSONScriptElement struct {
+ // ID of the element in the DOM.
+ ID string
+ // Type of the script element, defaults to "application/json".
+ Type string
+ // Data that will be encoded as JSON.
+ Data any
+ // Nonce is a function that returns a CSP nonce.
+ // Defaults to CSPNonceFromContext.
+ // See https://content-security-policy.com/nonce for more information.
+ Nonce func(ctx context.Context) string
+}
+
+func (j JSONScriptElement) Render(ctx context.Context, w io.Writer) (err error) {
+ if _, err = io.WriteString(w, "<script"); err != nil {
+ return err
+ }
+ if j.ID != "" {
+ if _, err = fmt.Fprintf(w, " id=\"%s\"", EscapeString(j.ID)); err != nil {
+ return err
+ }
+ }
+ if j.Type != "" {
+ if _, err = fmt.Fprintf(w, " type=\"%s\"", EscapeString(j.Type)); err != nil {
+ return err
+ }
+ }
+ if nonce := j.Nonce(ctx); nonce != "" {
+ if _, err = fmt.Fprintf(w, " nonce=\"%s\"", EscapeString(nonce)); err != nil {
+ return err
+ }
+ }
+ if _, err = io.WriteString(w, ">"); err != nil {
+ return err
+ }
+ if err = json.NewEncoder(w).Encode(j.Data); err != nil {
+ return err
+ }
+ if _, err = io.WriteString(w, "</script>"); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/vendor/github.com/a-h/templ/jsonstring.go b/vendor/github.com/a-h/templ/jsonstring.go
new file mode 100644
index 0000000..425e4e8
--- /dev/null
+++ b/vendor/github.com/a-h/templ/jsonstring.go
@@ -0,0 +1,14 @@
+package templ
+
+import (
+ "encoding/json"
+)
+
+// JSONString returns a JSON encoded string of v.
+func JSONString(v any) (string, error) {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return "", err
+ }
+ return string(b), nil
+}
diff --git a/vendor/github.com/a-h/templ/once.go b/vendor/github.com/a-h/templ/once.go
new file mode 100644
index 0000000..7860ab8
--- /dev/null
+++ b/vendor/github.com/a-h/templ/once.go
@@ -0,0 +1,64 @@
+package templ
+
+import (
+ "context"
+ "io"
+ "sync/atomic"
+)
+
+// onceHandleIndex is used to identify unique once handles in a program run.
+var onceHandleIndex int64
+
+type OnceOpt func(*OnceHandle)
+
+// WithOnceComponent sets the component to be rendered once per context.
+// This can be used instead of setting the children of the `Once` method,
+// for example, if creating a code component outside of a templ HTML template.
+func WithComponent(c Component) OnceOpt {
+ return func(o *OnceHandle) {
+ o.c = c
+ }
+}
+
+// NewOnceHandle creates a OnceHandle used to ensure that the children of its
+// `Once` method are only rendered once per context.
+func NewOnceHandle(opts ...OnceOpt) *OnceHandle {
+ oh := &OnceHandle{
+ id: atomic.AddInt64(&onceHandleIndex, 1),
+ }
+ for _, opt := range opts {
+ opt(oh)
+ }
+ return oh
+}
+
+// OnceHandle is used to ensure that the children of its `Once` method are are only
+// rendered once per context.
+type OnceHandle struct {
+ // id is used to identify which instance of the OnceHandle is being used.
+ // The OnceHandle can't be an empty struct, because:
+ //
+ // | Two distinct zero-size variables may
+ // | have the same address in memory
+ //
+ // https://go.dev/ref/spec#Size_and_alignment_guarantees
+ id int64
+ // c is the component to be rendered once per context.
+ // if c is nil, the children of the `Once` method are rendered.
+ c Component
+}
+
+// Once returns a component that renders its children once per context.
+func (o *OnceHandle) Once() Component {
+ return ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
+ _, v := getContext(ctx)
+ if v.getHasBeenRendered(o) {
+ return nil
+ }
+ v.setHasBeenRendered(o)
+ if o.c != nil {
+ return o.c.Render(ctx, w)
+ }
+ return GetChildren(ctx).Render(ctx, w)
+ })
+}
diff --git a/vendor/github.com/a-h/templ/push-tag.sh b/vendor/github.com/a-h/templ/push-tag.sh
new file mode 100644
index 0000000..9eedeed
--- /dev/null
+++ b/vendor/github.com/a-h/templ/push-tag.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+if [ `git rev-parse --abbrev-ref HEAD` != "main" ]; then
+ echo "Error: Not on main branch. Please switch to main branch.";
+ exit 1;
+fi
+git pull
+if ! git diff --quiet; then
+ echo "Error: Working directory is not clean. Please commit the changes first.";
+ exit 1;
+fi
+export VERSION=`cat .version`
+echo Adding git tag with version v${VERSION};
+git tag v${VERSION};
+git push origin v${VERSION};
diff --git a/vendor/github.com/a-h/templ/runtime.go b/vendor/github.com/a-h/templ/runtime.go
new file mode 100644
index 0000000..d4d5aa0
--- /dev/null
+++ b/vendor/github.com/a-h/templ/runtime.go
@@ -0,0 +1,855 @@
+package templ
+
+import (
+ "bytes"
+ "context"
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "html"
+ "html/template"
+ "io"
+ "net/http"
+ "os"
+ "reflect"
+ "runtime"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/a-h/templ/safehtml"
+)
+
+// Types exposed by all components.
+
+// Component is the interface that all templates implement.
+type Component interface {
+ // Render the template.
+ Render(ctx context.Context, w io.Writer) error
+}
+
+// ComponentFunc converts a function that matches the Component interface's
+// Render method into a Component.
+type ComponentFunc func(ctx context.Context, w io.Writer) error
+
+// Render the template.
+func (cf ComponentFunc) Render(ctx context.Context, w io.Writer) error {
+ return cf(ctx, w)
+}
+
+// WithNonce sets a CSP nonce on the context and returns it.
+func WithNonce(ctx context.Context, nonce string) context.Context {
+ ctx, v := getContext(ctx)
+ v.nonce = nonce
+ return ctx
+}
+
+// GetNonce returns the CSP nonce value set with WithNonce, or an
+// empty string if none has been set.
+func GetNonce(ctx context.Context) (nonce string) {
+ if ctx == nil {
+ return ""
+ }
+ _, v := getContext(ctx)
+ return v.nonce
+}
+
+func WithChildren(ctx context.Context, children Component) context.Context {
+ ctx, v := getContext(ctx)
+ v.children = &children
+ return ctx
+}
+
+func ClearChildren(ctx context.Context) context.Context {
+ _, v := getContext(ctx)
+ v.children = nil
+ return ctx
+}
+
+// NopComponent is a component that doesn't render anything.
+var NopComponent = ComponentFunc(func(ctx context.Context, w io.Writer) error { return nil })
+
+// GetChildren from the context.
+func GetChildren(ctx context.Context) Component {
+ _, v := getContext(ctx)
+ if v.children == nil {
+ return NopComponent
+ }
+ return *v.children
+}
+
+// EscapeString escapes HTML text within templates.
+func EscapeString(s string) string {
+ return html.EscapeString(s)
+}
+
+// Bool attribute value.
+func Bool(value bool) bool {
+ return value
+}
+
+// Classes for CSS.
+// Supported types are string, ConstantCSSClass, ComponentCSSClass, map[string]bool.
+func Classes(classes ...any) CSSClasses {
+ return CSSClasses(classes)
+}
+
+// CSSClasses is a slice of CSS classes.
+type CSSClasses []any
+
+// String returns the names of all CSS classes.
+func (classes CSSClasses) String() string {
+ if len(classes) == 0 {
+ return ""
+ }
+ cp := newCSSProcessor()
+ for _, v := range classes {
+ cp.Add(v)
+ }
+ return cp.String()
+}
+
+func newCSSProcessor() *cssProcessor {
+ return &cssProcessor{
+ classNameToEnabled: make(map[string]bool),
+ }
+}
+
+type cssProcessor struct {
+ classNameToEnabled map[string]bool
+ orderedNames []string
+}
+
+func (cp *cssProcessor) Add(item any) {
+ switch c := item.(type) {
+ case []string:
+ for _, className := range c {
+ cp.AddClassName(className, true)
+ }
+ case string:
+ cp.AddClassName(c, true)
+ case ConstantCSSClass:
+ cp.AddClassName(c.ClassName(), true)
+ case ComponentCSSClass:
+ cp.AddClassName(c.ClassName(), true)
+ case map[string]bool:
+ // In Go, map keys are iterated in a randomized order.
+ // So the keys in the map must be sorted to produce consistent output.
+ keys := make([]string, len(c))
+ var i int
+ for key := range c {
+ keys[i] = key
+ i++
+ }
+ sort.Strings(keys)
+ for _, className := range keys {
+ cp.AddClassName(className, c[className])
+ }
+ case []KeyValue[string, bool]:
+ for _, kv := range c {
+ cp.AddClassName(kv.Key, kv.Value)
+ }
+ case KeyValue[string, bool]:
+ cp.AddClassName(c.Key, c.Value)
+ case []KeyValue[CSSClass, bool]:
+ for _, kv := range c {
+ cp.AddClassName(kv.Key.ClassName(), kv.Value)
+ }
+ case KeyValue[CSSClass, bool]:
+ cp.AddClassName(c.Key.ClassName(), c.Value)
+ case CSSClasses:
+ for _, item := range c {
+ cp.Add(item)
+ }
+ case []CSSClass:
+ for _, item := range c {
+ cp.Add(item)
+ }
+ case func() CSSClass:
+ cp.AddClassName(c().ClassName(), true)
+ default:
+ cp.AddClassName(unknownTypeClassName, true)
+ }
+}
+
+func (cp *cssProcessor) AddClassName(className string, enabled bool) {
+ cp.classNameToEnabled[className] = enabled
+ cp.orderedNames = append(cp.orderedNames, className)
+}
+
+func (cp *cssProcessor) String() string {
+ // Order the outputs according to how they were input, and remove disabled names.
+ rendered := make(map[string]any, len(cp.classNameToEnabled))
+ var names []string
+ for _, name := range cp.orderedNames {
+ if enabled := cp.classNameToEnabled[name]; !enabled {
+ continue
+ }
+ if _, hasBeenRendered := rendered[name]; hasBeenRendered {
+ continue
+ }
+ names = append(names, name)
+ rendered[name] = struct{}{}
+ }
+
+ return strings.Join(names, " ")
+}
+
+// KeyValue is a key and value pair.
+type KeyValue[TKey comparable, TValue any] struct {
+ Key TKey `json:"name"`
+ Value TValue `json:"value"`
+}
+
+// KV creates a new key/value pair from the input key and value.
+func KV[TKey comparable, TValue any](key TKey, value TValue) KeyValue[TKey, TValue] {
+ return KeyValue[TKey, TValue]{
+ Key: key,
+ Value: value,
+ }
+}
+
+const unknownTypeClassName = "--templ-css-class-unknown-type"
+
+// Class returns a CSS class name.
+// Deprecated: use a string instead.
+func Class(name string) CSSClass {
+ return SafeClass(name)
+}
+
+// SafeClass bypasses CSS class name validation.
+// Deprecated: use a string instead.
+func SafeClass(name string) CSSClass {
+ return ConstantCSSClass(name)
+}
+
+// CSSClass provides a class name.
+type CSSClass interface {
+ ClassName() string
+}
+
+// ConstantCSSClass is a string constant of a CSS class name.
+// Deprecated: use a string instead.
+type ConstantCSSClass string
+
+// ClassName of the CSS class.
+func (css ConstantCSSClass) ClassName() string {
+ return string(css)
+}
+
+// ComponentCSSClass is a templ.CSS
+type ComponentCSSClass struct {
+ // ID of the class, will be autogenerated.
+ ID string
+ // Definition of the CSS.
+ Class SafeCSS
+}
+
+// ClassName of the CSS class.
+func (css ComponentCSSClass) ClassName() string {
+ return css.ID
+}
+
+// CSSID calculates an ID.
+func CSSID(name string, css string) string {
+ sum := sha256.Sum256([]byte(css))
+ hp := hex.EncodeToString(sum[:])[0:4]
+ // Benchmarking showed this was fastest, and with fewest allocations (1).
+ // Using strings.Builder (2 allocs).
+ // Using fmt.Sprintf (3 allocs).
+ return name + "_" + hp
+}
+
+// NewCSSMiddleware creates HTTP middleware that renders a global stylesheet of ComponentCSSClass
+// CSS if the request path matches, or updates the HTTP context to ensure that any handlers that
+// use templ.Components skip rendering <style> elements for classes that are included in the global
+// stylesheet. By default, the stylesheet path is /styles/templ.css
+func NewCSSMiddleware(next http.Handler, classes ...CSSClass) CSSMiddleware {
+ return CSSMiddleware{
+ Path: "/styles/templ.css",
+ CSSHandler: NewCSSHandler(classes...),
+ Next: next,
+ }
+}
+
+// CSSMiddleware renders a global stylesheet.
+type CSSMiddleware struct {
+ Path string
+ CSSHandler CSSHandler
+ Next http.Handler
+}
+
+func (cssm CSSMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path == cssm.Path {
+ cssm.CSSHandler.ServeHTTP(w, r)
+ return
+ }
+ // Add registered classes to the context.
+ ctx, v := getContext(r.Context())
+ for _, c := range cssm.CSSHandler.Classes {
+ v.addClass(c.ID)
+ }
+ // Serve the request. Templ components will use the updated context
+ // to know to skip rendering <style> elements for any component CSS
+ // classes that have been included in the global stylesheet.
+ cssm.Next.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// NewCSSHandler creates a handler that serves a stylesheet containing the CSS of the
+// classes passed in. This is used by the CSSMiddleware to provide global stylesheets
+// for templ components.
+func NewCSSHandler(classes ...CSSClass) CSSHandler {
+ ccssc := make([]ComponentCSSClass, 0, len(classes))
+ for _, c := range classes {
+ ccss, ok := c.(ComponentCSSClass)
+ if !ok {
+ continue
+ }
+ ccssc = append(ccssc, ccss)
+ }
+ return CSSHandler{
+ Classes: ccssc,
+ }
+}
+
+// CSSHandler is a HTTP handler that serves CSS.
+type CSSHandler struct {
+ Logger func(err error)
+ Classes []ComponentCSSClass
+}
+
+func (cssh CSSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/css")
+ for _, c := range cssh.Classes {
+ _, err := w.Write([]byte(c.Class))
+ if err != nil && cssh.Logger != nil {
+ cssh.Logger(err)
+ }
+ }
+}
+
+// RenderCSSItems renders the CSS to the writer, if the items haven't already been rendered.
+func RenderCSSItems(ctx context.Context, w io.Writer, classes ...any) (err error) {
+ if len(classes) == 0 {
+ return nil
+ }
+ _, v := getContext(ctx)
+ sb := new(strings.Builder)
+ renderCSSItemsToBuilder(sb, v, classes...)
+ if sb.Len() > 0 {
+ if _, err = io.WriteString(w, `<style type="text/css">`); err != nil {
+ return err
+ }
+ if _, err = io.WriteString(w, sb.String()); err != nil {
+ return err
+ }
+ if _, err = io.WriteString(w, `</style>`); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func renderCSSItemsToBuilder(sb *strings.Builder, v *contextValue, classes ...any) {
+ for _, c := range classes {
+ switch ccc := c.(type) {
+ case ComponentCSSClass:
+ if !v.hasClassBeenRendered(ccc.ID) {
+ sb.WriteString(string(ccc.Class))
+ v.addClass(ccc.ID)
+ }
+ case KeyValue[ComponentCSSClass, bool]:
+ if !ccc.Value {
+ continue
+ }
+ renderCSSItemsToBuilder(sb, v, ccc.Key)
+ case KeyValue[CSSClass, bool]:
+ if !ccc.Value {
+ continue
+ }
+ renderCSSItemsToBuilder(sb, v, ccc.Key)
+ case CSSClasses:
+ renderCSSItemsToBuilder(sb, v, ccc...)
+ case []CSSClass:
+ for _, item := range ccc {
+ renderCSSItemsToBuilder(sb, v, item)
+ }
+ case func() CSSClass:
+ renderCSSItemsToBuilder(sb, v, ccc())
+ case []string:
+ // Skip. These are class names, not CSS classes.
+ case string:
+ // Skip. This is a class name, not a CSS class.
+ case ConstantCSSClass:
+ // Skip. This is a class name, not a CSS class.
+ case CSSClass:
+ // Skip. This is a class name, not a CSS class.
+ case map[string]bool:
+ // Skip. These are class names, not CSS classes.
+ case KeyValue[string, bool]:
+ // Skip. These are class names, not CSS classes.
+ case []KeyValue[string, bool]:
+ // Skip. These are class names, not CSS classes.
+ case KeyValue[ConstantCSSClass, bool]:
+ // Skip. These are class names, not CSS classes.
+ case []KeyValue[ConstantCSSClass, bool]:
+ // Skip. These are class names, not CSS classes.
+ }
+ }
+}
+
+// SafeCSS is CSS that has been sanitized.
+type SafeCSS string
+
+type SafeCSSProperty string
+
+var safeCSSPropertyType = reflect.TypeOf(SafeCSSProperty(""))
+
+// SanitizeCSS sanitizes CSS properties to ensure that they are safe.
+func SanitizeCSS[T ~string](property string, value T) SafeCSS {
+ if reflect.TypeOf(value) == safeCSSPropertyType {
+ return SafeCSS(safehtml.SanitizeCSSProperty(property) + ":" + string(value) + ";")
+ }
+ p, v := safehtml.SanitizeCSS(property, string(value))
+ return SafeCSS(p + ":" + v + ";")
+}
+
+// Attributes is an alias to map[string]any made for spread attributes.
+type Attributes map[string]any
+
+// sortedKeys returns the keys of a map in sorted order.
+func sortedKeys(m map[string]any) (keys []string) {
+ keys = make([]string, len(m))
+ var i int
+ for k := range m {
+ keys[i] = k
+ i++
+ }
+ sort.Strings(keys)
+ return keys
+}
+
+func writeStrings(w io.Writer, ss ...string) (err error) {
+ for _, s := range ss {
+ if _, err = io.WriteString(w, s); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func RenderAttributes(ctx context.Context, w io.Writer, attributes Attributes) (err error) {
+ for _, key := range sortedKeys(attributes) {
+ value := attributes[key]
+ switch value := value.(type) {
+ case string:
+ if err = writeStrings(w, ` `, EscapeString(key), `="`, EscapeString(value), `"`); err != nil {
+ return err
+ }
+ case *string:
+ if value != nil {
+ if err = writeStrings(w, ` `, EscapeString(key), `="`, EscapeString(*value), `"`); err != nil {
+ return err
+ }
+ }
+ case bool:
+ if value {
+ if err = writeStrings(w, ` `, EscapeString(key)); err != nil {
+ return err
+ }
+ }
+ case *bool:
+ if value != nil && *value {
+ if err = writeStrings(w, ` `, EscapeString(key)); err != nil {
+ return err
+ }
+ }
+ case KeyValue[string, bool]:
+ if value.Value {
+ if err = writeStrings(w, ` `, EscapeString(key), `="`, EscapeString(value.Key), `"`); err != nil {
+ return err
+ }
+ }
+ case KeyValue[bool, bool]:
+ if value.Value && value.Key {
+ if err = writeStrings(w, ` `, EscapeString(key)); err != nil {
+ return err
+ }
+ }
+ case func() bool:
+ if value() {
+ if err = writeStrings(w, ` `, EscapeString(key)); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// Script handling.
+
+func safeEncodeScriptParams(escapeHTML bool, params []any) []string {
+ encodedParams := make([]string, len(params))
+ for i := 0; i < len(encodedParams); i++ {
+ enc, _ := json.Marshal(params[i])
+ if !escapeHTML {
+ encodedParams[i] = string(enc)
+ continue
+ }
+ encodedParams[i] = EscapeString(string(enc))
+ }
+ return encodedParams
+}
+
+// SafeScript encodes unknown parameters for safety for inside HTML attributes.
+func SafeScript(functionName string, params ...any) string {
+ encodedParams := safeEncodeScriptParams(true, params)
+ sb := new(strings.Builder)
+ sb.WriteString(functionName)
+ sb.WriteRune('(')
+ sb.WriteString(strings.Join(encodedParams, ","))
+ sb.WriteRune(')')
+ return sb.String()
+}
+
+// SafeScript encodes unknown parameters for safety for inline scripts.
+func SafeScriptInline(functionName string, params ...any) string {
+ encodedParams := safeEncodeScriptParams(false, params)
+ sb := new(strings.Builder)
+ sb.WriteString(functionName)
+ sb.WriteRune('(')
+ sb.WriteString(strings.Join(encodedParams, ","))
+ sb.WriteRune(')')
+ return sb.String()
+}
+
+type contextKeyType int
+
+const contextKey = contextKeyType(0)
+
+type contextValue struct {
+ ss map[string]struct{}
+ onceHandles map[*OnceHandle]struct{}
+ children *Component
+ nonce string
+}
+
+func (v *contextValue) setHasBeenRendered(h *OnceHandle) {
+ if v.onceHandles == nil {
+ v.onceHandles = map[*OnceHandle]struct{}{}
+ }
+ v.onceHandles[h] = struct{}{}
+}
+
+func (v *contextValue) getHasBeenRendered(h *OnceHandle) (ok bool) {
+ if v.onceHandles == nil {
+ v.onceHandles = map[*OnceHandle]struct{}{}
+ }
+ _, ok = v.onceHandles[h]
+ return
+}
+
+func (v *contextValue) addScript(s string) {
+ if v.ss == nil {
+ v.ss = map[string]struct{}{}
+ }
+ v.ss["script_"+s] = struct{}{}
+}
+
+func (v *contextValue) hasScriptBeenRendered(s string) (ok bool) {
+ if v.ss == nil {
+ v.ss = map[string]struct{}{}
+ }
+ _, ok = v.ss["script_"+s]
+ return
+}
+
+func (v *contextValue) addClass(s string) {
+ if v.ss == nil {
+ v.ss = map[string]struct{}{}
+ }
+ v.ss["class_"+s] = struct{}{}
+}
+
+func (v *contextValue) hasClassBeenRendered(s string) (ok bool) {
+ if v.ss == nil {
+ v.ss = map[string]struct{}{}
+ }
+ _, ok = v.ss["class_"+s]
+ return
+}
+
+// InitializeContext initializes context used to store internal state used during rendering.
+func InitializeContext(ctx context.Context) context.Context {
+ if _, ok := ctx.Value(contextKey).(*contextValue); ok {
+ return ctx
+ }
+ v := &contextValue{}
+ ctx = context.WithValue(ctx, contextKey, v)
+ return ctx
+}
+
+func getContext(ctx context.Context) (context.Context, *contextValue) {
+ v, ok := ctx.Value(contextKey).(*contextValue)
+ if !ok {
+ ctx = InitializeContext(ctx)
+ v = ctx.Value(contextKey).(*contextValue)
+ }
+ return ctx, v
+}
+
+// ComponentScript is a templ Script template.
+type ComponentScript struct {
+ // Name of the script, e.g. print.
+ Name string
+ // Function to render.
+ Function string
+ // Call of the function in JavaScript syntax, including parameters, and
+ // ensures parameters are HTML escaped; useful for injecting into HTML
+ // attributes like onclick, onhover, etc.
+ //
+ // Given:
+ // functionName("some string",12345)
+ // It would render:
+ // __templ_functionName_sha(&#34;some string&#34;,12345))
+ //
+ // This is can be injected into HTML attributes:
+ // <button onClick="__templ_functionName_sha(&#34;some string&#34;,12345))">Click Me</button>
+ Call string
+ // Call of the function in JavaScript syntax, including parameters. It
+ // does not HTML escape parameters; useful for directly calling in script
+ // elements.
+ //
+ // Given:
+ // functionName("some string",12345)
+ // It would render:
+ // __templ_functionName_sha("some string",12345))
+ //
+ // This is can be used to call the function inside a script tag:
+ // <script>__templ_functionName_sha("some string",12345))</script>
+ CallInline string
+}
+
+var _ Component = ComponentScript{}
+
+func writeScriptHeader(ctx context.Context, w io.Writer) (err error) {
+ var nonceAttr string
+ if nonce := GetNonce(ctx); nonce != "" {
+ nonceAttr = " nonce=\"" + EscapeString(nonce) + "\""
+ }
+ _, err = fmt.Fprintf(w, `<script type="text/javascript"%s>`, nonceAttr)
+ return err
+}
+
+func (c ComponentScript) Render(ctx context.Context, w io.Writer) error {
+ err := RenderScriptItems(ctx, w, c)
+ if err != nil {
+ return err
+ }
+ if len(c.Call) > 0 {
+ if err = writeScriptHeader(ctx, w); err != nil {
+ return err
+ }
+ if _, err = io.WriteString(w, c.CallInline); err != nil {
+ return err
+ }
+ if _, err = io.WriteString(w, `</script>`); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// RenderScriptItems renders a <script> element, if the script has not already been rendered.
+func RenderScriptItems(ctx context.Context, w io.Writer, scripts ...ComponentScript) (err error) {
+ if len(scripts) == 0 {
+ return nil
+ }
+ _, v := getContext(ctx)
+ sb := new(strings.Builder)
+ for _, s := range scripts {
+ if !v.hasScriptBeenRendered(s.Name) {
+ sb.WriteString(s.Function)
+ v.addScript(s.Name)
+ }
+ }
+ if sb.Len() > 0 {
+ if err = writeScriptHeader(ctx, w); err != nil {
+ return err
+ }
+ if _, err = io.WriteString(w, sb.String()); err != nil {
+ return err
+ }
+ if _, err = io.WriteString(w, `</script>`); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+var bufferPool = sync.Pool{
+ New: func() any {
+ return new(bytes.Buffer)
+ },
+}
+
+func GetBuffer() *bytes.Buffer {
+ return bufferPool.Get().(*bytes.Buffer)
+}
+
+func ReleaseBuffer(b *bytes.Buffer) {
+ b.Reset()
+ bufferPool.Put(b)
+}
+
+// JoinStringErrs joins an optional list of errors.
+func JoinStringErrs(s string, errs ...error) (string, error) {
+ return s, errors.Join(errs...)
+}
+
+// Error returned during template rendering.
+type Error struct {
+ Err error
+ // FileName of the template file.
+ FileName string
+ // Line index of the error.
+ Line int
+ // Col index of the error.
+ Col int
+}
+
+func (e Error) Error() string {
+ if e.FileName == "" {
+ e.FileName = "templ"
+ }
+ return fmt.Sprintf("%s: error at line %d, col %d: %v", e.FileName, e.Line, e.Col, e.Err)
+}
+
+func (e Error) Unwrap() error {
+ return e.Err
+}
+
+// Raw renders the input HTML to the output without applying HTML escaping.
+//
+// Use of this component presents a security risk - the HTML should come from
+// a trusted source, because it will be included as-is in the output.
+func Raw[T ~string](html T, errs ...error) Component {
+ return ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
+ if err = errors.Join(errs...); err != nil {
+ return err
+ }
+ _, err = io.WriteString(w, string(html))
+ return err
+ })
+}
+
+// FromGoHTML creates a templ Component from a Go html/template template.
+func FromGoHTML(t *template.Template, data any) Component {
+ return ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
+ return t.Execute(w, data)
+ })
+}
+
+// ToGoHTML renders the component to a Go html/template template.HTML string.
+func ToGoHTML(ctx context.Context, c Component) (s template.HTML, err error) {
+ b := GetBuffer()
+ defer ReleaseBuffer(b)
+ if err = c.Render(ctx, b); err != nil {
+ return
+ }
+ s = template.HTML(b.String())
+ return
+}
+
+// WriteWatchModeString is used when rendering templates in development mode.
+// the generator would have written non-go code to the _templ.txt file, which
+// is then read by this function and written to the output.
+func WriteWatchModeString(w io.Writer, lineNum int) error {
+ _, path, _, _ := runtime.Caller(1)
+ if !strings.HasSuffix(path, "_templ.go") {
+ return errors.New("templ: WriteWatchModeString can only be called from _templ.go")
+ }
+ txtFilePath := strings.Replace(path, "_templ.go", "_templ.txt", 1)
+
+ literals, err := getWatchedStrings(txtFilePath)
+ if err != nil {
+ return fmt.Errorf("templ: failed to cache strings: %w", err)
+ }
+
+ if lineNum > len(literals) {
+ return errors.New("templ: failed to find line " + strconv.Itoa(lineNum) + " in " + txtFilePath)
+ }
+
+ unquoted, err := strconv.Unquote(`"` + literals[lineNum-1] + `"`)
+ if err != nil {
+ return err
+ }
+ _, err = io.WriteString(w, unquoted)
+ return err
+}
+
+var (
+ watchModeCache = map[string]watchState{}
+ watchStateMutex sync.Mutex
+)
+
+type watchState struct {
+ modTime time.Time
+ strings []string
+}
+
+func getWatchedStrings(txtFilePath string) ([]string, error) {
+ watchStateMutex.Lock()
+ defer watchStateMutex.Unlock()
+
+ state, cached := watchModeCache[txtFilePath]
+ if !cached {
+ return cacheStrings(txtFilePath)
+ }
+
+ if time.Since(state.modTime) < time.Millisecond*100 {
+ return state.strings, nil
+ }
+
+ info, err := os.Stat(txtFilePath)
+ if err != nil {
+ return nil, fmt.Errorf("templ: failed to stat %s: %w", txtFilePath, err)
+ }
+
+ if !info.ModTime().After(state.modTime) {
+ return state.strings, nil
+ }
+
+ return cacheStrings(txtFilePath)
+}
+
+func cacheStrings(txtFilePath string) ([]string, error) {
+ txtFile, err := os.Open(txtFilePath)
+ if err != nil {
+ return nil, fmt.Errorf("templ: failed to open %s: %w", txtFilePath, err)
+ }
+ defer txtFile.Close()
+
+ info, err := txtFile.Stat()
+ if err != nil {
+ return nil, fmt.Errorf("templ: failed to stat %s: %w", txtFilePath, err)
+ }
+
+ all, err := io.ReadAll(txtFile)
+ if err != nil {
+ return nil, fmt.Errorf("templ: failed to read %s: %w", txtFilePath, err)
+ }
+
+ literals := strings.Split(string(all), "\n")
+ watchModeCache[txtFilePath] = watchState{
+ modTime: info.ModTime(),
+ strings: literals,
+ }
+
+ return literals, nil
+}
diff --git a/vendor/github.com/a-h/templ/runtime/buffer.go b/vendor/github.com/a-h/templ/runtime/buffer.go
new file mode 100644
index 0000000..63e4acd
--- /dev/null
+++ b/vendor/github.com/a-h/templ/runtime/buffer.go
@@ -0,0 +1,62 @@
+package runtime
+
+import (
+ "bufio"
+ "io"
+ "net/http"
+)
+
+// DefaultBufferSize is the default size of buffers. It is set to 4KB by default, which is the
+// same as the default buffer size of bufio.Writer.
+var DefaultBufferSize = 4 * 1024 // 4KB
+
+// Buffer is a wrapper around bufio.Writer that enables flushing and closing of
+// the underlying writer.
+type Buffer struct {
+ Underlying io.Writer
+ b *bufio.Writer
+}
+
+// Write the contents of p into the buffer.
+func (b *Buffer) Write(p []byte) (n int, err error) {
+ return b.b.Write(p)
+}
+
+// Flush writes any buffered data to the underlying io.Writer and
+// calls the Flush method of the underlying http.Flusher if it implements it.
+func (b *Buffer) Flush() error {
+ if err := b.b.Flush(); err != nil {
+ return err
+ }
+ if f, ok := b.Underlying.(http.Flusher); ok {
+ f.Flush()
+ }
+ return nil
+}
+
+// Close closes the buffer and the underlying io.Writer if it implements io.Closer.
+func (b *Buffer) Close() error {
+ if c, ok := b.Underlying.(io.Closer); ok {
+ return c.Close()
+ }
+ return nil
+}
+
+// Reset sets the underlying io.Writer to w and resets the buffer.
+func (b *Buffer) Reset(w io.Writer) {
+ if b.b == nil {
+ b.b = bufio.NewWriterSize(b, DefaultBufferSize)
+ }
+ b.Underlying = w
+ b.b.Reset(w)
+}
+
+// Size returns the size of the underlying buffer in bytes.
+func (b *Buffer) Size() int {
+ return b.b.Size()
+}
+
+// WriteString writes the contents of s into the buffer.
+func (b *Buffer) WriteString(s string) (n int, err error) {
+ return b.b.WriteString(s)
+}
diff --git a/vendor/github.com/a-h/templ/runtime/bufferpool.go b/vendor/github.com/a-h/templ/runtime/bufferpool.go
new file mode 100644
index 0000000..ca2a131
--- /dev/null
+++ b/vendor/github.com/a-h/templ/runtime/bufferpool.go
@@ -0,0 +1,38 @@
+package runtime
+
+import (
+ "io"
+ "sync"
+)
+
+var bufferPool = sync.Pool{
+ New: func() any {
+ return new(Buffer)
+ },
+}
+
+// GetBuffer creates and returns a new buffer if the writer is not already a buffer,
+// or returns the existing buffer if it is.
+func GetBuffer(w io.Writer) (b *Buffer, existing bool) {
+ if w == nil {
+ return nil, false
+ }
+ b, ok := w.(*Buffer)
+ if ok {
+ return b, true
+ }
+ b = bufferPool.Get().(*Buffer)
+ b.Reset(w)
+ return b, false
+}
+
+// ReleaseBuffer flushes the buffer and returns it to the pool.
+func ReleaseBuffer(w io.Writer) (err error) {
+ b, ok := w.(*Buffer)
+ if !ok {
+ return nil
+ }
+ err = b.Flush()
+ bufferPool.Put(b)
+ return err
+}
diff --git a/vendor/github.com/a-h/templ/runtime/builder.go b/vendor/github.com/a-h/templ/runtime/builder.go
new file mode 100644
index 0000000..0f4c9d4
--- /dev/null
+++ b/vendor/github.com/a-h/templ/runtime/builder.go
@@ -0,0 +1,8 @@
+package runtime
+
+import "strings"
+
+// GetBuilder returns a strings.Builder.
+func GetBuilder() (sb strings.Builder) {
+ return sb
+}
diff --git a/vendor/github.com/a-h/templ/runtime/runtime.go b/vendor/github.com/a-h/templ/runtime/runtime.go
new file mode 100644
index 0000000..aaa4a2c
--- /dev/null
+++ b/vendor/github.com/a-h/templ/runtime/runtime.go
@@ -0,0 +1,21 @@
+package runtime
+
+import (
+ "context"
+ "io"
+
+ "github.com/a-h/templ"
+)
+
+// GeneratedComponentInput is used to avoid generated code needing to import the `context` and `io` packages.
+type GeneratedComponentInput struct {
+ Context context.Context
+ Writer io.Writer
+}
+
+// GeneratedTemplate is used to avoid generated code needing to import the `context` and `io` packages.
+func GeneratedTemplate(f func(GeneratedComponentInput) error) templ.Component {
+ return templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
+ return f(GeneratedComponentInput{ctx, w})
+ })
+}
diff --git a/vendor/github.com/a-h/templ/safehtml/style.go b/vendor/github.com/a-h/templ/safehtml/style.go
new file mode 100644
index 0000000..486df7c
--- /dev/null
+++ b/vendor/github.com/a-h/templ/safehtml/style.go
@@ -0,0 +1,168 @@
+// Adapted from https://raw.githubusercontent.com/google/safehtml/3c4cd5b5d8c9a6c5882fba099979e9f50b65c876/style.go
+
+// Copyright (c) 2017 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 or at
+// https://developers.google.com/open-source/licenses/bsd
+
+package safehtml
+
+import (
+ "net/url"
+ "regexp"
+ "strings"
+)
+
+// SanitizeCSS attempts to sanitize CSS properties.
+func SanitizeCSS(property, value string) (string, string) {
+ property = SanitizeCSSProperty(property)
+ if property == InnocuousPropertyName {
+ return InnocuousPropertyName, InnocuousPropertyValue
+ }
+ return property, SanitizeCSSValue(property, value)
+}
+
+func SanitizeCSSValue(property, value string) string {
+ if sanitizer, ok := cssPropertyNameToValueSanitizer[property]; ok {
+ return sanitizer(value)
+ }
+ return sanitizeRegular(value)
+}
+
+func SanitizeCSSProperty(property string) string {
+ if !identifierPattern.MatchString(property) {
+ return InnocuousPropertyName
+ }
+ return strings.ToLower(property)
+}
+
+// identifierPattern matches a subset of valid <ident-token> values defined in
+// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram. This pattern matches all generic family name
+// keywords defined in https://drafts.csswg.org/css-fonts-3/#family-name-value.
+var identifierPattern = regexp.MustCompile(`^[-a-zA-Z]+$`)
+
+var cssPropertyNameToValueSanitizer = map[string]func(string) string{
+ "background-image": sanitizeBackgroundImage,
+ "font-family": sanitizeFontFamily,
+ "display": sanitizeEnum,
+ "background-color": sanitizeRegular,
+ "background-position": sanitizeRegular,
+ "background-repeat": sanitizeRegular,
+ "background-size": sanitizeRegular,
+ "color": sanitizeRegular,
+ "height": sanitizeRegular,
+ "width": sanitizeRegular,
+ "left": sanitizeRegular,
+ "right": sanitizeRegular,
+ "top": sanitizeRegular,
+ "bottom": sanitizeRegular,
+ "font-weight": sanitizeRegular,
+ "padding": sanitizeRegular,
+ "z-index": sanitizeRegular,
+}
+
+var validURLPrefixes = []string{
+ `url("`,
+ `url('`,
+ `url(`,
+}
+
+var validURLSuffixes = []string{
+ `")`,
+ `')`,
+ `)`,
+}
+
+func sanitizeBackgroundImage(v string) string {
+ // Check for <> as per https://github.com/google/safehtml/blob/be23134998433fcf0135dda53593fc8f8bf4df7c/style.go#L87C2-L89C3
+ if strings.ContainsAny(v, "<>") {
+ return InnocuousPropertyValue
+ }
+ for _, u := range strings.Split(v, ",") {
+ u = strings.TrimSpace(u)
+ var found bool
+ for i, prefix := range validURLPrefixes {
+ if strings.HasPrefix(u, prefix) && strings.HasSuffix(u, validURLSuffixes[i]) {
+ found = true
+ u = strings.TrimPrefix(u, validURLPrefixes[i])
+ u = strings.TrimSuffix(u, validURLSuffixes[i])
+ break
+ }
+ }
+ if !found || !urlIsSafe(u) {
+ return InnocuousPropertyValue
+ }
+ }
+ return v
+}
+
+func urlIsSafe(s string) bool {
+ u, err := url.Parse(s)
+ if err != nil {
+ return false
+ }
+ if u.IsAbs() {
+ if strings.EqualFold(u.Scheme, "http") || strings.EqualFold(u.Scheme, "https") || strings.EqualFold(u.Scheme, "mailto") {
+ return true
+ }
+ return false
+ }
+ return true
+}
+
+var genericFontFamilyName = regexp.MustCompile(`^[a-zA-Z][- a-zA-Z]+$`)
+
+func sanitizeFontFamily(s string) string {
+ for _, f := range strings.Split(s, ",") {
+ f = strings.TrimSpace(f)
+ if strings.HasPrefix(f, `"`) {
+ if !strings.HasSuffix(f, `"`) {
+ return InnocuousPropertyValue
+ }
+ continue
+ }
+ if !genericFontFamilyName.MatchString(f) {
+ return InnocuousPropertyValue
+ }
+ }
+ return s
+}
+
+func sanitizeEnum(s string) string {
+ if !safeEnumPropertyValuePattern.MatchString(s) {
+ return InnocuousPropertyValue
+ }
+ return s
+}
+
+func sanitizeRegular(s string) string {
+ if !safeRegularPropertyValuePattern.MatchString(s) {
+ return InnocuousPropertyValue
+ }
+ return s
+}
+
+// InnocuousPropertyName is an innocuous property generated by a sanitizer when its input is unsafe.
+const InnocuousPropertyName = "zTemplUnsafeCSSPropertyName"
+
+// InnocuousPropertyValue is an innocuous property generated by a sanitizer when its input is unsafe.
+const InnocuousPropertyValue = "zTemplUnsafeCSSPropertyValue"
+
+// safeRegularPropertyValuePattern matches strings that are safe to use as property values.
+// Specifically, it matches string where every '*' or '/' is followed by end-of-text or a safe rune
+// (i.e. alphanumerics or runes in the set [+-.!#%_ \t]). This regex ensures that the following
+// are disallowed:
+// - "/*" and "*/", which are CSS comment markers.
+// - "//", even though this is not a comment marker in the CSS specification. Disallowing
+// this string minimizes the chance that browser peculiarities or parsing bugs will allow
+// sanitization to be bypassed.
+// - '(' and ')', which can be used to call functions.
+// - ',', since it can be used to inject extra values into a property.
+// - Runes which could be matched on CSS error recovery of a previously malformed token, such as '@'
+// and ':'. See http://www.w3.org/TR/css3-syntax/#error-handling.
+var safeRegularPropertyValuePattern = regexp.MustCompile(`^(?:[*/]?(?:[0-9a-zA-Z+-.!#%_ \t]|$))*$`)
+
+// safeEnumPropertyValuePattern matches strings that are safe to use as enumerated property values.
+// Specifically, it matches strings that contain only alphabetic and '-' runes.
+var safeEnumPropertyValuePattern = regexp.MustCompile(`^[a-zA-Z-]*$`)
diff --git a/vendor/github.com/a-h/templ/templ.png b/vendor/github.com/a-h/templ/templ.png
new file mode 100644
index 0000000..1c4bc2f
--- /dev/null
+++ b/vendor/github.com/a-h/templ/templ.png
Binary files differ
diff --git a/vendor/github.com/a-h/templ/url.go b/vendor/github.com/a-h/templ/url.go
new file mode 100644
index 0000000..bf912e1
--- /dev/null
+++ b/vendor/github.com/a-h/templ/url.go
@@ -0,0 +1,20 @@
+package templ
+
+import "strings"
+
+// FailedSanitizationURL is returned if a URL fails sanitization checks.
+const FailedSanitizationURL = SafeURL("about:invalid#TemplFailedSanitizationURL")
+
+// URL sanitizes the input string s and returns a SafeURL.
+func URL(s string) SafeURL {
+ if i := strings.IndexRune(s, ':'); i >= 0 && !strings.ContainsRune(s[:i], '/') {
+ protocol := s[:i]
+ if !strings.EqualFold(protocol, "http") && !strings.EqualFold(protocol, "https") && !strings.EqualFold(protocol, "mailto") && !strings.EqualFold(protocol, "tel") && !strings.EqualFold(protocol, "ftp") && !strings.EqualFold(protocol, "ftps") {
+ return FailedSanitizationURL
+ }
+ }
+ return SafeURL(s)
+}
+
+// SafeURL is a URL that has been sanitized.
+type SafeURL string
diff --git a/vendor/github.com/a-h/templ/version.go b/vendor/github.com/a-h/templ/version.go
new file mode 100644
index 0000000..b7fbb6f
--- /dev/null
+++ b/vendor/github.com/a-h/templ/version.go
@@ -0,0 +1,10 @@
+package templ
+
+import _ "embed"
+
+//go:embed .version
+var version string
+
+func Version() string {
+ return "v" + version
+}
diff --git a/vendor/golang.org/x/text/LICENSE b/vendor/golang.org/x/text/LICENSE
new file mode 100644
index 0000000..2a7cf70
--- /dev/null
+++ b/vendor/golang.org/x/text/LICENSE
@@ -0,0 +1,27 @@
+Copyright 2009 The Go Authors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google LLC nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/text/PATENTS b/vendor/golang.org/x/text/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/text/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/text/feature/plural/common.go b/vendor/golang.org/x/text/feature/plural/common.go
new file mode 100644
index 0000000..fdcb373
--- /dev/null
+++ b/vendor/golang.org/x/text/feature/plural/common.go
@@ -0,0 +1,70 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package plural
+
+// Form defines a plural form.
+//
+// Not all languages support all forms. Also, the meaning of each form varies
+// per language. It is important to note that the name of a form does not
+// necessarily correspond one-to-one with the set of numbers. For instance,
+// for Croation, One matches not only 1, but also 11, 21, etc.
+//
+// Each language must at least support the form "other".
+type Form byte
+
+const (
+ Other Form = iota
+ Zero
+ One
+ Two
+ Few
+ Many
+)
+
+var countMap = map[string]Form{
+ "other": Other,
+ "zero": Zero,
+ "one": One,
+ "two": Two,
+ "few": Few,
+ "many": Many,
+}
+
+type pluralCheck struct {
+ // category:
+ // 3..7: opID
+ // 0..2: category
+ cat byte
+ setID byte
+}
+
+// opID identifies the type of operand in the plural rule, being i, n or f.
+// (v, w, and t are treated as filters in our implementation.)
+type opID byte
+
+const (
+ opMod opID = 0x1 // is '%' used?
+ opNotEqual opID = 0x2 // using "!=" to compare
+ opI opID = 0 << 2 // integers after taking the absolute value
+ opN opID = 1 << 2 // full number (must be integer)
+ opF opID = 2 << 2 // fraction
+ opV opID = 3 << 2 // number of visible digits
+ opW opID = 4 << 2 // number of visible digits without trailing zeros
+ opBretonM opID = 5 << 2 // hard-wired rule for Breton
+ opItalian800 opID = 6 << 2 // hard-wired rule for Italian
+ opAzerbaijan00s opID = 7 << 2 // hard-wired rule for Azerbaijan
+)
+const (
+ // Use this plural form to indicate the next rule needs to match as well.
+ // The last condition in the list will have the correct plural form.
+ andNext = 0x7
+ formMask = 0x7
+
+ opShift = 3
+
+ // numN indicates the maximum integer, or maximum mod value, for which we
+ // have inclusion masks.
+ numN = 100
+ // The common denominator of the modulo that is taken.
+ maxMod = 100
+)
diff --git a/vendor/golang.org/x/text/feature/plural/message.go b/vendor/golang.org/x/text/feature/plural/message.go
new file mode 100644
index 0000000..56d518c
--- /dev/null
+++ b/vendor/golang.org/x/text/feature/plural/message.go
@@ -0,0 +1,244 @@
+// Copyright 2017 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 plural
+
+import (
+ "fmt"
+ "io"
+ "reflect"
+ "strconv"
+
+ "golang.org/x/text/internal/catmsg"
+ "golang.org/x/text/internal/number"
+ "golang.org/x/text/language"
+ "golang.org/x/text/message/catalog"
+)
+
+// TODO: consider deleting this interface. Maybe VisibleDigits is always
+// sufficient and practical.
+
+// Interface is used for types that can determine their own plural form.
+type Interface interface {
+ // PluralForm reports the plural form for the given language of the
+ // underlying value. It also returns the integer value. If the integer value
+ // is larger than fits in n, PluralForm may return a value modulo
+ // 10,000,000.
+ PluralForm(t language.Tag, scale int) (f Form, n int)
+}
+
+// Selectf returns the first case for which its selector is a match for the
+// arg-th substitution argument to a formatting call, formatting it as indicated
+// by format.
+//
+// The cases argument are pairs of selectors and messages. Selectors are of type
+// string or Form. Messages are of type string or catalog.Message. A selector
+// matches an argument if:
+// - it is "other" or Other
+// - it matches the plural form of the argument: "zero", "one", "two", "few",
+// or "many", or the equivalent Form
+// - it is of the form "=x" where x is an integer that matches the value of
+// the argument.
+// - it is of the form "<x" where x is an integer that is larger than the
+// argument.
+//
+// The format argument determines the formatting parameters for which to
+// determine the plural form. This is especially relevant for non-integer
+// values.
+//
+// The format string may be "", in which case a best-effort attempt is made to
+// find a reasonable representation on which to base the plural form. Examples
+// of format strings are:
+// - %.2f decimal with scale 2
+// - %.2e scientific notation with precision 3 (scale + 1)
+// - %d integer
+func Selectf(arg int, format string, cases ...interface{}) catalog.Message {
+ var p parser
+ // Intercept the formatting parameters of format by doing a dummy print.
+ fmt.Fprintf(io.Discard, format, &p)
+ m := &message{arg, kindDefault, 0, cases}
+ switch p.verb {
+ case 'g':
+ m.kind = kindPrecision
+ m.scale = p.scale
+ case 'f':
+ m.kind = kindScale
+ m.scale = p.scale
+ case 'e':
+ m.kind = kindScientific
+ m.scale = p.scale
+ case 'd':
+ m.kind = kindScale
+ m.scale = 0
+ default:
+ // TODO: do we need to handle errors?
+ }
+ return m
+}
+
+type parser struct {
+ verb rune
+ scale int
+}
+
+func (p *parser) Format(s fmt.State, verb rune) {
+ p.verb = verb
+ p.scale = -1
+ if prec, ok := s.Precision(); ok {
+ p.scale = prec
+ }
+}
+
+type message struct {
+ arg int
+ kind int
+ scale int
+ cases []interface{}
+}
+
+const (
+ // Start with non-ASCII to allow skipping values.
+ kindDefault = 0x80 + iota
+ kindScale // verb f, number of fraction digits follows
+ kindScientific // verb e, number of fraction digits follows
+ kindPrecision // verb g, number of significant digits follows
+)
+
+var handle = catmsg.Register("golang.org/x/text/feature/plural:plural", execute)
+
+func (m *message) Compile(e *catmsg.Encoder) error {
+ e.EncodeMessageType(handle)
+
+ e.EncodeUint(uint64(m.arg))
+
+ e.EncodeUint(uint64(m.kind))
+ if m.kind > kindDefault {
+ e.EncodeUint(uint64(m.scale))
+ }
+
+ forms := validForms(cardinal, e.Language())
+
+ for i := 0; i < len(m.cases); {
+ if err := compileSelector(e, forms, m.cases[i]); err != nil {
+ return err
+ }
+ if i++; i >= len(m.cases) {
+ return fmt.Errorf("plural: no message defined for selector %v", m.cases[i-1])
+ }
+ var msg catalog.Message
+ switch x := m.cases[i].(type) {
+ case string:
+ msg = catalog.String(x)
+ case catalog.Message:
+ msg = x
+ default:
+ return fmt.Errorf("plural: message of type %T; must be string or catalog.Message", x)
+ }
+ if err := e.EncodeMessage(msg); err != nil {
+ return err
+ }
+ i++
+ }
+ return nil
+}
+
+func compileSelector(e *catmsg.Encoder, valid []Form, selector interface{}) error {
+ form := Other
+ switch x := selector.(type) {
+ case string:
+ if x == "" {
+ return fmt.Errorf("plural: empty selector")
+ }
+ if c := x[0]; c == '=' || c == '<' {
+ val, err := strconv.ParseUint(x[1:], 10, 16)
+ if err != nil {
+ return fmt.Errorf("plural: invalid number in selector %q: %v", selector, err)
+ }
+ e.EncodeUint(uint64(c))
+ e.EncodeUint(val)
+ return nil
+ }
+ var ok bool
+ form, ok = countMap[x]
+ if !ok {
+ return fmt.Errorf("plural: invalid plural form %q", selector)
+ }
+ case Form:
+ form = x
+ default:
+ return fmt.Errorf("plural: selector of type %T; want string or Form", selector)
+ }
+
+ ok := false
+ for _, f := range valid {
+ if f == form {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ return fmt.Errorf("plural: form %q not supported for language %q", selector, e.Language())
+ }
+ e.EncodeUint(uint64(form))
+ return nil
+}
+
+func execute(d *catmsg.Decoder) bool {
+ lang := d.Language()
+ argN := int(d.DecodeUint())
+ kind := int(d.DecodeUint())
+ scale := -1 // default
+ if kind > kindDefault {
+ scale = int(d.DecodeUint())
+ }
+ form := Other
+ n := -1
+ if arg := d.Arg(argN); arg == nil {
+ // Default to Other.
+ } else if x, ok := arg.(number.VisibleDigits); ok {
+ d := x.Digits(nil, lang, scale)
+ form, n = cardinal.matchDisplayDigits(lang, &d)
+ } else if x, ok := arg.(Interface); ok {
+ // This covers lists and formatters from the number package.
+ form, n = x.PluralForm(lang, scale)
+ } else {
+ var f number.Formatter
+ switch kind {
+ case kindScale:
+ f.InitDecimal(lang)
+ f.SetScale(scale)
+ case kindScientific:
+ f.InitScientific(lang)
+ f.SetScale(scale)
+ case kindPrecision:
+ f.InitDecimal(lang)
+ f.SetPrecision(scale)
+ case kindDefault:
+ // sensible default
+ f.InitDecimal(lang)
+ if k := reflect.TypeOf(arg).Kind(); reflect.Int <= k && k <= reflect.Uintptr {
+ f.SetScale(0)
+ } else {
+ f.SetScale(2)
+ }
+ }
+ var dec number.Decimal // TODO: buffer in Printer
+ dec.Convert(f.RoundingContext, arg)
+ v := number.FormatDigits(&dec, f.RoundingContext)
+ if !v.NaN && !v.Inf {
+ form, n = cardinal.matchDisplayDigits(d.Language(), &v)
+ }
+ }
+ for !d.Done() {
+ f := d.DecodeUint()
+ if (f == '=' && n == int(d.DecodeUint())) ||
+ (f == '<' && 0 <= n && n < int(d.DecodeUint())) ||
+ form == Form(f) ||
+ Other == Form(f) {
+ return d.ExecuteMessage()
+ }
+ d.SkipMessage()
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/text/feature/plural/plural.go b/vendor/golang.org/x/text/feature/plural/plural.go
new file mode 100644
index 0000000..e9f2d42
--- /dev/null
+++ b/vendor/golang.org/x/text/feature/plural/plural.go
@@ -0,0 +1,262 @@
+// Copyright 2016 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 gen.go gen_common.go
+
+// Package plural provides utilities for handling linguistic plurals in text.
+//
+// The definitions in this package are based on the plural rule handling defined
+// in CLDR. See
+// https://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules for
+// details.
+package plural
+
+import (
+ "golang.org/x/text/internal/language/compact"
+ "golang.org/x/text/internal/number"
+ "golang.org/x/text/language"
+)
+
+// Rules defines the plural rules for all languages for a certain plural type.
+//
+// This package is UNDER CONSTRUCTION and its API may change.
+type Rules struct {
+ rules []pluralCheck
+ index []byte
+ langToIndex []byte
+ inclusionMasks []uint64
+}
+
+var (
+ // Cardinal defines the plural rules for numbers indicating quantities.
+ Cardinal *Rules = cardinal
+
+ // Ordinal defines the plural rules for numbers indicating position
+ // (first, second, etc.).
+ Ordinal *Rules = ordinal
+
+ ordinal = &Rules{
+ ordinalRules,
+ ordinalIndex,
+ ordinalLangToIndex,
+ ordinalInclusionMasks[:],
+ }
+
+ cardinal = &Rules{
+ cardinalRules,
+ cardinalIndex,
+ cardinalLangToIndex,
+ cardinalInclusionMasks[:],
+ }
+)
+
+// getIntApprox converts the digits in slice digits[start:end] to an integer
+// according to the following rules:
+// - Let i be asInt(digits[start:end]), where out-of-range digits are assumed
+// to be zero.
+// - Result n is big if i / 10^nMod > 1.
+// - Otherwise the result is i % 10^nMod.
+//
+// For example, if digits is {1, 2, 3} and start:end is 0:5, then the result
+// for various values of nMod is:
+// - when nMod == 2, n == big
+// - when nMod == 3, n == big
+// - when nMod == 4, n == big
+// - when nMod == 5, n == 12300
+// - when nMod == 6, n == 12300
+// - when nMod == 7, n == 12300
+func getIntApprox(digits []byte, start, end, nMod, big int) (n int) {
+ // Leading 0 digits just result in 0.
+ p := start
+ if p < 0 {
+ p = 0
+ }
+ // Range only over the part for which we have digits.
+ mid := end
+ if mid >= len(digits) {
+ mid = len(digits)
+ }
+ // Check digits more significant that nMod.
+ if q := end - nMod; q > 0 {
+ if q > mid {
+ q = mid
+ }
+ for ; p < q; p++ {
+ if digits[p] != 0 {
+ return big
+ }
+ }
+ }
+ for ; p < mid; p++ {
+ n = 10*n + int(digits[p])
+ }
+ // Multiply for trailing zeros.
+ for ; p < end; p++ {
+ n *= 10
+ }
+ return n
+}
+
+// MatchDigits computes the plural form for the given language and the given
+// decimal floating point digits. The digits are stored in big-endian order and
+// are of value byte(0) - byte(9). The floating point position is indicated by
+// exp and the number of visible decimals is scale. All leading and trailing
+// zeros may be omitted from digits.
+//
+// The following table contains examples of possible arguments to represent
+// the given numbers.
+//
+// decimal digits exp scale
+// 123 []byte{1, 2, 3} 3 0
+// 123.4 []byte{1, 2, 3, 4} 3 1
+// 123.40 []byte{1, 2, 3, 4} 3 2
+// 100000 []byte{1} 6 0
+// 100000.00 []byte{1} 6 3
+func (p *Rules) MatchDigits(t language.Tag, digits []byte, exp, scale int) Form {
+ index := tagToID(t)
+
+ // Differentiate up to including mod 1000000 for the integer part.
+ n := getIntApprox(digits, 0, exp, 6, 1000000)
+
+ // Differentiate up to including mod 100 for the fractional part.
+ f := getIntApprox(digits, exp, exp+scale, 2, 100)
+
+ return matchPlural(p, index, n, f, scale)
+}
+
+func (p *Rules) matchDisplayDigits(t language.Tag, d *number.Digits) (Form, int) {
+ n := getIntApprox(d.Digits, 0, int(d.Exp), 6, 1000000)
+ return p.MatchDigits(t, d.Digits, int(d.Exp), d.NumFracDigits()), n
+}
+
+func validForms(p *Rules, t language.Tag) (forms []Form) {
+ offset := p.langToIndex[tagToID(t)]
+ rules := p.rules[p.index[offset]:p.index[offset+1]]
+
+ forms = append(forms, Other)
+ last := Other
+ for _, r := range rules {
+ if cat := Form(r.cat & formMask); cat != andNext && last != cat {
+ forms = append(forms, cat)
+ last = cat
+ }
+ }
+ return forms
+}
+
+func (p *Rules) matchComponents(t language.Tag, n, f, scale int) Form {
+ return matchPlural(p, tagToID(t), n, f, scale)
+}
+
+// MatchPlural returns the plural form for the given language and plural
+// operands (as defined in
+// https://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules):
+//
+// where
+// n absolute value of the source number (integer and decimals)
+// input
+// i integer digits of n.
+// v number of visible fraction digits in n, with trailing zeros.
+// w number of visible fraction digits in n, without trailing zeros.
+// f visible fractional digits in n, with trailing zeros (f = t * 10^(v-w))
+// t visible fractional digits in n, without trailing zeros.
+//
+// If any of the operand values is too large to fit in an int, it is okay to
+// pass the value modulo 10,000,000.
+func (p *Rules) MatchPlural(lang language.Tag, i, v, w, f, t int) Form {
+ return matchPlural(p, tagToID(lang), i, f, v)
+}
+
+func matchPlural(p *Rules, index compact.ID, n, f, v int) Form {
+ nMask := p.inclusionMasks[n%maxMod]
+ // Compute the fMask inline in the rules below, as it is relatively rare.
+ // fMask := p.inclusionMasks[f%maxMod]
+ vMask := p.inclusionMasks[v%maxMod]
+
+ // Do the matching
+ offset := p.langToIndex[index]
+ rules := p.rules[p.index[offset]:p.index[offset+1]]
+ for i := 0; i < len(rules); i++ {
+ rule := rules[i]
+ setBit := uint64(1 << rule.setID)
+ var skip bool
+ switch op := opID(rule.cat >> opShift); op {
+ case opI: // i = x
+ skip = n >= numN || nMask&setBit == 0
+
+ case opI | opNotEqual: // i != x
+ skip = n < numN && nMask&setBit != 0
+
+ case opI | opMod: // i % m = x
+ skip = nMask&setBit == 0
+
+ case opI | opMod | opNotEqual: // i % m != x
+ skip = nMask&setBit != 0
+
+ case opN: // n = x
+ skip = f != 0 || n >= numN || nMask&setBit == 0
+
+ case opN | opNotEqual: // n != x
+ skip = f == 0 && n < numN && nMask&setBit != 0
+
+ case opN | opMod: // n % m = x
+ skip = f != 0 || nMask&setBit == 0
+
+ case opN | opMod | opNotEqual: // n % m != x
+ skip = f == 0 && nMask&setBit != 0
+
+ case opF: // f = x
+ skip = f >= numN || p.inclusionMasks[f%maxMod]&setBit == 0
+
+ case opF | opNotEqual: // f != x
+ skip = f < numN && p.inclusionMasks[f%maxMod]&setBit != 0
+
+ case opF | opMod: // f % m = x
+ skip = p.inclusionMasks[f%maxMod]&setBit == 0
+
+ case opF | opMod | opNotEqual: // f % m != x
+ skip = p.inclusionMasks[f%maxMod]&setBit != 0
+
+ case opV: // v = x
+ skip = v < numN && vMask&setBit == 0
+
+ case opV | opNotEqual: // v != x
+ skip = v < numN && vMask&setBit != 0
+
+ case opW: // w == 0
+ skip = f != 0
+
+ case opW | opNotEqual: // w != 0
+ skip = f == 0
+
+ // Hard-wired rules that cannot be handled by our algorithm.
+
+ case opBretonM:
+ skip = f != 0 || n == 0 || n%1000000 != 0
+
+ case opAzerbaijan00s:
+ // 100,200,300,400,500,600,700,800,900
+ skip = n == 0 || n >= 1000 || n%100 != 0
+
+ case opItalian800:
+ skip = (f != 0 || n >= numN || nMask&setBit == 0) && n != 800
+ }
+ if skip {
+ // advance over AND entries.
+ for ; i < len(rules) && rules[i].cat&formMask == andNext; i++ {
+ }
+ continue
+ }
+ // return if we have a final entry.
+ if cat := rule.cat & formMask; cat != andNext {
+ return Form(cat)
+ }
+ }
+ return Other
+}
+
+func tagToID(t language.Tag) compact.ID {
+ id, _ := compact.RegionalID(compact.Tag(t))
+ return id
+}
diff --git a/vendor/golang.org/x/text/feature/plural/tables.go b/vendor/golang.org/x/text/feature/plural/tables.go
new file mode 100644
index 0000000..b06b9cb
--- /dev/null
+++ b/vendor/golang.org/x/text/feature/plural/tables.go
@@ -0,0 +1,552 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package plural
+
+// CLDRVersion is the CLDR version from which the tables in this package are derived.
+const CLDRVersion = "32"
+
+var ordinalRules = []pluralCheck{ // 64 elements
+ 0: {cat: 0x2f, setID: 0x4},
+ 1: {cat: 0x3a, setID: 0x5},
+ 2: {cat: 0x22, setID: 0x1},
+ 3: {cat: 0x22, setID: 0x6},
+ 4: {cat: 0x22, setID: 0x7},
+ 5: {cat: 0x2f, setID: 0x8},
+ 6: {cat: 0x3c, setID: 0x9},
+ 7: {cat: 0x2f, setID: 0xa},
+ 8: {cat: 0x3c, setID: 0xb},
+ 9: {cat: 0x2c, setID: 0xc},
+ 10: {cat: 0x24, setID: 0xd},
+ 11: {cat: 0x2d, setID: 0xe},
+ 12: {cat: 0x2d, setID: 0xf},
+ 13: {cat: 0x2f, setID: 0x10},
+ 14: {cat: 0x35, setID: 0x3},
+ 15: {cat: 0xc5, setID: 0x11},
+ 16: {cat: 0x2, setID: 0x1},
+ 17: {cat: 0x5, setID: 0x3},
+ 18: {cat: 0xd, setID: 0x12},
+ 19: {cat: 0x22, setID: 0x1},
+ 20: {cat: 0x2f, setID: 0x13},
+ 21: {cat: 0x3d, setID: 0x14},
+ 22: {cat: 0x2f, setID: 0x15},
+ 23: {cat: 0x3a, setID: 0x16},
+ 24: {cat: 0x2f, setID: 0x17},
+ 25: {cat: 0x3b, setID: 0x18},
+ 26: {cat: 0x2f, setID: 0xa},
+ 27: {cat: 0x3c, setID: 0xb},
+ 28: {cat: 0x22, setID: 0x1},
+ 29: {cat: 0x23, setID: 0x19},
+ 30: {cat: 0x24, setID: 0x1a},
+ 31: {cat: 0x22, setID: 0x1b},
+ 32: {cat: 0x23, setID: 0x2},
+ 33: {cat: 0x24, setID: 0x1a},
+ 34: {cat: 0xf, setID: 0x15},
+ 35: {cat: 0x1a, setID: 0x16},
+ 36: {cat: 0xf, setID: 0x17},
+ 37: {cat: 0x1b, setID: 0x18},
+ 38: {cat: 0xf, setID: 0x1c},
+ 39: {cat: 0x1d, setID: 0x1d},
+ 40: {cat: 0xa, setID: 0x1e},
+ 41: {cat: 0xa, setID: 0x1f},
+ 42: {cat: 0xc, setID: 0x20},
+ 43: {cat: 0xe4, setID: 0x0},
+ 44: {cat: 0x5, setID: 0x3},
+ 45: {cat: 0xd, setID: 0xe},
+ 46: {cat: 0xd, setID: 0x21},
+ 47: {cat: 0x22, setID: 0x1},
+ 48: {cat: 0x23, setID: 0x19},
+ 49: {cat: 0x24, setID: 0x1a},
+ 50: {cat: 0x25, setID: 0x22},
+ 51: {cat: 0x22, setID: 0x23},
+ 52: {cat: 0x23, setID: 0x19},
+ 53: {cat: 0x24, setID: 0x1a},
+ 54: {cat: 0x25, setID: 0x22},
+ 55: {cat: 0x22, setID: 0x24},
+ 56: {cat: 0x23, setID: 0x19},
+ 57: {cat: 0x24, setID: 0x1a},
+ 58: {cat: 0x25, setID: 0x22},
+ 59: {cat: 0x21, setID: 0x25},
+ 60: {cat: 0x22, setID: 0x1},
+ 61: {cat: 0x23, setID: 0x2},
+ 62: {cat: 0x24, setID: 0x26},
+ 63: {cat: 0x25, setID: 0x27},
+} // Size: 152 bytes
+
+var ordinalIndex = []uint8{ // 22 elements
+ 0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x07, 0x09,
+ 0x0b, 0x0f, 0x10, 0x13, 0x16, 0x1c, 0x1f, 0x22,
+ 0x28, 0x2f, 0x33, 0x37, 0x3b, 0x40,
+} // Size: 46 bytes
+
+var ordinalLangToIndex = []uint8{ // 775 elements
+ // Entry 0 - 3F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x00, 0x00, 0x05, 0x05, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 40 - 7F
+ 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
+ 0x0e, 0x0e, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 80 - BF
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ // Entry C0 - FF
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 100 - 13F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 140 - 17F
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+ 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 180 - 1BF
+ 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 1C0 - 1FF
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x0d, 0x0d, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 200 - 23F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x13, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 240 - 27F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 280 - 2BF
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x0b, 0x0b, 0x0b, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00,
+ // Entry 2C0 - 2FF
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 300 - 33F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0c,
+} // Size: 799 bytes
+
+var ordinalInclusionMasks = []uint64{ // 100 elements
+ // Entry 0 - 1F
+ 0x0000002000010009, 0x00000018482000d3, 0x0000000042840195, 0x000000410a040581,
+ 0x00000041040c0081, 0x0000009840040041, 0x0000008400045001, 0x0000003850040001,
+ 0x0000003850060001, 0x0000003800049001, 0x0000000800052001, 0x0000000040660031,
+ 0x0000000041840331, 0x0000000100040f01, 0x00000001001c0001, 0x0000000040040001,
+ 0x0000000000045001, 0x0000000070040001, 0x0000000070040001, 0x0000000000049001,
+ 0x0000000080050001, 0x0000000040200011, 0x0000000040800111, 0x0000000100000501,
+ 0x0000000100080001, 0x0000000040000001, 0x0000000000005001, 0x0000000050000001,
+ 0x0000000050000001, 0x0000000000009001, 0x0000000000010001, 0x0000000040200011,
+ // Entry 20 - 3F
+ 0x0000000040800111, 0x0000000100000501, 0x0000000100080001, 0x0000000040000001,
+ 0x0000000000005001, 0x0000000050000001, 0x0000000050000001, 0x0000000000009001,
+ 0x0000000200050001, 0x0000000040200011, 0x0000000040800111, 0x0000000100000501,
+ 0x0000000100080001, 0x0000000040000001, 0x0000000000005001, 0x0000000050000001,
+ 0x0000000050000001, 0x0000000000009001, 0x0000000080010001, 0x0000000040200011,
+ 0x0000000040800111, 0x0000000100000501, 0x0000000100080001, 0x0000000040000001,
+ 0x0000000000005001, 0x0000000050000001, 0x0000000050000001, 0x0000000000009001,
+ 0x0000000200050001, 0x0000000040200011, 0x0000000040800111, 0x0000000100000501,
+ // Entry 40 - 5F
+ 0x0000000100080001, 0x0000000040000001, 0x0000000000005001, 0x0000000050000001,
+ 0x0000000050000001, 0x0000000000009001, 0x0000000080010001, 0x0000000040200011,
+ 0x0000000040800111, 0x0000000100000501, 0x0000000100080001, 0x0000000040000001,
+ 0x0000000000005001, 0x0000000050000001, 0x0000000050000001, 0x0000000000009001,
+ 0x0000000080070001, 0x0000000040200011, 0x0000000040800111, 0x0000000100000501,
+ 0x0000000100080001, 0x0000000040000001, 0x0000000000005001, 0x0000000050000001,
+ 0x0000000050000001, 0x0000000000009001, 0x0000000200010001, 0x0000000040200011,
+ 0x0000000040800111, 0x0000000100000501, 0x0000000100080001, 0x0000000040000001,
+ // Entry 60 - 7F
+ 0x0000000000005001, 0x0000000050000001, 0x0000000050000001, 0x0000000000009001,
+} // Size: 824 bytes
+
+// Slots used for ordinal: 40 of 0xFF rules; 16 of 0xFF indexes; 40 of 64 sets
+
+var cardinalRules = []pluralCheck{ // 166 elements
+ 0: {cat: 0x2, setID: 0x3},
+ 1: {cat: 0x22, setID: 0x1},
+ 2: {cat: 0x2, setID: 0x4},
+ 3: {cat: 0x2, setID: 0x4},
+ 4: {cat: 0x7, setID: 0x1},
+ 5: {cat: 0x62, setID: 0x3},
+ 6: {cat: 0x22, setID: 0x4},
+ 7: {cat: 0x7, setID: 0x3},
+ 8: {cat: 0x42, setID: 0x1},
+ 9: {cat: 0x22, setID: 0x4},
+ 10: {cat: 0x22, setID: 0x4},
+ 11: {cat: 0x22, setID: 0x5},
+ 12: {cat: 0x22, setID: 0x1},
+ 13: {cat: 0x22, setID: 0x1},
+ 14: {cat: 0x7, setID: 0x4},
+ 15: {cat: 0x92, setID: 0x3},
+ 16: {cat: 0xf, setID: 0x6},
+ 17: {cat: 0x1f, setID: 0x7},
+ 18: {cat: 0x82, setID: 0x3},
+ 19: {cat: 0x92, setID: 0x3},
+ 20: {cat: 0xf, setID: 0x6},
+ 21: {cat: 0x62, setID: 0x3},
+ 22: {cat: 0x4a, setID: 0x6},
+ 23: {cat: 0x7, setID: 0x8},
+ 24: {cat: 0x62, setID: 0x3},
+ 25: {cat: 0x1f, setID: 0x9},
+ 26: {cat: 0x62, setID: 0x3},
+ 27: {cat: 0x5f, setID: 0x9},
+ 28: {cat: 0x72, setID: 0x3},
+ 29: {cat: 0x29, setID: 0xa},
+ 30: {cat: 0x29, setID: 0xb},
+ 31: {cat: 0x4f, setID: 0xb},
+ 32: {cat: 0x61, setID: 0x2},
+ 33: {cat: 0x2f, setID: 0x6},
+ 34: {cat: 0x3a, setID: 0x7},
+ 35: {cat: 0x4f, setID: 0x6},
+ 36: {cat: 0x5f, setID: 0x7},
+ 37: {cat: 0x62, setID: 0x2},
+ 38: {cat: 0x4f, setID: 0x6},
+ 39: {cat: 0x72, setID: 0x2},
+ 40: {cat: 0x21, setID: 0x3},
+ 41: {cat: 0x7, setID: 0x4},
+ 42: {cat: 0x32, setID: 0x3},
+ 43: {cat: 0x21, setID: 0x3},
+ 44: {cat: 0x22, setID: 0x1},
+ 45: {cat: 0x22, setID: 0x1},
+ 46: {cat: 0x23, setID: 0x2},
+ 47: {cat: 0x2, setID: 0x3},
+ 48: {cat: 0x22, setID: 0x1},
+ 49: {cat: 0x24, setID: 0xc},
+ 50: {cat: 0x7, setID: 0x1},
+ 51: {cat: 0x62, setID: 0x3},
+ 52: {cat: 0x74, setID: 0x3},
+ 53: {cat: 0x24, setID: 0x3},
+ 54: {cat: 0x2f, setID: 0xd},
+ 55: {cat: 0x34, setID: 0x1},
+ 56: {cat: 0xf, setID: 0x6},
+ 57: {cat: 0x1f, setID: 0x7},
+ 58: {cat: 0x62, setID: 0x3},
+ 59: {cat: 0x4f, setID: 0x6},
+ 60: {cat: 0x5a, setID: 0x7},
+ 61: {cat: 0xf, setID: 0xe},
+ 62: {cat: 0x1f, setID: 0xf},
+ 63: {cat: 0x64, setID: 0x3},
+ 64: {cat: 0x4f, setID: 0xe},
+ 65: {cat: 0x5c, setID: 0xf},
+ 66: {cat: 0x22, setID: 0x10},
+ 67: {cat: 0x23, setID: 0x11},
+ 68: {cat: 0x24, setID: 0x12},
+ 69: {cat: 0xf, setID: 0x1},
+ 70: {cat: 0x62, setID: 0x3},
+ 71: {cat: 0xf, setID: 0x2},
+ 72: {cat: 0x63, setID: 0x3},
+ 73: {cat: 0xf, setID: 0x13},
+ 74: {cat: 0x64, setID: 0x3},
+ 75: {cat: 0x74, setID: 0x3},
+ 76: {cat: 0xf, setID: 0x1},
+ 77: {cat: 0x62, setID: 0x3},
+ 78: {cat: 0x4a, setID: 0x1},
+ 79: {cat: 0xf, setID: 0x2},
+ 80: {cat: 0x63, setID: 0x3},
+ 81: {cat: 0x4b, setID: 0x2},
+ 82: {cat: 0xf, setID: 0x13},
+ 83: {cat: 0x64, setID: 0x3},
+ 84: {cat: 0x4c, setID: 0x13},
+ 85: {cat: 0x7, setID: 0x1},
+ 86: {cat: 0x62, setID: 0x3},
+ 87: {cat: 0x7, setID: 0x2},
+ 88: {cat: 0x63, setID: 0x3},
+ 89: {cat: 0x2f, setID: 0xa},
+ 90: {cat: 0x37, setID: 0x14},
+ 91: {cat: 0x65, setID: 0x3},
+ 92: {cat: 0x7, setID: 0x1},
+ 93: {cat: 0x62, setID: 0x3},
+ 94: {cat: 0x7, setID: 0x15},
+ 95: {cat: 0x64, setID: 0x3},
+ 96: {cat: 0x75, setID: 0x3},
+ 97: {cat: 0x7, setID: 0x1},
+ 98: {cat: 0x62, setID: 0x3},
+ 99: {cat: 0xf, setID: 0xe},
+ 100: {cat: 0x1f, setID: 0xf},
+ 101: {cat: 0x64, setID: 0x3},
+ 102: {cat: 0xf, setID: 0x16},
+ 103: {cat: 0x17, setID: 0x1},
+ 104: {cat: 0x65, setID: 0x3},
+ 105: {cat: 0xf, setID: 0x17},
+ 106: {cat: 0x65, setID: 0x3},
+ 107: {cat: 0xf, setID: 0xf},
+ 108: {cat: 0x65, setID: 0x3},
+ 109: {cat: 0x2f, setID: 0x6},
+ 110: {cat: 0x3a, setID: 0x7},
+ 111: {cat: 0x2f, setID: 0xe},
+ 112: {cat: 0x3c, setID: 0xf},
+ 113: {cat: 0x2d, setID: 0xa},
+ 114: {cat: 0x2d, setID: 0x17},
+ 115: {cat: 0x2d, setID: 0x18},
+ 116: {cat: 0x2f, setID: 0x6},
+ 117: {cat: 0x3a, setID: 0xb},
+ 118: {cat: 0x2f, setID: 0x19},
+ 119: {cat: 0x3c, setID: 0xb},
+ 120: {cat: 0x55, setID: 0x3},
+ 121: {cat: 0x22, setID: 0x1},
+ 122: {cat: 0x24, setID: 0x3},
+ 123: {cat: 0x2c, setID: 0xc},
+ 124: {cat: 0x2d, setID: 0xb},
+ 125: {cat: 0xf, setID: 0x6},
+ 126: {cat: 0x1f, setID: 0x7},
+ 127: {cat: 0x62, setID: 0x3},
+ 128: {cat: 0xf, setID: 0xe},
+ 129: {cat: 0x1f, setID: 0xf},
+ 130: {cat: 0x64, setID: 0x3},
+ 131: {cat: 0xf, setID: 0xa},
+ 132: {cat: 0x65, setID: 0x3},
+ 133: {cat: 0xf, setID: 0x17},
+ 134: {cat: 0x65, setID: 0x3},
+ 135: {cat: 0xf, setID: 0x18},
+ 136: {cat: 0x65, setID: 0x3},
+ 137: {cat: 0x2f, setID: 0x6},
+ 138: {cat: 0x3a, setID: 0x1a},
+ 139: {cat: 0x2f, setID: 0x1b},
+ 140: {cat: 0x3b, setID: 0x1c},
+ 141: {cat: 0x2f, setID: 0x1d},
+ 142: {cat: 0x3c, setID: 0x1e},
+ 143: {cat: 0x37, setID: 0x3},
+ 144: {cat: 0xa5, setID: 0x0},
+ 145: {cat: 0x22, setID: 0x1},
+ 146: {cat: 0x23, setID: 0x2},
+ 147: {cat: 0x24, setID: 0x1f},
+ 148: {cat: 0x25, setID: 0x20},
+ 149: {cat: 0xf, setID: 0x6},
+ 150: {cat: 0x62, setID: 0x3},
+ 151: {cat: 0xf, setID: 0x1b},
+ 152: {cat: 0x63, setID: 0x3},
+ 153: {cat: 0xf, setID: 0x21},
+ 154: {cat: 0x64, setID: 0x3},
+ 155: {cat: 0x75, setID: 0x3},
+ 156: {cat: 0x21, setID: 0x3},
+ 157: {cat: 0x22, setID: 0x1},
+ 158: {cat: 0x23, setID: 0x2},
+ 159: {cat: 0x2c, setID: 0x22},
+ 160: {cat: 0x2d, setID: 0x5},
+ 161: {cat: 0x21, setID: 0x3},
+ 162: {cat: 0x22, setID: 0x1},
+ 163: {cat: 0x23, setID: 0x2},
+ 164: {cat: 0x24, setID: 0x23},
+ 165: {cat: 0x25, setID: 0x24},
+} // Size: 356 bytes
+
+var cardinalIndex = []uint8{ // 36 elements
+ 0x00, 0x00, 0x02, 0x03, 0x04, 0x06, 0x09, 0x0a,
+ 0x0c, 0x0d, 0x10, 0x14, 0x17, 0x1d, 0x28, 0x2b,
+ 0x2d, 0x2f, 0x32, 0x38, 0x42, 0x45, 0x4c, 0x55,
+ 0x5c, 0x61, 0x6d, 0x74, 0x79, 0x7d, 0x89, 0x91,
+ 0x95, 0x9c, 0xa1, 0xa6,
+} // Size: 60 bytes
+
+var cardinalLangToIndex = []uint8{ // 775 elements
+ // Entry 0 - 3F
+ 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x06, 0x06,
+ 0x01, 0x01, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+ 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+ 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+ 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+ 0x01, 0x01, 0x08, 0x08, 0x04, 0x04, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x00, 0x00, 0x1a, 0x1a, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x06, 0x00, 0x00,
+ // Entry 40 - 7F
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x1e,
+ 0x08, 0x08, 0x13, 0x13, 0x13, 0x13, 0x13, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x18, 0x18, 0x00, 0x00, 0x22, 0x22, 0x09, 0x09,
+ 0x09, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x00, 0x00, 0x16, 0x16, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 80 - BF
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ // Entry C0 - FF
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ // Entry 100 - 13F
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04,
+ 0x08, 0x08, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x0c, 0x0c,
+ 0x08, 0x08, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 140 - 17F
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x08, 0x08, 0x04, 0x04, 0x1f, 0x1f,
+ 0x14, 0x14, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08,
+ 0x01, 0x01, 0x06, 0x00, 0x00, 0x20, 0x20, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x17, 0x17, 0x01,
+ 0x01, 0x13, 0x13, 0x13, 0x16, 0x16, 0x08, 0x08,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 180 - 1BF
+ 0x00, 0x04, 0x0a, 0x0a, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x10, 0x17, 0x00, 0x00, 0x00, 0x08, 0x08,
+ 0x04, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x02,
+ 0x02, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
+ 0x08, 0x08, 0x00, 0x00, 0x0f, 0x0f, 0x08, 0x10,
+ // Entry 1C0 - 1FF
+ 0x10, 0x08, 0x08, 0x0e, 0x0e, 0x08, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x1b, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0d, 0x08,
+ 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06,
+ 0x00, 0x00, 0x08, 0x08, 0x0b, 0x0b, 0x08, 0x08,
+ 0x08, 0x08, 0x12, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 200 - 23F
+ 0x00, 0x08, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00,
+ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08,
+ 0x06, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x08, 0x19, 0x19, 0x0d, 0x0d,
+ 0x08, 0x08, 0x03, 0x04, 0x03, 0x04, 0x04, 0x04,
+ // Entry 240 - 27F
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x12,
+ 0x12, 0x12, 0x08, 0x08, 0x1d, 0x1d, 0x1d, 0x1d,
+ 0x1d, 0x1d, 0x1d, 0x00, 0x00, 0x08, 0x08, 0x00,
+ 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08,
+ 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x05, 0x05, 0x18, 0x18, 0x15, 0x15, 0x10, 0x10,
+ // Entry 280 - 2BF
+ 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x13,
+ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
+ 0x13, 0x13, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06,
+ 0x08, 0x08, 0x08, 0x0c, 0x08, 0x00, 0x00, 0x08,
+ // Entry 2C0 - 2FF
+ 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x07, 0x08, 0x08, 0x1d, 0x1d, 0x04, 0x04, 0x04,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08,
+ 0x08, 0x08, 0x08, 0x06, 0x08, 0x08, 0x00, 0x00,
+ 0x08, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 300 - 33F
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x04, 0x04,
+} // Size: 799 bytes
+
+var cardinalInclusionMasks = []uint64{ // 100 elements
+ // Entry 0 - 1F
+ 0x0000000200500419, 0x0000000000512153, 0x000000000a327105, 0x0000000ca23c7101,
+ 0x00000004a23c7201, 0x0000000482943001, 0x0000001482943201, 0x0000000502943001,
+ 0x0000000502943001, 0x0000000522943201, 0x0000000540543401, 0x00000000454128e1,
+ 0x000000005b02e821, 0x000000006304e821, 0x000000006304ea21, 0x0000000042842821,
+ 0x0000000042842a21, 0x0000000042842821, 0x0000000042842821, 0x0000000062842a21,
+ 0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
+ 0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
+ 0x0000000002800021, 0x0000000022800221, 0x0000000000400421, 0x0000000000400061,
+ // Entry 20 - 3F
+ 0x000000000a004021, 0x0000000022004021, 0x0000000022004221, 0x0000000002800021,
+ 0x0000000002800221, 0x0000000002800021, 0x0000000002800021, 0x0000000022800221,
+ 0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
+ 0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
+ 0x0000000002800021, 0x0000000022800221, 0x0000000000400421, 0x0000000000400061,
+ 0x000000000a004021, 0x0000000022004021, 0x0000000022004221, 0x0000000002800021,
+ 0x0000000002800221, 0x0000000002800021, 0x0000000002800021, 0x0000000022800221,
+ 0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
+ // Entry 40 - 5F
+ 0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
+ 0x0000000002800021, 0x0000000022800221, 0x0000000040400421, 0x0000000044400061,
+ 0x000000005a004021, 0x0000000062004021, 0x0000000062004221, 0x0000000042800021,
+ 0x0000000042800221, 0x0000000042800021, 0x0000000042800021, 0x0000000062800221,
+ 0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
+ 0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
+ 0x0000000002800021, 0x0000000022800221, 0x0000000040400421, 0x0000000044400061,
+ 0x000000005a004021, 0x0000000062004021, 0x0000000062004221, 0x0000000042800021,
+ // Entry 60 - 7F
+ 0x0000000042800221, 0x0000000042800021, 0x0000000042800021, 0x0000000062800221,
+} // Size: 824 bytes
+
+// Slots used for cardinal: A6 of 0xFF rules; 24 of 0xFF indexes; 37 of 64 sets
+
+// Total table size 3860 bytes (3KiB); checksum: AAFBF21
diff --git a/vendor/golang.org/x/text/internal/catmsg/catmsg.go b/vendor/golang.org/x/text/internal/catmsg/catmsg.go
new file mode 100644
index 0000000..1b257a7
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/catmsg/catmsg.go
@@ -0,0 +1,417 @@
+// Copyright 2017 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 catmsg contains support types for package x/text/message/catalog.
+//
+// This package contains the low-level implementations of Message used by the
+// catalog package and provides primitives for other packages to implement their
+// own. For instance, the plural package provides functionality for selecting
+// translation strings based on the plural category of substitution arguments.
+//
+// # Encoding and Decoding
+//
+// Catalogs store Messages encoded as a single string. Compiling a message into
+// a string both results in compacter representation and speeds up evaluation.
+//
+// A Message must implement a Compile method to convert its arbitrary
+// representation to a string. The Compile method takes an Encoder which
+// facilitates serializing the message. Encoders also provide more context of
+// the messages's creation (such as for which language the message is intended),
+// which may not be known at the time of the creation of the message.
+//
+// Each message type must also have an accompanying decoder registered to decode
+// the message. This decoder takes a Decoder argument which provides the
+// counterparts for the decoding.
+//
+// # Renderers
+//
+// A Decoder must be initialized with a Renderer implementation. These
+// implementations must be provided by packages that use Catalogs, typically
+// formatting packages such as x/text/message. A typical user will not need to
+// worry about this type; it is only relevant to packages that do string
+// formatting and want to use the catalog package to handle localized strings.
+//
+// A package that uses catalogs for selecting strings receives selection results
+// as sequence of substrings passed to the Renderer. The following snippet shows
+// how to express the above example using the message package.
+//
+// message.Set(language.English, "You are %d minute(s) late.",
+// catalog.Var("minutes", plural.Select(1, "one", "minute")),
+// catalog.String("You are %[1]d ${minutes} late."))
+//
+// p := message.NewPrinter(language.English)
+// p.Printf("You are %d minute(s) late.", 5) // always 5 minutes late.
+//
+// To evaluate the Printf, package message wraps the arguments in a Renderer
+// that is passed to the catalog for message decoding. The call sequence that
+// results from evaluating the above message, assuming the person is rather
+// tardy, is:
+//
+// Render("You are %[1]d ")
+// Arg(1)
+// Render("minutes")
+// Render(" late.")
+//
+// The calls to Arg is caused by the plural.Select execution, which evaluates
+// the argument to determine whether the singular or plural message form should
+// be selected. The calls to Render reports the partial results to the message
+// package for further evaluation.
+package catmsg
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+ "sync"
+
+ "golang.org/x/text/language"
+)
+
+// A Handle refers to a registered message type.
+type Handle int
+
+// A Handler decodes and evaluates data compiled by a Message and sends the
+// result to the Decoder. The output may depend on the value of the substitution
+// arguments, accessible by the Decoder's Arg method. The Handler returns false
+// if there is no translation for the given substitution arguments.
+type Handler func(d *Decoder) bool
+
+// Register records the existence of a message type and returns a Handle that
+// can be used in the Encoder's EncodeMessageType method to create such
+// messages. The prefix of the name should be the package path followed by
+// an optional disambiguating string.
+// Register will panic if a handle for the same name was already registered.
+func Register(name string, handler Handler) Handle {
+ mutex.Lock()
+ defer mutex.Unlock()
+
+ if _, ok := names[name]; ok {
+ panic(fmt.Errorf("catmsg: handler for %q already exists", name))
+ }
+ h := Handle(len(handlers))
+ names[name] = h
+ handlers = append(handlers, handler)
+ return h
+}
+
+// These handlers require fixed positions in the handlers slice.
+const (
+ msgVars Handle = iota
+ msgFirst
+ msgRaw
+ msgString
+ msgAffix
+ // Leave some arbitrary room for future expansion: 20 should suffice.
+ numInternal = 20
+)
+
+const prefix = "golang.org/x/text/internal/catmsg."
+
+var (
+ // TODO: find a more stable way to link handles to message types.
+ mutex sync.Mutex
+ names = map[string]Handle{
+ prefix + "Vars": msgVars,
+ prefix + "First": msgFirst,
+ prefix + "Raw": msgRaw,
+ prefix + "String": msgString,
+ prefix + "Affix": msgAffix,
+ }
+ handlers = make([]Handler, numInternal)
+)
+
+func init() {
+ // This handler is a message type wrapper that initializes a decoder
+ // with a variable block. This message type, if present, is always at the
+ // start of an encoded message.
+ handlers[msgVars] = func(d *Decoder) bool {
+ blockSize := int(d.DecodeUint())
+ d.vars = d.data[:blockSize]
+ d.data = d.data[blockSize:]
+ return d.executeMessage()
+ }
+
+ // First takes the first message in a sequence that results in a match for
+ // the given substitution arguments.
+ handlers[msgFirst] = func(d *Decoder) bool {
+ for !d.Done() {
+ if d.ExecuteMessage() {
+ return true
+ }
+ }
+ return false
+ }
+
+ handlers[msgRaw] = func(d *Decoder) bool {
+ d.Render(d.data)
+ return true
+ }
+
+ // A String message alternates between a string constant and a variable
+ // substitution.
+ handlers[msgString] = func(d *Decoder) bool {
+ for !d.Done() {
+ if str := d.DecodeString(); str != "" {
+ d.Render(str)
+ }
+ if d.Done() {
+ break
+ }
+ d.ExecuteSubstitution()
+ }
+ return true
+ }
+
+ handlers[msgAffix] = func(d *Decoder) bool {
+ // TODO: use an alternative method for common cases.
+ prefix := d.DecodeString()
+ suffix := d.DecodeString()
+ if prefix != "" {
+ d.Render(prefix)
+ }
+ ret := d.ExecuteMessage()
+ if suffix != "" {
+ d.Render(suffix)
+ }
+ return ret
+ }
+}
+
+var (
+ // ErrIncomplete indicates a compiled message does not define translations
+ // for all possible argument values. If this message is returned, evaluating
+ // a message may result in the ErrNoMatch error.
+ ErrIncomplete = errors.New("catmsg: incomplete message; may not give result for all inputs")
+
+ // ErrNoMatch indicates no translation message matched the given input
+ // parameters when evaluating a message.
+ ErrNoMatch = errors.New("catmsg: no translation for inputs")
+)
+
+// A Message holds a collection of translations for the same phrase that may
+// vary based on the values of substitution arguments.
+type Message interface {
+ // Compile encodes the format string(s) of the message as a string for later
+ // evaluation.
+ //
+ // The first call Compile makes on the encoder must be EncodeMessageType.
+ // The handle passed to this call may either be a handle returned by
+ // Register to encode a single custom message, or HandleFirst followed by
+ // a sequence of calls to EncodeMessage.
+ //
+ // Compile must return ErrIncomplete if it is possible for evaluation to
+ // not match any translation for a given set of formatting parameters.
+ // For example, selecting a translation based on plural form may not yield
+ // a match if the form "Other" is not one of the selectors.
+ //
+ // Compile may return any other application-specific error. For backwards
+ // compatibility with package like fmt, which often do not do sanity
+ // checking of format strings ahead of time, Compile should still make an
+ // effort to have some sensible fallback in case of an error.
+ Compile(e *Encoder) error
+}
+
+// Compile converts a Message to a data string that can be stored in a Catalog.
+// The resulting string can subsequently be decoded by passing to the Execute
+// method of a Decoder.
+func Compile(tag language.Tag, macros Dictionary, m Message) (data string, err error) {
+ // TODO: pass macros so they can be used for validation.
+ v := &Encoder{inBody: true} // encoder for variables
+ v.root = v
+ e := &Encoder{root: v, parent: v, tag: tag} // encoder for messages
+ err = m.Compile(e)
+ // This package serves te message package, which in turn is meant to be a
+ // drop-in replacement for fmt. With the fmt package, format strings are
+ // evaluated lazily and errors are handled by substituting strings in the
+ // result, rather then returning an error. Dealing with multiple languages
+ // makes it more important to check errors ahead of time. We chose to be
+ // consistent and compatible and allow graceful degradation in case of
+ // errors.
+ buf := e.buf[stripPrefix(e.buf):]
+ if len(v.buf) > 0 {
+ // Prepend variable block.
+ b := make([]byte, 1+maxVarintBytes+len(v.buf)+len(buf))
+ b[0] = byte(msgVars)
+ b = b[:1+encodeUint(b[1:], uint64(len(v.buf)))]
+ b = append(b, v.buf...)
+ b = append(b, buf...)
+ buf = b
+ }
+ if err == nil {
+ err = v.err
+ }
+ return string(buf), err
+}
+
+// FirstOf is a message type that prints the first message in the sequence that
+// resolves to a match for the given substitution arguments.
+type FirstOf []Message
+
+// Compile implements Message.
+func (s FirstOf) Compile(e *Encoder) error {
+ e.EncodeMessageType(msgFirst)
+ err := ErrIncomplete
+ for i, m := range s {
+ if err == nil {
+ return fmt.Errorf("catalog: message argument %d is complete and blocks subsequent messages", i-1)
+ }
+ err = e.EncodeMessage(m)
+ }
+ return err
+}
+
+// Var defines a message that can be substituted for a placeholder of the same
+// name. If an expression does not result in a string after evaluation, Name is
+// used as the substitution. For example:
+//
+// Var{
+// Name: "minutes",
+// Message: plural.Select(1, "one", "minute"),
+// }
+//
+// will resolve to minute for singular and minutes for plural forms.
+type Var struct {
+ Name string
+ Message Message
+}
+
+var errIsVar = errors.New("catmsg: variable used as message")
+
+// Compile implements Message.
+//
+// Note that this method merely registers a variable; it does not create an
+// encoded message.
+func (v *Var) Compile(e *Encoder) error {
+ if err := e.addVar(v.Name, v.Message); err != nil {
+ return err
+ }
+ // Using a Var by itself is an error. If it is in a sequence followed by
+ // other messages referring to it, this error will be ignored.
+ return errIsVar
+}
+
+// Raw is a message consisting of a single format string that is passed as is
+// to the Renderer.
+//
+// Note that a Renderer may still do its own variable substitution.
+type Raw string
+
+// Compile implements Message.
+func (r Raw) Compile(e *Encoder) (err error) {
+ e.EncodeMessageType(msgRaw)
+ // Special case: raw strings don't have a size encoding and so don't use
+ // EncodeString.
+ e.buf = append(e.buf, r...)
+ return nil
+}
+
+// String is a message consisting of a single format string which contains
+// placeholders that may be substituted with variables.
+//
+// Variable substitutions are marked with placeholders and a variable name of
+// the form ${name}. Any other substitutions such as Go templates or
+// printf-style substitutions are left to be done by the Renderer.
+//
+// When evaluation a string interpolation, a Renderer will receive separate
+// calls for each placeholder and interstitial string. For example, for the
+// message: "%[1]v ${invites} %[2]v to ${their} party." The sequence of calls
+// is:
+//
+// d.Render("%[1]v ")
+// d.Arg(1)
+// d.Render(resultOfInvites)
+// d.Render(" %[2]v to ")
+// d.Arg(2)
+// d.Render(resultOfTheir)
+// d.Render(" party.")
+//
+// where the messages for "invites" and "their" both use a plural.Select
+// referring to the first argument.
+//
+// Strings may also invoke macros. Macros are essentially variables that can be
+// reused. Macros may, for instance, be used to make selections between
+// different conjugations of a verb. See the catalog package description for an
+// overview of macros.
+type String string
+
+// Compile implements Message. It parses the placeholder formats and returns
+// any error.
+func (s String) Compile(e *Encoder) (err error) {
+ msg := string(s)
+ const subStart = "${"
+ hasHeader := false
+ p := 0
+ b := []byte{}
+ for {
+ i := strings.Index(msg[p:], subStart)
+ if i == -1 {
+ break
+ }
+ b = append(b, msg[p:p+i]...)
+ p += i + len(subStart)
+ if i = strings.IndexByte(msg[p:], '}'); i == -1 {
+ b = append(b, "$!(MISSINGBRACE)"...)
+ err = fmt.Errorf("catmsg: missing '}'")
+ p = len(msg)
+ break
+ }
+ name := strings.TrimSpace(msg[p : p+i])
+ if q := strings.IndexByte(name, '('); q == -1 {
+ if !hasHeader {
+ hasHeader = true
+ e.EncodeMessageType(msgString)
+ }
+ e.EncodeString(string(b))
+ e.EncodeSubstitution(name)
+ b = b[:0]
+ } else if j := strings.IndexByte(name[q:], ')'); j == -1 {
+ // TODO: what should the error be?
+ b = append(b, "$!(MISSINGPAREN)"...)
+ err = fmt.Errorf("catmsg: missing ')'")
+ } else if x, sErr := strconv.ParseUint(strings.TrimSpace(name[q+1:q+j]), 10, 32); sErr != nil {
+ // TODO: handle more than one argument
+ b = append(b, "$!(BADNUM)"...)
+ err = fmt.Errorf("catmsg: invalid number %q", strings.TrimSpace(name[q+1:q+j]))
+ } else {
+ if !hasHeader {
+ hasHeader = true
+ e.EncodeMessageType(msgString)
+ }
+ e.EncodeString(string(b))
+ e.EncodeSubstitution(name[:q], int(x))
+ b = b[:0]
+ }
+ p += i + 1
+ }
+ b = append(b, msg[p:]...)
+ if !hasHeader {
+ // Simplify string to a raw string.
+ Raw(string(b)).Compile(e)
+ } else if len(b) > 0 {
+ e.EncodeString(string(b))
+ }
+ return err
+}
+
+// Affix is a message that adds a prefix and suffix to another message.
+// This is mostly used add back whitespace to a translation that was stripped
+// before sending it out.
+type Affix struct {
+ Message Message
+ Prefix string
+ Suffix string
+}
+
+// Compile implements Message.
+func (a Affix) Compile(e *Encoder) (err error) {
+ // TODO: consider adding a special message type that just adds a single
+ // return. This is probably common enough to handle the majority of cases.
+ // Get some stats first, though.
+ e.EncodeMessageType(msgAffix)
+ e.EncodeString(a.Prefix)
+ e.EncodeString(a.Suffix)
+ e.EncodeMessage(a.Message)
+ return nil
+}
diff --git a/vendor/golang.org/x/text/internal/catmsg/codec.go b/vendor/golang.org/x/text/internal/catmsg/codec.go
new file mode 100644
index 0000000..49c9fc9
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/catmsg/codec.go
@@ -0,0 +1,407 @@
+// Copyright 2017 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 catmsg
+
+import (
+ "errors"
+ "fmt"
+
+ "golang.org/x/text/language"
+)
+
+// A Renderer renders a Message.
+type Renderer interface {
+ // Render renders the given string. The given string may be interpreted as a
+ // format string, such as the one used by the fmt package or a template.
+ Render(s string)
+
+ // Arg returns the i-th argument passed to format a message. This method
+ // should return nil if there is no such argument. Messages need access to
+ // arguments to allow selecting a message based on linguistic features of
+ // those arguments.
+ Arg(i int) interface{}
+}
+
+// A Dictionary specifies a source of messages, including variables or macros.
+type Dictionary interface {
+ // Lookup returns the message for the given key. It returns false for ok if
+ // such a message could not be found.
+ Lookup(key string) (data string, ok bool)
+
+ // TODO: consider returning an interface, instead of a string. This will
+ // allow implementations to do their own message type decoding.
+}
+
+// An Encoder serializes a Message to a string.
+type Encoder struct {
+ // The root encoder is used for storing encoded variables.
+ root *Encoder
+ // The parent encoder provides the surrounding scopes for resolving variable
+ // names.
+ parent *Encoder
+
+ tag language.Tag
+
+ // buf holds the encoded message so far. After a message completes encoding,
+ // the contents of buf, prefixed by the encoded length, are flushed to the
+ // parent buffer.
+ buf []byte
+
+ // vars is the lookup table of variables in the current scope.
+ vars []keyVal
+
+ err error
+ inBody bool // if false next call must be EncodeMessageType
+}
+
+type keyVal struct {
+ key string
+ offset int
+}
+
+// Language reports the language for which the encoded message will be stored
+// in the Catalog.
+func (e *Encoder) Language() language.Tag { return e.tag }
+
+func (e *Encoder) setError(err error) {
+ if e.root.err == nil {
+ e.root.err = err
+ }
+}
+
+// EncodeUint encodes x.
+func (e *Encoder) EncodeUint(x uint64) {
+ e.checkInBody()
+ var buf [maxVarintBytes]byte
+ n := encodeUint(buf[:], x)
+ e.buf = append(e.buf, buf[:n]...)
+}
+
+// EncodeString encodes s.
+func (e *Encoder) EncodeString(s string) {
+ e.checkInBody()
+ e.EncodeUint(uint64(len(s)))
+ e.buf = append(e.buf, s...)
+}
+
+// EncodeMessageType marks the current message to be of type h.
+//
+// It must be the first call of a Message's Compile method.
+func (e *Encoder) EncodeMessageType(h Handle) {
+ if e.inBody {
+ panic("catmsg: EncodeMessageType not the first method called")
+ }
+ e.inBody = true
+ e.EncodeUint(uint64(h))
+}
+
+// EncodeMessage serializes the given message inline at the current position.
+func (e *Encoder) EncodeMessage(m Message) error {
+ e = &Encoder{root: e.root, parent: e, tag: e.tag}
+ err := m.Compile(e)
+ if _, ok := m.(*Var); !ok {
+ e.flushTo(e.parent)
+ }
+ return err
+}
+
+func (e *Encoder) checkInBody() {
+ if !e.inBody {
+ panic("catmsg: expected prior call to EncodeMessageType")
+ }
+}
+
+// stripPrefix indicates the number of prefix bytes that must be stripped to
+// turn a single-element sequence into a message that is just this single member
+// without its size prefix. If the message can be stripped, b[1:n] contains the
+// size prefix.
+func stripPrefix(b []byte) (n int) {
+ if len(b) > 0 && Handle(b[0]) == msgFirst {
+ x, n, _ := decodeUint(b[1:])
+ if 1+n+int(x) == len(b) {
+ return 1 + n
+ }
+ }
+ return 0
+}
+
+func (e *Encoder) flushTo(dst *Encoder) {
+ data := e.buf
+ p := stripPrefix(data)
+ if p > 0 {
+ data = data[1:]
+ } else {
+ // Prefix the size.
+ dst.EncodeUint(uint64(len(data)))
+ }
+ dst.buf = append(dst.buf, data...)
+}
+
+func (e *Encoder) addVar(key string, m Message) error {
+ for _, v := range e.parent.vars {
+ if v.key == key {
+ err := fmt.Errorf("catmsg: duplicate variable %q", key)
+ e.setError(err)
+ return err
+ }
+ }
+ scope := e.parent
+ // If a variable message is Incomplete, and does not evaluate to a message
+ // during execution, we fall back to the variable name. We encode this by
+ // appending the variable name if the message reports it's incomplete.
+
+ err := m.Compile(e)
+ if err != ErrIncomplete {
+ e.setError(err)
+ }
+ switch {
+ case len(e.buf) == 1 && Handle(e.buf[0]) == msgFirst: // empty sequence
+ e.buf = e.buf[:0]
+ e.inBody = false
+ fallthrough
+ case len(e.buf) == 0:
+ // Empty message.
+ if err := String(key).Compile(e); err != nil {
+ e.setError(err)
+ }
+ case err == ErrIncomplete:
+ if Handle(e.buf[0]) != msgFirst {
+ seq := &Encoder{root: e.root, parent: e}
+ seq.EncodeMessageType(msgFirst)
+ e.flushTo(seq)
+ e = seq
+ }
+ // e contains a sequence; append the fallback string.
+ e.EncodeMessage(String(key))
+ }
+
+ // Flush result to variable heap.
+ offset := len(e.root.buf)
+ e.flushTo(e.root)
+ e.buf = e.buf[:0]
+
+ // Record variable offset in current scope.
+ scope.vars = append(scope.vars, keyVal{key: key, offset: offset})
+ return err
+}
+
+const (
+ substituteVar = iota
+ substituteMacro
+ substituteError
+)
+
+// EncodeSubstitution inserts a resolved reference to a variable or macro.
+//
+// This call must be matched with a call to ExecuteSubstitution at decoding
+// time.
+func (e *Encoder) EncodeSubstitution(name string, arguments ...int) {
+ if arity := len(arguments); arity > 0 {
+ // TODO: also resolve macros.
+ e.EncodeUint(substituteMacro)
+ e.EncodeString(name)
+ for _, a := range arguments {
+ e.EncodeUint(uint64(a))
+ }
+ return
+ }
+ for scope := e; scope != nil; scope = scope.parent {
+ for _, v := range scope.vars {
+ if v.key != name {
+ continue
+ }
+ e.EncodeUint(substituteVar) // TODO: support arity > 0
+ e.EncodeUint(uint64(v.offset))
+ return
+ }
+ }
+ // TODO: refer to dictionary-wide scoped variables.
+ e.EncodeUint(substituteError)
+ e.EncodeString(name)
+ e.setError(fmt.Errorf("catmsg: unknown var %q", name))
+}
+
+// A Decoder deserializes and evaluates messages that are encoded by an encoder.
+type Decoder struct {
+ tag language.Tag
+ dst Renderer
+ macros Dictionary
+
+ err error
+ vars string
+ data string
+
+ macroArg int // TODO: allow more than one argument
+}
+
+// NewDecoder returns a new Decoder.
+//
+// Decoders are designed to be reused for multiple invocations of Execute.
+// Only one goroutine may call Execute concurrently.
+func NewDecoder(tag language.Tag, r Renderer, macros Dictionary) *Decoder {
+ return &Decoder{
+ tag: tag,
+ dst: r,
+ macros: macros,
+ }
+}
+
+func (d *Decoder) setError(err error) {
+ if d.err == nil {
+ d.err = err
+ }
+}
+
+// Language returns the language in which the message is being rendered.
+//
+// The destination language may be a child language of the language used for
+// encoding. For instance, a decoding language of "pt-PT"" is consistent with an
+// encoding language of "pt".
+func (d *Decoder) Language() language.Tag { return d.tag }
+
+// Done reports whether there are more bytes to process in this message.
+func (d *Decoder) Done() bool { return len(d.data) == 0 }
+
+// Render implements Renderer.
+func (d *Decoder) Render(s string) { d.dst.Render(s) }
+
+// Arg implements Renderer.
+//
+// During evaluation of macros, the argument positions may be mapped to
+// arguments that differ from the original call.
+func (d *Decoder) Arg(i int) interface{} {
+ if d.macroArg != 0 {
+ if i != 1 {
+ panic("catmsg: only macros with single argument supported")
+ }
+ i = d.macroArg
+ }
+ return d.dst.Arg(i)
+}
+
+// DecodeUint decodes a number that was encoded with EncodeUint and advances the
+// position.
+func (d *Decoder) DecodeUint() uint64 {
+ x, n, err := decodeUintString(d.data)
+ d.data = d.data[n:]
+ if err != nil {
+ d.setError(err)
+ }
+ return x
+}
+
+// DecodeString decodes a string that was encoded with EncodeString and advances
+// the position.
+func (d *Decoder) DecodeString() string {
+ size := d.DecodeUint()
+ s := d.data[:size]
+ d.data = d.data[size:]
+ return s
+}
+
+// SkipMessage skips the message at the current location and advances the
+// position.
+func (d *Decoder) SkipMessage() {
+ n := int(d.DecodeUint())
+ d.data = d.data[n:]
+}
+
+// Execute decodes and evaluates msg.
+//
+// Only one goroutine may call execute.
+func (d *Decoder) Execute(msg string) error {
+ d.err = nil
+ if !d.execute(msg) {
+ return ErrNoMatch
+ }
+ return d.err
+}
+
+func (d *Decoder) execute(msg string) bool {
+ saved := d.data
+ d.data = msg
+ ok := d.executeMessage()
+ d.data = saved
+ return ok
+}
+
+// executeMessageFromData is like execute, but also decodes a leading message
+// size and clips the given string accordingly.
+//
+// It reports the number of bytes consumed and whether a message was selected.
+func (d *Decoder) executeMessageFromData(s string) (n int, ok bool) {
+ saved := d.data
+ d.data = s
+ size := int(d.DecodeUint())
+ n = len(s) - len(d.data)
+ // Sanitize the setting. This allows skipping a size argument for
+ // RawString and method Done.
+ d.data = d.data[:size]
+ ok = d.executeMessage()
+ n += size - len(d.data)
+ d.data = saved
+ return n, ok
+}
+
+var errUnknownHandler = errors.New("catmsg: string contains unsupported handler")
+
+// executeMessage reads the handle id, initializes the decoder and executes the
+// message. It is assumed that all of d.data[d.p:] is the single message.
+func (d *Decoder) executeMessage() bool {
+ if d.Done() {
+ // We interpret no data as a valid empty message.
+ return true
+ }
+ handle := d.DecodeUint()
+
+ var fn Handler
+ mutex.Lock()
+ if int(handle) < len(handlers) {
+ fn = handlers[handle]
+ }
+ mutex.Unlock()
+ if fn == nil {
+ d.setError(errUnknownHandler)
+ d.execute(fmt.Sprintf("\x02$!(UNKNOWNMSGHANDLER=%#x)", handle))
+ return true
+ }
+ return fn(d)
+}
+
+// ExecuteMessage decodes and executes the message at the current position.
+func (d *Decoder) ExecuteMessage() bool {
+ n, ok := d.executeMessageFromData(d.data)
+ d.data = d.data[n:]
+ return ok
+}
+
+// ExecuteSubstitution executes the message corresponding to the substitution
+// as encoded by EncodeSubstitution.
+func (d *Decoder) ExecuteSubstitution() {
+ switch x := d.DecodeUint(); x {
+ case substituteVar:
+ offset := d.DecodeUint()
+ d.executeMessageFromData(d.vars[offset:])
+ case substituteMacro:
+ name := d.DecodeString()
+ data, ok := d.macros.Lookup(name)
+ old := d.macroArg
+ // TODO: support macros of arity other than 1.
+ d.macroArg = int(d.DecodeUint())
+ switch {
+ case !ok:
+ // TODO: detect this at creation time.
+ d.setError(fmt.Errorf("catmsg: undefined macro %q", name))
+ fallthrough
+ case !d.execute(data):
+ d.dst.Render(name) // fall back to macro name.
+ }
+ d.macroArg = old
+ case substituteError:
+ d.dst.Render(d.DecodeString())
+ default:
+ panic("catmsg: unreachable")
+ }
+}
diff --git a/vendor/golang.org/x/text/internal/catmsg/varint.go b/vendor/golang.org/x/text/internal/catmsg/varint.go
new file mode 100644
index 0000000..a2cee2c
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/catmsg/varint.go
@@ -0,0 +1,62 @@
+// Copyright 2017 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 catmsg
+
+// This file implements varint encoding analogous to the one in encoding/binary.
+// We need a string version of this function, so we add that here and then add
+// the rest for consistency.
+
+import "errors"
+
+var (
+ errIllegalVarint = errors.New("catmsg: illegal varint")
+ errVarintTooLarge = errors.New("catmsg: varint too large for uint64")
+)
+
+const maxVarintBytes = 10 // maximum length of a varint
+
+// encodeUint encodes x as a variable-sized integer into buf and returns the
+// number of bytes written. buf must be at least maxVarintBytes long
+func encodeUint(buf []byte, x uint64) (n int) {
+ for ; x > 127; n++ {
+ buf[n] = 0x80 | uint8(x&0x7F)
+ x >>= 7
+ }
+ buf[n] = uint8(x)
+ n++
+ return n
+}
+
+func decodeUintString(s string) (x uint64, size int, err error) {
+ i := 0
+ for shift := uint(0); shift < 64; shift += 7 {
+ if i >= len(s) {
+ return 0, i, errIllegalVarint
+ }
+ b := uint64(s[i])
+ i++
+ x |= (b & 0x7F) << shift
+ if b&0x80 == 0 {
+ return x, i, nil
+ }
+ }
+ return 0, i, errVarintTooLarge
+}
+
+func decodeUint(b []byte) (x uint64, size int, err error) {
+ i := 0
+ for shift := uint(0); shift < 64; shift += 7 {
+ if i >= len(b) {
+ return 0, i, errIllegalVarint
+ }
+ c := uint64(b[i])
+ i++
+ x |= (c & 0x7F) << shift
+ if c&0x80 == 0 {
+ return x, i, nil
+ }
+ }
+ return 0, i, errVarintTooLarge
+}
diff --git a/vendor/golang.org/x/text/internal/format/format.go b/vendor/golang.org/x/text/internal/format/format.go
new file mode 100644
index 0000000..ee1c57a
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/format/format.go
@@ -0,0 +1,41 @@
+// Copyright 2015 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 format contains types for defining language-specific formatting of
+// values.
+//
+// This package is internal now, but will eventually be exposed after the API
+// settles.
+package format // import "golang.org/x/text/internal/format"
+
+import (
+ "fmt"
+
+ "golang.org/x/text/language"
+)
+
+// State represents the printer state passed to custom formatters. It provides
+// access to the fmt.State interface and the sentence and language-related
+// context.
+type State interface {
+ fmt.State
+
+ // Language reports the requested language in which to render a message.
+ Language() language.Tag
+
+ // TODO: consider this and removing rune from the Format method in the
+ // Formatter interface.
+ //
+ // Verb returns the format variant to render, analogous to the types used
+ // in fmt. Use 'v' for the default or only variant.
+ // Verb() rune
+
+ // TODO: more info:
+ // - sentence context such as linguistic features passed by the translator.
+}
+
+// Formatter is analogous to fmt.Formatter.
+type Formatter interface {
+ Format(state State, verb rune)
+}
diff --git a/vendor/golang.org/x/text/internal/format/parser.go b/vendor/golang.org/x/text/internal/format/parser.go
new file mode 100644
index 0000000..855aed7
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/format/parser.go
@@ -0,0 +1,358 @@
+// Copyright 2017 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 format
+
+import (
+ "reflect"
+ "unicode/utf8"
+)
+
+// A Parser parses a format string. The result from the parse are set in the
+// struct fields.
+type Parser struct {
+ Verb rune
+
+ WidthPresent bool
+ PrecPresent bool
+ Minus bool
+ Plus bool
+ Sharp bool
+ Space bool
+ Zero bool
+
+ // For the formats %+v %#v, we set the plusV/sharpV flags
+ // and clear the plus/sharp flags since %+v and %#v are in effect
+ // different, flagless formats set at the top level.
+ PlusV bool
+ SharpV bool
+
+ HasIndex bool
+
+ Width int
+ Prec int // precision
+
+ // retain arguments across calls.
+ Args []interface{}
+ // retain current argument number across calls
+ ArgNum int
+
+ // reordered records whether the format string used argument reordering.
+ Reordered bool
+ // goodArgNum records whether the most recent reordering directive was valid.
+ goodArgNum bool
+
+ // position info
+ format string
+ startPos int
+ endPos int
+ Status Status
+}
+
+// Reset initializes a parser to scan format strings for the given args.
+func (p *Parser) Reset(args []interface{}) {
+ p.Args = args
+ p.ArgNum = 0
+ p.startPos = 0
+ p.Reordered = false
+}
+
+// Text returns the part of the format string that was parsed by the last call
+// to Scan. It returns the original substitution clause if the current scan
+// parsed a substitution.
+func (p *Parser) Text() string { return p.format[p.startPos:p.endPos] }
+
+// SetFormat sets a new format string to parse. It does not reset the argument
+// count.
+func (p *Parser) SetFormat(format string) {
+ p.format = format
+ p.startPos = 0
+ p.endPos = 0
+}
+
+// Status indicates the result type of a call to Scan.
+type Status int
+
+const (
+ StatusText Status = iota
+ StatusSubstitution
+ StatusBadWidthSubstitution
+ StatusBadPrecSubstitution
+ StatusNoVerb
+ StatusBadArgNum
+ StatusMissingArg
+)
+
+// ClearFlags reset the parser to default behavior.
+func (p *Parser) ClearFlags() {
+ p.WidthPresent = false
+ p.PrecPresent = false
+ p.Minus = false
+ p.Plus = false
+ p.Sharp = false
+ p.Space = false
+ p.Zero = false
+
+ p.PlusV = false
+ p.SharpV = false
+
+ p.HasIndex = false
+}
+
+// Scan scans the next part of the format string and sets the status to
+// indicate whether it scanned a string literal, substitution or error.
+func (p *Parser) Scan() bool {
+ p.Status = StatusText
+ format := p.format
+ end := len(format)
+ if p.endPos >= end {
+ return false
+ }
+ afterIndex := false // previous item in format was an index like [3].
+
+ p.startPos = p.endPos
+ p.goodArgNum = true
+ i := p.startPos
+ for i < end && format[i] != '%' {
+ i++
+ }
+ if i > p.startPos {
+ p.endPos = i
+ return true
+ }
+ // Process one verb
+ i++
+
+ p.Status = StatusSubstitution
+
+ // Do we have flags?
+ p.ClearFlags()
+
+simpleFormat:
+ for ; i < end; i++ {
+ c := p.format[i]
+ switch c {
+ case '#':
+ p.Sharp = true
+ case '0':
+ p.Zero = !p.Minus // Only allow zero padding to the left.
+ case '+':
+ p.Plus = true
+ case '-':
+ p.Minus = true
+ p.Zero = false // Do not pad with zeros to the right.
+ case ' ':
+ p.Space = true
+ default:
+ // Fast path for common case of ascii lower case simple verbs
+ // without precision or width or argument indices.
+ if 'a' <= c && c <= 'z' && p.ArgNum < len(p.Args) {
+ if c == 'v' {
+ // Go syntax
+ p.SharpV = p.Sharp
+ p.Sharp = false
+ // Struct-field syntax
+ p.PlusV = p.Plus
+ p.Plus = false
+ }
+ p.Verb = rune(c)
+ p.ArgNum++
+ p.endPos = i + 1
+ return true
+ }
+ // Format is more complex than simple flags and a verb or is malformed.
+ break simpleFormat
+ }
+ }
+
+ // Do we have an explicit argument index?
+ i, afterIndex = p.updateArgNumber(format, i)
+
+ // Do we have width?
+ if i < end && format[i] == '*' {
+ i++
+ p.Width, p.WidthPresent = p.intFromArg()
+
+ if !p.WidthPresent {
+ p.Status = StatusBadWidthSubstitution
+ }
+
+ // We have a negative width, so take its value and ensure
+ // that the minus flag is set
+ if p.Width < 0 {
+ p.Width = -p.Width
+ p.Minus = true
+ p.Zero = false // Do not pad with zeros to the right.
+ }
+ afterIndex = false
+ } else {
+ p.Width, p.WidthPresent, i = parsenum(format, i, end)
+ if afterIndex && p.WidthPresent { // "%[3]2d"
+ p.goodArgNum = false
+ }
+ }
+
+ // Do we have precision?
+ if i+1 < end && format[i] == '.' {
+ i++
+ if afterIndex { // "%[3].2d"
+ p.goodArgNum = false
+ }
+ i, afterIndex = p.updateArgNumber(format, i)
+ if i < end && format[i] == '*' {
+ i++
+ p.Prec, p.PrecPresent = p.intFromArg()
+ // Negative precision arguments don't make sense
+ if p.Prec < 0 {
+ p.Prec = 0
+ p.PrecPresent = false
+ }
+ if !p.PrecPresent {
+ p.Status = StatusBadPrecSubstitution
+ }
+ afterIndex = false
+ } else {
+ p.Prec, p.PrecPresent, i = parsenum(format, i, end)
+ if !p.PrecPresent {
+ p.Prec = 0
+ p.PrecPresent = true
+ }
+ }
+ }
+
+ if !afterIndex {
+ i, afterIndex = p.updateArgNumber(format, i)
+ }
+ p.HasIndex = afterIndex
+
+ if i >= end {
+ p.endPos = i
+ p.Status = StatusNoVerb
+ return true
+ }
+
+ verb, w := utf8.DecodeRuneInString(format[i:])
+ p.endPos = i + w
+ p.Verb = verb
+
+ switch {
+ case verb == '%': // Percent does not absorb operands and ignores f.wid and f.prec.
+ p.startPos = p.endPos - 1
+ p.Status = StatusText
+ case !p.goodArgNum:
+ p.Status = StatusBadArgNum
+ case p.ArgNum >= len(p.Args): // No argument left over to print for the current verb.
+ p.Status = StatusMissingArg
+ p.ArgNum++
+ case verb == 'v':
+ // Go syntax
+ p.SharpV = p.Sharp
+ p.Sharp = false
+ // Struct-field syntax
+ p.PlusV = p.Plus
+ p.Plus = false
+ fallthrough
+ default:
+ p.ArgNum++
+ }
+ return true
+}
+
+// intFromArg gets the ArgNumth element of Args. On return, isInt reports
+// whether the argument has integer type.
+func (p *Parser) intFromArg() (num int, isInt bool) {
+ if p.ArgNum < len(p.Args) {
+ arg := p.Args[p.ArgNum]
+ num, isInt = arg.(int) // Almost always OK.
+ if !isInt {
+ // Work harder.
+ switch v := reflect.ValueOf(arg); v.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ n := v.Int()
+ if int64(int(n)) == n {
+ num = int(n)
+ isInt = true
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ n := v.Uint()
+ if int64(n) >= 0 && uint64(int(n)) == n {
+ num = int(n)
+ isInt = true
+ }
+ default:
+ // Already 0, false.
+ }
+ }
+ p.ArgNum++
+ if tooLarge(num) {
+ num = 0
+ isInt = false
+ }
+ }
+ return
+}
+
+// parseArgNumber returns the value of the bracketed number, minus 1
+// (explicit argument numbers are one-indexed but we want zero-indexed).
+// The opening bracket is known to be present at format[0].
+// The returned values are the index, the number of bytes to consume
+// up to the closing paren, if present, and whether the number parsed
+// ok. The bytes to consume will be 1 if no closing paren is present.
+func parseArgNumber(format string) (index int, wid int, ok bool) {
+ // There must be at least 3 bytes: [n].
+ if len(format) < 3 {
+ return 0, 1, false
+ }
+
+ // Find closing bracket.
+ for i := 1; i < len(format); i++ {
+ if format[i] == ']' {
+ width, ok, newi := parsenum(format, 1, i)
+ if !ok || newi != i {
+ return 0, i + 1, false
+ }
+ return width - 1, i + 1, true // arg numbers are one-indexed and skip paren.
+ }
+ }
+ return 0, 1, false
+}
+
+// updateArgNumber returns the next argument to evaluate, which is either the value of the passed-in
+// argNum or the value of the bracketed integer that begins format[i:]. It also returns
+// the new value of i, that is, the index of the next byte of the format to process.
+func (p *Parser) updateArgNumber(format string, i int) (newi int, found bool) {
+ if len(format) <= i || format[i] != '[' {
+ return i, false
+ }
+ p.Reordered = true
+ index, wid, ok := parseArgNumber(format[i:])
+ if ok && 0 <= index && index < len(p.Args) {
+ p.ArgNum = index
+ return i + wid, true
+ }
+ p.goodArgNum = false
+ return i + wid, ok
+}
+
+// tooLarge reports whether the magnitude of the integer is
+// too large to be used as a formatting width or precision.
+func tooLarge(x int) bool {
+ const max int = 1e6
+ return x > max || x < -max
+}
+
+// parsenum converts ASCII to integer. num is 0 (and isnum is false) if no number present.
+func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
+ if start >= end {
+ return 0, false, end
+ }
+ for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ {
+ if tooLarge(num) {
+ return 0, false, end // Overflow; crazy long number most likely.
+ }
+ num = num*10 + int(s[newi]-'0')
+ isnum = true
+ }
+ return
+}
diff --git a/vendor/golang.org/x/text/internal/internal.go b/vendor/golang.org/x/text/internal/internal.go
new file mode 100644
index 0000000..3cddbbd
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/internal.go
@@ -0,0 +1,49 @@
+// Copyright 2015 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 internal contains non-exported functionality that are used by
+// packages in the text repository.
+package internal // import "golang.org/x/text/internal"
+
+import (
+ "sort"
+
+ "golang.org/x/text/language"
+)
+
+// SortTags sorts tags in place.
+func SortTags(tags []language.Tag) {
+ sort.Sort(sorter(tags))
+}
+
+type sorter []language.Tag
+
+func (s sorter) Len() int {
+ return len(s)
+}
+
+func (s sorter) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s sorter) Less(i, j int) bool {
+ return s[i].String() < s[j].String()
+}
+
+// UniqueTags sorts and filters duplicate tags in place and returns a slice with
+// only unique tags.
+func UniqueTags(tags []language.Tag) []language.Tag {
+ if len(tags) <= 1 {
+ return tags
+ }
+ SortTags(tags)
+ k := 0
+ for i := 1; i < len(tags); i++ {
+ if tags[k].String() < tags[i].String() {
+ k++
+ tags[k] = tags[i]
+ }
+ }
+ return tags[:k+1]
+}
diff --git a/vendor/golang.org/x/text/internal/language/common.go b/vendor/golang.org/x/text/internal/language/common.go
new file mode 100644
index 0000000..cdfdb74
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/common.go
@@ -0,0 +1,16 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package language
+
+// This file contains code common to the maketables.go and the package code.
+
+// AliasType is the type of an alias in AliasMap.
+type AliasType int8
+
+const (
+ Deprecated AliasType = iota
+ Macro
+ Legacy
+
+ AliasTypeUnknown AliasType = -1
+)
diff --git a/vendor/golang.org/x/text/internal/language/compact.go b/vendor/golang.org/x/text/internal/language/compact.go
new file mode 100644
index 0000000..46a0015
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/compact.go
@@ -0,0 +1,29 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package language
+
+// CompactCoreInfo is a compact integer with the three core tags encoded.
+type CompactCoreInfo uint32
+
+// GetCompactCore generates a uint32 value that is guaranteed to be unique for
+// different language, region, and script values.
+func GetCompactCore(t Tag) (cci CompactCoreInfo, ok bool) {
+ if t.LangID > langNoIndexOffset {
+ return 0, false
+ }
+ cci |= CompactCoreInfo(t.LangID) << (8 + 12)
+ cci |= CompactCoreInfo(t.ScriptID) << 12
+ cci |= CompactCoreInfo(t.RegionID)
+ return cci, true
+}
+
+// Tag generates a tag from c.
+func (c CompactCoreInfo) Tag() Tag {
+ return Tag{
+ LangID: Language(c >> 20),
+ RegionID: Region(c & 0x3ff),
+ ScriptID: Script(c>>12) & 0xff,
+ }
+}
diff --git a/vendor/golang.org/x/text/internal/language/compact/compact.go b/vendor/golang.org/x/text/internal/language/compact/compact.go
new file mode 100644
index 0000000..1b36935
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/compact/compact.go
@@ -0,0 +1,61 @@
+// Copyright 2018 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 compact defines a compact representation of language tags.
+//
+// Common language tags (at least all for which locale information is defined
+// in CLDR) are assigned a unique index. Each Tag is associated with such an
+// ID for selecting language-related resources (such as translations) as well
+// as one for selecting regional defaults (currency, number formatting, etc.)
+//
+// It may want to export this functionality at some point, but at this point
+// this is only available for use within x/text.
+package compact // import "golang.org/x/text/internal/language/compact"
+
+import (
+ "sort"
+ "strings"
+
+ "golang.org/x/text/internal/language"
+)
+
+// ID is an integer identifying a single tag.
+type ID uint16
+
+func getCoreIndex(t language.Tag) (id ID, ok bool) {
+ cci, ok := language.GetCompactCore(t)
+ if !ok {
+ return 0, false
+ }
+ i := sort.Search(len(coreTags), func(i int) bool {
+ return cci <= coreTags[i]
+ })
+ if i == len(coreTags) || coreTags[i] != cci {
+ return 0, false
+ }
+ return ID(i), true
+}
+
+// Parent returns the ID of the parent or the root ID if id is already the root.
+func (id ID) Parent() ID {
+ return parents[id]
+}
+
+// Tag converts id to an internal language Tag.
+func (id ID) Tag() language.Tag {
+ if int(id) >= len(coreTags) {
+ return specialTags[int(id)-len(coreTags)]
+ }
+ return coreTags[id].Tag()
+}
+
+var specialTags []language.Tag
+
+func init() {
+ tags := strings.Split(specialTagsStr, " ")
+ specialTags = make([]language.Tag, len(tags))
+ for i, t := range tags {
+ specialTags[i] = language.MustParse(t)
+ }
+}
diff --git a/vendor/golang.org/x/text/internal/language/compact/language.go b/vendor/golang.org/x/text/internal/language/compact/language.go
new file mode 100644
index 0000000..8c1b666
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/compact/language.go
@@ -0,0 +1,260 @@
+// 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 gen.go gen_index.go -output tables.go
+//go:generate go run gen_parents.go
+
+package compact
+
+// TODO: Remove above NOTE after:
+// - verifying that tables are dropped correctly (most notably matcher tables).
+
+import (
+ "strings"
+
+ "golang.org/x/text/internal/language"
+)
+
+// Tag represents a BCP 47 language tag. It is used to specify an instance of a
+// specific language or locale. All language tag values are guaranteed to be
+// well-formed.
+type Tag struct {
+ // NOTE: exported tags will become part of the public API.
+ language ID
+ locale ID
+ full fullTag // always a language.Tag for now.
+}
+
+const _und = 0
+
+type fullTag interface {
+ IsRoot() bool
+ Parent() language.Tag
+}
+
+// Make a compact Tag from a fully specified internal language Tag.
+func Make(t language.Tag) (tag Tag) {
+ if region := t.TypeForKey("rg"); len(region) == 6 && region[2:] == "zzzz" {
+ if r, err := language.ParseRegion(region[:2]); err == nil {
+ tFull := t
+ t, _ = t.SetTypeForKey("rg", "")
+ // TODO: should we not consider "va" for the language tag?
+ var exact1, exact2 bool
+ tag.language, exact1 = FromTag(t)
+ t.RegionID = r
+ tag.locale, exact2 = FromTag(t)
+ if !exact1 || !exact2 {
+ tag.full = tFull
+ }
+ return tag
+ }
+ }
+ lang, ok := FromTag(t)
+ tag.language = lang
+ tag.locale = lang
+ if !ok {
+ tag.full = t
+ }
+ return tag
+}
+
+// Tag returns an internal language Tag version of this tag.
+func (t Tag) Tag() language.Tag {
+ if t.full != nil {
+ return t.full.(language.Tag)
+ }
+ tag := t.language.Tag()
+ if t.language != t.locale {
+ loc := t.locale.Tag()
+ tag, _ = tag.SetTypeForKey("rg", strings.ToLower(loc.RegionID.String())+"zzzz")
+ }
+ return tag
+}
+
+// IsCompact reports whether this tag is fully defined in terms of ID.
+func (t *Tag) IsCompact() bool {
+ return t.full == nil
+}
+
+// MayHaveVariants reports whether a tag may have variants. If it returns false
+// it is guaranteed the tag does not have variants.
+func (t Tag) MayHaveVariants() bool {
+ return t.full != nil || int(t.language) >= len(coreTags)
+}
+
+// MayHaveExtensions reports whether a tag may have extensions. If it returns
+// false it is guaranteed the tag does not have them.
+func (t Tag) MayHaveExtensions() bool {
+ return t.full != nil ||
+ int(t.language) >= len(coreTags) ||
+ t.language != t.locale
+}
+
+// IsRoot returns true if t is equal to language "und".
+func (t Tag) IsRoot() bool {
+ if t.full != nil {
+ return t.full.IsRoot()
+ }
+ return t.language == _und
+}
+
+// Parent returns the CLDR parent of t. In CLDR, missing fields in data for a
+// specific language are substituted with fields from the parent language.
+// The parent for a language may change for newer versions of CLDR.
+func (t Tag) Parent() Tag {
+ if t.full != nil {
+ return Make(t.full.Parent())
+ }
+ if t.language != t.locale {
+ // Simulate stripping -u-rg-xxxxxx
+ return Tag{language: t.language, locale: t.language}
+ }
+ // TODO: use parent lookup table once cycle from internal package is
+ // removed. Probably by internalizing the table and declaring this fast
+ // enough.
+ // lang := compactID(internal.Parent(uint16(t.language)))
+ lang, _ := FromTag(t.language.Tag().Parent())
+ return Tag{language: lang, locale: lang}
+}
+
+// nextToken returns token t and the rest of the string.
+func nextToken(s string) (t, tail string) {
+ p := strings.Index(s[1:], "-")
+ if p == -1 {
+ return s[1:], ""
+ }
+ p++
+ return s[1:p], s[p:]
+}
+
+// LanguageID returns an index, where 0 <= index < NumCompactTags, for tags
+// for which data exists in the text repository.The index will change over time
+// and should not be stored in persistent storage. If t does not match a compact
+// index, exact will be false and the compact index will be returned for the
+// first match after repeatedly taking the Parent of t.
+func LanguageID(t Tag) (id ID, exact bool) {
+ return t.language, t.full == nil
+}
+
+// RegionalID returns the ID for the regional variant of this tag. This index is
+// used to indicate region-specific overrides, such as default currency, default
+// calendar and week data, default time cycle, and default measurement system
+// and unit preferences.
+//
+// For instance, the tag en-GB-u-rg-uszzzz specifies British English with US
+// settings for currency, number formatting, etc. The CompactIndex for this tag
+// will be that for en-GB, while the RegionalID will be the one corresponding to
+// en-US.
+func RegionalID(t Tag) (id ID, exact bool) {
+ return t.locale, t.full == nil
+}
+
+// LanguageTag returns t stripped of regional variant indicators.
+//
+// At the moment this means it is stripped of a regional and variant subtag "rg"
+// and "va" in the "u" extension.
+func (t Tag) LanguageTag() Tag {
+ if t.full == nil {
+ return Tag{language: t.language, locale: t.language}
+ }
+ tt := t.Tag()
+ tt.SetTypeForKey("rg", "")
+ tt.SetTypeForKey("va", "")
+ return Make(tt)
+}
+
+// RegionalTag returns the regional variant of the tag.
+//
+// At the moment this means that the region is set from the regional subtag
+// "rg" in the "u" extension.
+func (t Tag) RegionalTag() Tag {
+ rt := Tag{language: t.locale, locale: t.locale}
+ if t.full == nil {
+ return rt
+ }
+ b := language.Builder{}
+ tag := t.Tag()
+ // tag, _ = tag.SetTypeForKey("rg", "")
+ b.SetTag(t.locale.Tag())
+ if v := tag.Variants(); v != "" {
+ for _, v := range strings.Split(v, "-") {
+ b.AddVariant(v)
+ }
+ }
+ for _, e := range tag.Extensions() {
+ b.AddExt(e)
+ }
+ return t
+}
+
+// FromTag reports closest matching ID for an internal language Tag.
+func FromTag(t language.Tag) (id ID, exact bool) {
+ // TODO: perhaps give more frequent tags a lower index.
+ // TODO: we could make the indexes stable. This will excluded some
+ // possibilities for optimization, so don't do this quite yet.
+ exact = true
+
+ b, s, r := t.Raw()
+ if t.HasString() {
+ if t.IsPrivateUse() {
+ // We have no entries for user-defined tags.
+ return 0, false
+ }
+ hasExtra := false
+ if t.HasVariants() {
+ if t.HasExtensions() {
+ build := language.Builder{}
+ build.SetTag(language.Tag{LangID: b, ScriptID: s, RegionID: r})
+ build.AddVariant(t.Variants())
+ exact = false
+ t = build.Make()
+ }
+ hasExtra = true
+ } else if _, ok := t.Extension('u'); ok {
+ // TODO: va may mean something else. Consider not considering it.
+ // Strip all but the 'va' entry.
+ old := t
+ variant := t.TypeForKey("va")
+ t = language.Tag{LangID: b, ScriptID: s, RegionID: r}
+ if variant != "" {
+ t, _ = t.SetTypeForKey("va", variant)
+ hasExtra = true
+ }
+ exact = old == t
+ } else {
+ exact = false
+ }
+ if hasExtra {
+ // We have some variants.
+ for i, s := range specialTags {
+ if s == t {
+ return ID(i + len(coreTags)), exact
+ }
+ }
+ exact = false
+ }
+ }
+ if x, ok := getCoreIndex(t); ok {
+ return x, exact
+ }
+ exact = false
+ if r != 0 && s == 0 {
+ // Deal with cases where an extra script is inserted for the region.
+ t, _ := t.Maximize()
+ if x, ok := getCoreIndex(t); ok {
+ return x, exact
+ }
+ }
+ for t = t.Parent(); t != root; t = t.Parent() {
+ // No variants specified: just compare core components.
+ // The key has the form lllssrrr, where l, s, and r are nibbles for
+ // respectively the langID, scriptID, and regionID.
+ if x, ok := getCoreIndex(t); ok {
+ return x, exact
+ }
+ }
+ return 0, exact
+}
+
+var root = language.Tag{}
diff --git a/vendor/golang.org/x/text/internal/language/compact/parents.go b/vendor/golang.org/x/text/internal/language/compact/parents.go
new file mode 100644
index 0000000..8d81072
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/compact/parents.go
@@ -0,0 +1,120 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package compact
+
+// parents maps a compact index of a tag to the compact index of the parent of
+// this tag.
+var parents = []ID{ // 775 elements
+ // Entry 0 - 3F
+ 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0004, 0x0000, 0x0006,
+ 0x0000, 0x0008, 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a,
+ 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a,
+ 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a,
+ 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0000,
+ 0x0000, 0x0028, 0x0000, 0x002a, 0x0000, 0x002c, 0x0000, 0x0000,
+ 0x002f, 0x002e, 0x002e, 0x0000, 0x0033, 0x0000, 0x0035, 0x0000,
+ 0x0037, 0x0000, 0x0039, 0x0000, 0x003b, 0x0000, 0x0000, 0x003e,
+ // Entry 40 - 7F
+ 0x0000, 0x0040, 0x0040, 0x0000, 0x0043, 0x0043, 0x0000, 0x0046,
+ 0x0000, 0x0048, 0x0000, 0x0000, 0x004b, 0x004a, 0x004a, 0x0000,
+ 0x004f, 0x004f, 0x004f, 0x004f, 0x0000, 0x0054, 0x0054, 0x0000,
+ 0x0057, 0x0000, 0x0059, 0x0000, 0x005b, 0x0000, 0x005d, 0x005d,
+ 0x0000, 0x0060, 0x0000, 0x0062, 0x0000, 0x0064, 0x0000, 0x0066,
+ 0x0066, 0x0000, 0x0069, 0x0000, 0x006b, 0x006b, 0x006b, 0x006b,
+ 0x006b, 0x006b, 0x006b, 0x0000, 0x0073, 0x0000, 0x0075, 0x0000,
+ 0x0077, 0x0000, 0x0000, 0x007a, 0x0000, 0x007c, 0x0000, 0x007e,
+ // Entry 80 - BF
+ 0x0000, 0x0080, 0x0080, 0x0000, 0x0083, 0x0083, 0x0000, 0x0086,
+ 0x0087, 0x0087, 0x0087, 0x0086, 0x0088, 0x0087, 0x0087, 0x0087,
+ 0x0086, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0088,
+ 0x0087, 0x0087, 0x0087, 0x0087, 0x0088, 0x0087, 0x0088, 0x0087,
+ 0x0087, 0x0088, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087,
+ 0x0087, 0x0087, 0x0087, 0x0086, 0x0087, 0x0087, 0x0087, 0x0087,
+ 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087,
+ 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0086, 0x0087, 0x0086,
+ // Entry C0 - FF
+ 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087,
+ 0x0088, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087,
+ 0x0086, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0088, 0x0087,
+ 0x0087, 0x0088, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087,
+ 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0086, 0x0086, 0x0087,
+ 0x0087, 0x0086, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0000,
+ 0x00ef, 0x0000, 0x00f1, 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f2,
+ 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f1, 0x00f2, 0x00f1, 0x00f1,
+ // Entry 100 - 13F
+ 0x00f2, 0x00f2, 0x00f1, 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f1,
+ 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x0000, 0x010e,
+ 0x0000, 0x0110, 0x0000, 0x0112, 0x0000, 0x0114, 0x0114, 0x0000,
+ 0x0117, 0x0117, 0x0117, 0x0117, 0x0000, 0x011c, 0x0000, 0x011e,
+ 0x0000, 0x0120, 0x0120, 0x0000, 0x0123, 0x0123, 0x0123, 0x0123,
+ 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123,
+ 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123,
+ 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123,
+ // Entry 140 - 17F
+ 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123,
+ 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123,
+ 0x0123, 0x0123, 0x0000, 0x0152, 0x0000, 0x0154, 0x0000, 0x0156,
+ 0x0000, 0x0158, 0x0000, 0x015a, 0x0000, 0x015c, 0x015c, 0x015c,
+ 0x0000, 0x0160, 0x0000, 0x0000, 0x0163, 0x0000, 0x0165, 0x0000,
+ 0x0167, 0x0167, 0x0167, 0x0000, 0x016b, 0x0000, 0x016d, 0x0000,
+ 0x016f, 0x0000, 0x0171, 0x0171, 0x0000, 0x0174, 0x0000, 0x0176,
+ 0x0000, 0x0178, 0x0000, 0x017a, 0x0000, 0x017c, 0x0000, 0x017e,
+ // Entry 180 - 1BF
+ 0x0000, 0x0000, 0x0000, 0x0182, 0x0000, 0x0184, 0x0184, 0x0184,
+ 0x0184, 0x0000, 0x0000, 0x0000, 0x018b, 0x0000, 0x0000, 0x018e,
+ 0x0000, 0x0000, 0x0191, 0x0000, 0x0000, 0x0000, 0x0195, 0x0000,
+ 0x0197, 0x0000, 0x0000, 0x019a, 0x0000, 0x0000, 0x019d, 0x0000,
+ 0x019f, 0x0000, 0x01a1, 0x0000, 0x01a3, 0x0000, 0x01a5, 0x0000,
+ 0x01a7, 0x0000, 0x01a9, 0x0000, 0x01ab, 0x0000, 0x01ad, 0x0000,
+ 0x01af, 0x0000, 0x01b1, 0x01b1, 0x0000, 0x01b4, 0x0000, 0x01b6,
+ 0x0000, 0x01b8, 0x0000, 0x01ba, 0x0000, 0x01bc, 0x0000, 0x0000,
+ // Entry 1C0 - 1FF
+ 0x01bf, 0x0000, 0x01c1, 0x0000, 0x01c3, 0x0000, 0x01c5, 0x0000,
+ 0x01c7, 0x0000, 0x01c9, 0x0000, 0x01cb, 0x01cb, 0x01cb, 0x01cb,
+ 0x0000, 0x01d0, 0x0000, 0x01d2, 0x01d2, 0x0000, 0x01d5, 0x0000,
+ 0x01d7, 0x0000, 0x01d9, 0x0000, 0x01db, 0x0000, 0x01dd, 0x0000,
+ 0x01df, 0x01df, 0x0000, 0x01e2, 0x0000, 0x01e4, 0x0000, 0x01e6,
+ 0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x0000, 0x01ee,
+ 0x0000, 0x01f0, 0x0000, 0x0000, 0x01f3, 0x0000, 0x01f5, 0x01f5,
+ 0x01f5, 0x0000, 0x01f9, 0x0000, 0x01fb, 0x0000, 0x01fd, 0x0000,
+ // Entry 200 - 23F
+ 0x01ff, 0x0000, 0x0000, 0x0202, 0x0000, 0x0204, 0x0204, 0x0000,
+ 0x0207, 0x0000, 0x0209, 0x0209, 0x0000, 0x020c, 0x020c, 0x0000,
+ 0x020f, 0x020f, 0x020f, 0x020f, 0x020f, 0x020f, 0x020f, 0x0000,
+ 0x0217, 0x0000, 0x0219, 0x0000, 0x021b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0221, 0x0000, 0x0000, 0x0224, 0x0000, 0x0226,
+ 0x0226, 0x0000, 0x0229, 0x0000, 0x022b, 0x022b, 0x0000, 0x0000,
+ 0x022f, 0x022e, 0x022e, 0x0000, 0x0000, 0x0234, 0x0000, 0x0236,
+ 0x0000, 0x0238, 0x0000, 0x0244, 0x023a, 0x0244, 0x0244, 0x0244,
+ // Entry 240 - 27F
+ 0x0244, 0x0244, 0x0244, 0x0244, 0x023a, 0x0244, 0x0244, 0x0000,
+ 0x0247, 0x0247, 0x0247, 0x0000, 0x024b, 0x0000, 0x024d, 0x0000,
+ 0x024f, 0x024f, 0x0000, 0x0252, 0x0000, 0x0254, 0x0254, 0x0254,
+ 0x0254, 0x0254, 0x0254, 0x0000, 0x025b, 0x0000, 0x025d, 0x0000,
+ 0x025f, 0x0000, 0x0261, 0x0000, 0x0263, 0x0000, 0x0265, 0x0000,
+ 0x0000, 0x0268, 0x0268, 0x0268, 0x0000, 0x026c, 0x0000, 0x026e,
+ 0x0000, 0x0270, 0x0000, 0x0000, 0x0000, 0x0274, 0x0273, 0x0273,
+ 0x0000, 0x0278, 0x0000, 0x027a, 0x0000, 0x027c, 0x0000, 0x0000,
+ // Entry 280 - 2BF
+ 0x0000, 0x0000, 0x0281, 0x0000, 0x0000, 0x0284, 0x0000, 0x0286,
+ 0x0286, 0x0286, 0x0286, 0x0000, 0x028b, 0x028b, 0x028b, 0x0000,
+ 0x028f, 0x028f, 0x028f, 0x028f, 0x028f, 0x0000, 0x0295, 0x0295,
+ 0x0295, 0x0295, 0x0000, 0x0000, 0x0000, 0x0000, 0x029d, 0x029d,
+ 0x029d, 0x0000, 0x02a1, 0x02a1, 0x02a1, 0x02a1, 0x0000, 0x0000,
+ 0x02a7, 0x02a7, 0x02a7, 0x02a7, 0x0000, 0x02ac, 0x0000, 0x02ae,
+ 0x02ae, 0x0000, 0x02b1, 0x0000, 0x02b3, 0x0000, 0x02b5, 0x02b5,
+ 0x0000, 0x0000, 0x02b9, 0x0000, 0x0000, 0x0000, 0x02bd, 0x0000,
+ // Entry 2C0 - 2FF
+ 0x02bf, 0x02bf, 0x0000, 0x0000, 0x02c3, 0x0000, 0x02c5, 0x0000,
+ 0x02c7, 0x0000, 0x02c9, 0x0000, 0x02cb, 0x0000, 0x02cd, 0x02cd,
+ 0x0000, 0x0000, 0x02d1, 0x0000, 0x02d3, 0x02d0, 0x02d0, 0x0000,
+ 0x0000, 0x02d8, 0x02d7, 0x02d7, 0x0000, 0x0000, 0x02dd, 0x0000,
+ 0x02df, 0x0000, 0x02e1, 0x0000, 0x0000, 0x02e4, 0x0000, 0x02e6,
+ 0x0000, 0x0000, 0x02e9, 0x0000, 0x02eb, 0x0000, 0x02ed, 0x0000,
+ 0x02ef, 0x02ef, 0x0000, 0x0000, 0x02f3, 0x02f2, 0x02f2, 0x0000,
+ 0x02f7, 0x0000, 0x02f9, 0x02f9, 0x02f9, 0x02f9, 0x02f9, 0x0000,
+ // Entry 300 - 33F
+ 0x02ff, 0x0300, 0x02ff, 0x0000, 0x0303, 0x0051, 0x00e6,
+} // Size: 1574 bytes
+
+// Total table size 1574 bytes (1KiB); checksum: 895AAF0B
diff --git a/vendor/golang.org/x/text/internal/language/compact/tables.go b/vendor/golang.org/x/text/internal/language/compact/tables.go
new file mode 100644
index 0000000..a09ed19
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/compact/tables.go
@@ -0,0 +1,1015 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package compact
+
+import "golang.org/x/text/internal/language"
+
+// CLDRVersion is the CLDR version from which the tables in this package are derived.
+const CLDRVersion = "32"
+
+// NumCompactTags is the number of common tags. The maximum tag is
+// NumCompactTags-1.
+const NumCompactTags = 775
+const (
+ undIndex ID = 0
+ afIndex ID = 1
+ afNAIndex ID = 2
+ afZAIndex ID = 3
+ agqIndex ID = 4
+ agqCMIndex ID = 5
+ akIndex ID = 6
+ akGHIndex ID = 7
+ amIndex ID = 8
+ amETIndex ID = 9
+ arIndex ID = 10
+ ar001Index ID = 11
+ arAEIndex ID = 12
+ arBHIndex ID = 13
+ arDJIndex ID = 14
+ arDZIndex ID = 15
+ arEGIndex ID = 16
+ arEHIndex ID = 17
+ arERIndex ID = 18
+ arILIndex ID = 19
+ arIQIndex ID = 20
+ arJOIndex ID = 21
+ arKMIndex ID = 22
+ arKWIndex ID = 23
+ arLBIndex ID = 24
+ arLYIndex ID = 25
+ arMAIndex ID = 26
+ arMRIndex ID = 27
+ arOMIndex ID = 28
+ arPSIndex ID = 29
+ arQAIndex ID = 30
+ arSAIndex ID = 31
+ arSDIndex ID = 32
+ arSOIndex ID = 33
+ arSSIndex ID = 34
+ arSYIndex ID = 35
+ arTDIndex ID = 36
+ arTNIndex ID = 37
+ arYEIndex ID = 38
+ arsIndex ID = 39
+ asIndex ID = 40
+ asINIndex ID = 41
+ asaIndex ID = 42
+ asaTZIndex ID = 43
+ astIndex ID = 44
+ astESIndex ID = 45
+ azIndex ID = 46
+ azCyrlIndex ID = 47
+ azCyrlAZIndex ID = 48
+ azLatnIndex ID = 49
+ azLatnAZIndex ID = 50
+ basIndex ID = 51
+ basCMIndex ID = 52
+ beIndex ID = 53
+ beBYIndex ID = 54
+ bemIndex ID = 55
+ bemZMIndex ID = 56
+ bezIndex ID = 57
+ bezTZIndex ID = 58
+ bgIndex ID = 59
+ bgBGIndex ID = 60
+ bhIndex ID = 61
+ bmIndex ID = 62
+ bmMLIndex ID = 63
+ bnIndex ID = 64
+ bnBDIndex ID = 65
+ bnINIndex ID = 66
+ boIndex ID = 67
+ boCNIndex ID = 68
+ boINIndex ID = 69
+ brIndex ID = 70
+ brFRIndex ID = 71
+ brxIndex ID = 72
+ brxINIndex ID = 73
+ bsIndex ID = 74
+ bsCyrlIndex ID = 75
+ bsCyrlBAIndex ID = 76
+ bsLatnIndex ID = 77
+ bsLatnBAIndex ID = 78
+ caIndex ID = 79
+ caADIndex ID = 80
+ caESIndex ID = 81
+ caFRIndex ID = 82
+ caITIndex ID = 83
+ ccpIndex ID = 84
+ ccpBDIndex ID = 85
+ ccpINIndex ID = 86
+ ceIndex ID = 87
+ ceRUIndex ID = 88
+ cggIndex ID = 89
+ cggUGIndex ID = 90
+ chrIndex ID = 91
+ chrUSIndex ID = 92
+ ckbIndex ID = 93
+ ckbIQIndex ID = 94
+ ckbIRIndex ID = 95
+ csIndex ID = 96
+ csCZIndex ID = 97
+ cuIndex ID = 98
+ cuRUIndex ID = 99
+ cyIndex ID = 100
+ cyGBIndex ID = 101
+ daIndex ID = 102
+ daDKIndex ID = 103
+ daGLIndex ID = 104
+ davIndex ID = 105
+ davKEIndex ID = 106
+ deIndex ID = 107
+ deATIndex ID = 108
+ deBEIndex ID = 109
+ deCHIndex ID = 110
+ deDEIndex ID = 111
+ deITIndex ID = 112
+ deLIIndex ID = 113
+ deLUIndex ID = 114
+ djeIndex ID = 115
+ djeNEIndex ID = 116
+ dsbIndex ID = 117
+ dsbDEIndex ID = 118
+ duaIndex ID = 119
+ duaCMIndex ID = 120
+ dvIndex ID = 121
+ dyoIndex ID = 122
+ dyoSNIndex ID = 123
+ dzIndex ID = 124
+ dzBTIndex ID = 125
+ ebuIndex ID = 126
+ ebuKEIndex ID = 127
+ eeIndex ID = 128
+ eeGHIndex ID = 129
+ eeTGIndex ID = 130
+ elIndex ID = 131
+ elCYIndex ID = 132
+ elGRIndex ID = 133
+ enIndex ID = 134
+ en001Index ID = 135
+ en150Index ID = 136
+ enAGIndex ID = 137
+ enAIIndex ID = 138
+ enASIndex ID = 139
+ enATIndex ID = 140
+ enAUIndex ID = 141
+ enBBIndex ID = 142
+ enBEIndex ID = 143
+ enBIIndex ID = 144
+ enBMIndex ID = 145
+ enBSIndex ID = 146
+ enBWIndex ID = 147
+ enBZIndex ID = 148
+ enCAIndex ID = 149
+ enCCIndex ID = 150
+ enCHIndex ID = 151
+ enCKIndex ID = 152
+ enCMIndex ID = 153
+ enCXIndex ID = 154
+ enCYIndex ID = 155
+ enDEIndex ID = 156
+ enDGIndex ID = 157
+ enDKIndex ID = 158
+ enDMIndex ID = 159
+ enERIndex ID = 160
+ enFIIndex ID = 161
+ enFJIndex ID = 162
+ enFKIndex ID = 163
+ enFMIndex ID = 164
+ enGBIndex ID = 165
+ enGDIndex ID = 166
+ enGGIndex ID = 167
+ enGHIndex ID = 168
+ enGIIndex ID = 169
+ enGMIndex ID = 170
+ enGUIndex ID = 171
+ enGYIndex ID = 172
+ enHKIndex ID = 173
+ enIEIndex ID = 174
+ enILIndex ID = 175
+ enIMIndex ID = 176
+ enINIndex ID = 177
+ enIOIndex ID = 178
+ enJEIndex ID = 179
+ enJMIndex ID = 180
+ enKEIndex ID = 181
+ enKIIndex ID = 182
+ enKNIndex ID = 183
+ enKYIndex ID = 184
+ enLCIndex ID = 185
+ enLRIndex ID = 186
+ enLSIndex ID = 187
+ enMGIndex ID = 188
+ enMHIndex ID = 189
+ enMOIndex ID = 190
+ enMPIndex ID = 191
+ enMSIndex ID = 192
+ enMTIndex ID = 193
+ enMUIndex ID = 194
+ enMWIndex ID = 195
+ enMYIndex ID = 196
+ enNAIndex ID = 197
+ enNFIndex ID = 198
+ enNGIndex ID = 199
+ enNLIndex ID = 200
+ enNRIndex ID = 201
+ enNUIndex ID = 202
+ enNZIndex ID = 203
+ enPGIndex ID = 204
+ enPHIndex ID = 205
+ enPKIndex ID = 206
+ enPNIndex ID = 207
+ enPRIndex ID = 208
+ enPWIndex ID = 209
+ enRWIndex ID = 210
+ enSBIndex ID = 211
+ enSCIndex ID = 212
+ enSDIndex ID = 213
+ enSEIndex ID = 214
+ enSGIndex ID = 215
+ enSHIndex ID = 216
+ enSIIndex ID = 217
+ enSLIndex ID = 218
+ enSSIndex ID = 219
+ enSXIndex ID = 220
+ enSZIndex ID = 221
+ enTCIndex ID = 222
+ enTKIndex ID = 223
+ enTOIndex ID = 224
+ enTTIndex ID = 225
+ enTVIndex ID = 226
+ enTZIndex ID = 227
+ enUGIndex ID = 228
+ enUMIndex ID = 229
+ enUSIndex ID = 230
+ enVCIndex ID = 231
+ enVGIndex ID = 232
+ enVIIndex ID = 233
+ enVUIndex ID = 234
+ enWSIndex ID = 235
+ enZAIndex ID = 236
+ enZMIndex ID = 237
+ enZWIndex ID = 238
+ eoIndex ID = 239
+ eo001Index ID = 240
+ esIndex ID = 241
+ es419Index ID = 242
+ esARIndex ID = 243
+ esBOIndex ID = 244
+ esBRIndex ID = 245
+ esBZIndex ID = 246
+ esCLIndex ID = 247
+ esCOIndex ID = 248
+ esCRIndex ID = 249
+ esCUIndex ID = 250
+ esDOIndex ID = 251
+ esEAIndex ID = 252
+ esECIndex ID = 253
+ esESIndex ID = 254
+ esGQIndex ID = 255
+ esGTIndex ID = 256
+ esHNIndex ID = 257
+ esICIndex ID = 258
+ esMXIndex ID = 259
+ esNIIndex ID = 260
+ esPAIndex ID = 261
+ esPEIndex ID = 262
+ esPHIndex ID = 263
+ esPRIndex ID = 264
+ esPYIndex ID = 265
+ esSVIndex ID = 266
+ esUSIndex ID = 267
+ esUYIndex ID = 268
+ esVEIndex ID = 269
+ etIndex ID = 270
+ etEEIndex ID = 271
+ euIndex ID = 272
+ euESIndex ID = 273
+ ewoIndex ID = 274
+ ewoCMIndex ID = 275
+ faIndex ID = 276
+ faAFIndex ID = 277
+ faIRIndex ID = 278
+ ffIndex ID = 279
+ ffCMIndex ID = 280
+ ffGNIndex ID = 281
+ ffMRIndex ID = 282
+ ffSNIndex ID = 283
+ fiIndex ID = 284
+ fiFIIndex ID = 285
+ filIndex ID = 286
+ filPHIndex ID = 287
+ foIndex ID = 288
+ foDKIndex ID = 289
+ foFOIndex ID = 290
+ frIndex ID = 291
+ frBEIndex ID = 292
+ frBFIndex ID = 293
+ frBIIndex ID = 294
+ frBJIndex ID = 295
+ frBLIndex ID = 296
+ frCAIndex ID = 297
+ frCDIndex ID = 298
+ frCFIndex ID = 299
+ frCGIndex ID = 300
+ frCHIndex ID = 301
+ frCIIndex ID = 302
+ frCMIndex ID = 303
+ frDJIndex ID = 304
+ frDZIndex ID = 305
+ frFRIndex ID = 306
+ frGAIndex ID = 307
+ frGFIndex ID = 308
+ frGNIndex ID = 309
+ frGPIndex ID = 310
+ frGQIndex ID = 311
+ frHTIndex ID = 312
+ frKMIndex ID = 313
+ frLUIndex ID = 314
+ frMAIndex ID = 315
+ frMCIndex ID = 316
+ frMFIndex ID = 317
+ frMGIndex ID = 318
+ frMLIndex ID = 319
+ frMQIndex ID = 320
+ frMRIndex ID = 321
+ frMUIndex ID = 322
+ frNCIndex ID = 323
+ frNEIndex ID = 324
+ frPFIndex ID = 325
+ frPMIndex ID = 326
+ frREIndex ID = 327
+ frRWIndex ID = 328
+ frSCIndex ID = 329
+ frSNIndex ID = 330
+ frSYIndex ID = 331
+ frTDIndex ID = 332
+ frTGIndex ID = 333
+ frTNIndex ID = 334
+ frVUIndex ID = 335
+ frWFIndex ID = 336
+ frYTIndex ID = 337
+ furIndex ID = 338
+ furITIndex ID = 339
+ fyIndex ID = 340
+ fyNLIndex ID = 341
+ gaIndex ID = 342
+ gaIEIndex ID = 343
+ gdIndex ID = 344
+ gdGBIndex ID = 345
+ glIndex ID = 346
+ glESIndex ID = 347
+ gswIndex ID = 348
+ gswCHIndex ID = 349
+ gswFRIndex ID = 350
+ gswLIIndex ID = 351
+ guIndex ID = 352
+ guINIndex ID = 353
+ guwIndex ID = 354
+ guzIndex ID = 355
+ guzKEIndex ID = 356
+ gvIndex ID = 357
+ gvIMIndex ID = 358
+ haIndex ID = 359
+ haGHIndex ID = 360
+ haNEIndex ID = 361
+ haNGIndex ID = 362
+ hawIndex ID = 363
+ hawUSIndex ID = 364
+ heIndex ID = 365
+ heILIndex ID = 366
+ hiIndex ID = 367
+ hiINIndex ID = 368
+ hrIndex ID = 369
+ hrBAIndex ID = 370
+ hrHRIndex ID = 371
+ hsbIndex ID = 372
+ hsbDEIndex ID = 373
+ huIndex ID = 374
+ huHUIndex ID = 375
+ hyIndex ID = 376
+ hyAMIndex ID = 377
+ idIndex ID = 378
+ idIDIndex ID = 379
+ igIndex ID = 380
+ igNGIndex ID = 381
+ iiIndex ID = 382
+ iiCNIndex ID = 383
+ inIndex ID = 384
+ ioIndex ID = 385
+ isIndex ID = 386
+ isISIndex ID = 387
+ itIndex ID = 388
+ itCHIndex ID = 389
+ itITIndex ID = 390
+ itSMIndex ID = 391
+ itVAIndex ID = 392
+ iuIndex ID = 393
+ iwIndex ID = 394
+ jaIndex ID = 395
+ jaJPIndex ID = 396
+ jboIndex ID = 397
+ jgoIndex ID = 398
+ jgoCMIndex ID = 399
+ jiIndex ID = 400
+ jmcIndex ID = 401
+ jmcTZIndex ID = 402
+ jvIndex ID = 403
+ jwIndex ID = 404
+ kaIndex ID = 405
+ kaGEIndex ID = 406
+ kabIndex ID = 407
+ kabDZIndex ID = 408
+ kajIndex ID = 409
+ kamIndex ID = 410
+ kamKEIndex ID = 411
+ kcgIndex ID = 412
+ kdeIndex ID = 413
+ kdeTZIndex ID = 414
+ keaIndex ID = 415
+ keaCVIndex ID = 416
+ khqIndex ID = 417
+ khqMLIndex ID = 418
+ kiIndex ID = 419
+ kiKEIndex ID = 420
+ kkIndex ID = 421
+ kkKZIndex ID = 422
+ kkjIndex ID = 423
+ kkjCMIndex ID = 424
+ klIndex ID = 425
+ klGLIndex ID = 426
+ klnIndex ID = 427
+ klnKEIndex ID = 428
+ kmIndex ID = 429
+ kmKHIndex ID = 430
+ knIndex ID = 431
+ knINIndex ID = 432
+ koIndex ID = 433
+ koKPIndex ID = 434
+ koKRIndex ID = 435
+ kokIndex ID = 436
+ kokINIndex ID = 437
+ ksIndex ID = 438
+ ksINIndex ID = 439
+ ksbIndex ID = 440
+ ksbTZIndex ID = 441
+ ksfIndex ID = 442
+ ksfCMIndex ID = 443
+ kshIndex ID = 444
+ kshDEIndex ID = 445
+ kuIndex ID = 446
+ kwIndex ID = 447
+ kwGBIndex ID = 448
+ kyIndex ID = 449
+ kyKGIndex ID = 450
+ lagIndex ID = 451
+ lagTZIndex ID = 452
+ lbIndex ID = 453
+ lbLUIndex ID = 454
+ lgIndex ID = 455
+ lgUGIndex ID = 456
+ lktIndex ID = 457
+ lktUSIndex ID = 458
+ lnIndex ID = 459
+ lnAOIndex ID = 460
+ lnCDIndex ID = 461
+ lnCFIndex ID = 462
+ lnCGIndex ID = 463
+ loIndex ID = 464
+ loLAIndex ID = 465
+ lrcIndex ID = 466
+ lrcIQIndex ID = 467
+ lrcIRIndex ID = 468
+ ltIndex ID = 469
+ ltLTIndex ID = 470
+ luIndex ID = 471
+ luCDIndex ID = 472
+ luoIndex ID = 473
+ luoKEIndex ID = 474
+ luyIndex ID = 475
+ luyKEIndex ID = 476
+ lvIndex ID = 477
+ lvLVIndex ID = 478
+ masIndex ID = 479
+ masKEIndex ID = 480
+ masTZIndex ID = 481
+ merIndex ID = 482
+ merKEIndex ID = 483
+ mfeIndex ID = 484
+ mfeMUIndex ID = 485
+ mgIndex ID = 486
+ mgMGIndex ID = 487
+ mghIndex ID = 488
+ mghMZIndex ID = 489
+ mgoIndex ID = 490
+ mgoCMIndex ID = 491
+ mkIndex ID = 492
+ mkMKIndex ID = 493
+ mlIndex ID = 494
+ mlINIndex ID = 495
+ mnIndex ID = 496
+ mnMNIndex ID = 497
+ moIndex ID = 498
+ mrIndex ID = 499
+ mrINIndex ID = 500
+ msIndex ID = 501
+ msBNIndex ID = 502
+ msMYIndex ID = 503
+ msSGIndex ID = 504
+ mtIndex ID = 505
+ mtMTIndex ID = 506
+ muaIndex ID = 507
+ muaCMIndex ID = 508
+ myIndex ID = 509
+ myMMIndex ID = 510
+ mznIndex ID = 511
+ mznIRIndex ID = 512
+ nahIndex ID = 513
+ naqIndex ID = 514
+ naqNAIndex ID = 515
+ nbIndex ID = 516
+ nbNOIndex ID = 517
+ nbSJIndex ID = 518
+ ndIndex ID = 519
+ ndZWIndex ID = 520
+ ndsIndex ID = 521
+ ndsDEIndex ID = 522
+ ndsNLIndex ID = 523
+ neIndex ID = 524
+ neINIndex ID = 525
+ neNPIndex ID = 526
+ nlIndex ID = 527
+ nlAWIndex ID = 528
+ nlBEIndex ID = 529
+ nlBQIndex ID = 530
+ nlCWIndex ID = 531
+ nlNLIndex ID = 532
+ nlSRIndex ID = 533
+ nlSXIndex ID = 534
+ nmgIndex ID = 535
+ nmgCMIndex ID = 536
+ nnIndex ID = 537
+ nnNOIndex ID = 538
+ nnhIndex ID = 539
+ nnhCMIndex ID = 540
+ noIndex ID = 541
+ nqoIndex ID = 542
+ nrIndex ID = 543
+ nsoIndex ID = 544
+ nusIndex ID = 545
+ nusSSIndex ID = 546
+ nyIndex ID = 547
+ nynIndex ID = 548
+ nynUGIndex ID = 549
+ omIndex ID = 550
+ omETIndex ID = 551
+ omKEIndex ID = 552
+ orIndex ID = 553
+ orINIndex ID = 554
+ osIndex ID = 555
+ osGEIndex ID = 556
+ osRUIndex ID = 557
+ paIndex ID = 558
+ paArabIndex ID = 559
+ paArabPKIndex ID = 560
+ paGuruIndex ID = 561
+ paGuruINIndex ID = 562
+ papIndex ID = 563
+ plIndex ID = 564
+ plPLIndex ID = 565
+ prgIndex ID = 566
+ prg001Index ID = 567
+ psIndex ID = 568
+ psAFIndex ID = 569
+ ptIndex ID = 570
+ ptAOIndex ID = 571
+ ptBRIndex ID = 572
+ ptCHIndex ID = 573
+ ptCVIndex ID = 574
+ ptGQIndex ID = 575
+ ptGWIndex ID = 576
+ ptLUIndex ID = 577
+ ptMOIndex ID = 578
+ ptMZIndex ID = 579
+ ptPTIndex ID = 580
+ ptSTIndex ID = 581
+ ptTLIndex ID = 582
+ quIndex ID = 583
+ quBOIndex ID = 584
+ quECIndex ID = 585
+ quPEIndex ID = 586
+ rmIndex ID = 587
+ rmCHIndex ID = 588
+ rnIndex ID = 589
+ rnBIIndex ID = 590
+ roIndex ID = 591
+ roMDIndex ID = 592
+ roROIndex ID = 593
+ rofIndex ID = 594
+ rofTZIndex ID = 595
+ ruIndex ID = 596
+ ruBYIndex ID = 597
+ ruKGIndex ID = 598
+ ruKZIndex ID = 599
+ ruMDIndex ID = 600
+ ruRUIndex ID = 601
+ ruUAIndex ID = 602
+ rwIndex ID = 603
+ rwRWIndex ID = 604
+ rwkIndex ID = 605
+ rwkTZIndex ID = 606
+ sahIndex ID = 607
+ sahRUIndex ID = 608
+ saqIndex ID = 609
+ saqKEIndex ID = 610
+ sbpIndex ID = 611
+ sbpTZIndex ID = 612
+ sdIndex ID = 613
+ sdPKIndex ID = 614
+ sdhIndex ID = 615
+ seIndex ID = 616
+ seFIIndex ID = 617
+ seNOIndex ID = 618
+ seSEIndex ID = 619
+ sehIndex ID = 620
+ sehMZIndex ID = 621
+ sesIndex ID = 622
+ sesMLIndex ID = 623
+ sgIndex ID = 624
+ sgCFIndex ID = 625
+ shIndex ID = 626
+ shiIndex ID = 627
+ shiLatnIndex ID = 628
+ shiLatnMAIndex ID = 629
+ shiTfngIndex ID = 630
+ shiTfngMAIndex ID = 631
+ siIndex ID = 632
+ siLKIndex ID = 633
+ skIndex ID = 634
+ skSKIndex ID = 635
+ slIndex ID = 636
+ slSIIndex ID = 637
+ smaIndex ID = 638
+ smiIndex ID = 639
+ smjIndex ID = 640
+ smnIndex ID = 641
+ smnFIIndex ID = 642
+ smsIndex ID = 643
+ snIndex ID = 644
+ snZWIndex ID = 645
+ soIndex ID = 646
+ soDJIndex ID = 647
+ soETIndex ID = 648
+ soKEIndex ID = 649
+ soSOIndex ID = 650
+ sqIndex ID = 651
+ sqALIndex ID = 652
+ sqMKIndex ID = 653
+ sqXKIndex ID = 654
+ srIndex ID = 655
+ srCyrlIndex ID = 656
+ srCyrlBAIndex ID = 657
+ srCyrlMEIndex ID = 658
+ srCyrlRSIndex ID = 659
+ srCyrlXKIndex ID = 660
+ srLatnIndex ID = 661
+ srLatnBAIndex ID = 662
+ srLatnMEIndex ID = 663
+ srLatnRSIndex ID = 664
+ srLatnXKIndex ID = 665
+ ssIndex ID = 666
+ ssyIndex ID = 667
+ stIndex ID = 668
+ svIndex ID = 669
+ svAXIndex ID = 670
+ svFIIndex ID = 671
+ svSEIndex ID = 672
+ swIndex ID = 673
+ swCDIndex ID = 674
+ swKEIndex ID = 675
+ swTZIndex ID = 676
+ swUGIndex ID = 677
+ syrIndex ID = 678
+ taIndex ID = 679
+ taINIndex ID = 680
+ taLKIndex ID = 681
+ taMYIndex ID = 682
+ taSGIndex ID = 683
+ teIndex ID = 684
+ teINIndex ID = 685
+ teoIndex ID = 686
+ teoKEIndex ID = 687
+ teoUGIndex ID = 688
+ tgIndex ID = 689
+ tgTJIndex ID = 690
+ thIndex ID = 691
+ thTHIndex ID = 692
+ tiIndex ID = 693
+ tiERIndex ID = 694
+ tiETIndex ID = 695
+ tigIndex ID = 696
+ tkIndex ID = 697
+ tkTMIndex ID = 698
+ tlIndex ID = 699
+ tnIndex ID = 700
+ toIndex ID = 701
+ toTOIndex ID = 702
+ trIndex ID = 703
+ trCYIndex ID = 704
+ trTRIndex ID = 705
+ tsIndex ID = 706
+ ttIndex ID = 707
+ ttRUIndex ID = 708
+ twqIndex ID = 709
+ twqNEIndex ID = 710
+ tzmIndex ID = 711
+ tzmMAIndex ID = 712
+ ugIndex ID = 713
+ ugCNIndex ID = 714
+ ukIndex ID = 715
+ ukUAIndex ID = 716
+ urIndex ID = 717
+ urINIndex ID = 718
+ urPKIndex ID = 719
+ uzIndex ID = 720
+ uzArabIndex ID = 721
+ uzArabAFIndex ID = 722
+ uzCyrlIndex ID = 723
+ uzCyrlUZIndex ID = 724
+ uzLatnIndex ID = 725
+ uzLatnUZIndex ID = 726
+ vaiIndex ID = 727
+ vaiLatnIndex ID = 728
+ vaiLatnLRIndex ID = 729
+ vaiVaiiIndex ID = 730
+ vaiVaiiLRIndex ID = 731
+ veIndex ID = 732
+ viIndex ID = 733
+ viVNIndex ID = 734
+ voIndex ID = 735
+ vo001Index ID = 736
+ vunIndex ID = 737
+ vunTZIndex ID = 738
+ waIndex ID = 739
+ waeIndex ID = 740
+ waeCHIndex ID = 741
+ woIndex ID = 742
+ woSNIndex ID = 743
+ xhIndex ID = 744
+ xogIndex ID = 745
+ xogUGIndex ID = 746
+ yavIndex ID = 747
+ yavCMIndex ID = 748
+ yiIndex ID = 749
+ yi001Index ID = 750
+ yoIndex ID = 751
+ yoBJIndex ID = 752
+ yoNGIndex ID = 753
+ yueIndex ID = 754
+ yueHansIndex ID = 755
+ yueHansCNIndex ID = 756
+ yueHantIndex ID = 757
+ yueHantHKIndex ID = 758
+ zghIndex ID = 759
+ zghMAIndex ID = 760
+ zhIndex ID = 761
+ zhHansIndex ID = 762
+ zhHansCNIndex ID = 763
+ zhHansHKIndex ID = 764
+ zhHansMOIndex ID = 765
+ zhHansSGIndex ID = 766
+ zhHantIndex ID = 767
+ zhHantHKIndex ID = 768
+ zhHantMOIndex ID = 769
+ zhHantTWIndex ID = 770
+ zuIndex ID = 771
+ zuZAIndex ID = 772
+ caESvalenciaIndex ID = 773
+ enUSuvaposixIndex ID = 774
+)
+
+var coreTags = []language.CompactCoreInfo{ // 773 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x01600000, 0x016000d3, 0x01600162,
+ 0x01c00000, 0x01c00052, 0x02100000, 0x02100081,
+ 0x02700000, 0x02700070, 0x03a00000, 0x03a00001,
+ 0x03a00023, 0x03a00039, 0x03a00063, 0x03a00068,
+ 0x03a0006c, 0x03a0006d, 0x03a0006e, 0x03a00098,
+ 0x03a0009c, 0x03a000a2, 0x03a000a9, 0x03a000ad,
+ 0x03a000b1, 0x03a000ba, 0x03a000bb, 0x03a000ca,
+ 0x03a000e2, 0x03a000ee, 0x03a000f4, 0x03a00109,
+ // Entry 20 - 3F
+ 0x03a0010c, 0x03a00116, 0x03a00118, 0x03a0011d,
+ 0x03a00121, 0x03a00129, 0x03a0015f, 0x04000000,
+ 0x04300000, 0x0430009a, 0x04400000, 0x04400130,
+ 0x04800000, 0x0480006f, 0x05800000, 0x05820000,
+ 0x05820032, 0x0585b000, 0x0585b032, 0x05e00000,
+ 0x05e00052, 0x07100000, 0x07100047, 0x07500000,
+ 0x07500163, 0x07900000, 0x07900130, 0x07e00000,
+ 0x07e00038, 0x08200000, 0x0a000000, 0x0a0000c4,
+ // Entry 40 - 5F
+ 0x0a500000, 0x0a500035, 0x0a50009a, 0x0a900000,
+ 0x0a900053, 0x0a90009a, 0x0b200000, 0x0b200079,
+ 0x0b500000, 0x0b50009a, 0x0b700000, 0x0b720000,
+ 0x0b720033, 0x0b75b000, 0x0b75b033, 0x0d700000,
+ 0x0d700022, 0x0d70006f, 0x0d700079, 0x0d70009f,
+ 0x0db00000, 0x0db00035, 0x0db0009a, 0x0dc00000,
+ 0x0dc00107, 0x0df00000, 0x0df00132, 0x0e500000,
+ 0x0e500136, 0x0e900000, 0x0e90009c, 0x0e90009d,
+ // Entry 60 - 7F
+ 0x0fa00000, 0x0fa0005f, 0x0fe00000, 0x0fe00107,
+ 0x10000000, 0x1000007c, 0x10100000, 0x10100064,
+ 0x10100083, 0x10800000, 0x108000a5, 0x10d00000,
+ 0x10d0002e, 0x10d00036, 0x10d0004e, 0x10d00061,
+ 0x10d0009f, 0x10d000b3, 0x10d000b8, 0x11700000,
+ 0x117000d5, 0x11f00000, 0x11f00061, 0x12400000,
+ 0x12400052, 0x12800000, 0x12b00000, 0x12b00115,
+ 0x12d00000, 0x12d00043, 0x12f00000, 0x12f000a5,
+ // Entry 80 - 9F
+ 0x13000000, 0x13000081, 0x13000123, 0x13600000,
+ 0x1360005e, 0x13600088, 0x13900000, 0x13900001,
+ 0x1390001a, 0x13900025, 0x13900026, 0x1390002d,
+ 0x1390002e, 0x1390002f, 0x13900034, 0x13900036,
+ 0x1390003a, 0x1390003d, 0x13900042, 0x13900046,
+ 0x13900048, 0x13900049, 0x1390004a, 0x1390004e,
+ 0x13900050, 0x13900052, 0x1390005d, 0x1390005e,
+ 0x13900061, 0x13900062, 0x13900064, 0x13900065,
+ // Entry A0 - BF
+ 0x1390006e, 0x13900073, 0x13900074, 0x13900075,
+ 0x13900076, 0x1390007c, 0x1390007d, 0x13900080,
+ 0x13900081, 0x13900082, 0x13900084, 0x1390008b,
+ 0x1390008d, 0x1390008e, 0x13900097, 0x13900098,
+ 0x13900099, 0x1390009a, 0x1390009b, 0x139000a0,
+ 0x139000a1, 0x139000a5, 0x139000a8, 0x139000aa,
+ 0x139000ae, 0x139000b2, 0x139000b5, 0x139000b6,
+ 0x139000c0, 0x139000c1, 0x139000c7, 0x139000c8,
+ // Entry C0 - DF
+ 0x139000cb, 0x139000cc, 0x139000cd, 0x139000cf,
+ 0x139000d1, 0x139000d3, 0x139000d6, 0x139000d7,
+ 0x139000da, 0x139000de, 0x139000e0, 0x139000e1,
+ 0x139000e7, 0x139000e8, 0x139000e9, 0x139000ec,
+ 0x139000ed, 0x139000f1, 0x13900108, 0x1390010a,
+ 0x1390010b, 0x1390010c, 0x1390010d, 0x1390010e,
+ 0x1390010f, 0x13900110, 0x13900113, 0x13900118,
+ 0x1390011c, 0x1390011e, 0x13900120, 0x13900126,
+ // Entry E0 - FF
+ 0x1390012a, 0x1390012d, 0x1390012e, 0x13900130,
+ 0x13900132, 0x13900134, 0x13900136, 0x1390013a,
+ 0x1390013d, 0x1390013e, 0x13900140, 0x13900143,
+ 0x13900162, 0x13900163, 0x13900165, 0x13c00000,
+ 0x13c00001, 0x13e00000, 0x13e0001f, 0x13e0002c,
+ 0x13e0003f, 0x13e00041, 0x13e00048, 0x13e00051,
+ 0x13e00054, 0x13e00057, 0x13e0005a, 0x13e00066,
+ 0x13e00069, 0x13e0006a, 0x13e0006f, 0x13e00087,
+ // Entry 100 - 11F
+ 0x13e0008a, 0x13e00090, 0x13e00095, 0x13e000d0,
+ 0x13e000d9, 0x13e000e3, 0x13e000e5, 0x13e000e8,
+ 0x13e000ed, 0x13e000f2, 0x13e0011b, 0x13e00136,
+ 0x13e00137, 0x13e0013c, 0x14000000, 0x1400006b,
+ 0x14500000, 0x1450006f, 0x14600000, 0x14600052,
+ 0x14800000, 0x14800024, 0x1480009d, 0x14e00000,
+ 0x14e00052, 0x14e00085, 0x14e000ca, 0x14e00115,
+ 0x15100000, 0x15100073, 0x15300000, 0x153000e8,
+ // Entry 120 - 13F
+ 0x15800000, 0x15800064, 0x15800077, 0x15e00000,
+ 0x15e00036, 0x15e00037, 0x15e0003a, 0x15e0003b,
+ 0x15e0003c, 0x15e00049, 0x15e0004b, 0x15e0004c,
+ 0x15e0004d, 0x15e0004e, 0x15e0004f, 0x15e00052,
+ 0x15e00063, 0x15e00068, 0x15e00079, 0x15e0007b,
+ 0x15e0007f, 0x15e00085, 0x15e00086, 0x15e00087,
+ 0x15e00092, 0x15e000a9, 0x15e000b8, 0x15e000bb,
+ 0x15e000bc, 0x15e000bf, 0x15e000c0, 0x15e000c4,
+ // Entry 140 - 15F
+ 0x15e000c9, 0x15e000ca, 0x15e000cd, 0x15e000d4,
+ 0x15e000d5, 0x15e000e6, 0x15e000eb, 0x15e00103,
+ 0x15e00108, 0x15e0010b, 0x15e00115, 0x15e0011d,
+ 0x15e00121, 0x15e00123, 0x15e00129, 0x15e00140,
+ 0x15e00141, 0x15e00160, 0x16900000, 0x1690009f,
+ 0x16d00000, 0x16d000da, 0x16e00000, 0x16e00097,
+ 0x17e00000, 0x17e0007c, 0x19000000, 0x1900006f,
+ 0x1a300000, 0x1a30004e, 0x1a300079, 0x1a3000b3,
+ // Entry 160 - 17F
+ 0x1a400000, 0x1a40009a, 0x1a900000, 0x1ab00000,
+ 0x1ab000a5, 0x1ac00000, 0x1ac00099, 0x1b400000,
+ 0x1b400081, 0x1b4000d5, 0x1b4000d7, 0x1b800000,
+ 0x1b800136, 0x1bc00000, 0x1bc00098, 0x1be00000,
+ 0x1be0009a, 0x1d100000, 0x1d100033, 0x1d100091,
+ 0x1d200000, 0x1d200061, 0x1d500000, 0x1d500093,
+ 0x1d700000, 0x1d700028, 0x1e100000, 0x1e100096,
+ 0x1e700000, 0x1e7000d7, 0x1ea00000, 0x1ea00053,
+ // Entry 180 - 19F
+ 0x1f300000, 0x1f500000, 0x1f800000, 0x1f80009e,
+ 0x1f900000, 0x1f90004e, 0x1f90009f, 0x1f900114,
+ 0x1f900139, 0x1fa00000, 0x1fb00000, 0x20000000,
+ 0x200000a3, 0x20300000, 0x20700000, 0x20700052,
+ 0x20800000, 0x20a00000, 0x20a00130, 0x20e00000,
+ 0x20f00000, 0x21000000, 0x2100007e, 0x21200000,
+ 0x21200068, 0x21600000, 0x21700000, 0x217000a5,
+ 0x21f00000, 0x22300000, 0x22300130, 0x22700000,
+ // Entry 1A0 - 1BF
+ 0x2270005b, 0x23400000, 0x234000c4, 0x23900000,
+ 0x239000a5, 0x24200000, 0x242000af, 0x24400000,
+ 0x24400052, 0x24500000, 0x24500083, 0x24600000,
+ 0x246000a5, 0x24a00000, 0x24a000a7, 0x25100000,
+ 0x2510009a, 0x25400000, 0x254000ab, 0x254000ac,
+ 0x25600000, 0x2560009a, 0x26a00000, 0x26a0009a,
+ 0x26b00000, 0x26b00130, 0x26d00000, 0x26d00052,
+ 0x26e00000, 0x26e00061, 0x27400000, 0x28100000,
+ // Entry 1C0 - 1DF
+ 0x2810007c, 0x28a00000, 0x28a000a6, 0x29100000,
+ 0x29100130, 0x29500000, 0x295000b8, 0x2a300000,
+ 0x2a300132, 0x2af00000, 0x2af00136, 0x2b500000,
+ 0x2b50002a, 0x2b50004b, 0x2b50004c, 0x2b50004d,
+ 0x2b800000, 0x2b8000b0, 0x2bf00000, 0x2bf0009c,
+ 0x2bf0009d, 0x2c000000, 0x2c0000b7, 0x2c200000,
+ 0x2c20004b, 0x2c400000, 0x2c4000a5, 0x2c500000,
+ 0x2c5000a5, 0x2c700000, 0x2c7000b9, 0x2d100000,
+ // Entry 1E0 - 1FF
+ 0x2d1000a5, 0x2d100130, 0x2e900000, 0x2e9000a5,
+ 0x2ed00000, 0x2ed000cd, 0x2f100000, 0x2f1000c0,
+ 0x2f200000, 0x2f2000d2, 0x2f400000, 0x2f400052,
+ 0x2ff00000, 0x2ff000c3, 0x30400000, 0x3040009a,
+ 0x30b00000, 0x30b000c6, 0x31000000, 0x31b00000,
+ 0x31b0009a, 0x31f00000, 0x31f0003e, 0x31f000d1,
+ 0x31f0010e, 0x32000000, 0x320000cc, 0x32500000,
+ 0x32500052, 0x33100000, 0x331000c5, 0x33a00000,
+ // Entry 200 - 21F
+ 0x33a0009d, 0x34100000, 0x34500000, 0x345000d3,
+ 0x34700000, 0x347000db, 0x34700111, 0x34e00000,
+ 0x34e00165, 0x35000000, 0x35000061, 0x350000da,
+ 0x35100000, 0x3510009a, 0x351000dc, 0x36700000,
+ 0x36700030, 0x36700036, 0x36700040, 0x3670005c,
+ 0x367000da, 0x36700117, 0x3670011c, 0x36800000,
+ 0x36800052, 0x36a00000, 0x36a000db, 0x36c00000,
+ 0x36c00052, 0x36f00000, 0x37500000, 0x37600000,
+ // Entry 220 - 23F
+ 0x37a00000, 0x38000000, 0x38000118, 0x38700000,
+ 0x38900000, 0x38900132, 0x39000000, 0x39000070,
+ 0x390000a5, 0x39500000, 0x3950009a, 0x39800000,
+ 0x3980007e, 0x39800107, 0x39d00000, 0x39d05000,
+ 0x39d050e9, 0x39d36000, 0x39d3609a, 0x3a100000,
+ 0x3b300000, 0x3b3000ea, 0x3bd00000, 0x3bd00001,
+ 0x3be00000, 0x3be00024, 0x3c000000, 0x3c00002a,
+ 0x3c000041, 0x3c00004e, 0x3c00005b, 0x3c000087,
+ // Entry 240 - 25F
+ 0x3c00008c, 0x3c0000b8, 0x3c0000c7, 0x3c0000d2,
+ 0x3c0000ef, 0x3c000119, 0x3c000127, 0x3c400000,
+ 0x3c40003f, 0x3c40006a, 0x3c4000e5, 0x3d400000,
+ 0x3d40004e, 0x3d900000, 0x3d90003a, 0x3dc00000,
+ 0x3dc000bd, 0x3dc00105, 0x3de00000, 0x3de00130,
+ 0x3e200000, 0x3e200047, 0x3e2000a6, 0x3e2000af,
+ 0x3e2000bd, 0x3e200107, 0x3e200131, 0x3e500000,
+ 0x3e500108, 0x3e600000, 0x3e600130, 0x3eb00000,
+ // Entry 260 - 27F
+ 0x3eb00107, 0x3ec00000, 0x3ec000a5, 0x3f300000,
+ 0x3f300130, 0x3fa00000, 0x3fa000e9, 0x3fc00000,
+ 0x3fd00000, 0x3fd00073, 0x3fd000db, 0x3fd0010d,
+ 0x3ff00000, 0x3ff000d2, 0x40100000, 0x401000c4,
+ 0x40200000, 0x4020004c, 0x40700000, 0x40800000,
+ 0x4085b000, 0x4085b0bb, 0x408eb000, 0x408eb0bb,
+ 0x40c00000, 0x40c000b4, 0x41200000, 0x41200112,
+ 0x41600000, 0x41600110, 0x41c00000, 0x41d00000,
+ // Entry 280 - 29F
+ 0x41e00000, 0x41f00000, 0x41f00073, 0x42200000,
+ 0x42300000, 0x42300165, 0x42900000, 0x42900063,
+ 0x42900070, 0x429000a5, 0x42900116, 0x43100000,
+ 0x43100027, 0x431000c3, 0x4310014e, 0x43200000,
+ 0x43220000, 0x43220033, 0x432200be, 0x43220106,
+ 0x4322014e, 0x4325b000, 0x4325b033, 0x4325b0be,
+ 0x4325b106, 0x4325b14e, 0x43700000, 0x43a00000,
+ 0x43b00000, 0x44400000, 0x44400031, 0x44400073,
+ // Entry 2A0 - 2BF
+ 0x4440010d, 0x44500000, 0x4450004b, 0x445000a5,
+ 0x44500130, 0x44500132, 0x44e00000, 0x45000000,
+ 0x4500009a, 0x450000b4, 0x450000d1, 0x4500010e,
+ 0x46100000, 0x4610009a, 0x46400000, 0x464000a5,
+ 0x46400132, 0x46700000, 0x46700125, 0x46b00000,
+ 0x46b00124, 0x46f00000, 0x46f0006e, 0x46f00070,
+ 0x47100000, 0x47600000, 0x47600128, 0x47a00000,
+ 0x48000000, 0x48200000, 0x4820012a, 0x48a00000,
+ // Entry 2C0 - 2DF
+ 0x48a0005e, 0x48a0012c, 0x48e00000, 0x49400000,
+ 0x49400107, 0x4a400000, 0x4a4000d5, 0x4a900000,
+ 0x4a9000bb, 0x4ac00000, 0x4ac00053, 0x4ae00000,
+ 0x4ae00131, 0x4b400000, 0x4b40009a, 0x4b4000e9,
+ 0x4bc00000, 0x4bc05000, 0x4bc05024, 0x4bc20000,
+ 0x4bc20138, 0x4bc5b000, 0x4bc5b138, 0x4be00000,
+ 0x4be5b000, 0x4be5b0b5, 0x4bef4000, 0x4bef40b5,
+ 0x4c000000, 0x4c300000, 0x4c30013f, 0x4c900000,
+ // Entry 2E0 - 2FF
+ 0x4c900001, 0x4cc00000, 0x4cc00130, 0x4ce00000,
+ 0x4cf00000, 0x4cf0004e, 0x4e500000, 0x4e500115,
+ 0x4f200000, 0x4fb00000, 0x4fb00132, 0x50900000,
+ 0x50900052, 0x51200000, 0x51200001, 0x51800000,
+ 0x5180003b, 0x518000d7, 0x51f00000, 0x51f3b000,
+ 0x51f3b053, 0x51f3c000, 0x51f3c08e, 0x52800000,
+ 0x528000bb, 0x52900000, 0x5293b000, 0x5293b053,
+ 0x5293b08e, 0x5293b0c7, 0x5293b10e, 0x5293c000,
+ // Entry 300 - 31F
+ 0x5293c08e, 0x5293c0c7, 0x5293c12f, 0x52f00000,
+ 0x52f00162,
+} // Size: 3116 bytes
+
+const specialTagsStr string = "ca-ES-valencia en-US-u-va-posix"
+
+// Total table size 3147 bytes (3KiB); checksum: 5A8FFFA5
diff --git a/vendor/golang.org/x/text/internal/language/compact/tags.go b/vendor/golang.org/x/text/internal/language/compact/tags.go
new file mode 100644
index 0000000..ca135d2
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/compact/tags.go
@@ -0,0 +1,91 @@
+// 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 compact
+
+var (
+ und = Tag{}
+
+ Und Tag = Tag{}
+
+ Afrikaans Tag = Tag{language: afIndex, locale: afIndex}
+ Amharic Tag = Tag{language: amIndex, locale: amIndex}
+ Arabic Tag = Tag{language: arIndex, locale: arIndex}
+ ModernStandardArabic Tag = Tag{language: ar001Index, locale: ar001Index}
+ Azerbaijani Tag = Tag{language: azIndex, locale: azIndex}
+ Bulgarian Tag = Tag{language: bgIndex, locale: bgIndex}
+ Bengali Tag = Tag{language: bnIndex, locale: bnIndex}
+ Catalan Tag = Tag{language: caIndex, locale: caIndex}
+ Czech Tag = Tag{language: csIndex, locale: csIndex}
+ Danish Tag = Tag{language: daIndex, locale: daIndex}
+ German Tag = Tag{language: deIndex, locale: deIndex}
+ Greek Tag = Tag{language: elIndex, locale: elIndex}
+ English Tag = Tag{language: enIndex, locale: enIndex}
+ AmericanEnglish Tag = Tag{language: enUSIndex, locale: enUSIndex}
+ BritishEnglish Tag = Tag{language: enGBIndex, locale: enGBIndex}
+ Spanish Tag = Tag{language: esIndex, locale: esIndex}
+ EuropeanSpanish Tag = Tag{language: esESIndex, locale: esESIndex}
+ LatinAmericanSpanish Tag = Tag{language: es419Index, locale: es419Index}
+ Estonian Tag = Tag{language: etIndex, locale: etIndex}
+ Persian Tag = Tag{language: faIndex, locale: faIndex}
+ Finnish Tag = Tag{language: fiIndex, locale: fiIndex}
+ Filipino Tag = Tag{language: filIndex, locale: filIndex}
+ French Tag = Tag{language: frIndex, locale: frIndex}
+ CanadianFrench Tag = Tag{language: frCAIndex, locale: frCAIndex}
+ Gujarati Tag = Tag{language: guIndex, locale: guIndex}
+ Hebrew Tag = Tag{language: heIndex, locale: heIndex}
+ Hindi Tag = Tag{language: hiIndex, locale: hiIndex}
+ Croatian Tag = Tag{language: hrIndex, locale: hrIndex}
+ Hungarian Tag = Tag{language: huIndex, locale: huIndex}
+ Armenian Tag = Tag{language: hyIndex, locale: hyIndex}
+ Indonesian Tag = Tag{language: idIndex, locale: idIndex}
+ Icelandic Tag = Tag{language: isIndex, locale: isIndex}
+ Italian Tag = Tag{language: itIndex, locale: itIndex}
+ Japanese Tag = Tag{language: jaIndex, locale: jaIndex}
+ Georgian Tag = Tag{language: kaIndex, locale: kaIndex}
+ Kazakh Tag = Tag{language: kkIndex, locale: kkIndex}
+ Khmer Tag = Tag{language: kmIndex, locale: kmIndex}
+ Kannada Tag = Tag{language: knIndex, locale: knIndex}
+ Korean Tag = Tag{language: koIndex, locale: koIndex}
+ Kirghiz Tag = Tag{language: kyIndex, locale: kyIndex}
+ Lao Tag = Tag{language: loIndex, locale: loIndex}
+ Lithuanian Tag = Tag{language: ltIndex, locale: ltIndex}
+ Latvian Tag = Tag{language: lvIndex, locale: lvIndex}
+ Macedonian Tag = Tag{language: mkIndex, locale: mkIndex}
+ Malayalam Tag = Tag{language: mlIndex, locale: mlIndex}
+ Mongolian Tag = Tag{language: mnIndex, locale: mnIndex}
+ Marathi Tag = Tag{language: mrIndex, locale: mrIndex}
+ Malay Tag = Tag{language: msIndex, locale: msIndex}
+ Burmese Tag = Tag{language: myIndex, locale: myIndex}
+ Nepali Tag = Tag{language: neIndex, locale: neIndex}
+ Dutch Tag = Tag{language: nlIndex, locale: nlIndex}
+ Norwegian Tag = Tag{language: noIndex, locale: noIndex}
+ Punjabi Tag = Tag{language: paIndex, locale: paIndex}
+ Polish Tag = Tag{language: plIndex, locale: plIndex}
+ Portuguese Tag = Tag{language: ptIndex, locale: ptIndex}
+ BrazilianPortuguese Tag = Tag{language: ptBRIndex, locale: ptBRIndex}
+ EuropeanPortuguese Tag = Tag{language: ptPTIndex, locale: ptPTIndex}
+ Romanian Tag = Tag{language: roIndex, locale: roIndex}
+ Russian Tag = Tag{language: ruIndex, locale: ruIndex}
+ Sinhala Tag = Tag{language: siIndex, locale: siIndex}
+ Slovak Tag = Tag{language: skIndex, locale: skIndex}
+ Slovenian Tag = Tag{language: slIndex, locale: slIndex}
+ Albanian Tag = Tag{language: sqIndex, locale: sqIndex}
+ Serbian Tag = Tag{language: srIndex, locale: srIndex}
+ SerbianLatin Tag = Tag{language: srLatnIndex, locale: srLatnIndex}
+ Swedish Tag = Tag{language: svIndex, locale: svIndex}
+ Swahili Tag = Tag{language: swIndex, locale: swIndex}
+ Tamil Tag = Tag{language: taIndex, locale: taIndex}
+ Telugu Tag = Tag{language: teIndex, locale: teIndex}
+ Thai Tag = Tag{language: thIndex, locale: thIndex}
+ Turkish Tag = Tag{language: trIndex, locale: trIndex}
+ Ukrainian Tag = Tag{language: ukIndex, locale: ukIndex}
+ Urdu Tag = Tag{language: urIndex, locale: urIndex}
+ Uzbek Tag = Tag{language: uzIndex, locale: uzIndex}
+ Vietnamese Tag = Tag{language: viIndex, locale: viIndex}
+ Chinese Tag = Tag{language: zhIndex, locale: zhIndex}
+ SimplifiedChinese Tag = Tag{language: zhHansIndex, locale: zhHansIndex}
+ TraditionalChinese Tag = Tag{language: zhHantIndex, locale: zhHantIndex}
+ Zulu Tag = Tag{language: zuIndex, locale: zuIndex}
+)
diff --git a/vendor/golang.org/x/text/internal/language/compose.go b/vendor/golang.org/x/text/internal/language/compose.go
new file mode 100644
index 0000000..4ae78e0
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/compose.go
@@ -0,0 +1,167 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package language
+
+import (
+ "sort"
+ "strings"
+)
+
+// A Builder allows constructing a Tag from individual components.
+// Its main user is Compose in the top-level language package.
+type Builder struct {
+ Tag Tag
+
+ private string // the x extension
+ variants []string
+ extensions []string
+}
+
+// Make returns a new Tag from the current settings.
+func (b *Builder) Make() Tag {
+ t := b.Tag
+
+ if len(b.extensions) > 0 || len(b.variants) > 0 {
+ sort.Sort(sortVariants(b.variants))
+ sort.Strings(b.extensions)
+
+ if b.private != "" {
+ b.extensions = append(b.extensions, b.private)
+ }
+ n := maxCoreSize + tokenLen(b.variants...) + tokenLen(b.extensions...)
+ buf := make([]byte, n)
+ p := t.genCoreBytes(buf)
+ t.pVariant = byte(p)
+ p += appendTokens(buf[p:], b.variants...)
+ t.pExt = uint16(p)
+ p += appendTokens(buf[p:], b.extensions...)
+ t.str = string(buf[:p])
+ // We may not always need to remake the string, but when or when not
+ // to do so is rather tricky.
+ scan := makeScanner(buf[:p])
+ t, _ = parse(&scan, "")
+ return t
+
+ } else if b.private != "" {
+ t.str = b.private
+ t.RemakeString()
+ }
+ return t
+}
+
+// SetTag copies all the settings from a given Tag. Any previously set values
+// are discarded.
+func (b *Builder) SetTag(t Tag) {
+ b.Tag.LangID = t.LangID
+ b.Tag.RegionID = t.RegionID
+ b.Tag.ScriptID = t.ScriptID
+ // TODO: optimize
+ b.variants = b.variants[:0]
+ if variants := t.Variants(); variants != "" {
+ for _, vr := range strings.Split(variants[1:], "-") {
+ b.variants = append(b.variants, vr)
+ }
+ }
+ b.extensions, b.private = b.extensions[:0], ""
+ for _, e := range t.Extensions() {
+ b.AddExt(e)
+ }
+}
+
+// AddExt adds extension e to the tag. e must be a valid extension as returned
+// by Tag.Extension. If the extension already exists, it will be discarded,
+// except for a -u extension, where non-existing key-type pairs will added.
+func (b *Builder) AddExt(e string) {
+ if e[0] == 'x' {
+ if b.private == "" {
+ b.private = e
+ }
+ return
+ }
+ for i, s := range b.extensions {
+ if s[0] == e[0] {
+ if e[0] == 'u' {
+ b.extensions[i] += e[1:]
+ }
+ return
+ }
+ }
+ b.extensions = append(b.extensions, e)
+}
+
+// SetExt sets the extension e to the tag. e must be a valid extension as
+// returned by Tag.Extension. If the extension already exists, it will be
+// overwritten, except for a -u extension, where the individual key-type pairs
+// will be set.
+func (b *Builder) SetExt(e string) {
+ if e[0] == 'x' {
+ b.private = e
+ return
+ }
+ for i, s := range b.extensions {
+ if s[0] == e[0] {
+ if e[0] == 'u' {
+ b.extensions[i] = e + s[1:]
+ } else {
+ b.extensions[i] = e
+ }
+ return
+ }
+ }
+ b.extensions = append(b.extensions, e)
+}
+
+// AddVariant adds any number of variants.
+func (b *Builder) AddVariant(v ...string) {
+ for _, v := range v {
+ if v != "" {
+ b.variants = append(b.variants, v)
+ }
+ }
+}
+
+// ClearVariants removes any variants previously added, including those
+// copied from a Tag in SetTag.
+func (b *Builder) ClearVariants() {
+ b.variants = b.variants[:0]
+}
+
+// ClearExtensions removes any extensions previously added, including those
+// copied from a Tag in SetTag.
+func (b *Builder) ClearExtensions() {
+ b.private = ""
+ b.extensions = b.extensions[:0]
+}
+
+func tokenLen(token ...string) (n int) {
+ for _, t := range token {
+ n += len(t) + 1
+ }
+ return
+}
+
+func appendTokens(b []byte, token ...string) int {
+ p := 0
+ for _, t := range token {
+ b[p] = '-'
+ copy(b[p+1:], t)
+ p += 1 + len(t)
+ }
+ return p
+}
+
+type sortVariants []string
+
+func (s sortVariants) Len() int {
+ return len(s)
+}
+
+func (s sortVariants) Swap(i, j int) {
+ s[j], s[i] = s[i], s[j]
+}
+
+func (s sortVariants) Less(i, j int) bool {
+ return variantIndex[s[i]] < variantIndex[s[j]]
+}
diff --git a/vendor/golang.org/x/text/internal/language/coverage.go b/vendor/golang.org/x/text/internal/language/coverage.go
new file mode 100644
index 0000000..9b20b88
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/coverage.go
@@ -0,0 +1,28 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package language
+
+// BaseLanguages returns the list of all supported base languages. It generates
+// the list by traversing the internal structures.
+func BaseLanguages() []Language {
+ base := make([]Language, 0, NumLanguages)
+ for i := 0; i < langNoIndexOffset; i++ {
+ // We included "und" already for the value 0.
+ if i != nonCanonicalUnd {
+ base = append(base, Language(i))
+ }
+ }
+ i := langNoIndexOffset
+ for _, v := range langNoIndex {
+ for k := 0; k < 8; k++ {
+ if v&1 == 1 {
+ base = append(base, Language(i))
+ }
+ v >>= 1
+ i++
+ }
+ }
+ return base
+}
diff --git a/vendor/golang.org/x/text/internal/language/language.go b/vendor/golang.org/x/text/internal/language/language.go
new file mode 100644
index 0000000..09d41c7
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/language.go
@@ -0,0 +1,627 @@
+// 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 gen.go gen_common.go -output tables.go
+
+package language // import "golang.org/x/text/internal/language"
+
+// TODO: Remove above NOTE after:
+// - verifying that tables are dropped correctly (most notably matcher tables).
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+)
+
+const (
+ // maxCoreSize is the maximum size of a BCP 47 tag without variants and
+ // extensions. Equals max lang (3) + script (4) + max reg (3) + 2 dashes.
+ maxCoreSize = 12
+
+ // max99thPercentileSize is a somewhat arbitrary buffer size that presumably
+ // is large enough to hold at least 99% of the BCP 47 tags.
+ max99thPercentileSize = 32
+
+ // maxSimpleUExtensionSize is the maximum size of a -u extension with one
+ // key-type pair. Equals len("-u-") + key (2) + dash + max value (8).
+ maxSimpleUExtensionSize = 14
+)
+
+// Tag represents a BCP 47 language tag. It is used to specify an instance of a
+// specific language or locale. All language tag values are guaranteed to be
+// well-formed. The zero value of Tag is Und.
+type Tag struct {
+ // TODO: the following fields have the form TagTypeID. This name is chosen
+ // to allow refactoring the public package without conflicting with its
+ // Base, Script, and Region methods. Once the transition is fully completed
+ // the ID can be stripped from the name.
+
+ LangID Language
+ RegionID Region
+ // TODO: we will soon run out of positions for ScriptID. Idea: instead of
+ // storing lang, region, and ScriptID codes, store only the compact index and
+ // have a lookup table from this code to its expansion. This greatly speeds
+ // up table lookup, speed up common variant cases.
+ // This will also immediately free up 3 extra bytes. Also, the pVariant
+ // field can now be moved to the lookup table, as the compact index uniquely
+ // determines the offset of a possible variant.
+ ScriptID Script
+ pVariant byte // offset in str, includes preceding '-'
+ pExt uint16 // offset of first extension, includes preceding '-'
+
+ // str is the string representation of the Tag. It will only be used if the
+ // tag has variants or extensions.
+ str string
+}
+
+// Make is a convenience wrapper for Parse that omits the error.
+// In case of an error, a sensible default is returned.
+func Make(s string) Tag {
+ t, _ := Parse(s)
+ return t
+}
+
+// Raw returns the raw base language, script and region, without making an
+// attempt to infer their values.
+// TODO: consider removing
+func (t Tag) Raw() (b Language, s Script, r Region) {
+ return t.LangID, t.ScriptID, t.RegionID
+}
+
+// equalTags compares language, script and region subtags only.
+func (t Tag) equalTags(a Tag) bool {
+ return t.LangID == a.LangID && t.ScriptID == a.ScriptID && t.RegionID == a.RegionID
+}
+
+// IsRoot returns true if t is equal to language "und".
+func (t Tag) IsRoot() bool {
+ if int(t.pVariant) < len(t.str) {
+ return false
+ }
+ return t.equalTags(Und)
+}
+
+// IsPrivateUse reports whether the Tag consists solely of an IsPrivateUse use
+// tag.
+func (t Tag) IsPrivateUse() bool {
+ return t.str != "" && t.pVariant == 0
+}
+
+// RemakeString is used to update t.str in case lang, script or region changed.
+// It is assumed that pExt and pVariant still point to the start of the
+// respective parts.
+func (t *Tag) RemakeString() {
+ if t.str == "" {
+ return
+ }
+ extra := t.str[t.pVariant:]
+ if t.pVariant > 0 {
+ extra = extra[1:]
+ }
+ if t.equalTags(Und) && strings.HasPrefix(extra, "x-") {
+ t.str = extra
+ t.pVariant = 0
+ t.pExt = 0
+ return
+ }
+ var buf [max99thPercentileSize]byte // avoid extra memory allocation in most cases.
+ b := buf[:t.genCoreBytes(buf[:])]
+ if extra != "" {
+ diff := len(b) - int(t.pVariant)
+ b = append(b, '-')
+ b = append(b, extra...)
+ t.pVariant = uint8(int(t.pVariant) + diff)
+ t.pExt = uint16(int(t.pExt) + diff)
+ } else {
+ t.pVariant = uint8(len(b))
+ t.pExt = uint16(len(b))
+ }
+ t.str = string(b)
+}
+
+// genCoreBytes writes a string for the base languages, script and region tags
+// to the given buffer and returns the number of bytes written. It will never
+// write more than maxCoreSize bytes.
+func (t *Tag) genCoreBytes(buf []byte) int {
+ n := t.LangID.StringToBuf(buf[:])
+ if t.ScriptID != 0 {
+ n += copy(buf[n:], "-")
+ n += copy(buf[n:], t.ScriptID.String())
+ }
+ if t.RegionID != 0 {
+ n += copy(buf[n:], "-")
+ n += copy(buf[n:], t.RegionID.String())
+ }
+ return n
+}
+
+// String returns the canonical string representation of the language tag.
+func (t Tag) String() string {
+ if t.str != "" {
+ return t.str
+ }
+ if t.ScriptID == 0 && t.RegionID == 0 {
+ return t.LangID.String()
+ }
+ buf := [maxCoreSize]byte{}
+ return string(buf[:t.genCoreBytes(buf[:])])
+}
+
+// MarshalText implements encoding.TextMarshaler.
+func (t Tag) MarshalText() (text []byte, err error) {
+ if t.str != "" {
+ text = append(text, t.str...)
+ } else if t.ScriptID == 0 && t.RegionID == 0 {
+ text = append(text, t.LangID.String()...)
+ } else {
+ buf := [maxCoreSize]byte{}
+ text = buf[:t.genCoreBytes(buf[:])]
+ }
+ return text, nil
+}
+
+// UnmarshalText implements encoding.TextUnmarshaler.
+func (t *Tag) UnmarshalText(text []byte) error {
+ tag, err := Parse(string(text))
+ *t = tag
+ return err
+}
+
+// Variants returns the part of the tag holding all variants or the empty string
+// if there are no variants defined.
+func (t Tag) Variants() string {
+ if t.pVariant == 0 {
+ return ""
+ }
+ return t.str[t.pVariant:t.pExt]
+}
+
+// VariantOrPrivateUseTags returns variants or private use tags.
+func (t Tag) VariantOrPrivateUseTags() string {
+ if t.pExt > 0 {
+ return t.str[t.pVariant:t.pExt]
+ }
+ return t.str[t.pVariant:]
+}
+
+// HasString reports whether this tag defines more than just the raw
+// components.
+func (t Tag) HasString() bool {
+ return t.str != ""
+}
+
+// Parent returns the CLDR parent of t. In CLDR, missing fields in data for a
+// specific language are substituted with fields from the parent language.
+// The parent for a language may change for newer versions of CLDR.
+func (t Tag) Parent() Tag {
+ if t.str != "" {
+ // Strip the variants and extensions.
+ b, s, r := t.Raw()
+ t = Tag{LangID: b, ScriptID: s, RegionID: r}
+ if t.RegionID == 0 && t.ScriptID != 0 && t.LangID != 0 {
+ base, _ := addTags(Tag{LangID: t.LangID})
+ if base.ScriptID == t.ScriptID {
+ return Tag{LangID: t.LangID}
+ }
+ }
+ return t
+ }
+ if t.LangID != 0 {
+ if t.RegionID != 0 {
+ maxScript := t.ScriptID
+ if maxScript == 0 {
+ max, _ := addTags(t)
+ maxScript = max.ScriptID
+ }
+
+ for i := range parents {
+ if Language(parents[i].lang) == t.LangID && Script(parents[i].maxScript) == maxScript {
+ for _, r := range parents[i].fromRegion {
+ if Region(r) == t.RegionID {
+ return Tag{
+ LangID: t.LangID,
+ ScriptID: Script(parents[i].script),
+ RegionID: Region(parents[i].toRegion),
+ }
+ }
+ }
+ }
+ }
+
+ // Strip the script if it is the default one.
+ base, _ := addTags(Tag{LangID: t.LangID})
+ if base.ScriptID != maxScript {
+ return Tag{LangID: t.LangID, ScriptID: maxScript}
+ }
+ return Tag{LangID: t.LangID}
+ } else if t.ScriptID != 0 {
+ // The parent for an base-script pair with a non-default script is
+ // "und" instead of the base language.
+ base, _ := addTags(Tag{LangID: t.LangID})
+ if base.ScriptID != t.ScriptID {
+ return Und
+ }
+ return Tag{LangID: t.LangID}
+ }
+ }
+ return Und
+}
+
+// ParseExtension parses s as an extension and returns it on success.
+func ParseExtension(s string) (ext string, err error) {
+ defer func() {
+ if recover() != nil {
+ ext = ""
+ err = ErrSyntax
+ }
+ }()
+
+ scan := makeScannerString(s)
+ var end int
+ if n := len(scan.token); n != 1 {
+ return "", ErrSyntax
+ }
+ scan.toLower(0, len(scan.b))
+ end = parseExtension(&scan)
+ if end != len(s) {
+ return "", ErrSyntax
+ }
+ return string(scan.b), nil
+}
+
+// HasVariants reports whether t has variants.
+func (t Tag) HasVariants() bool {
+ return uint16(t.pVariant) < t.pExt
+}
+
+// HasExtensions reports whether t has extensions.
+func (t Tag) HasExtensions() bool {
+ return int(t.pExt) < len(t.str)
+}
+
+// Extension returns the extension of type x for tag t. It will return
+// false for ok if t does not have the requested extension. The returned
+// extension will be invalid in this case.
+func (t Tag) Extension(x byte) (ext string, ok bool) {
+ for i := int(t.pExt); i < len(t.str)-1; {
+ var ext string
+ i, ext = getExtension(t.str, i)
+ if ext[0] == x {
+ return ext, true
+ }
+ }
+ return "", false
+}
+
+// Extensions returns all extensions of t.
+func (t Tag) Extensions() []string {
+ e := []string{}
+ for i := int(t.pExt); i < len(t.str)-1; {
+ var ext string
+ i, ext = getExtension(t.str, i)
+ e = append(e, ext)
+ }
+ return e
+}
+
+// TypeForKey returns the type associated with the given key, where key and type
+// are of the allowed values defined for the Unicode locale extension ('u') in
+// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers.
+// TypeForKey will traverse the inheritance chain to get the correct value.
+//
+// If there are multiple types associated with a key, only the first will be
+// returned. If there is no type associated with a key, it returns the empty
+// string.
+func (t Tag) TypeForKey(key string) string {
+ if _, start, end, _ := t.findTypeForKey(key); end != start {
+ s := t.str[start:end]
+ if p := strings.IndexByte(s, '-'); p >= 0 {
+ s = s[:p]
+ }
+ return s
+ }
+ return ""
+}
+
+var (
+ errPrivateUse = errors.New("cannot set a key on a private use tag")
+ errInvalidArguments = errors.New("invalid key or type")
+)
+
+// SetTypeForKey returns a new Tag with the key set to type, where key and type
+// are of the allowed values defined for the Unicode locale extension ('u') in
+// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers.
+// An empty value removes an existing pair with the same key.
+func (t Tag) SetTypeForKey(key, value string) (Tag, error) {
+ if t.IsPrivateUse() {
+ return t, errPrivateUse
+ }
+ if len(key) != 2 {
+ return t, errInvalidArguments
+ }
+
+ // Remove the setting if value is "".
+ if value == "" {
+ start, sep, end, _ := t.findTypeForKey(key)
+ if start != sep {
+ // Remove a possible empty extension.
+ switch {
+ case t.str[start-2] != '-': // has previous elements.
+ case end == len(t.str), // end of string
+ end+2 < len(t.str) && t.str[end+2] == '-': // end of extension
+ start -= 2
+ }
+ if start == int(t.pVariant) && end == len(t.str) {
+ t.str = ""
+ t.pVariant, t.pExt = 0, 0
+ } else {
+ t.str = fmt.Sprintf("%s%s", t.str[:start], t.str[end:])
+ }
+ }
+ return t, nil
+ }
+
+ if len(value) < 3 || len(value) > 8 {
+ return t, errInvalidArguments
+ }
+
+ var (
+ buf [maxCoreSize + maxSimpleUExtensionSize]byte
+ uStart int // start of the -u extension.
+ )
+
+ // Generate the tag string if needed.
+ if t.str == "" {
+ uStart = t.genCoreBytes(buf[:])
+ buf[uStart] = '-'
+ uStart++
+ }
+
+ // Create new key-type pair and parse it to verify.
+ b := buf[uStart:]
+ copy(b, "u-")
+ copy(b[2:], key)
+ b[4] = '-'
+ b = b[:5+copy(b[5:], value)]
+ scan := makeScanner(b)
+ if parseExtensions(&scan); scan.err != nil {
+ return t, scan.err
+ }
+
+ // Assemble the replacement string.
+ if t.str == "" {
+ t.pVariant, t.pExt = byte(uStart-1), uint16(uStart-1)
+ t.str = string(buf[:uStart+len(b)])
+ } else {
+ s := t.str
+ start, sep, end, hasExt := t.findTypeForKey(key)
+ if start == sep {
+ if hasExt {
+ b = b[2:]
+ }
+ t.str = fmt.Sprintf("%s-%s%s", s[:sep], b, s[end:])
+ } else {
+ t.str = fmt.Sprintf("%s-%s%s", s[:start+3], value, s[end:])
+ }
+ }
+ return t, nil
+}
+
+// findTypeForKey returns the start and end position for the type corresponding
+// to key or the point at which to insert the key-value pair if the type
+// wasn't found. The hasExt return value reports whether an -u extension was present.
+// Note: the extensions are typically very small and are likely to contain
+// only one key-type pair.
+func (t Tag) findTypeForKey(key string) (start, sep, end int, hasExt bool) {
+ p := int(t.pExt)
+ if len(key) != 2 || p == len(t.str) || p == 0 {
+ return p, p, p, false
+ }
+ s := t.str
+
+ // Find the correct extension.
+ for p++; s[p] != 'u'; p++ {
+ if s[p] > 'u' {
+ p--
+ return p, p, p, false
+ }
+ if p = nextExtension(s, p); p == len(s) {
+ return len(s), len(s), len(s), false
+ }
+ }
+ // Proceed to the hyphen following the extension name.
+ p++
+
+ // curKey is the key currently being processed.
+ curKey := ""
+
+ // Iterate over keys until we get the end of a section.
+ for {
+ end = p
+ for p++; p < len(s) && s[p] != '-'; p++ {
+ }
+ n := p - end - 1
+ if n <= 2 && curKey == key {
+ if sep < end {
+ sep++
+ }
+ return start, sep, end, true
+ }
+ switch n {
+ case 0, // invalid string
+ 1: // next extension
+ return end, end, end, true
+ case 2:
+ // next key
+ curKey = s[end+1 : p]
+ if curKey > key {
+ return end, end, end, true
+ }
+ start = end
+ sep = p
+ }
+ }
+}
+
+// ParseBase parses a 2- or 3-letter ISO 639 code.
+// It returns a ValueError if s is a well-formed but unknown language identifier
+// or another error if another error occurred.
+func ParseBase(s string) (l Language, err error) {
+ defer func() {
+ if recover() != nil {
+ l = 0
+ err = ErrSyntax
+ }
+ }()
+
+ if n := len(s); n < 2 || 3 < n {
+ return 0, ErrSyntax
+ }
+ var buf [3]byte
+ return getLangID(buf[:copy(buf[:], s)])
+}
+
+// ParseScript parses a 4-letter ISO 15924 code.
+// It returns a ValueError if s is a well-formed but unknown script identifier
+// or another error if another error occurred.
+func ParseScript(s string) (scr Script, err error) {
+ defer func() {
+ if recover() != nil {
+ scr = 0
+ err = ErrSyntax
+ }
+ }()
+
+ if len(s) != 4 {
+ return 0, ErrSyntax
+ }
+ var buf [4]byte
+ return getScriptID(script, buf[:copy(buf[:], s)])
+}
+
+// EncodeM49 returns the Region for the given UN M.49 code.
+// It returns an error if r is not a valid code.
+func EncodeM49(r int) (Region, error) {
+ return getRegionM49(r)
+}
+
+// ParseRegion parses a 2- or 3-letter ISO 3166-1 or a UN M.49 code.
+// It returns a ValueError if s is a well-formed but unknown region identifier
+// or another error if another error occurred.
+func ParseRegion(s string) (r Region, err error) {
+ defer func() {
+ if recover() != nil {
+ r = 0
+ err = ErrSyntax
+ }
+ }()
+
+ if n := len(s); n < 2 || 3 < n {
+ return 0, ErrSyntax
+ }
+ var buf [3]byte
+ return getRegionID(buf[:copy(buf[:], s)])
+}
+
+// IsCountry returns whether this region is a country or autonomous area. This
+// includes non-standard definitions from CLDR.
+func (r Region) IsCountry() bool {
+ if r == 0 || r.IsGroup() || r.IsPrivateUse() && r != _XK {
+ return false
+ }
+ return true
+}
+
+// IsGroup returns whether this region defines a collection of regions. This
+// includes non-standard definitions from CLDR.
+func (r Region) IsGroup() bool {
+ if r == 0 {
+ return false
+ }
+ return int(regionInclusion[r]) < len(regionContainment)
+}
+
+// Contains returns whether Region c is contained by Region r. It returns true
+// if c == r.
+func (r Region) Contains(c Region) bool {
+ if r == c {
+ return true
+ }
+ g := regionInclusion[r]
+ if g >= nRegionGroups {
+ return false
+ }
+ m := regionContainment[g]
+
+ d := regionInclusion[c]
+ b := regionInclusionBits[d]
+
+ // A contained country may belong to multiple disjoint groups. Matching any
+ // of these indicates containment. If the contained region is a group, it
+ // must strictly be a subset.
+ if d >= nRegionGroups {
+ return b&m != 0
+ }
+ return b&^m == 0
+}
+
+var errNoTLD = errors.New("language: region is not a valid ccTLD")
+
+// TLD returns the country code top-level domain (ccTLD). UK is returned for GB.
+// In all other cases it returns either the region itself or an error.
+//
+// This method may return an error for a region for which there exists a
+// canonical form with a ccTLD. To get that ccTLD canonicalize r first. The
+// region will already be canonicalized it was obtained from a Tag that was
+// obtained using any of the default methods.
+func (r Region) TLD() (Region, error) {
+ // See http://en.wikipedia.org/wiki/Country_code_top-level_domain for the
+ // difference between ISO 3166-1 and IANA ccTLD.
+ if r == _GB {
+ r = _UK
+ }
+ if (r.typ() & ccTLD) == 0 {
+ return 0, errNoTLD
+ }
+ return r, nil
+}
+
+// Canonicalize returns the region or a possible replacement if the region is
+// deprecated. It will not return a replacement for deprecated regions that
+// are split into multiple regions.
+func (r Region) Canonicalize() Region {
+ if cr := normRegion(r); cr != 0 {
+ return cr
+ }
+ return r
+}
+
+// Variant represents a registered variant of a language as defined by BCP 47.
+type Variant struct {
+ ID uint8
+ str string
+}
+
+// ParseVariant parses and returns a Variant. An error is returned if s is not
+// a valid variant.
+func ParseVariant(s string) (v Variant, err error) {
+ defer func() {
+ if recover() != nil {
+ v = Variant{}
+ err = ErrSyntax
+ }
+ }()
+
+ s = strings.ToLower(s)
+ if id, ok := variantIndex[s]; ok {
+ return Variant{id, s}, nil
+ }
+ return Variant{}, NewValueError([]byte(s))
+}
+
+// String returns the string representation of the variant.
+func (v Variant) String() string {
+ return v.str
+}
diff --git a/vendor/golang.org/x/text/internal/language/lookup.go b/vendor/golang.org/x/text/internal/language/lookup.go
new file mode 100644
index 0000000..231b4fb
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/lookup.go
@@ -0,0 +1,412 @@
+// 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 language
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+ "strconv"
+
+ "golang.org/x/text/internal/tag"
+)
+
+// findIndex tries to find the given tag in idx and returns a standardized error
+// if it could not be found.
+func findIndex(idx tag.Index, key []byte, form string) (index int, err error) {
+ if !tag.FixCase(form, key) {
+ return 0, ErrSyntax
+ }
+ i := idx.Index(key)
+ if i == -1 {
+ return 0, NewValueError(key)
+ }
+ return i, nil
+}
+
+func searchUint(imap []uint16, key uint16) int {
+ return sort.Search(len(imap), func(i int) bool {
+ return imap[i] >= key
+ })
+}
+
+type Language uint16
+
+// getLangID returns the langID of s if s is a canonical subtag
+// or langUnknown if s is not a canonical subtag.
+func getLangID(s []byte) (Language, error) {
+ if len(s) == 2 {
+ return getLangISO2(s)
+ }
+ return getLangISO3(s)
+}
+
+// TODO language normalization as well as the AliasMaps could be moved to the
+// higher level package, but it is a bit tricky to separate the generation.
+
+func (id Language) Canonicalize() (Language, AliasType) {
+ return normLang(id)
+}
+
+// normLang returns the mapped langID of id according to mapping m.
+func normLang(id Language) (Language, AliasType) {
+ k := sort.Search(len(AliasMap), func(i int) bool {
+ return AliasMap[i].From >= uint16(id)
+ })
+ if k < len(AliasMap) && AliasMap[k].From == uint16(id) {
+ return Language(AliasMap[k].To), AliasTypes[k]
+ }
+ return id, AliasTypeUnknown
+}
+
+// getLangISO2 returns the langID for the given 2-letter ISO language code
+// or unknownLang if this does not exist.
+func getLangISO2(s []byte) (Language, error) {
+ if !tag.FixCase("zz", s) {
+ return 0, ErrSyntax
+ }
+ if i := lang.Index(s); i != -1 && lang.Elem(i)[3] != 0 {
+ return Language(i), nil
+ }
+ return 0, NewValueError(s)
+}
+
+const base = 'z' - 'a' + 1
+
+func strToInt(s []byte) uint {
+ v := uint(0)
+ for i := 0; i < len(s); i++ {
+ v *= base
+ v += uint(s[i] - 'a')
+ }
+ return v
+}
+
+// converts the given integer to the original ASCII string passed to strToInt.
+// len(s) must match the number of characters obtained.
+func intToStr(v uint, s []byte) {
+ for i := len(s) - 1; i >= 0; i-- {
+ s[i] = byte(v%base) + 'a'
+ v /= base
+ }
+}
+
+// getLangISO3 returns the langID for the given 3-letter ISO language code
+// or unknownLang if this does not exist.
+func getLangISO3(s []byte) (Language, error) {
+ if tag.FixCase("und", s) {
+ // first try to match canonical 3-letter entries
+ for i := lang.Index(s[:2]); i != -1; i = lang.Next(s[:2], i) {
+ if e := lang.Elem(i); e[3] == 0 && e[2] == s[2] {
+ // We treat "und" as special and always translate it to "unspecified".
+ // Note that ZZ and Zzzz are private use and are not treated as
+ // unspecified by default.
+ id := Language(i)
+ if id == nonCanonicalUnd {
+ return 0, nil
+ }
+ return id, nil
+ }
+ }
+ if i := altLangISO3.Index(s); i != -1 {
+ return Language(altLangIndex[altLangISO3.Elem(i)[3]]), nil
+ }
+ n := strToInt(s)
+ if langNoIndex[n/8]&(1<<(n%8)) != 0 {
+ return Language(n) + langNoIndexOffset, nil
+ }
+ // Check for non-canonical uses of ISO3.
+ for i := lang.Index(s[:1]); i != -1; i = lang.Next(s[:1], i) {
+ if e := lang.Elem(i); e[2] == s[1] && e[3] == s[2] {
+ return Language(i), nil
+ }
+ }
+ return 0, NewValueError(s)
+ }
+ return 0, ErrSyntax
+}
+
+// StringToBuf writes the string to b and returns the number of bytes
+// written. cap(b) must be >= 3.
+func (id Language) StringToBuf(b []byte) int {
+ if id >= langNoIndexOffset {
+ intToStr(uint(id)-langNoIndexOffset, b[:3])
+ return 3
+ } else if id == 0 {
+ return copy(b, "und")
+ }
+ l := lang[id<<2:]
+ if l[3] == 0 {
+ return copy(b, l[:3])
+ }
+ return copy(b, l[:2])
+}
+
+// String returns the BCP 47 representation of the langID.
+// Use b as variable name, instead of id, to ensure the variable
+// used is consistent with that of Base in which this type is embedded.
+func (b Language) String() string {
+ if b == 0 {
+ return "und"
+ } else if b >= langNoIndexOffset {
+ b -= langNoIndexOffset
+ buf := [3]byte{}
+ intToStr(uint(b), buf[:])
+ return string(buf[:])
+ }
+ l := lang.Elem(int(b))
+ if l[3] == 0 {
+ return l[:3]
+ }
+ return l[:2]
+}
+
+// ISO3 returns the ISO 639-3 language code.
+func (b Language) ISO3() string {
+ if b == 0 || b >= langNoIndexOffset {
+ return b.String()
+ }
+ l := lang.Elem(int(b))
+ if l[3] == 0 {
+ return l[:3]
+ } else if l[2] == 0 {
+ return altLangISO3.Elem(int(l[3]))[:3]
+ }
+ // This allocation will only happen for 3-letter ISO codes
+ // that are non-canonical BCP 47 language identifiers.
+ return l[0:1] + l[2:4]
+}
+
+// IsPrivateUse reports whether this language code is reserved for private use.
+func (b Language) IsPrivateUse() bool {
+ return langPrivateStart <= b && b <= langPrivateEnd
+}
+
+// SuppressScript returns the script marked as SuppressScript in the IANA
+// language tag repository, or 0 if there is no such script.
+func (b Language) SuppressScript() Script {
+ if b < langNoIndexOffset {
+ return Script(suppressScript[b])
+ }
+ return 0
+}
+
+type Region uint16
+
+// getRegionID returns the region id for s if s is a valid 2-letter region code
+// or unknownRegion.
+func getRegionID(s []byte) (Region, error) {
+ if len(s) == 3 {
+ if isAlpha(s[0]) {
+ return getRegionISO3(s)
+ }
+ if i, err := strconv.ParseUint(string(s), 10, 10); err == nil {
+ return getRegionM49(int(i))
+ }
+ }
+ return getRegionISO2(s)
+}
+
+// getRegionISO2 returns the regionID for the given 2-letter ISO country code
+// or unknownRegion if this does not exist.
+func getRegionISO2(s []byte) (Region, error) {
+ i, err := findIndex(regionISO, s, "ZZ")
+ if err != nil {
+ return 0, err
+ }
+ return Region(i) + isoRegionOffset, nil
+}
+
+// getRegionISO3 returns the regionID for the given 3-letter ISO country code
+// or unknownRegion if this does not exist.
+func getRegionISO3(s []byte) (Region, error) {
+ if tag.FixCase("ZZZ", s) {
+ for i := regionISO.Index(s[:1]); i != -1; i = regionISO.Next(s[:1], i) {
+ if e := regionISO.Elem(i); e[2] == s[1] && e[3] == s[2] {
+ return Region(i) + isoRegionOffset, nil
+ }
+ }
+ for i := 0; i < len(altRegionISO3); i += 3 {
+ if tag.Compare(altRegionISO3[i:i+3], s) == 0 {
+ return Region(altRegionIDs[i/3]), nil
+ }
+ }
+ return 0, NewValueError(s)
+ }
+ return 0, ErrSyntax
+}
+
+func getRegionM49(n int) (Region, error) {
+ if 0 < n && n <= 999 {
+ const (
+ searchBits = 7
+ regionBits = 9
+ regionMask = 1<<regionBits - 1
+ )
+ idx := n >> searchBits
+ buf := fromM49[m49Index[idx]:m49Index[idx+1]]
+ val := uint16(n) << regionBits // we rely on bits shifting out
+ i := sort.Search(len(buf), func(i int) bool {
+ return buf[i] >= val
+ })
+ if r := fromM49[int(m49Index[idx])+i]; r&^regionMask == val {
+ return Region(r & regionMask), nil
+ }
+ }
+ var e ValueError
+ fmt.Fprint(bytes.NewBuffer([]byte(e.v[:])), n)
+ return 0, e
+}
+
+// normRegion returns a region if r is deprecated or 0 otherwise.
+// TODO: consider supporting BYS (-> BLR), CSK (-> 200 or CZ), PHI (-> PHL) and AFI (-> DJ).
+// TODO: consider mapping split up regions to new most populous one (like CLDR).
+func normRegion(r Region) Region {
+ m := regionOldMap
+ k := sort.Search(len(m), func(i int) bool {
+ return m[i].From >= uint16(r)
+ })
+ if k < len(m) && m[k].From == uint16(r) {
+ return Region(m[k].To)
+ }
+ return 0
+}
+
+const (
+ iso3166UserAssigned = 1 << iota
+ ccTLD
+ bcp47Region
+)
+
+func (r Region) typ() byte {
+ return regionTypes[r]
+}
+
+// String returns the BCP 47 representation for the region.
+// It returns "ZZ" for an unspecified region.
+func (r Region) String() string {
+ if r < isoRegionOffset {
+ if r == 0 {
+ return "ZZ"
+ }
+ return fmt.Sprintf("%03d", r.M49())
+ }
+ r -= isoRegionOffset
+ return regionISO.Elem(int(r))[:2]
+}
+
+// ISO3 returns the 3-letter ISO code of r.
+// Note that not all regions have a 3-letter ISO code.
+// In such cases this method returns "ZZZ".
+func (r Region) ISO3() string {
+ if r < isoRegionOffset {
+ return "ZZZ"
+ }
+ r -= isoRegionOffset
+ reg := regionISO.Elem(int(r))
+ switch reg[2] {
+ case 0:
+ return altRegionISO3[reg[3]:][:3]
+ case ' ':
+ return "ZZZ"
+ }
+ return reg[0:1] + reg[2:4]
+}
+
+// M49 returns the UN M.49 encoding of r, or 0 if this encoding
+// is not defined for r.
+func (r Region) M49() int {
+ return int(m49[r])
+}
+
+// IsPrivateUse reports whether r has the ISO 3166 User-assigned status. This
+// may include private-use tags that are assigned by CLDR and used in this
+// implementation. So IsPrivateUse and IsCountry can be simultaneously true.
+func (r Region) IsPrivateUse() bool {
+ return r.typ()&iso3166UserAssigned != 0
+}
+
+type Script uint16
+
+// getScriptID returns the script id for string s. It assumes that s
+// is of the format [A-Z][a-z]{3}.
+func getScriptID(idx tag.Index, s []byte) (Script, error) {
+ i, err := findIndex(idx, s, "Zzzz")
+ return Script(i), err
+}
+
+// String returns the script code in title case.
+// It returns "Zzzz" for an unspecified script.
+func (s Script) String() string {
+ if s == 0 {
+ return "Zzzz"
+ }
+ return script.Elem(int(s))
+}
+
+// IsPrivateUse reports whether this script code is reserved for private use.
+func (s Script) IsPrivateUse() bool {
+ return _Qaaa <= s && s <= _Qabx
+}
+
+const (
+ maxAltTaglen = len("en-US-POSIX")
+ maxLen = maxAltTaglen
+)
+
+var (
+ // grandfatheredMap holds a mapping from legacy and grandfathered tags to
+ // their base language or index to more elaborate tag.
+ grandfatheredMap = map[[maxLen]byte]int16{
+ [maxLen]byte{'a', 'r', 't', '-', 'l', 'o', 'j', 'b', 'a', 'n'}: _jbo, // art-lojban
+ [maxLen]byte{'i', '-', 'a', 'm', 'i'}: _ami, // i-ami
+ [maxLen]byte{'i', '-', 'b', 'n', 'n'}: _bnn, // i-bnn
+ [maxLen]byte{'i', '-', 'h', 'a', 'k'}: _hak, // i-hak
+ [maxLen]byte{'i', '-', 'k', 'l', 'i', 'n', 'g', 'o', 'n'}: _tlh, // i-klingon
+ [maxLen]byte{'i', '-', 'l', 'u', 'x'}: _lb, // i-lux
+ [maxLen]byte{'i', '-', 'n', 'a', 'v', 'a', 'j', 'o'}: _nv, // i-navajo
+ [maxLen]byte{'i', '-', 'p', 'w', 'n'}: _pwn, // i-pwn
+ [maxLen]byte{'i', '-', 't', 'a', 'o'}: _tao, // i-tao
+ [maxLen]byte{'i', '-', 't', 'a', 'y'}: _tay, // i-tay
+ [maxLen]byte{'i', '-', 't', 's', 'u'}: _tsu, // i-tsu
+ [maxLen]byte{'n', 'o', '-', 'b', 'o', 'k'}: _nb, // no-bok
+ [maxLen]byte{'n', 'o', '-', 'n', 'y', 'n'}: _nn, // no-nyn
+ [maxLen]byte{'s', 'g', 'n', '-', 'b', 'e', '-', 'f', 'r'}: _sfb, // sgn-BE-FR
+ [maxLen]byte{'s', 'g', 'n', '-', 'b', 'e', '-', 'n', 'l'}: _vgt, // sgn-BE-NL
+ [maxLen]byte{'s', 'g', 'n', '-', 'c', 'h', '-', 'd', 'e'}: _sgg, // sgn-CH-DE
+ [maxLen]byte{'z', 'h', '-', 'g', 'u', 'o', 'y', 'u'}: _cmn, // zh-guoyu
+ [maxLen]byte{'z', 'h', '-', 'h', 'a', 'k', 'k', 'a'}: _hak, // zh-hakka
+ [maxLen]byte{'z', 'h', '-', 'm', 'i', 'n', '-', 'n', 'a', 'n'}: _nan, // zh-min-nan
+ [maxLen]byte{'z', 'h', '-', 'x', 'i', 'a', 'n', 'g'}: _hsn, // zh-xiang
+
+ // Grandfathered tags with no modern replacement will be converted as
+ // follows:
+ [maxLen]byte{'c', 'e', 'l', '-', 'g', 'a', 'u', 'l', 'i', 's', 'h'}: -1, // cel-gaulish
+ [maxLen]byte{'e', 'n', '-', 'g', 'b', '-', 'o', 'e', 'd'}: -2, // en-GB-oed
+ [maxLen]byte{'i', '-', 'd', 'e', 'f', 'a', 'u', 'l', 't'}: -3, // i-default
+ [maxLen]byte{'i', '-', 'e', 'n', 'o', 'c', 'h', 'i', 'a', 'n'}: -4, // i-enochian
+ [maxLen]byte{'i', '-', 'm', 'i', 'n', 'g', 'o'}: -5, // i-mingo
+ [maxLen]byte{'z', 'h', '-', 'm', 'i', 'n'}: -6, // zh-min
+
+ // CLDR-specific tag.
+ [maxLen]byte{'r', 'o', 'o', 't'}: 0, // root
+ [maxLen]byte{'e', 'n', '-', 'u', 's', '-', 'p', 'o', 's', 'i', 'x'}: -7, // en_US_POSIX"
+ }
+
+ altTagIndex = [...]uint8{0, 17, 31, 45, 61, 74, 86, 102}
+
+ altTags = "xtg-x-cel-gaulishen-GB-oxendicten-x-i-defaultund-x-i-enochiansee-x-i-mingonan-x-zh-minen-US-u-va-posix"
+)
+
+func grandfathered(s [maxAltTaglen]byte) (t Tag, ok bool) {
+ if v, ok := grandfatheredMap[s]; ok {
+ if v < 0 {
+ return Make(altTags[altTagIndex[-v-1]:altTagIndex[-v]]), true
+ }
+ t.LangID = Language(v)
+ return t, true
+ }
+ return t, false
+}
diff --git a/vendor/golang.org/x/text/internal/language/match.go b/vendor/golang.org/x/text/internal/language/match.go
new file mode 100644
index 0000000..75a2dbc
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/match.go
@@ -0,0 +1,226 @@
+// 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 language
+
+import "errors"
+
+type scriptRegionFlags uint8
+
+const (
+ isList = 1 << iota
+ scriptInFrom
+ regionInFrom
+)
+
+func (t *Tag) setUndefinedLang(id Language) {
+ if t.LangID == 0 {
+ t.LangID = id
+ }
+}
+
+func (t *Tag) setUndefinedScript(id Script) {
+ if t.ScriptID == 0 {
+ t.ScriptID = id
+ }
+}
+
+func (t *Tag) setUndefinedRegion(id Region) {
+ if t.RegionID == 0 || t.RegionID.Contains(id) {
+ t.RegionID = id
+ }
+}
+
+// ErrMissingLikelyTagsData indicates no information was available
+// to compute likely values of missing tags.
+var ErrMissingLikelyTagsData = errors.New("missing likely tags data")
+
+// addLikelySubtags sets subtags to their most likely value, given the locale.
+// In most cases this means setting fields for unknown values, but in some
+// cases it may alter a value. It returns an ErrMissingLikelyTagsData error
+// if the given locale cannot be expanded.
+func (t Tag) addLikelySubtags() (Tag, error) {
+ id, err := addTags(t)
+ if err != nil {
+ return t, err
+ } else if id.equalTags(t) {
+ return t, nil
+ }
+ id.RemakeString()
+ return id, nil
+}
+
+// specializeRegion attempts to specialize a group region.
+func specializeRegion(t *Tag) bool {
+ if i := regionInclusion[t.RegionID]; i < nRegionGroups {
+ x := likelyRegionGroup[i]
+ if Language(x.lang) == t.LangID && Script(x.script) == t.ScriptID {
+ t.RegionID = Region(x.region)
+ }
+ return true
+ }
+ return false
+}
+
+// Maximize returns a new tag with missing tags filled in.
+func (t Tag) Maximize() (Tag, error) {
+ return addTags(t)
+}
+
+func addTags(t Tag) (Tag, error) {
+ // We leave private use identifiers alone.
+ if t.IsPrivateUse() {
+ return t, nil
+ }
+ if t.ScriptID != 0 && t.RegionID != 0 {
+ if t.LangID != 0 {
+ // already fully specified
+ specializeRegion(&t)
+ return t, nil
+ }
+ // Search matches for und-script-region. Note that for these cases
+ // region will never be a group so there is no need to check for this.
+ list := likelyRegion[t.RegionID : t.RegionID+1]
+ if x := list[0]; x.flags&isList != 0 {
+ list = likelyRegionList[x.lang : x.lang+uint16(x.script)]
+ }
+ for _, x := range list {
+ // Deviating from the spec. See match_test.go for details.
+ if Script(x.script) == t.ScriptID {
+ t.setUndefinedLang(Language(x.lang))
+ return t, nil
+ }
+ }
+ }
+ if t.LangID != 0 {
+ // Search matches for lang-script and lang-region, where lang != und.
+ if t.LangID < langNoIndexOffset {
+ x := likelyLang[t.LangID]
+ if x.flags&isList != 0 {
+ list := likelyLangList[x.region : x.region+uint16(x.script)]
+ if t.ScriptID != 0 {
+ for _, x := range list {
+ if Script(x.script) == t.ScriptID && x.flags&scriptInFrom != 0 {
+ t.setUndefinedRegion(Region(x.region))
+ return t, nil
+ }
+ }
+ } else if t.RegionID != 0 {
+ count := 0
+ goodScript := true
+ tt := t
+ for _, x := range list {
+ // We visit all entries for which the script was not
+ // defined, including the ones where the region was not
+ // defined. This allows for proper disambiguation within
+ // regions.
+ if x.flags&scriptInFrom == 0 && t.RegionID.Contains(Region(x.region)) {
+ tt.RegionID = Region(x.region)
+ tt.setUndefinedScript(Script(x.script))
+ goodScript = goodScript && tt.ScriptID == Script(x.script)
+ count++
+ }
+ }
+ if count == 1 {
+ return tt, nil
+ }
+ // Even if we fail to find a unique Region, we might have
+ // an unambiguous script.
+ if goodScript {
+ t.ScriptID = tt.ScriptID
+ }
+ }
+ }
+ }
+ } else {
+ // Search matches for und-script.
+ if t.ScriptID != 0 {
+ x := likelyScript[t.ScriptID]
+ if x.region != 0 {
+ t.setUndefinedRegion(Region(x.region))
+ t.setUndefinedLang(Language(x.lang))
+ return t, nil
+ }
+ }
+ // Search matches for und-region. If und-script-region exists, it would
+ // have been found earlier.
+ if t.RegionID != 0 {
+ if i := regionInclusion[t.RegionID]; i < nRegionGroups {
+ x := likelyRegionGroup[i]
+ if x.region != 0 {
+ t.setUndefinedLang(Language(x.lang))
+ t.setUndefinedScript(Script(x.script))
+ t.RegionID = Region(x.region)
+ }
+ } else {
+ x := likelyRegion[t.RegionID]
+ if x.flags&isList != 0 {
+ x = likelyRegionList[x.lang]
+ }
+ if x.script != 0 && x.flags != scriptInFrom {
+ t.setUndefinedLang(Language(x.lang))
+ t.setUndefinedScript(Script(x.script))
+ return t, nil
+ }
+ }
+ }
+ }
+
+ // Search matches for lang.
+ if t.LangID < langNoIndexOffset {
+ x := likelyLang[t.LangID]
+ if x.flags&isList != 0 {
+ x = likelyLangList[x.region]
+ }
+ if x.region != 0 {
+ t.setUndefinedScript(Script(x.script))
+ t.setUndefinedRegion(Region(x.region))
+ }
+ specializeRegion(&t)
+ if t.LangID == 0 {
+ t.LangID = _en // default language
+ }
+ return t, nil
+ }
+ return t, ErrMissingLikelyTagsData
+}
+
+func (t *Tag) setTagsFrom(id Tag) {
+ t.LangID = id.LangID
+ t.ScriptID = id.ScriptID
+ t.RegionID = id.RegionID
+}
+
+// minimize removes the region or script subtags from t such that
+// t.addLikelySubtags() == t.minimize().addLikelySubtags().
+func (t Tag) minimize() (Tag, error) {
+ t, err := minimizeTags(t)
+ if err != nil {
+ return t, err
+ }
+ t.RemakeString()
+ return t, nil
+}
+
+// minimizeTags mimics the behavior of the ICU 51 C implementation.
+func minimizeTags(t Tag) (Tag, error) {
+ if t.equalTags(Und) {
+ return t, nil
+ }
+ max, err := addTags(t)
+ if err != nil {
+ return t, err
+ }
+ for _, id := range [...]Tag{
+ {LangID: t.LangID},
+ {LangID: t.LangID, RegionID: t.RegionID},
+ {LangID: t.LangID, ScriptID: t.ScriptID},
+ } {
+ if x, err := addTags(id); err == nil && max.equalTags(x) {
+ t.setTagsFrom(id)
+ break
+ }
+ }
+ return t, nil
+}
diff --git a/vendor/golang.org/x/text/internal/language/parse.go b/vendor/golang.org/x/text/internal/language/parse.go
new file mode 100644
index 0000000..aad1e0a
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/parse.go
@@ -0,0 +1,608 @@
+// 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 language
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "sort"
+
+ "golang.org/x/text/internal/tag"
+)
+
+// isAlpha returns true if the byte is not a digit.
+// b must be an ASCII letter or digit.
+func isAlpha(b byte) bool {
+ return b > '9'
+}
+
+// isAlphaNum returns true if the string contains only ASCII letters or digits.
+func isAlphaNum(s []byte) bool {
+ for _, c := range s {
+ if !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9') {
+ return false
+ }
+ }
+ return true
+}
+
+// ErrSyntax is returned by any of the parsing functions when the
+// input is not well-formed, according to BCP 47.
+// TODO: return the position at which the syntax error occurred?
+var ErrSyntax = errors.New("language: tag is not well-formed")
+
+// ErrDuplicateKey is returned when a tag contains the same key twice with
+// different values in the -u section.
+var ErrDuplicateKey = errors.New("language: different values for same key in -u extension")
+
+// ValueError is returned by any of the parsing functions when the
+// input is well-formed but the respective subtag is not recognized
+// as a valid value.
+type ValueError struct {
+ v [8]byte
+}
+
+// NewValueError creates a new ValueError.
+func NewValueError(tag []byte) ValueError {
+ var e ValueError
+ copy(e.v[:], tag)
+ return e
+}
+
+func (e ValueError) tag() []byte {
+ n := bytes.IndexByte(e.v[:], 0)
+ if n == -1 {
+ n = 8
+ }
+ return e.v[:n]
+}
+
+// Error implements the error interface.
+func (e ValueError) Error() string {
+ return fmt.Sprintf("language: subtag %q is well-formed but unknown", e.tag())
+}
+
+// Subtag returns the subtag for which the error occurred.
+func (e ValueError) Subtag() string {
+ return string(e.tag())
+}
+
+// scanner is used to scan BCP 47 tokens, which are separated by _ or -.
+type scanner struct {
+ b []byte
+ bytes [max99thPercentileSize]byte
+ token []byte
+ start int // start position of the current token
+ end int // end position of the current token
+ next int // next point for scan
+ err error
+ done bool
+}
+
+func makeScannerString(s string) scanner {
+ scan := scanner{}
+ if len(s) <= len(scan.bytes) {
+ scan.b = scan.bytes[:copy(scan.bytes[:], s)]
+ } else {
+ scan.b = []byte(s)
+ }
+ scan.init()
+ return scan
+}
+
+// makeScanner returns a scanner using b as the input buffer.
+// b is not copied and may be modified by the scanner routines.
+func makeScanner(b []byte) scanner {
+ scan := scanner{b: b}
+ scan.init()
+ return scan
+}
+
+func (s *scanner) init() {
+ for i, c := range s.b {
+ if c == '_' {
+ s.b[i] = '-'
+ }
+ }
+ s.scan()
+}
+
+// restToLower converts the string between start and end to lower case.
+func (s *scanner) toLower(start, end int) {
+ for i := start; i < end; i++ {
+ c := s.b[i]
+ if 'A' <= c && c <= 'Z' {
+ s.b[i] += 'a' - 'A'
+ }
+ }
+}
+
+func (s *scanner) setError(e error) {
+ if s.err == nil || (e == ErrSyntax && s.err != ErrSyntax) {
+ s.err = e
+ }
+}
+
+// resizeRange shrinks or grows the array at position oldStart such that
+// a new string of size newSize can fit between oldStart and oldEnd.
+// Sets the scan point to after the resized range.
+func (s *scanner) resizeRange(oldStart, oldEnd, newSize int) {
+ s.start = oldStart
+ if end := oldStart + newSize; end != oldEnd {
+ diff := end - oldEnd
+ var b []byte
+ if n := len(s.b) + diff; n > cap(s.b) {
+ b = make([]byte, n)
+ copy(b, s.b[:oldStart])
+ } else {
+ b = s.b[:n]
+ }
+ copy(b[end:], s.b[oldEnd:])
+ s.b = b
+ s.next = end + (s.next - s.end)
+ s.end = end
+ }
+}
+
+// replace replaces the current token with repl.
+func (s *scanner) replace(repl string) {
+ s.resizeRange(s.start, s.end, len(repl))
+ copy(s.b[s.start:], repl)
+}
+
+// gobble removes the current token from the input.
+// Caller must call scan after calling gobble.
+func (s *scanner) gobble(e error) {
+ s.setError(e)
+ if s.start == 0 {
+ s.b = s.b[:+copy(s.b, s.b[s.next:])]
+ s.end = 0
+ } else {
+ s.b = s.b[:s.start-1+copy(s.b[s.start-1:], s.b[s.end:])]
+ s.end = s.start - 1
+ }
+ s.next = s.start
+}
+
+// deleteRange removes the given range from s.b before the current token.
+func (s *scanner) deleteRange(start, end int) {
+ s.b = s.b[:start+copy(s.b[start:], s.b[end:])]
+ diff := end - start
+ s.next -= diff
+ s.start -= diff
+ s.end -= diff
+}
+
+// scan parses the next token of a BCP 47 string. Tokens that are larger
+// than 8 characters or include non-alphanumeric characters result in an error
+// and are gobbled and removed from the output.
+// It returns the end position of the last token consumed.
+func (s *scanner) scan() (end int) {
+ end = s.end
+ s.token = nil
+ for s.start = s.next; s.next < len(s.b); {
+ i := bytes.IndexByte(s.b[s.next:], '-')
+ if i == -1 {
+ s.end = len(s.b)
+ s.next = len(s.b)
+ i = s.end - s.start
+ } else {
+ s.end = s.next + i
+ s.next = s.end + 1
+ }
+ token := s.b[s.start:s.end]
+ if i < 1 || i > 8 || !isAlphaNum(token) {
+ s.gobble(ErrSyntax)
+ continue
+ }
+ s.token = token
+ return end
+ }
+ if n := len(s.b); n > 0 && s.b[n-1] == '-' {
+ s.setError(ErrSyntax)
+ s.b = s.b[:len(s.b)-1]
+ }
+ s.done = true
+ return end
+}
+
+// acceptMinSize parses multiple tokens of the given size or greater.
+// It returns the end position of the last token consumed.
+func (s *scanner) acceptMinSize(min int) (end int) {
+ end = s.end
+ s.scan()
+ for ; len(s.token) >= min; s.scan() {
+ end = s.end
+ }
+ return end
+}
+
+// Parse parses the given BCP 47 string and returns a valid Tag. If parsing
+// failed it returns an error and any part of the tag that could be parsed.
+// If parsing succeeded but an unknown value was found, it returns
+// ValueError. The Tag returned in this case is just stripped of the unknown
+// value. All other values are preserved. It accepts tags in the BCP 47 format
+// and extensions to this standard defined in
+// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers.
+func Parse(s string) (t Tag, err error) {
+ // TODO: consider supporting old-style locale key-value pairs.
+ if s == "" {
+ return Und, ErrSyntax
+ }
+ defer func() {
+ if recover() != nil {
+ t = Und
+ err = ErrSyntax
+ return
+ }
+ }()
+ if len(s) <= maxAltTaglen {
+ b := [maxAltTaglen]byte{}
+ for i, c := range s {
+ // Generating invalid UTF-8 is okay as it won't match.
+ if 'A' <= c && c <= 'Z' {
+ c += 'a' - 'A'
+ } else if c == '_' {
+ c = '-'
+ }
+ b[i] = byte(c)
+ }
+ if t, ok := grandfathered(b); ok {
+ return t, nil
+ }
+ }
+ scan := makeScannerString(s)
+ return parse(&scan, s)
+}
+
+func parse(scan *scanner, s string) (t Tag, err error) {
+ t = Und
+ var end int
+ if n := len(scan.token); n <= 1 {
+ scan.toLower(0, len(scan.b))
+ if n == 0 || scan.token[0] != 'x' {
+ return t, ErrSyntax
+ }
+ end = parseExtensions(scan)
+ } else if n >= 4 {
+ return Und, ErrSyntax
+ } else { // the usual case
+ t, end = parseTag(scan, true)
+ if n := len(scan.token); n == 1 {
+ t.pExt = uint16(end)
+ end = parseExtensions(scan)
+ } else if end < len(scan.b) {
+ scan.setError(ErrSyntax)
+ scan.b = scan.b[:end]
+ }
+ }
+ if int(t.pVariant) < len(scan.b) {
+ if end < len(s) {
+ s = s[:end]
+ }
+ if len(s) > 0 && tag.Compare(s, scan.b) == 0 {
+ t.str = s
+ } else {
+ t.str = string(scan.b)
+ }
+ } else {
+ t.pVariant, t.pExt = 0, 0
+ }
+ return t, scan.err
+}
+
+// parseTag parses language, script, region and variants.
+// It returns a Tag and the end position in the input that was parsed.
+// If doNorm is true, then <lang>-<extlang> will be normalized to <extlang>.
+func parseTag(scan *scanner, doNorm bool) (t Tag, end int) {
+ var e error
+ // TODO: set an error if an unknown lang, script or region is encountered.
+ t.LangID, e = getLangID(scan.token)
+ scan.setError(e)
+ scan.replace(t.LangID.String())
+ langStart := scan.start
+ end = scan.scan()
+ for len(scan.token) == 3 && isAlpha(scan.token[0]) {
+ // From http://tools.ietf.org/html/bcp47, <lang>-<extlang> tags are equivalent
+ // to a tag of the form <extlang>.
+ if doNorm {
+ lang, e := getLangID(scan.token)
+ if lang != 0 {
+ t.LangID = lang
+ langStr := lang.String()
+ copy(scan.b[langStart:], langStr)
+ scan.b[langStart+len(langStr)] = '-'
+ scan.start = langStart + len(langStr) + 1
+ }
+ scan.gobble(e)
+ }
+ end = scan.scan()
+ }
+ if len(scan.token) == 4 && isAlpha(scan.token[0]) {
+ t.ScriptID, e = getScriptID(script, scan.token)
+ if t.ScriptID == 0 {
+ scan.gobble(e)
+ }
+ end = scan.scan()
+ }
+ if n := len(scan.token); n >= 2 && n <= 3 {
+ t.RegionID, e = getRegionID(scan.token)
+ if t.RegionID == 0 {
+ scan.gobble(e)
+ } else {
+ scan.replace(t.RegionID.String())
+ }
+ end = scan.scan()
+ }
+ scan.toLower(scan.start, len(scan.b))
+ t.pVariant = byte(end)
+ end = parseVariants(scan, end, t)
+ t.pExt = uint16(end)
+ return t, end
+}
+
+var separator = []byte{'-'}
+
+// parseVariants scans tokens as long as each token is a valid variant string.
+// Duplicate variants are removed.
+func parseVariants(scan *scanner, end int, t Tag) int {
+ start := scan.start
+ varIDBuf := [4]uint8{}
+ variantBuf := [4][]byte{}
+ varID := varIDBuf[:0]
+ variant := variantBuf[:0]
+ last := -1
+ needSort := false
+ for ; len(scan.token) >= 4; scan.scan() {
+ // TODO: measure the impact of needing this conversion and redesign
+ // the data structure if there is an issue.
+ v, ok := variantIndex[string(scan.token)]
+ if !ok {
+ // unknown variant
+ // TODO: allow user-defined variants?
+ scan.gobble(NewValueError(scan.token))
+ continue
+ }
+ varID = append(varID, v)
+ variant = append(variant, scan.token)
+ if !needSort {
+ if last < int(v) {
+ last = int(v)
+ } else {
+ needSort = true
+ // There is no legal combinations of more than 7 variants
+ // (and this is by no means a useful sequence).
+ const maxVariants = 8
+ if len(varID) > maxVariants {
+ break
+ }
+ }
+ }
+ end = scan.end
+ }
+ if needSort {
+ sort.Sort(variantsSort{varID, variant})
+ k, l := 0, -1
+ for i, v := range varID {
+ w := int(v)
+ if l == w {
+ // Remove duplicates.
+ continue
+ }
+ varID[k] = varID[i]
+ variant[k] = variant[i]
+ k++
+ l = w
+ }
+ if str := bytes.Join(variant[:k], separator); len(str) == 0 {
+ end = start - 1
+ } else {
+ scan.resizeRange(start, end, len(str))
+ copy(scan.b[scan.start:], str)
+ end = scan.end
+ }
+ }
+ return end
+}
+
+type variantsSort struct {
+ i []uint8
+ v [][]byte
+}
+
+func (s variantsSort) Len() int {
+ return len(s.i)
+}
+
+func (s variantsSort) Swap(i, j int) {
+ s.i[i], s.i[j] = s.i[j], s.i[i]
+ s.v[i], s.v[j] = s.v[j], s.v[i]
+}
+
+func (s variantsSort) Less(i, j int) bool {
+ return s.i[i] < s.i[j]
+}
+
+type bytesSort struct {
+ b [][]byte
+ n int // first n bytes to compare
+}
+
+func (b bytesSort) Len() int {
+ return len(b.b)
+}
+
+func (b bytesSort) Swap(i, j int) {
+ b.b[i], b.b[j] = b.b[j], b.b[i]
+}
+
+func (b bytesSort) Less(i, j int) bool {
+ for k := 0; k < b.n; k++ {
+ if b.b[i][k] == b.b[j][k] {
+ continue
+ }
+ return b.b[i][k] < b.b[j][k]
+ }
+ return false
+}
+
+// parseExtensions parses and normalizes the extensions in the buffer.
+// It returns the last position of scan.b that is part of any extension.
+// It also trims scan.b to remove excess parts accordingly.
+func parseExtensions(scan *scanner) int {
+ start := scan.start
+ exts := [][]byte{}
+ private := []byte{}
+ end := scan.end
+ for len(scan.token) == 1 {
+ extStart := scan.start
+ ext := scan.token[0]
+ end = parseExtension(scan)
+ extension := scan.b[extStart:end]
+ if len(extension) < 3 || (ext != 'x' && len(extension) < 4) {
+ scan.setError(ErrSyntax)
+ end = extStart
+ continue
+ } else if start == extStart && (ext == 'x' || scan.start == len(scan.b)) {
+ scan.b = scan.b[:end]
+ return end
+ } else if ext == 'x' {
+ private = extension
+ break
+ }
+ exts = append(exts, extension)
+ }
+ sort.Sort(bytesSort{exts, 1})
+ if len(private) > 0 {
+ exts = append(exts, private)
+ }
+ scan.b = scan.b[:start]
+ if len(exts) > 0 {
+ scan.b = append(scan.b, bytes.Join(exts, separator)...)
+ } else if start > 0 {
+ // Strip trailing '-'.
+ scan.b = scan.b[:start-1]
+ }
+ return end
+}
+
+// parseExtension parses a single extension and returns the position of
+// the extension end.
+func parseExtension(scan *scanner) int {
+ start, end := scan.start, scan.end
+ switch scan.token[0] {
+ case 'u': // https://www.ietf.org/rfc/rfc6067.txt
+ attrStart := end
+ scan.scan()
+ for last := []byte{}; len(scan.token) > 2; scan.scan() {
+ if bytes.Compare(scan.token, last) != -1 {
+ // Attributes are unsorted. Start over from scratch.
+ p := attrStart + 1
+ scan.next = p
+ attrs := [][]byte{}
+ for scan.scan(); len(scan.token) > 2; scan.scan() {
+ attrs = append(attrs, scan.token)
+ end = scan.end
+ }
+ sort.Sort(bytesSort{attrs, 3})
+ copy(scan.b[p:], bytes.Join(attrs, separator))
+ break
+ }
+ last = scan.token
+ end = scan.end
+ }
+ // Scan key-type sequences. A key is of length 2 and may be followed
+ // by 0 or more "type" subtags from 3 to the maximum of 8 letters.
+ var last, key []byte
+ for attrEnd := end; len(scan.token) == 2; last = key {
+ key = scan.token
+ end = scan.end
+ for scan.scan(); end < scan.end && len(scan.token) > 2; scan.scan() {
+ end = scan.end
+ }
+ // TODO: check key value validity
+ if bytes.Compare(key, last) != 1 || scan.err != nil {
+ // We have an invalid key or the keys are not sorted.
+ // Start scanning keys from scratch and reorder.
+ p := attrEnd + 1
+ scan.next = p
+ keys := [][]byte{}
+ for scan.scan(); len(scan.token) == 2; {
+ keyStart := scan.start
+ end = scan.end
+ for scan.scan(); end < scan.end && len(scan.token) > 2; scan.scan() {
+ end = scan.end
+ }
+ keys = append(keys, scan.b[keyStart:end])
+ }
+ sort.Stable(bytesSort{keys, 2})
+ if n := len(keys); n > 0 {
+ k := 0
+ for i := 1; i < n; i++ {
+ if !bytes.Equal(keys[k][:2], keys[i][:2]) {
+ k++
+ keys[k] = keys[i]
+ } else if !bytes.Equal(keys[k], keys[i]) {
+ scan.setError(ErrDuplicateKey)
+ }
+ }
+ keys = keys[:k+1]
+ }
+ reordered := bytes.Join(keys, separator)
+ if e := p + len(reordered); e < end {
+ scan.deleteRange(e, end)
+ end = e
+ }
+ copy(scan.b[p:], reordered)
+ break
+ }
+ }
+ case 't': // https://www.ietf.org/rfc/rfc6497.txt
+ scan.scan()
+ if n := len(scan.token); n >= 2 && n <= 3 && isAlpha(scan.token[1]) {
+ _, end = parseTag(scan, false)
+ scan.toLower(start, end)
+ }
+ for len(scan.token) == 2 && !isAlpha(scan.token[1]) {
+ end = scan.acceptMinSize(3)
+ }
+ case 'x':
+ end = scan.acceptMinSize(1)
+ default:
+ end = scan.acceptMinSize(2)
+ }
+ return end
+}
+
+// getExtension returns the name, body and end position of the extension.
+func getExtension(s string, p int) (end int, ext string) {
+ if s[p] == '-' {
+ p++
+ }
+ if s[p] == 'x' {
+ return len(s), s[p:]
+ }
+ end = nextExtension(s, p)
+ return end, s[p:end]
+}
+
+// nextExtension finds the next extension within the string, searching
+// for the -<char>- pattern from position p.
+// In the fast majority of cases, language tags will have at most
+// one extension and extensions tend to be small.
+func nextExtension(s string, p int) int {
+ for n := len(s) - 3; p < n; {
+ if s[p] == '-' {
+ if s[p+2] == '-' {
+ return p
+ }
+ p += 3
+ } else {
+ p++
+ }
+ }
+ return len(s)
+}
diff --git a/vendor/golang.org/x/text/internal/language/tables.go b/vendor/golang.org/x/text/internal/language/tables.go
new file mode 100644
index 0000000..14167e7
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/tables.go
@@ -0,0 +1,3494 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package language
+
+import "golang.org/x/text/internal/tag"
+
+// CLDRVersion is the CLDR version from which the tables in this package are derived.
+const CLDRVersion = "32"
+
+const NumLanguages = 8798
+
+const NumScripts = 261
+
+const NumRegions = 358
+
+type FromTo struct {
+ From uint16
+ To uint16
+}
+
+const nonCanonicalUnd = 1201
+const (
+ _af = 22
+ _am = 39
+ _ar = 58
+ _az = 88
+ _bg = 126
+ _bn = 165
+ _ca = 215
+ _cs = 250
+ _da = 257
+ _de = 269
+ _el = 310
+ _en = 313
+ _es = 318
+ _et = 320
+ _fa = 328
+ _fi = 337
+ _fil = 339
+ _fr = 350
+ _gu = 420
+ _he = 444
+ _hi = 446
+ _hr = 465
+ _hu = 469
+ _hy = 471
+ _id = 481
+ _is = 504
+ _it = 505
+ _ja = 512
+ _ka = 528
+ _kk = 578
+ _km = 586
+ _kn = 593
+ _ko = 596
+ _ky = 650
+ _lo = 696
+ _lt = 704
+ _lv = 711
+ _mk = 767
+ _ml = 772
+ _mn = 779
+ _mo = 784
+ _mr = 795
+ _ms = 799
+ _mul = 806
+ _my = 817
+ _nb = 839
+ _ne = 849
+ _nl = 871
+ _no = 879
+ _pa = 925
+ _pl = 947
+ _pt = 960
+ _ro = 988
+ _ru = 994
+ _sh = 1031
+ _si = 1036
+ _sk = 1042
+ _sl = 1046
+ _sq = 1073
+ _sr = 1074
+ _sv = 1092
+ _sw = 1093
+ _ta = 1104
+ _te = 1121
+ _th = 1131
+ _tl = 1146
+ _tn = 1152
+ _tr = 1162
+ _uk = 1198
+ _ur = 1204
+ _uz = 1212
+ _vi = 1219
+ _zh = 1321
+ _zu = 1327
+ _jbo = 515
+ _ami = 1650
+ _bnn = 2357
+ _hak = 438
+ _tlh = 14467
+ _lb = 661
+ _nv = 899
+ _pwn = 12055
+ _tao = 14188
+ _tay = 14198
+ _tsu = 14662
+ _nn = 874
+ _sfb = 13629
+ _vgt = 15701
+ _sgg = 13660
+ _cmn = 3007
+ _nan = 835
+ _hsn = 467
+)
+
+const langPrivateStart = 0x2f72
+
+const langPrivateEnd = 0x3179
+
+// lang holds an alphabetically sorted list of ISO-639 language identifiers.
+// All entries are 4 bytes. The index of the identifier (divided by 4) is the language tag.
+// For 2-byte language identifiers, the two successive bytes have the following meaning:
+// - if the first letter of the 2- and 3-letter ISO codes are the same:
+// the second and third letter of the 3-letter ISO code.
+// - otherwise: a 0 and a by 2 bits right-shifted index into altLangISO3.
+//
+// For 3-byte language identifiers the 4th byte is 0.
+const lang tag.Index = "" + // Size: 5324 bytes
+ "---\x00aaaraai\x00aak\x00aau\x00abbkabi\x00abq\x00abr\x00abt\x00aby\x00a" +
+ "cd\x00ace\x00ach\x00ada\x00ade\x00adj\x00ady\x00adz\x00aeveaeb\x00aey" +
+ "\x00affragc\x00agd\x00agg\x00agm\x00ago\x00agq\x00aha\x00ahl\x00aho\x00a" +
+ "jg\x00akkaakk\x00ala\x00ali\x00aln\x00alt\x00ammhamm\x00amn\x00amo\x00am" +
+ "p\x00anrganc\x00ank\x00ann\x00any\x00aoj\x00aom\x00aoz\x00apc\x00apd\x00" +
+ "ape\x00apr\x00aps\x00apz\x00arraarc\x00arh\x00arn\x00aro\x00arq\x00ars" +
+ "\x00ary\x00arz\x00assmasa\x00ase\x00asg\x00aso\x00ast\x00ata\x00atg\x00a" +
+ "tj\x00auy\x00avvaavl\x00avn\x00avt\x00avu\x00awa\x00awb\x00awo\x00awx" +
+ "\x00ayymayb\x00azzebaakbal\x00ban\x00bap\x00bar\x00bas\x00bav\x00bax\x00" +
+ "bba\x00bbb\x00bbc\x00bbd\x00bbj\x00bbp\x00bbr\x00bcf\x00bch\x00bci\x00bc" +
+ "m\x00bcn\x00bco\x00bcq\x00bcu\x00bdd\x00beelbef\x00beh\x00bej\x00bem\x00" +
+ "bet\x00bew\x00bex\x00bez\x00bfd\x00bfq\x00bft\x00bfy\x00bgulbgc\x00bgn" +
+ "\x00bgx\x00bhihbhb\x00bhg\x00bhi\x00bhk\x00bhl\x00bho\x00bhy\x00biisbib" +
+ "\x00big\x00bik\x00bim\x00bin\x00bio\x00biq\x00bjh\x00bji\x00bjj\x00bjn" +
+ "\x00bjo\x00bjr\x00bjt\x00bjz\x00bkc\x00bkm\x00bkq\x00bku\x00bkv\x00blt" +
+ "\x00bmambmh\x00bmk\x00bmq\x00bmu\x00bnenbng\x00bnm\x00bnp\x00boodboj\x00" +
+ "bom\x00bon\x00bpy\x00bqc\x00bqi\x00bqp\x00bqv\x00brrebra\x00brh\x00brx" +
+ "\x00brz\x00bsosbsj\x00bsq\x00bss\x00bst\x00bto\x00btt\x00btv\x00bua\x00b" +
+ "uc\x00bud\x00bug\x00buk\x00bum\x00buo\x00bus\x00buu\x00bvb\x00bwd\x00bwr" +
+ "\x00bxh\x00bye\x00byn\x00byr\x00bys\x00byv\x00byx\x00bza\x00bze\x00bzf" +
+ "\x00bzh\x00bzw\x00caatcan\x00cbj\x00cch\x00ccp\x00ceheceb\x00cfa\x00cgg" +
+ "\x00chhachk\x00chm\x00cho\x00chp\x00chr\x00cja\x00cjm\x00cjv\x00ckb\x00c" +
+ "kl\x00cko\x00cky\x00cla\x00cme\x00cmg\x00cooscop\x00cps\x00crrecrh\x00cr" +
+ "j\x00crk\x00crl\x00crm\x00crs\x00csescsb\x00csw\x00ctd\x00cuhucvhvcyymda" +
+ "andad\x00daf\x00dag\x00dah\x00dak\x00dar\x00dav\x00dbd\x00dbq\x00dcc\x00" +
+ "ddn\x00deeuded\x00den\x00dga\x00dgh\x00dgi\x00dgl\x00dgr\x00dgz\x00dia" +
+ "\x00dje\x00dnj\x00dob\x00doi\x00dop\x00dow\x00dri\x00drs\x00dsb\x00dtm" +
+ "\x00dtp\x00dts\x00dty\x00dua\x00duc\x00dud\x00dug\x00dvivdva\x00dww\x00d" +
+ "yo\x00dyu\x00dzzodzg\x00ebu\x00eeweefi\x00egl\x00egy\x00eka\x00eky\x00el" +
+ "llema\x00emi\x00enngenn\x00enq\x00eopoeri\x00es\x00\x05esu\x00etstetr" +
+ "\x00ett\x00etu\x00etx\x00euusewo\x00ext\x00faasfaa\x00fab\x00fag\x00fai" +
+ "\x00fan\x00ffulffi\x00ffm\x00fiinfia\x00fil\x00fit\x00fjijflr\x00fmp\x00" +
+ "foaofod\x00fon\x00for\x00fpe\x00fqs\x00frrafrc\x00frp\x00frr\x00frs\x00f" +
+ "ub\x00fud\x00fue\x00fuf\x00fuh\x00fuq\x00fur\x00fuv\x00fuy\x00fvr\x00fyr" +
+ "ygalegaa\x00gaf\x00gag\x00gah\x00gaj\x00gam\x00gan\x00gaw\x00gay\x00gba" +
+ "\x00gbf\x00gbm\x00gby\x00gbz\x00gcr\x00gdlagde\x00gdn\x00gdr\x00geb\x00g" +
+ "ej\x00gel\x00gez\x00gfk\x00ggn\x00ghs\x00gil\x00gim\x00gjk\x00gjn\x00gju" +
+ "\x00gkn\x00gkp\x00gllgglk\x00gmm\x00gmv\x00gnrngnd\x00gng\x00god\x00gof" +
+ "\x00goi\x00gom\x00gon\x00gor\x00gos\x00got\x00grb\x00grc\x00grt\x00grw" +
+ "\x00gsw\x00guujgub\x00guc\x00gud\x00gur\x00guw\x00gux\x00guz\x00gvlvgvf" +
+ "\x00gvr\x00gvs\x00gwc\x00gwi\x00gwt\x00gyi\x00haauhag\x00hak\x00ham\x00h" +
+ "aw\x00haz\x00hbb\x00hdy\x00heebhhy\x00hiinhia\x00hif\x00hig\x00hih\x00hi" +
+ "l\x00hla\x00hlu\x00hmd\x00hmt\x00hnd\x00hne\x00hnj\x00hnn\x00hno\x00homo" +
+ "hoc\x00hoj\x00hot\x00hrrvhsb\x00hsn\x00htathuunhui\x00hyyehzerianaian" +
+ "\x00iar\x00iba\x00ibb\x00iby\x00ica\x00ich\x00idndidd\x00idi\x00idu\x00i" +
+ "eleife\x00igboigb\x00ige\x00iiiiijj\x00ikpkikk\x00ikt\x00ikw\x00ikx\x00i" +
+ "lo\x00imo\x00inndinh\x00iodoiou\x00iri\x00isslittaiukuiw\x00\x03iwm\x00i" +
+ "ws\x00izh\x00izi\x00japnjab\x00jam\x00jbo\x00jbu\x00jen\x00jgk\x00jgo" +
+ "\x00ji\x00\x06jib\x00jmc\x00jml\x00jra\x00jut\x00jvavjwavkaatkaa\x00kab" +
+ "\x00kac\x00kad\x00kai\x00kaj\x00kam\x00kao\x00kbd\x00kbm\x00kbp\x00kbq" +
+ "\x00kbx\x00kby\x00kcg\x00kck\x00kcl\x00kct\x00kde\x00kdh\x00kdl\x00kdt" +
+ "\x00kea\x00ken\x00kez\x00kfo\x00kfr\x00kfy\x00kgonkge\x00kgf\x00kgp\x00k" +
+ "ha\x00khb\x00khn\x00khq\x00khs\x00kht\x00khw\x00khz\x00kiikkij\x00kiu" +
+ "\x00kiw\x00kjuakjd\x00kjg\x00kjs\x00kjy\x00kkazkkc\x00kkj\x00klalkln\x00" +
+ "klq\x00klt\x00klx\x00kmhmkmb\x00kmh\x00kmo\x00kms\x00kmu\x00kmw\x00knank" +
+ "nf\x00knp\x00koorkoi\x00kok\x00kol\x00kos\x00koz\x00kpe\x00kpf\x00kpo" +
+ "\x00kpr\x00kpx\x00kqb\x00kqf\x00kqs\x00kqy\x00kraukrc\x00kri\x00krj\x00k" +
+ "rl\x00krs\x00kru\x00ksasksb\x00ksd\x00ksf\x00ksh\x00ksj\x00ksr\x00ktb" +
+ "\x00ktm\x00kto\x00kuurkub\x00kud\x00kue\x00kuj\x00kum\x00kun\x00kup\x00k" +
+ "us\x00kvomkvg\x00kvr\x00kvx\x00kw\x00\x01kwj\x00kwo\x00kxa\x00kxc\x00kxm" +
+ "\x00kxp\x00kxw\x00kxz\x00kyirkye\x00kyx\x00kzr\x00laatlab\x00lad\x00lag" +
+ "\x00lah\x00laj\x00las\x00lbtzlbe\x00lbu\x00lbw\x00lcm\x00lcp\x00ldb\x00l" +
+ "ed\x00lee\x00lem\x00lep\x00leq\x00leu\x00lez\x00lguglgg\x00liimlia\x00li" +
+ "d\x00lif\x00lig\x00lih\x00lij\x00lis\x00ljp\x00lki\x00lkt\x00lle\x00lln" +
+ "\x00lmn\x00lmo\x00lmp\x00lninlns\x00lnu\x00loaoloj\x00lok\x00lol\x00lor" +
+ "\x00los\x00loz\x00lrc\x00ltitltg\x00luublua\x00luo\x00luy\x00luz\x00lvav" +
+ "lwl\x00lzh\x00lzz\x00mad\x00maf\x00mag\x00mai\x00mak\x00man\x00mas\x00ma" +
+ "w\x00maz\x00mbh\x00mbo\x00mbq\x00mbu\x00mbw\x00mci\x00mcp\x00mcq\x00mcr" +
+ "\x00mcu\x00mda\x00mde\x00mdf\x00mdh\x00mdj\x00mdr\x00mdx\x00med\x00mee" +
+ "\x00mek\x00men\x00mer\x00met\x00meu\x00mfa\x00mfe\x00mfn\x00mfo\x00mfq" +
+ "\x00mglgmgh\x00mgl\x00mgo\x00mgp\x00mgy\x00mhahmhi\x00mhl\x00mirimif\x00" +
+ "min\x00mis\x00miw\x00mkkdmki\x00mkl\x00mkp\x00mkw\x00mlalmle\x00mlp\x00m" +
+ "ls\x00mmo\x00mmu\x00mmx\x00mnonmna\x00mnf\x00mni\x00mnw\x00moolmoa\x00mo" +
+ "e\x00moh\x00mos\x00mox\x00mpp\x00mps\x00mpt\x00mpx\x00mql\x00mrarmrd\x00" +
+ "mrj\x00mro\x00mssamtltmtc\x00mtf\x00mti\x00mtr\x00mua\x00mul\x00mur\x00m" +
+ "us\x00mva\x00mvn\x00mvy\x00mwk\x00mwr\x00mwv\x00mxc\x00mxm\x00myyamyk" +
+ "\x00mym\x00myv\x00myw\x00myx\x00myz\x00mzk\x00mzm\x00mzn\x00mzp\x00mzw" +
+ "\x00mzz\x00naaunac\x00naf\x00nah\x00nak\x00nan\x00nap\x00naq\x00nas\x00n" +
+ "bobnca\x00nce\x00ncf\x00nch\x00nco\x00ncu\x00nddendc\x00nds\x00neepneb" +
+ "\x00new\x00nex\x00nfr\x00ngdonga\x00ngb\x00ngl\x00nhb\x00nhe\x00nhw\x00n" +
+ "if\x00nii\x00nij\x00nin\x00niu\x00niy\x00niz\x00njo\x00nkg\x00nko\x00nll" +
+ "dnmg\x00nmz\x00nnnonnf\x00nnh\x00nnk\x00nnm\x00noornod\x00noe\x00non\x00" +
+ "nop\x00nou\x00nqo\x00nrblnrb\x00nsk\x00nsn\x00nso\x00nss\x00ntm\x00ntr" +
+ "\x00nui\x00nup\x00nus\x00nuv\x00nux\x00nvavnwb\x00nxq\x00nxr\x00nyyanym" +
+ "\x00nyn\x00nzi\x00occiogc\x00ojjiokr\x00okv\x00omrmong\x00onn\x00ons\x00" +
+ "opm\x00orrioro\x00oru\x00osssosa\x00ota\x00otk\x00ozm\x00paanpag\x00pal" +
+ "\x00pam\x00pap\x00pau\x00pbi\x00pcd\x00pcm\x00pdc\x00pdt\x00ped\x00peo" +
+ "\x00pex\x00pfl\x00phl\x00phn\x00pilipil\x00pip\x00pka\x00pko\x00plolpla" +
+ "\x00pms\x00png\x00pnn\x00pnt\x00pon\x00ppo\x00pra\x00prd\x00prg\x00psusp" +
+ "ss\x00ptorptp\x00puu\x00pwa\x00quuequc\x00qug\x00rai\x00raj\x00rao\x00rc" +
+ "f\x00rej\x00rel\x00res\x00rgn\x00rhg\x00ria\x00rif\x00rjs\x00rkt\x00rmoh" +
+ "rmf\x00rmo\x00rmt\x00rmu\x00rnunrna\x00rng\x00roonrob\x00rof\x00roo\x00r" +
+ "ro\x00rtm\x00ruusrue\x00rug\x00rw\x00\x04rwk\x00rwo\x00ryu\x00saansaf" +
+ "\x00sah\x00saq\x00sas\x00sat\x00sav\x00saz\x00sba\x00sbe\x00sbp\x00scrds" +
+ "ck\x00scl\x00scn\x00sco\x00scs\x00sdndsdc\x00sdh\x00semesef\x00seh\x00se" +
+ "i\x00ses\x00sgagsga\x00sgs\x00sgw\x00sgz\x00sh\x00\x02shi\x00shk\x00shn" +
+ "\x00shu\x00siinsid\x00sig\x00sil\x00sim\x00sjr\x00sklkskc\x00skr\x00sks" +
+ "\x00sllvsld\x00sli\x00sll\x00sly\x00smmosma\x00smi\x00smj\x00smn\x00smp" +
+ "\x00smq\x00sms\x00snnasnc\x00snk\x00snp\x00snx\x00sny\x00soomsok\x00soq" +
+ "\x00sou\x00soy\x00spd\x00spl\x00sps\x00sqqisrrpsrb\x00srn\x00srr\x00srx" +
+ "\x00ssswssd\x00ssg\x00ssy\x00stotstk\x00stq\x00suunsua\x00sue\x00suk\x00" +
+ "sur\x00sus\x00svweswwaswb\x00swc\x00swg\x00swp\x00swv\x00sxn\x00sxw\x00s" +
+ "yl\x00syr\x00szl\x00taamtaj\x00tal\x00tan\x00taq\x00tbc\x00tbd\x00tbf" +
+ "\x00tbg\x00tbo\x00tbw\x00tbz\x00tci\x00tcy\x00tdd\x00tdg\x00tdh\x00teelt" +
+ "ed\x00tem\x00teo\x00tet\x00tfi\x00tggktgc\x00tgo\x00tgu\x00thhathl\x00th" +
+ "q\x00thr\x00tiirtif\x00tig\x00tik\x00tim\x00tio\x00tiv\x00tkuktkl\x00tkr" +
+ "\x00tkt\x00tlgltlf\x00tlx\x00tly\x00tmh\x00tmy\x00tnsntnh\x00toontof\x00" +
+ "tog\x00toq\x00tpi\x00tpm\x00tpz\x00tqo\x00trurtru\x00trv\x00trw\x00tssot" +
+ "sd\x00tsf\x00tsg\x00tsj\x00tsw\x00ttatttd\x00tte\x00ttj\x00ttr\x00tts" +
+ "\x00ttt\x00tuh\x00tul\x00tum\x00tuq\x00tvd\x00tvl\x00tvu\x00twwitwh\x00t" +
+ "wq\x00txg\x00tyahtya\x00tyv\x00tzm\x00ubu\x00udm\x00ugiguga\x00ukkruli" +
+ "\x00umb\x00und\x00unr\x00unx\x00urrduri\x00urt\x00urw\x00usa\x00utr\x00u" +
+ "vh\x00uvl\x00uzzbvag\x00vai\x00van\x00veenvec\x00vep\x00viievic\x00viv" +
+ "\x00vls\x00vmf\x00vmw\x00voolvot\x00vro\x00vun\x00vut\x00walnwae\x00waj" +
+ "\x00wal\x00wan\x00war\x00wbp\x00wbq\x00wbr\x00wci\x00wer\x00wgi\x00whg" +
+ "\x00wib\x00wiu\x00wiv\x00wja\x00wji\x00wls\x00wmo\x00wnc\x00wni\x00wnu" +
+ "\x00woolwob\x00wos\x00wrs\x00wsk\x00wtm\x00wuu\x00wuv\x00wwa\x00xav\x00x" +
+ "bi\x00xcr\x00xes\x00xhhoxla\x00xlc\x00xld\x00xmf\x00xmn\x00xmr\x00xna" +
+ "\x00xnr\x00xog\x00xon\x00xpr\x00xrb\x00xsa\x00xsi\x00xsm\x00xsr\x00xwe" +
+ "\x00yam\x00yao\x00yap\x00yas\x00yat\x00yav\x00yay\x00yaz\x00yba\x00ybb" +
+ "\x00yby\x00yer\x00ygr\x00ygw\x00yiidyko\x00yle\x00ylg\x00yll\x00yml\x00y" +
+ "ooryon\x00yrb\x00yre\x00yrl\x00yss\x00yua\x00yue\x00yuj\x00yut\x00yuw" +
+ "\x00zahazag\x00zbl\x00zdj\x00zea\x00zgh\x00zhhozhx\x00zia\x00zlm\x00zmi" +
+ "\x00zne\x00zuulzxx\x00zza\x00\xff\xff\xff\xff"
+
+const langNoIndexOffset = 1330
+
+// langNoIndex is a bit vector of all 3-letter language codes that are not used as an index
+// in lookup tables. The language ids for these language codes are derived directly
+// from the letters and are not consecutive.
+// Size: 2197 bytes, 2197 elements
+var langNoIndex = [2197]uint8{
+ // Entry 0 - 3F
+ 0xff, 0xf8, 0xed, 0xfe, 0xeb, 0xd3, 0x3b, 0xd2,
+ 0xfb, 0xbf, 0x7a, 0xfa, 0x37, 0x1d, 0x3c, 0x57,
+ 0x6e, 0x97, 0x73, 0x38, 0xfb, 0xea, 0xbf, 0x70,
+ 0xad, 0x03, 0xff, 0xff, 0xcf, 0x05, 0x84, 0x72,
+ 0xe9, 0xbf, 0xfd, 0xbf, 0xbf, 0xf7, 0xfd, 0x77,
+ 0x0f, 0xff, 0xef, 0x6f, 0xff, 0xfb, 0xdf, 0xe2,
+ 0xc9, 0xf8, 0x7f, 0x7e, 0x4d, 0xbc, 0x0a, 0x6a,
+ 0x7c, 0xea, 0xe3, 0xfa, 0x7a, 0xbf, 0x67, 0xff,
+ // Entry 40 - 7F
+ 0xff, 0xff, 0xff, 0xdf, 0x2a, 0x54, 0x91, 0xc0,
+ 0x5d, 0xe3, 0x97, 0x14, 0x07, 0x20, 0xdd, 0xed,
+ 0x9f, 0x3f, 0xc9, 0x21, 0xf8, 0x3f, 0x94, 0x35,
+ 0x7c, 0x5f, 0xff, 0x5f, 0x8e, 0x6e, 0xdf, 0xff,
+ 0xff, 0xff, 0x55, 0x7c, 0xd3, 0xfd, 0xbf, 0xb5,
+ 0x7b, 0xdf, 0x7f, 0xf7, 0xca, 0xfe, 0xdb, 0xa3,
+ 0xa8, 0xff, 0x1f, 0x67, 0x7d, 0xeb, 0xef, 0xce,
+ 0xff, 0xff, 0x9f, 0xff, 0xb7, 0xef, 0xfe, 0xcf,
+ // Entry 80 - BF
+ 0xdb, 0xff, 0xf3, 0xcd, 0xfb, 0x7f, 0xff, 0xff,
+ 0xbb, 0xee, 0xf7, 0xbd, 0xdb, 0xff, 0x5f, 0xf7,
+ 0xfd, 0xf2, 0xfd, 0xff, 0x5e, 0x2f, 0x3b, 0xba,
+ 0x7e, 0xff, 0xff, 0xfe, 0xf7, 0xff, 0xdd, 0xff,
+ 0xfd, 0xdf, 0xfb, 0xfe, 0x9d, 0xb4, 0xd3, 0xff,
+ 0xef, 0xff, 0xdf, 0xf7, 0x7f, 0xb7, 0xfd, 0xd5,
+ 0xa5, 0x77, 0x40, 0xff, 0x9c, 0xc1, 0x41, 0x2c,
+ 0x08, 0x21, 0x41, 0x00, 0x50, 0x40, 0x00, 0x80,
+ // Entry C0 - FF
+ 0xfb, 0x4a, 0xf2, 0x9f, 0xb4, 0x42, 0x41, 0x96,
+ 0x1b, 0x14, 0x08, 0xf3, 0x2b, 0xe7, 0x17, 0x56,
+ 0x05, 0x7d, 0x0e, 0x1c, 0x37, 0x7f, 0xf3, 0xef,
+ 0x97, 0xff, 0x5d, 0x38, 0x64, 0x08, 0x00, 0x10,
+ 0xbc, 0x85, 0xaf, 0xdf, 0xff, 0xff, 0x7b, 0x35,
+ 0x3e, 0xc7, 0xc7, 0xdf, 0xff, 0x01, 0x81, 0x00,
+ 0xb0, 0x05, 0x80, 0x00, 0x20, 0x00, 0x00, 0x03,
+ 0x40, 0x00, 0x40, 0x92, 0x21, 0x50, 0xb1, 0x5d,
+ // Entry 100 - 13F
+ 0xfd, 0xdc, 0xbe, 0x5e, 0x00, 0x00, 0x02, 0x64,
+ 0x0d, 0x19, 0x41, 0xdf, 0x79, 0x22, 0x00, 0x00,
+ 0x00, 0x5e, 0x64, 0xdc, 0x24, 0xe5, 0xd9, 0xe3,
+ 0xfe, 0xff, 0xfd, 0xcb, 0x9f, 0x14, 0x41, 0x0c,
+ 0x86, 0x00, 0xd1, 0x00, 0xf0, 0xc7, 0x67, 0x5f,
+ 0x56, 0x99, 0x5e, 0xb5, 0x6c, 0xaf, 0x03, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xc0, 0x37, 0xda, 0x56,
+ 0x90, 0x6d, 0x01, 0x2e, 0x96, 0x69, 0x20, 0xfb,
+ // Entry 140 - 17F
+ 0xff, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x16,
+ 0x03, 0x00, 0x00, 0xb0, 0x14, 0x23, 0x50, 0x06,
+ 0x0a, 0x00, 0x01, 0x00, 0x00, 0x10, 0x11, 0x09,
+ 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x44, 0x00, 0x00, 0x10, 0x00, 0x05,
+ 0x08, 0x00, 0x00, 0x05, 0x00, 0x80, 0x28, 0x04,
+ 0x00, 0x00, 0x40, 0xd5, 0x2d, 0x00, 0x64, 0x35,
+ 0x24, 0x52, 0xf4, 0xd5, 0xbf, 0x62, 0xc9, 0x03,
+ // Entry 180 - 1BF
+ 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x13, 0x39, 0x01, 0xdd, 0x57, 0x98,
+ 0x21, 0x18, 0x81, 0x08, 0x00, 0x01, 0x40, 0x82,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x40, 0x00, 0x44, 0x00, 0x00, 0x80, 0xea,
+ 0xa9, 0x39, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ // Entry 1C0 - 1FF
+ 0x00, 0x03, 0x28, 0x05, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x20, 0x04, 0xa6, 0x00, 0x04, 0x00, 0x00,
+ 0x81, 0x50, 0x00, 0x00, 0x00, 0x11, 0x84, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x55,
+ 0x02, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x40,
+ 0x30, 0x83, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1e, 0xcd, 0xbf, 0x7a, 0xbf,
+ // Entry 200 - 23F
+ 0xdf, 0xc3, 0x83, 0x82, 0xc0, 0xfb, 0x57, 0x27,
+ 0xed, 0x55, 0xe7, 0x01, 0x00, 0x20, 0xb2, 0xc5,
+ 0xa4, 0x45, 0x25, 0x9b, 0x02, 0xdf, 0xe1, 0xdf,
+ 0x03, 0x44, 0x08, 0x90, 0x01, 0x04, 0x81, 0xe3,
+ 0x92, 0x54, 0xdb, 0x28, 0xd3, 0x5f, 0xfe, 0x6d,
+ 0x79, 0xed, 0x1c, 0x7f, 0x04, 0x08, 0x00, 0x01,
+ 0x21, 0x12, 0x64, 0x5f, 0xdd, 0x0e, 0x85, 0x4f,
+ 0x40, 0x40, 0x00, 0x04, 0xf1, 0xfd, 0x3d, 0x54,
+ // Entry 240 - 27F
+ 0xe8, 0x03, 0xb4, 0x27, 0x23, 0x0d, 0x00, 0x00,
+ 0x20, 0x7b, 0x78, 0x02, 0x07, 0x84, 0x00, 0xf0,
+ 0xbb, 0x7e, 0x5a, 0x00, 0x18, 0x04, 0x81, 0x00,
+ 0x00, 0x00, 0x80, 0x10, 0x90, 0x1c, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x04,
+ 0x08, 0xa0, 0x70, 0xa5, 0x0c, 0x40, 0x00, 0x00,
+ 0x91, 0x24, 0x04, 0x68, 0x00, 0x20, 0x70, 0xff,
+ 0x7b, 0x7f, 0x70, 0x00, 0x05, 0x9b, 0xdd, 0x66,
+ // Entry 280 - 2BF
+ 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, 0x40, 0x05,
+ 0xb5, 0xb6, 0x80, 0x08, 0x04, 0x00, 0x04, 0x51,
+ 0xe2, 0xef, 0xfd, 0x3f, 0x05, 0x09, 0x08, 0x05,
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x60,
+ 0xe7, 0x48, 0x00, 0x81, 0x20, 0xc0, 0x05, 0x80,
+ 0x03, 0x00, 0x00, 0x00, 0x8c, 0x50, 0x40, 0x04,
+ 0x84, 0x47, 0x84, 0x40, 0x20, 0x10, 0x00, 0x20,
+ // Entry 2C0 - 2FF
+ 0x02, 0x50, 0x80, 0x11, 0x00, 0x99, 0x6c, 0xe2,
+ 0x50, 0x27, 0x1d, 0x11, 0x29, 0x0e, 0x59, 0xe9,
+ 0x33, 0x08, 0x00, 0x20, 0x04, 0x40, 0x10, 0x00,
+ 0x00, 0x00, 0x50, 0x44, 0x92, 0x49, 0xd6, 0x5d,
+ 0xa7, 0x81, 0x47, 0x97, 0xfb, 0x00, 0x10, 0x00,
+ 0x08, 0x00, 0x80, 0x00, 0x40, 0x04, 0x00, 0x01,
+ 0x02, 0x00, 0x01, 0x40, 0x80, 0x00, 0x40, 0x08,
+ 0xd8, 0xeb, 0xf6, 0x39, 0xc4, 0x8d, 0x12, 0x00,
+ // Entry 300 - 33F
+ 0x00, 0x0c, 0x04, 0x01, 0x20, 0x20, 0xdd, 0xa0,
+ 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+ 0x04, 0x10, 0xd0, 0x9d, 0x95, 0x13, 0x04, 0x80,
+ 0x00, 0x01, 0xd0, 0x16, 0x40, 0x00, 0x10, 0xb0,
+ 0x10, 0x62, 0x4c, 0xd2, 0x02, 0x01, 0x4a, 0x00,
+ 0x46, 0x04, 0x00, 0x08, 0x02, 0x00, 0x20, 0x80,
+ 0x00, 0x80, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0xf0, 0xd8, 0x6f, 0x15, 0x02, 0x08, 0x00,
+ // Entry 340 - 37F
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0xf0, 0x84, 0xe3,
+ 0xdd, 0xbf, 0xf9, 0xf9, 0x3b, 0x7f, 0x7f, 0xdb,
+ 0xfd, 0xfc, 0xfe, 0xdf, 0xff, 0xfd, 0xff, 0xf6,
+ 0xfb, 0xfc, 0xf7, 0x1f, 0xff, 0xb3, 0x6c, 0xff,
+ 0xd9, 0xad, 0xdf, 0xfe, 0xef, 0xba, 0xdf, 0xff,
+ 0xff, 0xff, 0xb7, 0xdd, 0x7d, 0xbf, 0xab, 0x7f,
+ 0xfd, 0xfd, 0xdf, 0x2f, 0x9c, 0xdf, 0xf3, 0x6f,
+ // Entry 380 - 3BF
+ 0xdf, 0xdd, 0xff, 0xfb, 0xee, 0xd2, 0xab, 0x5f,
+ 0xd5, 0xdf, 0x7f, 0xff, 0xeb, 0xff, 0xe4, 0x4d,
+ 0xf9, 0xff, 0xfe, 0xf7, 0xfd, 0xdf, 0xfb, 0xbf,
+ 0xee, 0xdb, 0x6f, 0xef, 0xff, 0x7f, 0xff, 0xff,
+ 0xf7, 0x5f, 0xd3, 0x3b, 0xfd, 0xd9, 0xdf, 0xeb,
+ 0xbc, 0x08, 0x05, 0x24, 0xff, 0x07, 0x70, 0xfe,
+ 0xe6, 0x5e, 0x00, 0x08, 0x00, 0x83, 0x7d, 0x1f,
+ 0x06, 0xe6, 0x72, 0x60, 0xd1, 0x3c, 0x7f, 0x44,
+ // Entry 3C0 - 3FF
+ 0x02, 0x30, 0x9f, 0x7a, 0x16, 0xbd, 0x7f, 0x57,
+ 0xf2, 0xff, 0x31, 0xff, 0xf2, 0x1e, 0x90, 0xf7,
+ 0xf1, 0xf9, 0x45, 0x80, 0x01, 0x02, 0x00, 0x20,
+ 0x40, 0x54, 0x9f, 0x8a, 0xdf, 0xf9, 0x6e, 0x11,
+ 0x86, 0x51, 0xc0, 0xf3, 0xfb, 0x47, 0x40, 0x03,
+ 0x05, 0xd1, 0x50, 0x5c, 0x00, 0x40, 0x00, 0x10,
+ 0x04, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x17, 0xd2,
+ 0xb9, 0xfd, 0xfc, 0xba, 0xfe, 0xef, 0xc7, 0xbe,
+ // Entry 400 - 43F
+ 0x53, 0x6f, 0xdf, 0xe7, 0xdb, 0x65, 0xbb, 0x7f,
+ 0xfa, 0xff, 0x77, 0xf3, 0xef, 0xbf, 0xfd, 0xf7,
+ 0xdf, 0xdf, 0x9b, 0x7f, 0xff, 0xff, 0x7f, 0x6f,
+ 0xf7, 0xfb, 0xeb, 0xdf, 0xbc, 0xff, 0xbf, 0x6b,
+ 0x7b, 0xfb, 0xff, 0xce, 0x76, 0xbd, 0xf7, 0xf7,
+ 0xdf, 0xdc, 0xf7, 0xf7, 0xff, 0xdf, 0xf3, 0xfe,
+ 0xef, 0xff, 0xff, 0xff, 0xb6, 0x7f, 0x7f, 0xde,
+ 0xf7, 0xb9, 0xeb, 0x77, 0xff, 0xfb, 0xbf, 0xdf,
+ // Entry 440 - 47F
+ 0xfd, 0xfe, 0xfb, 0xff, 0xfe, 0xeb, 0x1f, 0x7d,
+ 0x2f, 0xfd, 0xb6, 0xb5, 0xa5, 0xfc, 0xff, 0xfd,
+ 0x7f, 0x4e, 0xbf, 0x8f, 0xae, 0xff, 0xee, 0xdf,
+ 0x7f, 0xf7, 0x73, 0x02, 0x02, 0x04, 0xfc, 0xf7,
+ 0xff, 0xb7, 0xd7, 0xef, 0xfe, 0xcd, 0xf5, 0xce,
+ 0xe2, 0x8e, 0xe7, 0xbf, 0xb7, 0xff, 0x56, 0xfd,
+ 0xcd, 0xff, 0xfb, 0xff, 0xdf, 0xd7, 0xea, 0xff,
+ 0xe5, 0x5f, 0x6d, 0x0f, 0xa7, 0x51, 0x06, 0xc4,
+ // Entry 480 - 4BF
+ 0x93, 0x50, 0x5d, 0xaf, 0xa6, 0xff, 0x99, 0xfb,
+ 0x63, 0x1d, 0x53, 0xff, 0xef, 0xb7, 0x35, 0x20,
+ 0x14, 0x00, 0x55, 0x51, 0xc2, 0x65, 0xf5, 0x41,
+ 0xe2, 0xff, 0xfc, 0xdf, 0x02, 0x85, 0xc5, 0x05,
+ 0x00, 0x22, 0x00, 0x74, 0x69, 0x10, 0x08, 0x05,
+ 0x41, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x51, 0x20, 0x05, 0x04, 0x01, 0x00, 0x00,
+ 0x06, 0x11, 0x20, 0x00, 0x18, 0x01, 0x92, 0xf1,
+ // Entry 4C0 - 4FF
+ 0xfd, 0x47, 0x69, 0x06, 0x95, 0x06, 0x57, 0xed,
+ 0xfb, 0x4d, 0x1c, 0x6b, 0x83, 0x04, 0x62, 0x40,
+ 0x00, 0x11, 0x42, 0x00, 0x00, 0x00, 0x54, 0x83,
+ 0xb8, 0x4f, 0x10, 0x8e, 0x89, 0x46, 0xde, 0xf7,
+ 0x13, 0x31, 0x00, 0x20, 0x00, 0x00, 0x00, 0x90,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x00,
+ 0x01, 0x00, 0x00, 0xf0, 0x5b, 0xf4, 0xbe, 0x3d,
+ 0xbe, 0xcf, 0xf7, 0xaf, 0x42, 0x04, 0x84, 0x41,
+ // Entry 500 - 53F
+ 0x30, 0xff, 0x79, 0x72, 0x04, 0x00, 0x00, 0x49,
+ 0x2d, 0x14, 0x27, 0x5f, 0xed, 0xf1, 0x3f, 0xe7,
+ 0x3f, 0x00, 0x00, 0x02, 0xc6, 0xa0, 0x1e, 0xf8,
+ 0xbb, 0xff, 0xfd, 0xfb, 0xb7, 0xfd, 0xe7, 0xf7,
+ 0xfd, 0xfc, 0xd5, 0xed, 0x47, 0xf4, 0x7e, 0x10,
+ 0x01, 0x01, 0x84, 0x6d, 0xff, 0xf7, 0xdd, 0xf9,
+ 0x5b, 0x05, 0x86, 0xed, 0xf5, 0x77, 0xbd, 0x3c,
+ 0x00, 0x00, 0x00, 0x42, 0x71, 0x42, 0x00, 0x40,
+ // Entry 540 - 57F
+ 0x00, 0x00, 0x01, 0x43, 0x19, 0x24, 0x08, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ // Entry 580 - 5BF
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xab, 0xbd, 0xe7, 0x57, 0xee, 0x13, 0x5d,
+ 0x09, 0xc1, 0x40, 0x21, 0xfa, 0x17, 0x01, 0x80,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0xce, 0xfb, 0xbf,
+ 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x30, 0x15, 0xa3, 0x10, 0x00, 0x00, 0x00,
+ 0x11, 0x04, 0x16, 0x00, 0x00, 0x02, 0x20, 0x81,
+ 0xa3, 0x01, 0x50, 0x00, 0x00, 0x83, 0x11, 0x40,
+ // Entry 5C0 - 5FF
+ 0x00, 0x00, 0x00, 0xf0, 0xdd, 0x7b, 0xbe, 0x02,
+ 0xaa, 0x10, 0x5d, 0x98, 0x52, 0x00, 0x80, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x02,
+ 0x3d, 0x40, 0x10, 0x02, 0x10, 0x61, 0x5a, 0x9d,
+ 0x31, 0x00, 0x00, 0x00, 0x01, 0x18, 0x02, 0x20,
+ 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x20, 0x00,
+ 0x00, 0x1f, 0xdf, 0xd2, 0xb9, 0xff, 0xfd, 0x3f,
+ 0x1f, 0x98, 0xcf, 0x9c, 0xff, 0xaf, 0x5f, 0xfe,
+ // Entry 600 - 63F
+ 0x7b, 0x4b, 0x40, 0x10, 0xe1, 0xfd, 0xaf, 0xd9,
+ 0xb7, 0xf6, 0xfb, 0xb3, 0xc7, 0xff, 0x6f, 0xf1,
+ 0x73, 0xb1, 0x7f, 0x9f, 0x7f, 0xbd, 0xfc, 0xb7,
+ 0xee, 0x1c, 0xfa, 0xcb, 0xef, 0xdd, 0xf9, 0xbd,
+ 0x6e, 0xae, 0x55, 0xfd, 0x6e, 0x81, 0x76, 0x9f,
+ 0xd4, 0x77, 0xf5, 0x7d, 0xfb, 0xff, 0xeb, 0xfe,
+ 0xbe, 0x5f, 0x46, 0x5b, 0xe9, 0x5f, 0x50, 0x18,
+ 0x02, 0xfa, 0xf7, 0x9d, 0x15, 0x97, 0x05, 0x0f,
+ // Entry 640 - 67F
+ 0x75, 0xc4, 0x7d, 0x81, 0x92, 0xf5, 0x57, 0x6c,
+ 0xff, 0xe4, 0xef, 0x6f, 0xff, 0xfc, 0xdd, 0xde,
+ 0xfc, 0xfd, 0x76, 0x5f, 0x7a, 0x3f, 0x00, 0x98,
+ 0x02, 0xfb, 0xa3, 0xef, 0xf3, 0xd6, 0xf2, 0xff,
+ 0xb9, 0xda, 0x7d, 0xd0, 0x3e, 0x15, 0x7b, 0xb4,
+ 0xf5, 0x3e, 0xff, 0xff, 0xf1, 0xf7, 0xff, 0xe7,
+ 0x5f, 0xff, 0xff, 0x9e, 0xdf, 0xf6, 0xd7, 0xb9,
+ 0xef, 0x27, 0x80, 0xbb, 0xc5, 0xff, 0xff, 0xe3,
+ // Entry 680 - 6BF
+ 0x97, 0x9d, 0xbf, 0x9f, 0xf7, 0xc7, 0xfd, 0x37,
+ 0xce, 0x7f, 0x44, 0x1d, 0x73, 0x7f, 0xf8, 0xda,
+ 0x5d, 0xce, 0x7d, 0x06, 0xb9, 0xea, 0x79, 0xa0,
+ 0x1a, 0x20, 0x00, 0x30, 0x02, 0x04, 0x24, 0x08,
+ 0x04, 0x00, 0x00, 0x40, 0xd4, 0x02, 0x04, 0x00,
+ 0x00, 0x04, 0x00, 0x04, 0x00, 0x20, 0x09, 0x06,
+ 0x50, 0x00, 0x08, 0x00, 0x00, 0x00, 0x24, 0x00,
+ 0x04, 0x00, 0x10, 0xdc, 0x58, 0xd7, 0x0d, 0x0f,
+ // Entry 6C0 - 6FF
+ 0x54, 0x4d, 0xf1, 0x16, 0x44, 0xd5, 0x42, 0x08,
+ 0x40, 0x02, 0x00, 0x40, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0xdc, 0xfb, 0xcb, 0x0e, 0x58, 0x48, 0x41,
+ 0x24, 0x20, 0x04, 0x00, 0x30, 0x12, 0x40, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x80, 0x10, 0x10, 0xab,
+ 0x6d, 0x93, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x80, 0x25, 0x00, 0x00,
+ // Entry 700 - 73F
+ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x80, 0x86, 0xc2, 0x00, 0x00, 0x01, 0x00, 0x01,
+ 0xff, 0x18, 0x02, 0x00, 0x02, 0xf0, 0xfd, 0x79,
+ 0x3b, 0x00, 0x25, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x03, 0x00, 0x09, 0x20, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 740 - 77F
+ 0x00, 0x00, 0x00, 0xef, 0xd5, 0xfd, 0xcf, 0x7e,
+ 0xb0, 0x11, 0x00, 0x00, 0x00, 0x92, 0x01, 0x46,
+ 0xcd, 0xf9, 0x5c, 0x00, 0x01, 0x00, 0x30, 0x04,
+ 0x04, 0x55, 0x00, 0x01, 0x04, 0xf4, 0x3f, 0x4a,
+ 0x01, 0x00, 0x00, 0xb0, 0x80, 0x20, 0x55, 0x75,
+ 0x97, 0x7c, 0xdf, 0x31, 0xcc, 0x68, 0xd1, 0x03,
+ 0xd5, 0x57, 0x27, 0x14, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x2c, 0xf7, 0xcb, 0x1f, 0x14, 0x60,
+ // Entry 780 - 7BF
+ 0x83, 0x68, 0x01, 0x10, 0x8b, 0x38, 0x8a, 0x01,
+ 0x00, 0x00, 0x20, 0x00, 0x24, 0x44, 0x00, 0x00,
+ 0x10, 0x03, 0x31, 0x02, 0x01, 0x00, 0x00, 0xf0,
+ 0xf5, 0xff, 0xd5, 0x97, 0xbc, 0x70, 0xd6, 0x78,
+ 0x78, 0x15, 0x50, 0x05, 0xa4, 0x84, 0xa9, 0x41,
+ 0x00, 0x00, 0x00, 0x6b, 0x39, 0x52, 0x74, 0x40,
+ 0xe8, 0x30, 0x90, 0x6a, 0x92, 0x00, 0x00, 0x02,
+ 0xff, 0xef, 0xff, 0x4b, 0x85, 0x53, 0xf4, 0xed,
+ // Entry 7C0 - 7FF
+ 0xdd, 0xbf, 0xf2, 0x5d, 0xc7, 0x0c, 0xd5, 0x42,
+ 0xfc, 0xff, 0xf7, 0x1f, 0x00, 0x80, 0x40, 0x56,
+ 0xcc, 0x16, 0x9e, 0xea, 0x35, 0x7d, 0xef, 0xff,
+ 0xbd, 0xa4, 0xaf, 0x01, 0x44, 0x18, 0x01, 0x4d,
+ 0x4e, 0x4a, 0x08, 0x50, 0x28, 0x30, 0xe0, 0x80,
+ 0x10, 0x20, 0x24, 0x00, 0xff, 0x2f, 0xd3, 0x60,
+ 0xfe, 0x01, 0x02, 0x88, 0x2a, 0x40, 0x16, 0x01,
+ 0x01, 0x15, 0x2b, 0x3c, 0x01, 0x00, 0x00, 0x10,
+ // Entry 800 - 83F
+ 0x90, 0x49, 0x41, 0x02, 0x02, 0x01, 0xe1, 0xbf,
+ 0xbf, 0x03, 0x00, 0x00, 0x10, 0xdc, 0xa3, 0xd1,
+ 0x40, 0x9c, 0x44, 0xdf, 0xf5, 0x8f, 0x66, 0xb3,
+ 0x55, 0x20, 0xd4, 0xc1, 0xd8, 0x30, 0x3d, 0x80,
+ 0x00, 0x00, 0x00, 0x04, 0xd4, 0x11, 0xc5, 0x84,
+ 0x2f, 0x50, 0x00, 0x22, 0x50, 0x6e, 0xbd, 0x93,
+ 0x07, 0x00, 0x20, 0x10, 0x84, 0xb2, 0x45, 0x10,
+ 0x06, 0x44, 0x00, 0x00, 0x12, 0x02, 0x11, 0x00,
+ // Entry 840 - 87F
+ 0xf0, 0xfb, 0xfd, 0x7f, 0x05, 0x00, 0x16, 0x89,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x30, 0x02, 0x28,
+ 0x84, 0x00, 0x21, 0xc0, 0x23, 0x24, 0x00, 0x00,
+ 0x00, 0xcb, 0xe4, 0x3a, 0x46, 0x88, 0x54, 0xf1,
+ 0xef, 0xff, 0x7f, 0x12, 0x01, 0x01, 0x84, 0x50,
+ 0x07, 0xfc, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x40,
+ 0x10, 0x38, 0x01, 0x01, 0x1c, 0x12, 0x40, 0xe1,
+ // Entry 880 - 8BF
+ 0x76, 0x16, 0x08, 0x03, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x24,
+ 0x0a, 0x00, 0x80, 0x00, 0x00,
+}
+
+// altLangISO3 holds an alphabetically sorted list of 3-letter language code alternatives
+// to 2-letter language codes that cannot be derived using the method described above.
+// Each 3-letter code is followed by its 1-byte langID.
+const altLangISO3 tag.Index = "---\x00cor\x00hbs\x01heb\x02kin\x03spa\x04yid\x05\xff\xff\xff\xff"
+
+// altLangIndex is used to convert indexes in altLangISO3 to langIDs.
+// Size: 12 bytes, 6 elements
+var altLangIndex = [6]uint16{
+ 0x0281, 0x0407, 0x01fb, 0x03e5, 0x013e, 0x0208,
+}
+
+// AliasMap maps langIDs to their suggested replacements.
+// Size: 772 bytes, 193 elements
+var AliasMap = [193]FromTo{
+ 0: {From: 0x82, To: 0x88},
+ 1: {From: 0x187, To: 0x1ae},
+ 2: {From: 0x1f3, To: 0x1e1},
+ 3: {From: 0x1fb, To: 0x1bc},
+ 4: {From: 0x208, To: 0x512},
+ 5: {From: 0x20f, To: 0x20e},
+ 6: {From: 0x310, To: 0x3dc},
+ 7: {From: 0x347, To: 0x36f},
+ 8: {From: 0x407, To: 0x432},
+ 9: {From: 0x47a, To: 0x153},
+ 10: {From: 0x490, To: 0x451},
+ 11: {From: 0x4a2, To: 0x21},
+ 12: {From: 0x53e, To: 0x544},
+ 13: {From: 0x58f, To: 0x12d},
+ 14: {From: 0x62b, To: 0x34},
+ 15: {From: 0x62f, To: 0x14},
+ 16: {From: 0x630, To: 0x1eb1},
+ 17: {From: 0x651, To: 0x431},
+ 18: {From: 0x662, To: 0x431},
+ 19: {From: 0x6ed, To: 0x3a},
+ 20: {From: 0x6f8, To: 0x1d7},
+ 21: {From: 0x709, To: 0x3625},
+ 22: {From: 0x73e, To: 0x21a1},
+ 23: {From: 0x7b3, To: 0x56},
+ 24: {From: 0x7b9, To: 0x299b},
+ 25: {From: 0x7c5, To: 0x58},
+ 26: {From: 0x7e6, To: 0x145},
+ 27: {From: 0x80c, To: 0x5a},
+ 28: {From: 0x815, To: 0x8d},
+ 29: {From: 0x87e, To: 0x810},
+ 30: {From: 0x8a8, To: 0x8b7},
+ 31: {From: 0x8c3, To: 0xee3},
+ 32: {From: 0x8fa, To: 0x1dc},
+ 33: {From: 0x9ef, To: 0x331},
+ 34: {From: 0xa36, To: 0x2c5},
+ 35: {From: 0xa3d, To: 0xbf},
+ 36: {From: 0xabe, To: 0x3322},
+ 37: {From: 0xb38, To: 0x529},
+ 38: {From: 0xb75, To: 0x265a},
+ 39: {From: 0xb7e, To: 0xbc3},
+ 40: {From: 0xb9b, To: 0x44e},
+ 41: {From: 0xbbc, To: 0x4229},
+ 42: {From: 0xbbf, To: 0x529},
+ 43: {From: 0xbfe, To: 0x2da7},
+ 44: {From: 0xc2e, To: 0x3181},
+ 45: {From: 0xcb9, To: 0xf3},
+ 46: {From: 0xd08, To: 0xfa},
+ 47: {From: 0xdc8, To: 0x11a},
+ 48: {From: 0xdd7, To: 0x32d},
+ 49: {From: 0xdf8, To: 0xdfb},
+ 50: {From: 0xdfe, To: 0x531},
+ 51: {From: 0xe01, To: 0xdf3},
+ 52: {From: 0xedf, To: 0x205a},
+ 53: {From: 0xee9, To: 0x222e},
+ 54: {From: 0xeee, To: 0x2e9a},
+ 55: {From: 0xf39, To: 0x367},
+ 56: {From: 0x10d0, To: 0x140},
+ 57: {From: 0x1104, To: 0x2d0},
+ 58: {From: 0x11a0, To: 0x1ec},
+ 59: {From: 0x1279, To: 0x21},
+ 60: {From: 0x1424, To: 0x15e},
+ 61: {From: 0x1470, To: 0x14e},
+ 62: {From: 0x151f, To: 0xd9b},
+ 63: {From: 0x1523, To: 0x390},
+ 64: {From: 0x1532, To: 0x19f},
+ 65: {From: 0x1580, To: 0x210},
+ 66: {From: 0x1583, To: 0x10d},
+ 67: {From: 0x15a3, To: 0x3caf},
+ 68: {From: 0x1630, To: 0x222e},
+ 69: {From: 0x166a, To: 0x19b},
+ 70: {From: 0x16c8, To: 0x136},
+ 71: {From: 0x1700, To: 0x29f8},
+ 72: {From: 0x1718, To: 0x194},
+ 73: {From: 0x1727, To: 0xf3f},
+ 74: {From: 0x177a, To: 0x178},
+ 75: {From: 0x1809, To: 0x17b6},
+ 76: {From: 0x1816, To: 0x18f3},
+ 77: {From: 0x188a, To: 0x436},
+ 78: {From: 0x1979, To: 0x1d01},
+ 79: {From: 0x1a74, To: 0x2bb0},
+ 80: {From: 0x1a8a, To: 0x1f8},
+ 81: {From: 0x1b5a, To: 0x1fa},
+ 82: {From: 0x1b86, To: 0x1515},
+ 83: {From: 0x1d64, To: 0x2c9b},
+ 84: {From: 0x2038, To: 0x37b1},
+ 85: {From: 0x203d, To: 0x20dd},
+ 86: {From: 0x2042, To: 0x2e00},
+ 87: {From: 0x205a, To: 0x30b},
+ 88: {From: 0x20e3, To: 0x274},
+ 89: {From: 0x20ee, To: 0x263},
+ 90: {From: 0x20f2, To: 0x22d},
+ 91: {From: 0x20f9, To: 0x256},
+ 92: {From: 0x210f, To: 0x21eb},
+ 93: {From: 0x2135, To: 0x27d},
+ 94: {From: 0x2160, To: 0x913},
+ 95: {From: 0x2199, To: 0x121},
+ 96: {From: 0x21ce, To: 0x1561},
+ 97: {From: 0x21e6, To: 0x504},
+ 98: {From: 0x21f4, To: 0x49f},
+ 99: {From: 0x21fb, To: 0x269},
+ 100: {From: 0x222d, To: 0x121},
+ 101: {From: 0x2237, To: 0x121},
+ 102: {From: 0x2248, To: 0x217d},
+ 103: {From: 0x2262, To: 0x92a},
+ 104: {From: 0x2316, To: 0x3226},
+ 105: {From: 0x236a, To: 0x2835},
+ 106: {From: 0x2382, To: 0x3365},
+ 107: {From: 0x2472, To: 0x2c7},
+ 108: {From: 0x24e4, To: 0x2ff},
+ 109: {From: 0x24f0, To: 0x2fa},
+ 110: {From: 0x24fa, To: 0x31f},
+ 111: {From: 0x2550, To: 0xb5b},
+ 112: {From: 0x25a9, To: 0xe2},
+ 113: {From: 0x263e, To: 0x2d0},
+ 114: {From: 0x26c9, To: 0x26b4},
+ 115: {From: 0x26f9, To: 0x3c8},
+ 116: {From: 0x2727, To: 0x3caf},
+ 117: {From: 0x2755, To: 0x6a4},
+ 118: {From: 0x2765, To: 0x26b4},
+ 119: {From: 0x2789, To: 0x4358},
+ 120: {From: 0x27c9, To: 0x2001},
+ 121: {From: 0x28ea, To: 0x27b1},
+ 122: {From: 0x28ef, To: 0x2837},
+ 123: {From: 0x28fe, To: 0xaa5},
+ 124: {From: 0x2914, To: 0x351},
+ 125: {From: 0x2986, To: 0x2da7},
+ 126: {From: 0x29f0, To: 0x96b},
+ 127: {From: 0x2b1a, To: 0x38d},
+ 128: {From: 0x2bfc, To: 0x395},
+ 129: {From: 0x2c3f, To: 0x3caf},
+ 130: {From: 0x2ce1, To: 0x2201},
+ 131: {From: 0x2cfc, To: 0x3be},
+ 132: {From: 0x2d13, To: 0x597},
+ 133: {From: 0x2d47, To: 0x148},
+ 134: {From: 0x2d48, To: 0x148},
+ 135: {From: 0x2dff, To: 0x2f1},
+ 136: {From: 0x2e08, To: 0x19cc},
+ 137: {From: 0x2e10, To: 0xc45},
+ 138: {From: 0x2e1a, To: 0x2d95},
+ 139: {From: 0x2e21, To: 0x292},
+ 140: {From: 0x2e54, To: 0x7d},
+ 141: {From: 0x2e65, To: 0x2282},
+ 142: {From: 0x2e97, To: 0x1a4},
+ 143: {From: 0x2ea0, To: 0x2e9b},
+ 144: {From: 0x2eef, To: 0x2ed7},
+ 145: {From: 0x3193, To: 0x3c4},
+ 146: {From: 0x3366, To: 0x338e},
+ 147: {From: 0x342a, To: 0x3dc},
+ 148: {From: 0x34ee, To: 0x18d0},
+ 149: {From: 0x35c8, To: 0x2c9b},
+ 150: {From: 0x35e6, To: 0x412},
+ 151: {From: 0x35f5, To: 0x24b},
+ 152: {From: 0x360d, To: 0x1dc},
+ 153: {From: 0x3658, To: 0x246},
+ 154: {From: 0x3676, To: 0x3f4},
+ 155: {From: 0x36fd, To: 0x445},
+ 156: {From: 0x3747, To: 0x3b42},
+ 157: {From: 0x37c0, To: 0x121},
+ 158: {From: 0x3816, To: 0x38f2},
+ 159: {From: 0x382a, To: 0x2b48},
+ 160: {From: 0x382b, To: 0x2c9b},
+ 161: {From: 0x382f, To: 0xa9},
+ 162: {From: 0x3832, To: 0x3228},
+ 163: {From: 0x386c, To: 0x39a6},
+ 164: {From: 0x3892, To: 0x3fc0},
+ 165: {From: 0x38a0, To: 0x45f},
+ 166: {From: 0x38a5, To: 0x39d7},
+ 167: {From: 0x38b4, To: 0x1fa4},
+ 168: {From: 0x38b5, To: 0x2e9a},
+ 169: {From: 0x38fa, To: 0x38f1},
+ 170: {From: 0x395c, To: 0x47e},
+ 171: {From: 0x3b4e, To: 0xd91},
+ 172: {From: 0x3b78, To: 0x137},
+ 173: {From: 0x3c99, To: 0x4bc},
+ 174: {From: 0x3fbd, To: 0x100},
+ 175: {From: 0x4208, To: 0xa91},
+ 176: {From: 0x42be, To: 0x573},
+ 177: {From: 0x42f9, To: 0x3f60},
+ 178: {From: 0x4378, To: 0x25a},
+ 179: {From: 0x43b8, To: 0xe6c},
+ 180: {From: 0x43cd, To: 0x10f},
+ 181: {From: 0x43d4, To: 0x4848},
+ 182: {From: 0x44af, To: 0x3322},
+ 183: {From: 0x44e3, To: 0x512},
+ 184: {From: 0x45ca, To: 0x2409},
+ 185: {From: 0x45dd, To: 0x26dc},
+ 186: {From: 0x4610, To: 0x48ae},
+ 187: {From: 0x46ae, To: 0x46a0},
+ 188: {From: 0x473e, To: 0x4745},
+ 189: {From: 0x4817, To: 0x3503},
+ 190: {From: 0x483b, To: 0x208b},
+ 191: {From: 0x4916, To: 0x31f},
+ 192: {From: 0x49a7, To: 0x523},
+}
+
+// Size: 193 bytes, 193 elements
+var AliasTypes = [193]AliasType{
+ // Entry 0 - 3F
+ 1, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 1, 0, 0, 0, 0,
+ 1, 2, 1, 1, 2, 0, 0, 1, 0, 1, 2, 1, 1, 0, 0, 0,
+ 0, 2, 1, 1, 0, 2, 0, 0, 1, 0, 1, 0, 0, 1, 2, 1,
+ 1, 1, 1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 1, 0, 1,
+ // Entry 40 - 7F
+ 1, 2, 2, 0, 0, 1, 2, 0, 1, 0, 1, 1, 1, 1, 0, 0,
+ 2, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 0,
+ 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ // Entry 80 - BF
+ 1, 0, 0, 1, 0, 2, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 1, 1, 2, 0, 0, 2, 0, 0, 1, 1, 1, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 0,
+ 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1,
+ // Entry C0 - FF
+ 1,
+}
+
+const (
+ _Latn = 91
+ _Hani = 57
+ _Hans = 59
+ _Hant = 60
+ _Qaaa = 149
+ _Qaai = 157
+ _Qabx = 198
+ _Zinh = 255
+ _Zyyy = 260
+ _Zzzz = 261
+)
+
+// script is an alphabetically sorted list of ISO 15924 codes. The index
+// of the script in the string, divided by 4, is the internal scriptID.
+const script tag.Index = "" + // Size: 1052 bytes
+ "----AdlmAfakAghbAhomArabAranArmiArmnAvstBaliBamuBassBatkBengBhksBlisBopo" +
+ "BrahBraiBugiBuhdCakmCansCariChamCherChrsCirtCoptCpmnCprtCyrlCyrsDevaDiak" +
+ "DogrDsrtDuplEgydEgyhEgypElbaElymEthiGeokGeorGlagGongGonmGothGranGrekGujr" +
+ "GuruHanbHangHaniHanoHansHantHatrHebrHiraHluwHmngHmnpHrktHungIndsItalJamo" +
+ "JavaJpanJurcKaliKanaKawiKharKhmrKhojKitlKitsKndaKoreKpelKthiLanaLaooLatf" +
+ "LatgLatnLekeLepcLimbLinaLinbLisuLomaLyciLydiMahjMakaMandManiMarcMayaMedf" +
+ "MendMercMeroMlymModiMongMoonMrooMteiMultMymrNagmNandNarbNbatNewaNkdbNkgb" +
+ "NkooNshuOgamOlckOrkhOryaOsgeOsmaOugrPalmPaucPcunPelmPermPhagPhliPhlpPhlv" +
+ "PhnxPiqdPlrdPrtiPsinQaaaQaabQaacQaadQaaeQaafQaagQaahQaaiQaajQaakQaalQaam" +
+ "QaanQaaoQaapQaaqQaarQaasQaatQaauQaavQaawQaaxQaayQaazQabaQabbQabcQabdQabe" +
+ "QabfQabgQabhQabiQabjQabkQablQabmQabnQaboQabpQabqQabrQabsQabtQabuQabvQabw" +
+ "QabxRanjRjngRohgRoroRunrSamrSaraSarbSaurSgnwShawShrdShuiSiddSindSinhSogd" +
+ "SogoSoraSoyoSundSunuSyloSyrcSyreSyrjSyrnTagbTakrTaleTaluTamlTangTavtTelu" +
+ "TengTfngTglgThaaThaiTibtTirhTnsaTotoUgarVaiiVispVithWaraWchoWoleXpeoXsux" +
+ "YeziYiiiZanbZinhZmthZsyeZsymZxxxZyyyZzzz\xff\xff\xff\xff"
+
+// suppressScript is an index from langID to the dominant script for that language,
+// if it exists. If a script is given, it should be suppressed from the language tag.
+// Size: 1330 bytes, 1330 elements
+var suppressScript = [1330]uint8{
+ // Entry 0 - 3F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 40 - 7F
+ 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ // Entry 80 - BF
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry C0 - FF
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 100 - 13F
+ 0x5b, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xed, 0x00, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00,
+ 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x5b, 0x00,
+ // Entry 140 - 17F
+ 0x5b, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00,
+ 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ 0x00, 0x5b, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x5b, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 180 - 1BF
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5b, 0x35, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x22, 0x00,
+ // Entry 1C0 - 1FF
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5b, 0x5b, 0x00, 0x5b, 0x5b, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00,
+ 0x5b, 0x5b, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ // Entry 200 - 23F
+ 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 240 - 27F
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00,
+ 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, 0x22, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 280 - 2BF
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00,
+ 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 2C0 - 2FF
+ 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ // Entry 300 - 33F
+ 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x5b,
+ 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ // Entry 340 - 37F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ 0x5b, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5b, 0x00,
+ 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 380 - 3BF
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5b, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
+ // Entry 3C0 - 3FF
+ 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
+ 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 400 - 43F
+ 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00,
+ // Entry 440 - 47F
+ 0x00, 0x00, 0x00, 0x00, 0x5b, 0x5b, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe9, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x2c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ // Entry 480 - 4BF
+ 0x5b, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 4C0 - 4FF
+ 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 500 - 53F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0x00,
+}
+
+const (
+ _001 = 1
+ _419 = 31
+ _BR = 65
+ _CA = 73
+ _ES = 111
+ _GB = 124
+ _MD = 189
+ _PT = 239
+ _UK = 307
+ _US = 310
+ _ZZ = 358
+ _XA = 324
+ _XC = 326
+ _XK = 334
+)
+
+// isoRegionOffset needs to be added to the index of regionISO to obtain the regionID
+// for 2-letter ISO codes. (The first isoRegionOffset regionIDs are reserved for
+// the UN.M49 codes used for groups.)
+const isoRegionOffset = 32
+
+// regionTypes defines the status of a region for various standards.
+// Size: 359 bytes, 359 elements
+var regionTypes = [359]uint8{
+ // Entry 0 - 3F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ // Entry 40 - 7F
+ 0x06, 0x06, 0x06, 0x06, 0x04, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x04, 0x04, 0x06,
+ 0x04, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x04, 0x06, 0x04, 0x06, 0x06, 0x06, 0x06, 0x00,
+ 0x06, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x06, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06,
+ // Entry 80 - BF
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x00, 0x04, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x00, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ // Entry C0 - FF
+ 0x06, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x06, 0x04,
+ 0x06, 0x06, 0x06, 0x06, 0x00, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x06, 0x06, 0x00, 0x06, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ // Entry 100 - 13F
+ 0x05, 0x05, 0x05, 0x06, 0x00, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x04,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x02, 0x06, 0x04, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06,
+ // Entry 140 - 17F
+ 0x06, 0x06, 0x00, 0x06, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, 0x06,
+ 0x06, 0x04, 0x06, 0x06, 0x04, 0x06, 0x05,
+}
+
+// regionISO holds a list of alphabetically sorted 2-letter ISO region codes.
+// Each 2-letter codes is followed by two bytes with the following meaning:
+// - [A-Z}{2}: the first letter of the 2-letter code plus these two
+// letters form the 3-letter ISO code.
+// - 0, n: index into altRegionISO3.
+const regionISO tag.Index = "" + // Size: 1312 bytes
+ "AAAAACSCADNDAEREAFFGAGTGAIIAALLBAMRMANNTAOGOAQTAARRGASSMATUTAUUSAWBWAXLA" +
+ "AZZEBAIHBBRBBDGDBEELBFFABGGRBHHRBIDIBJENBLLMBMMUBNRNBOOLBQESBRRABSHSBTTN" +
+ "BUURBVVTBWWABYLRBZLZCAANCCCKCDODCFAFCGOGCHHECIIVCKOKCLHLCMMRCNHNCOOLCPPT" +
+ "CQ CRRICS\x00\x00CTTECUUBCVPVCWUWCXXRCYYPCZZEDDDRDEEUDGGADJJIDKNKDMMADO" +
+ "OMDYHYDZZAEA ECCUEESTEGGYEHSHERRIESSPETTHEU\x00\x03EZ FIINFJJIFKLKFMSM" +
+ "FOROFQ\x00\x18FRRAFXXXGAABGBBRGDRDGEEOGFUFGGGYGHHAGIIBGLRLGMMBGNINGPLPGQ" +
+ "NQGRRCGS\x00\x06GTTMGUUMGWNBGYUYHKKGHMMDHNNDHRRVHTTIHUUNHVVOIC IDDNIERL" +
+ "ILSRIMMNINNDIOOTIQRQIRRNISSLITTAJEEYJMAMJOORJPPNJTTNKEENKGGZKHHMKIIRKM" +
+ "\x00\x09KNNAKP\x00\x0cKRORKWWTKY\x00\x0fKZAZLAAOLBBNLCCALIIELKKALRBRLSSO" +
+ "LTTULUUXLVVALYBYMAARMCCOMDDAMENEMFAFMGDGMHHLMIIDMKKDMLLIMMMRMNNGMOACMPNP" +
+ "MQTQMRRTMSSRMTLTMUUSMVDVMWWIMXEXMYYSMZOZNAAMNCCLNEERNFFKNGGANHHBNIICNLLD" +
+ "NOORNPPLNQ\x00\x1eNRRUNTTZNUIUNZZLOMMNPAANPCCIPEERPFYFPGNGPHHLPKAKPLOLPM" +
+ "\x00\x12PNCNPRRIPSSEPTRTPUUSPWLWPYRYPZCZQAATQMMMQNNNQOOOQPPPQQQQQRRRQSSS" +
+ "QTTTQU\x00\x03QVVVQWWWQXXXQYYYQZZZREEURHHOROOURS\x00\x15RUUSRWWASAAUSBLB" +
+ "SCYCSDDNSEWESGGPSHHNSIVNSJJMSKVKSLLESMMRSNENSOOMSRURSSSDSTTPSUUNSVLVSXXM" +
+ "SYYRSZWZTAAATCCATDCDTF\x00\x18TGGOTHHATJJKTKKLTLLSTMKMTNUNTOONTPMPTRURTT" +
+ "TOTVUVTWWNTZZAUAKRUGGAUK UMMIUN USSAUYRYUZZBVAATVCCTVDDRVEENVGGBVIIRVN" +
+ "NMVUUTWFLFWKAKWSSMXAAAXBBBXCCCXDDDXEEEXFFFXGGGXHHHXIIIXJJJXKKKXLLLXMMMXN" +
+ "NNXOOOXPPPXQQQXRRRXSSSXTTTXUUUXVVVXWWWXXXXXYYYXZZZYDMDYEEMYT\x00\x1bYUUG" +
+ "ZAAFZMMBZRARZWWEZZZZ\xff\xff\xff\xff"
+
+// altRegionISO3 holds a list of 3-letter region codes that cannot be
+// mapped to 2-letter codes using the default algorithm. This is a short list.
+const altRegionISO3 string = "SCGQUUSGSCOMPRKCYMSPMSRBATFMYTATN"
+
+// altRegionIDs holds a list of regionIDs the positions of which match those
+// of the 3-letter ISO codes in altRegionISO3.
+// Size: 22 bytes, 11 elements
+var altRegionIDs = [11]uint16{
+ 0x0058, 0x0071, 0x0089, 0x00a9, 0x00ab, 0x00ae, 0x00eb, 0x0106,
+ 0x0122, 0x0160, 0x00dd,
+}
+
+// Size: 80 bytes, 20 elements
+var regionOldMap = [20]FromTo{
+ 0: {From: 0x44, To: 0xc5},
+ 1: {From: 0x59, To: 0xa8},
+ 2: {From: 0x60, To: 0x61},
+ 3: {From: 0x67, To: 0x3b},
+ 4: {From: 0x7a, To: 0x79},
+ 5: {From: 0x94, To: 0x37},
+ 6: {From: 0xa4, To: 0x134},
+ 7: {From: 0xc2, To: 0x134},
+ 8: {From: 0xd8, To: 0x140},
+ 9: {From: 0xdd, To: 0x2b},
+ 10: {From: 0xf0, To: 0x134},
+ 11: {From: 0xf3, To: 0xe3},
+ 12: {From: 0xfd, To: 0x71},
+ 13: {From: 0x104, To: 0x165},
+ 14: {From: 0x12b, To: 0x127},
+ 15: {From: 0x133, To: 0x7c},
+ 16: {From: 0x13b, To: 0x13f},
+ 17: {From: 0x142, To: 0x134},
+ 18: {From: 0x15e, To: 0x15f},
+ 19: {From: 0x164, To: 0x4b},
+}
+
+// m49 maps regionIDs to UN.M49 codes. The first isoRegionOffset entries are
+// codes indicating collections of regions.
+// Size: 718 bytes, 359 elements
+var m49 = [359]int16{
+ // Entry 0 - 3F
+ 0, 1, 2, 3, 5, 9, 11, 13,
+ 14, 15, 17, 18, 19, 21, 29, 30,
+ 34, 35, 39, 53, 54, 57, 61, 142,
+ 143, 145, 150, 151, 154, 155, 202, 419,
+ 958, 0, 20, 784, 4, 28, 660, 8,
+ 51, 530, 24, 10, 32, 16, 40, 36,
+ 533, 248, 31, 70, 52, 50, 56, 854,
+ 100, 48, 108, 204, 652, 60, 96, 68,
+ // Entry 40 - 7F
+ 535, 76, 44, 64, 104, 74, 72, 112,
+ 84, 124, 166, 180, 140, 178, 756, 384,
+ 184, 152, 120, 156, 170, 0, 0, 188,
+ 891, 296, 192, 132, 531, 162, 196, 203,
+ 278, 276, 0, 262, 208, 212, 214, 204,
+ 12, 0, 218, 233, 818, 732, 232, 724,
+ 231, 967, 0, 246, 242, 238, 583, 234,
+ 0, 250, 249, 266, 826, 308, 268, 254,
+ // Entry 80 - BF
+ 831, 288, 292, 304, 270, 324, 312, 226,
+ 300, 239, 320, 316, 624, 328, 344, 334,
+ 340, 191, 332, 348, 854, 0, 360, 372,
+ 376, 833, 356, 86, 368, 364, 352, 380,
+ 832, 388, 400, 392, 581, 404, 417, 116,
+ 296, 174, 659, 408, 410, 414, 136, 398,
+ 418, 422, 662, 438, 144, 430, 426, 440,
+ 442, 428, 434, 504, 492, 498, 499, 663,
+ // Entry C0 - FF
+ 450, 584, 581, 807, 466, 104, 496, 446,
+ 580, 474, 478, 500, 470, 480, 462, 454,
+ 484, 458, 508, 516, 540, 562, 574, 566,
+ 548, 558, 528, 578, 524, 10, 520, 536,
+ 570, 554, 512, 591, 0, 604, 258, 598,
+ 608, 586, 616, 666, 612, 630, 275, 620,
+ 581, 585, 600, 591, 634, 959, 960, 961,
+ 962, 963, 964, 965, 966, 967, 968, 969,
+ // Entry 100 - 13F
+ 970, 971, 972, 638, 716, 642, 688, 643,
+ 646, 682, 90, 690, 729, 752, 702, 654,
+ 705, 744, 703, 694, 674, 686, 706, 740,
+ 728, 678, 810, 222, 534, 760, 748, 0,
+ 796, 148, 260, 768, 764, 762, 772, 626,
+ 795, 788, 776, 626, 792, 780, 798, 158,
+ 834, 804, 800, 826, 581, 0, 840, 858,
+ 860, 336, 670, 704, 862, 92, 850, 704,
+ // Entry 140 - 17F
+ 548, 876, 581, 882, 973, 974, 975, 976,
+ 977, 978, 979, 980, 981, 982, 983, 984,
+ 985, 986, 987, 988, 989, 990, 991, 992,
+ 993, 994, 995, 996, 997, 998, 720, 887,
+ 175, 891, 710, 894, 180, 716, 999,
+}
+
+// m49Index gives indexes into fromM49 based on the three most significant bits
+// of a 10-bit UN.M49 code. To search an UN.M49 code in fromM49, search in
+//
+// fromM49[m49Index[msb39(code)]:m49Index[msb3(code)+1]]
+//
+// for an entry where the first 7 bits match the 7 lsb of the UN.M49 code.
+// The region code is stored in the 9 lsb of the indexed value.
+// Size: 18 bytes, 9 elements
+var m49Index = [9]int16{
+ 0, 59, 108, 143, 181, 220, 259, 291,
+ 333,
+}
+
+// fromM49 contains entries to map UN.M49 codes to regions. See m49Index for details.
+// Size: 666 bytes, 333 elements
+var fromM49 = [333]uint16{
+ // Entry 0 - 3F
+ 0x0201, 0x0402, 0x0603, 0x0824, 0x0a04, 0x1027, 0x1205, 0x142b,
+ 0x1606, 0x1868, 0x1a07, 0x1c08, 0x1e09, 0x202d, 0x220a, 0x240b,
+ 0x260c, 0x2822, 0x2a0d, 0x302a, 0x3825, 0x3a0e, 0x3c0f, 0x3e32,
+ 0x402c, 0x4410, 0x4611, 0x482f, 0x4e12, 0x502e, 0x5842, 0x6039,
+ 0x6435, 0x6628, 0x6834, 0x6a13, 0x6c14, 0x7036, 0x7215, 0x783d,
+ 0x7a16, 0x8043, 0x883f, 0x8c33, 0x9046, 0x9445, 0x9841, 0xa848,
+ 0xac9b, 0xb50a, 0xb93d, 0xc03e, 0xc838, 0xd0c5, 0xd83a, 0xe047,
+ 0xe8a7, 0xf052, 0xf849, 0x085b, 0x10ae, 0x184c, 0x1c17, 0x1e18,
+ // Entry 40 - 7F
+ 0x20b4, 0x2219, 0x2921, 0x2c1a, 0x2e1b, 0x3051, 0x341c, 0x361d,
+ 0x3853, 0x3d2f, 0x445d, 0x4c4a, 0x5454, 0x5ca9, 0x5f60, 0x644d,
+ 0x684b, 0x7050, 0x7857, 0x7e91, 0x805a, 0x885e, 0x941e, 0x965f,
+ 0x983b, 0xa064, 0xa865, 0xac66, 0xb46a, 0xbd1b, 0xc487, 0xcc70,
+ 0xce70, 0xd06e, 0xd26b, 0xd477, 0xdc75, 0xde89, 0xe474, 0xec73,
+ 0xf031, 0xf27a, 0xf479, 0xfc7f, 0x04e6, 0x0922, 0x0c63, 0x147b,
+ 0x187e, 0x1c84, 0x26ee, 0x2861, 0x2c60, 0x3061, 0x4081, 0x4882,
+ 0x50a8, 0x5888, 0x6083, 0x687d, 0x7086, 0x788b, 0x808a, 0x8885,
+ // Entry 80 - BF
+ 0x908d, 0x9892, 0x9c8f, 0xa139, 0xa890, 0xb08e, 0xb893, 0xc09e,
+ 0xc89a, 0xd096, 0xd89d, 0xe09c, 0xe897, 0xf098, 0xf89f, 0x004f,
+ 0x08a1, 0x10a3, 0x1caf, 0x20a2, 0x28a5, 0x30ab, 0x34ac, 0x3cad,
+ 0x42a6, 0x44b0, 0x461f, 0x4cb1, 0x54b6, 0x58b9, 0x5cb5, 0x64ba,
+ 0x6cb3, 0x70b7, 0x74b8, 0x7cc7, 0x84c0, 0x8ccf, 0x94d1, 0x9cce,
+ 0xa4c4, 0xaccc, 0xb4c9, 0xbcca, 0xc0cd, 0xc8d0, 0xd8bc, 0xe0c6,
+ 0xe4bd, 0xe6be, 0xe8cb, 0xf0bb, 0xf8d2, 0x00e2, 0x08d3, 0x10de,
+ 0x18dc, 0x20da, 0x2429, 0x265c, 0x2a30, 0x2d1c, 0x2e40, 0x30df,
+ // Entry C0 - FF
+ 0x38d4, 0x4940, 0x54e1, 0x5cd9, 0x64d5, 0x6cd7, 0x74e0, 0x7cd6,
+ 0x84db, 0x88c8, 0x8b34, 0x8e76, 0x90c1, 0x92f1, 0x94e9, 0x9ee3,
+ 0xace7, 0xb0f2, 0xb8e5, 0xc0e8, 0xc8ec, 0xd0ea, 0xd8ef, 0xe08c,
+ 0xe527, 0xeced, 0xf4f4, 0xfd03, 0x0505, 0x0707, 0x0d08, 0x183c,
+ 0x1d0f, 0x26aa, 0x2826, 0x2cb2, 0x2ebf, 0x34eb, 0x3d3a, 0x4514,
+ 0x4d19, 0x5509, 0x5d15, 0x6106, 0x650b, 0x6d13, 0x7d0e, 0x7f12,
+ 0x813f, 0x8310, 0x8516, 0x8d62, 0x9965, 0xa15e, 0xa86f, 0xb118,
+ 0xb30c, 0xb86d, 0xc10c, 0xc917, 0xd111, 0xd91e, 0xe10d, 0xe84e,
+ // Entry 100 - 13F
+ 0xf11d, 0xf525, 0xf924, 0x0123, 0x0926, 0x112a, 0x192d, 0x2023,
+ 0x2929, 0x312c, 0x3728, 0x3920, 0x3d2e, 0x4132, 0x4931, 0x4ec3,
+ 0x551a, 0x646c, 0x747c, 0x7e80, 0x80a0, 0x8299, 0x8530, 0x9136,
+ 0xa53e, 0xac37, 0xb537, 0xb938, 0xbd3c, 0xd941, 0xe543, 0xed5f,
+ 0xef5f, 0xf658, 0xfd63, 0x7c20, 0x7ef5, 0x80f6, 0x82f7, 0x84f8,
+ 0x86f9, 0x88fa, 0x8afb, 0x8cfc, 0x8e71, 0x90fe, 0x92ff, 0x9500,
+ 0x9701, 0x9902, 0x9b44, 0x9d45, 0x9f46, 0xa147, 0xa348, 0xa549,
+ 0xa74a, 0xa94b, 0xab4c, 0xad4d, 0xaf4e, 0xb14f, 0xb350, 0xb551,
+ // Entry 140 - 17F
+ 0xb752, 0xb953, 0xbb54, 0xbd55, 0xbf56, 0xc157, 0xc358, 0xc559,
+ 0xc75a, 0xc95b, 0xcb5c, 0xcd5d, 0xcf66,
+}
+
+// Size: 2128 bytes
+var variantIndex = map[string]uint8{
+ "1606nict": 0x0,
+ "1694acad": 0x1,
+ "1901": 0x2,
+ "1959acad": 0x3,
+ "1994": 0x67,
+ "1996": 0x4,
+ "abl1943": 0x5,
+ "akuapem": 0x6,
+ "alalc97": 0x69,
+ "aluku": 0x7,
+ "ao1990": 0x8,
+ "aranes": 0x9,
+ "arevela": 0xa,
+ "arevmda": 0xb,
+ "arkaika": 0xc,
+ "asante": 0xd,
+ "auvern": 0xe,
+ "baku1926": 0xf,
+ "balanka": 0x10,
+ "barla": 0x11,
+ "basiceng": 0x12,
+ "bauddha": 0x13,
+ "bciav": 0x14,
+ "bcizbl": 0x15,
+ "biscayan": 0x16,
+ "biske": 0x62,
+ "bohoric": 0x17,
+ "boont": 0x18,
+ "bornholm": 0x19,
+ "cisaup": 0x1a,
+ "colb1945": 0x1b,
+ "cornu": 0x1c,
+ "creiss": 0x1d,
+ "dajnko": 0x1e,
+ "ekavsk": 0x1f,
+ "emodeng": 0x20,
+ "fonipa": 0x6a,
+ "fonkirsh": 0x6b,
+ "fonnapa": 0x6c,
+ "fonupa": 0x6d,
+ "fonxsamp": 0x6e,
+ "gallo": 0x21,
+ "gascon": 0x22,
+ "grclass": 0x23,
+ "grital": 0x24,
+ "grmistr": 0x25,
+ "hepburn": 0x26,
+ "heploc": 0x68,
+ "hognorsk": 0x27,
+ "hsistemo": 0x28,
+ "ijekavsk": 0x29,
+ "itihasa": 0x2a,
+ "ivanchov": 0x2b,
+ "jauer": 0x2c,
+ "jyutping": 0x2d,
+ "kkcor": 0x2e,
+ "kociewie": 0x2f,
+ "kscor": 0x30,
+ "laukika": 0x31,
+ "lemosin": 0x32,
+ "lengadoc": 0x33,
+ "lipaw": 0x63,
+ "ltg1929": 0x34,
+ "ltg2007": 0x35,
+ "luna1918": 0x36,
+ "metelko": 0x37,
+ "monoton": 0x38,
+ "ndyuka": 0x39,
+ "nedis": 0x3a,
+ "newfound": 0x3b,
+ "nicard": 0x3c,
+ "njiva": 0x64,
+ "nulik": 0x3d,
+ "osojs": 0x65,
+ "oxendict": 0x3e,
+ "pahawh2": 0x3f,
+ "pahawh3": 0x40,
+ "pahawh4": 0x41,
+ "pamaka": 0x42,
+ "peano": 0x43,
+ "petr1708": 0x44,
+ "pinyin": 0x45,
+ "polyton": 0x46,
+ "provenc": 0x47,
+ "puter": 0x48,
+ "rigik": 0x49,
+ "rozaj": 0x4a,
+ "rumgr": 0x4b,
+ "scotland": 0x4c,
+ "scouse": 0x4d,
+ "simple": 0x6f,
+ "solba": 0x66,
+ "sotav": 0x4e,
+ "spanglis": 0x4f,
+ "surmiran": 0x50,
+ "sursilv": 0x51,
+ "sutsilv": 0x52,
+ "synnejyl": 0x53,
+ "tarask": 0x54,
+ "tongyong": 0x55,
+ "tunumiit": 0x56,
+ "uccor": 0x57,
+ "ucrcor": 0x58,
+ "ulster": 0x59,
+ "unifon": 0x5a,
+ "vaidika": 0x5b,
+ "valencia": 0x5c,
+ "vallader": 0x5d,
+ "vecdruka": 0x5e,
+ "vivaraup": 0x5f,
+ "wadegile": 0x60,
+ "xsistemo": 0x61,
+}
+
+// variantNumSpecialized is the number of specialized variants in variants.
+const variantNumSpecialized = 105
+
+// nRegionGroups is the number of region groups.
+const nRegionGroups = 33
+
+type likelyLangRegion struct {
+ lang uint16
+ region uint16
+}
+
+// likelyScript is a lookup table, indexed by scriptID, for the most likely
+// languages and regions given a script.
+// Size: 1052 bytes, 263 elements
+var likelyScript = [263]likelyLangRegion{
+ 1: {lang: 0x14e, region: 0x85},
+ 3: {lang: 0x2a2, region: 0x107},
+ 4: {lang: 0x1f, region: 0x9a},
+ 5: {lang: 0x3a, region: 0x6c},
+ 7: {lang: 0x3b, region: 0x9d},
+ 8: {lang: 0x1d7, region: 0x28},
+ 9: {lang: 0x13, region: 0x9d},
+ 10: {lang: 0x5b, region: 0x96},
+ 11: {lang: 0x60, region: 0x52},
+ 12: {lang: 0xb9, region: 0xb5},
+ 13: {lang: 0x63, region: 0x96},
+ 14: {lang: 0xa5, region: 0x35},
+ 15: {lang: 0x3e9, region: 0x9a},
+ 17: {lang: 0x529, region: 0x12f},
+ 18: {lang: 0x3b1, region: 0x9a},
+ 19: {lang: 0x15e, region: 0x79},
+ 20: {lang: 0xc2, region: 0x96},
+ 21: {lang: 0x9d, region: 0xe8},
+ 22: {lang: 0xdb, region: 0x35},
+ 23: {lang: 0xf3, region: 0x49},
+ 24: {lang: 0x4f0, region: 0x12c},
+ 25: {lang: 0xe7, region: 0x13f},
+ 26: {lang: 0xe5, region: 0x136},
+ 29: {lang: 0xf1, region: 0x6c},
+ 31: {lang: 0x1a0, region: 0x5e},
+ 32: {lang: 0x3e2, region: 0x107},
+ 34: {lang: 0x1be, region: 0x9a},
+ 38: {lang: 0x15e, region: 0x79},
+ 41: {lang: 0x133, region: 0x6c},
+ 42: {lang: 0x431, region: 0x27},
+ 44: {lang: 0x27, region: 0x70},
+ 46: {lang: 0x210, region: 0x7e},
+ 47: {lang: 0xfe, region: 0x38},
+ 49: {lang: 0x19b, region: 0x9a},
+ 50: {lang: 0x19e, region: 0x131},
+ 51: {lang: 0x3e9, region: 0x9a},
+ 52: {lang: 0x136, region: 0x88},
+ 53: {lang: 0x1a4, region: 0x9a},
+ 54: {lang: 0x39d, region: 0x9a},
+ 55: {lang: 0x529, region: 0x12f},
+ 56: {lang: 0x254, region: 0xac},
+ 57: {lang: 0x529, region: 0x53},
+ 58: {lang: 0x1cb, region: 0xe8},
+ 59: {lang: 0x529, region: 0x53},
+ 60: {lang: 0x529, region: 0x12f},
+ 61: {lang: 0x2fd, region: 0x9c},
+ 62: {lang: 0x1bc, region: 0x98},
+ 63: {lang: 0x200, region: 0xa3},
+ 64: {lang: 0x1c5, region: 0x12c},
+ 65: {lang: 0x1ca, region: 0xb0},
+ 68: {lang: 0x1d5, region: 0x93},
+ 70: {lang: 0x142, region: 0x9f},
+ 71: {lang: 0x254, region: 0xac},
+ 72: {lang: 0x20e, region: 0x96},
+ 73: {lang: 0x200, region: 0xa3},
+ 75: {lang: 0x135, region: 0xc5},
+ 76: {lang: 0x200, region: 0xa3},
+ 78: {lang: 0x3bb, region: 0xe9},
+ 79: {lang: 0x24a, region: 0xa7},
+ 80: {lang: 0x3fa, region: 0x9a},
+ 83: {lang: 0x251, region: 0x9a},
+ 84: {lang: 0x254, region: 0xac},
+ 86: {lang: 0x88, region: 0x9a},
+ 87: {lang: 0x370, region: 0x124},
+ 88: {lang: 0x2b8, region: 0xb0},
+ 93: {lang: 0x29f, region: 0x9a},
+ 94: {lang: 0x2a8, region: 0x9a},
+ 95: {lang: 0x28f, region: 0x88},
+ 96: {lang: 0x1a0, region: 0x88},
+ 97: {lang: 0x2ac, region: 0x53},
+ 99: {lang: 0x4f4, region: 0x12c},
+ 100: {lang: 0x4f5, region: 0x12c},
+ 101: {lang: 0x1be, region: 0x9a},
+ 103: {lang: 0x337, region: 0x9d},
+ 104: {lang: 0x4f7, region: 0x53},
+ 105: {lang: 0xa9, region: 0x53},
+ 108: {lang: 0x2e8, region: 0x113},
+ 109: {lang: 0x4f8, region: 0x10c},
+ 110: {lang: 0x4f8, region: 0x10c},
+ 111: {lang: 0x304, region: 0x9a},
+ 112: {lang: 0x31b, region: 0x9a},
+ 113: {lang: 0x30b, region: 0x53},
+ 115: {lang: 0x31e, region: 0x35},
+ 116: {lang: 0x30e, region: 0x9a},
+ 117: {lang: 0x414, region: 0xe9},
+ 118: {lang: 0x331, region: 0xc5},
+ 121: {lang: 0x4f9, region: 0x109},
+ 122: {lang: 0x3b, region: 0xa2},
+ 123: {lang: 0x353, region: 0xdc},
+ 126: {lang: 0x2d0, region: 0x85},
+ 127: {lang: 0x52a, region: 0x53},
+ 128: {lang: 0x403, region: 0x97},
+ 129: {lang: 0x3ee, region: 0x9a},
+ 130: {lang: 0x39b, region: 0xc6},
+ 131: {lang: 0x395, region: 0x9a},
+ 132: {lang: 0x399, region: 0x136},
+ 133: {lang: 0x429, region: 0x116},
+ 135: {lang: 0x3b, region: 0x11d},
+ 136: {lang: 0xfd, region: 0xc5},
+ 139: {lang: 0x27d, region: 0x107},
+ 140: {lang: 0x2c9, region: 0x53},
+ 141: {lang: 0x39f, region: 0x9d},
+ 142: {lang: 0x39f, region: 0x53},
+ 144: {lang: 0x3ad, region: 0xb1},
+ 146: {lang: 0x1c6, region: 0x53},
+ 147: {lang: 0x4fd, region: 0x9d},
+ 200: {lang: 0x3cb, region: 0x96},
+ 203: {lang: 0x372, region: 0x10d},
+ 204: {lang: 0x420, region: 0x98},
+ 206: {lang: 0x4ff, region: 0x15f},
+ 207: {lang: 0x3f0, region: 0x9a},
+ 208: {lang: 0x45, region: 0x136},
+ 209: {lang: 0x139, region: 0x7c},
+ 210: {lang: 0x3e9, region: 0x9a},
+ 212: {lang: 0x3e9, region: 0x9a},
+ 213: {lang: 0x3fa, region: 0x9a},
+ 214: {lang: 0x40c, region: 0xb4},
+ 217: {lang: 0x433, region: 0x9a},
+ 218: {lang: 0xef, region: 0xc6},
+ 219: {lang: 0x43e, region: 0x96},
+ 221: {lang: 0x44d, region: 0x35},
+ 222: {lang: 0x44e, region: 0x9c},
+ 226: {lang: 0x45a, region: 0xe8},
+ 227: {lang: 0x11a, region: 0x9a},
+ 228: {lang: 0x45e, region: 0x53},
+ 229: {lang: 0x232, region: 0x53},
+ 230: {lang: 0x450, region: 0x9a},
+ 231: {lang: 0x4a5, region: 0x53},
+ 232: {lang: 0x9f, region: 0x13f},
+ 233: {lang: 0x461, region: 0x9a},
+ 235: {lang: 0x528, region: 0xbb},
+ 236: {lang: 0x153, region: 0xe8},
+ 237: {lang: 0x128, region: 0xce},
+ 238: {lang: 0x46b, region: 0x124},
+ 239: {lang: 0xa9, region: 0x53},
+ 240: {lang: 0x2ce, region: 0x9a},
+ 243: {lang: 0x4ad, region: 0x11d},
+ 244: {lang: 0x4be, region: 0xb5},
+ 247: {lang: 0x1ce, region: 0x9a},
+ 250: {lang: 0x3a9, region: 0x9d},
+ 251: {lang: 0x22, region: 0x9c},
+ 253: {lang: 0x1ea, region: 0x53},
+ 254: {lang: 0xef, region: 0xc6},
+}
+
+type likelyScriptRegion struct {
+ region uint16
+ script uint16
+ flags uint8
+}
+
+// likelyLang is a lookup table, indexed by langID, for the most likely
+// scripts and regions given incomplete information. If more entries exist for a
+// given language, region and script are the index and size respectively
+// of the list in likelyLangList.
+// Size: 7980 bytes, 1330 elements
+var likelyLang = [1330]likelyScriptRegion{
+ 0: {region: 0x136, script: 0x5b, flags: 0x0},
+ 1: {region: 0x70, script: 0x5b, flags: 0x0},
+ 2: {region: 0x166, script: 0x5b, flags: 0x0},
+ 3: {region: 0x166, script: 0x5b, flags: 0x0},
+ 4: {region: 0x166, script: 0x5b, flags: 0x0},
+ 5: {region: 0x7e, script: 0x20, flags: 0x0},
+ 6: {region: 0x166, script: 0x5b, flags: 0x0},
+ 7: {region: 0x166, script: 0x20, flags: 0x0},
+ 8: {region: 0x81, script: 0x5b, flags: 0x0},
+ 9: {region: 0x166, script: 0x5b, flags: 0x0},
+ 10: {region: 0x166, script: 0x5b, flags: 0x0},
+ 11: {region: 0x166, script: 0x5b, flags: 0x0},
+ 12: {region: 0x96, script: 0x5b, flags: 0x0},
+ 13: {region: 0x132, script: 0x5b, flags: 0x0},
+ 14: {region: 0x81, script: 0x5b, flags: 0x0},
+ 15: {region: 0x166, script: 0x5b, flags: 0x0},
+ 16: {region: 0x166, script: 0x5b, flags: 0x0},
+ 17: {region: 0x107, script: 0x20, flags: 0x0},
+ 18: {region: 0x166, script: 0x5b, flags: 0x0},
+ 19: {region: 0x9d, script: 0x9, flags: 0x0},
+ 20: {region: 0x129, script: 0x5, flags: 0x0},
+ 21: {region: 0x166, script: 0x5b, flags: 0x0},
+ 22: {region: 0x162, script: 0x5b, flags: 0x0},
+ 23: {region: 0x166, script: 0x5b, flags: 0x0},
+ 24: {region: 0x166, script: 0x5b, flags: 0x0},
+ 25: {region: 0x166, script: 0x5b, flags: 0x0},
+ 26: {region: 0x166, script: 0x5b, flags: 0x0},
+ 27: {region: 0x166, script: 0x5b, flags: 0x0},
+ 28: {region: 0x52, script: 0x5b, flags: 0x0},
+ 29: {region: 0x166, script: 0x5b, flags: 0x0},
+ 30: {region: 0x166, script: 0x5b, flags: 0x0},
+ 31: {region: 0x9a, script: 0x4, flags: 0x0},
+ 32: {region: 0x166, script: 0x5b, flags: 0x0},
+ 33: {region: 0x81, script: 0x5b, flags: 0x0},
+ 34: {region: 0x9c, script: 0xfb, flags: 0x0},
+ 35: {region: 0x166, script: 0x5b, flags: 0x0},
+ 36: {region: 0x166, script: 0x5b, flags: 0x0},
+ 37: {region: 0x14e, script: 0x5b, flags: 0x0},
+ 38: {region: 0x107, script: 0x20, flags: 0x0},
+ 39: {region: 0x70, script: 0x2c, flags: 0x0},
+ 40: {region: 0x166, script: 0x5b, flags: 0x0},
+ 41: {region: 0x166, script: 0x5b, flags: 0x0},
+ 42: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 43: {region: 0x166, script: 0x5b, flags: 0x0},
+ 45: {region: 0x166, script: 0x5b, flags: 0x0},
+ 46: {region: 0x166, script: 0x5b, flags: 0x0},
+ 47: {region: 0x166, script: 0x5b, flags: 0x0},
+ 48: {region: 0x166, script: 0x5b, flags: 0x0},
+ 49: {region: 0x166, script: 0x5b, flags: 0x0},
+ 50: {region: 0x166, script: 0x5b, flags: 0x0},
+ 51: {region: 0x96, script: 0x5b, flags: 0x0},
+ 52: {region: 0x166, script: 0x5, flags: 0x0},
+ 53: {region: 0x123, script: 0x5, flags: 0x0},
+ 54: {region: 0x166, script: 0x5b, flags: 0x0},
+ 55: {region: 0x166, script: 0x5b, flags: 0x0},
+ 56: {region: 0x166, script: 0x5b, flags: 0x0},
+ 57: {region: 0x166, script: 0x5b, flags: 0x0},
+ 58: {region: 0x6c, script: 0x5, flags: 0x0},
+ 59: {region: 0x0, script: 0x3, flags: 0x1},
+ 60: {region: 0x166, script: 0x5b, flags: 0x0},
+ 61: {region: 0x51, script: 0x5b, flags: 0x0},
+ 62: {region: 0x3f, script: 0x5b, flags: 0x0},
+ 63: {region: 0x68, script: 0x5, flags: 0x0},
+ 65: {region: 0xbb, script: 0x5, flags: 0x0},
+ 66: {region: 0x6c, script: 0x5, flags: 0x0},
+ 67: {region: 0x9a, script: 0xe, flags: 0x0},
+ 68: {region: 0x130, script: 0x5b, flags: 0x0},
+ 69: {region: 0x136, script: 0xd0, flags: 0x0},
+ 70: {region: 0x166, script: 0x5b, flags: 0x0},
+ 71: {region: 0x166, script: 0x5b, flags: 0x0},
+ 72: {region: 0x6f, script: 0x5b, flags: 0x0},
+ 73: {region: 0x166, script: 0x5b, flags: 0x0},
+ 74: {region: 0x166, script: 0x5b, flags: 0x0},
+ 75: {region: 0x49, script: 0x5b, flags: 0x0},
+ 76: {region: 0x166, script: 0x5b, flags: 0x0},
+ 77: {region: 0x107, script: 0x20, flags: 0x0},
+ 78: {region: 0x166, script: 0x5, flags: 0x0},
+ 79: {region: 0x166, script: 0x5b, flags: 0x0},
+ 80: {region: 0x166, script: 0x5b, flags: 0x0},
+ 81: {region: 0x166, script: 0x5b, flags: 0x0},
+ 82: {region: 0x9a, script: 0x22, flags: 0x0},
+ 83: {region: 0x166, script: 0x5b, flags: 0x0},
+ 84: {region: 0x166, script: 0x5b, flags: 0x0},
+ 85: {region: 0x166, script: 0x5b, flags: 0x0},
+ 86: {region: 0x3f, script: 0x5b, flags: 0x0},
+ 87: {region: 0x166, script: 0x5b, flags: 0x0},
+ 88: {region: 0x3, script: 0x5, flags: 0x1},
+ 89: {region: 0x107, script: 0x20, flags: 0x0},
+ 90: {region: 0xe9, script: 0x5, flags: 0x0},
+ 91: {region: 0x96, script: 0x5b, flags: 0x0},
+ 92: {region: 0xdc, script: 0x22, flags: 0x0},
+ 93: {region: 0x2e, script: 0x5b, flags: 0x0},
+ 94: {region: 0x52, script: 0x5b, flags: 0x0},
+ 95: {region: 0x166, script: 0x5b, flags: 0x0},
+ 96: {region: 0x52, script: 0xb, flags: 0x0},
+ 97: {region: 0x166, script: 0x5b, flags: 0x0},
+ 98: {region: 0x166, script: 0x5b, flags: 0x0},
+ 99: {region: 0x96, script: 0x5b, flags: 0x0},
+ 100: {region: 0x166, script: 0x5b, flags: 0x0},
+ 101: {region: 0x52, script: 0x5b, flags: 0x0},
+ 102: {region: 0x166, script: 0x5b, flags: 0x0},
+ 103: {region: 0x166, script: 0x5b, flags: 0x0},
+ 104: {region: 0x166, script: 0x5b, flags: 0x0},
+ 105: {region: 0x166, script: 0x5b, flags: 0x0},
+ 106: {region: 0x4f, script: 0x5b, flags: 0x0},
+ 107: {region: 0x166, script: 0x5b, flags: 0x0},
+ 108: {region: 0x166, script: 0x5b, flags: 0x0},
+ 109: {region: 0x166, script: 0x5b, flags: 0x0},
+ 110: {region: 0x166, script: 0x2c, flags: 0x0},
+ 111: {region: 0x166, script: 0x5b, flags: 0x0},
+ 112: {region: 0x166, script: 0x5b, flags: 0x0},
+ 113: {region: 0x47, script: 0x20, flags: 0x0},
+ 114: {region: 0x166, script: 0x5b, flags: 0x0},
+ 115: {region: 0x166, script: 0x5b, flags: 0x0},
+ 116: {region: 0x10c, script: 0x5, flags: 0x0},
+ 117: {region: 0x163, script: 0x5b, flags: 0x0},
+ 118: {region: 0x166, script: 0x5b, flags: 0x0},
+ 119: {region: 0x96, script: 0x5b, flags: 0x0},
+ 120: {region: 0x166, script: 0x5b, flags: 0x0},
+ 121: {region: 0x130, script: 0x5b, flags: 0x0},
+ 122: {region: 0x52, script: 0x5b, flags: 0x0},
+ 123: {region: 0x9a, script: 0xe6, flags: 0x0},
+ 124: {region: 0xe9, script: 0x5, flags: 0x0},
+ 125: {region: 0x9a, script: 0x22, flags: 0x0},
+ 126: {region: 0x38, script: 0x20, flags: 0x0},
+ 127: {region: 0x9a, script: 0x22, flags: 0x0},
+ 128: {region: 0xe9, script: 0x5, flags: 0x0},
+ 129: {region: 0x12c, script: 0x34, flags: 0x0},
+ 131: {region: 0x9a, script: 0x22, flags: 0x0},
+ 132: {region: 0x166, script: 0x5b, flags: 0x0},
+ 133: {region: 0x9a, script: 0x22, flags: 0x0},
+ 134: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 135: {region: 0x166, script: 0x5b, flags: 0x0},
+ 136: {region: 0x9a, script: 0x22, flags: 0x0},
+ 137: {region: 0x166, script: 0x5b, flags: 0x0},
+ 138: {region: 0x140, script: 0x5b, flags: 0x0},
+ 139: {region: 0x166, script: 0x5b, flags: 0x0},
+ 140: {region: 0x166, script: 0x5b, flags: 0x0},
+ 141: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 142: {region: 0x166, script: 0x5b, flags: 0x0},
+ 143: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 144: {region: 0x166, script: 0x5b, flags: 0x0},
+ 145: {region: 0x166, script: 0x5b, flags: 0x0},
+ 146: {region: 0x166, script: 0x5b, flags: 0x0},
+ 147: {region: 0x166, script: 0x2c, flags: 0x0},
+ 148: {region: 0x9a, script: 0x22, flags: 0x0},
+ 149: {region: 0x96, script: 0x5b, flags: 0x0},
+ 150: {region: 0x166, script: 0x5b, flags: 0x0},
+ 151: {region: 0x166, script: 0x5b, flags: 0x0},
+ 152: {region: 0x115, script: 0x5b, flags: 0x0},
+ 153: {region: 0x166, script: 0x5b, flags: 0x0},
+ 154: {region: 0x166, script: 0x5b, flags: 0x0},
+ 155: {region: 0x52, script: 0x5b, flags: 0x0},
+ 156: {region: 0x166, script: 0x5b, flags: 0x0},
+ 157: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 158: {region: 0x166, script: 0x5b, flags: 0x0},
+ 159: {region: 0x13f, script: 0xe8, flags: 0x0},
+ 160: {region: 0xc4, script: 0x5b, flags: 0x0},
+ 161: {region: 0x166, script: 0x5b, flags: 0x0},
+ 162: {region: 0x166, script: 0x5b, flags: 0x0},
+ 163: {region: 0xc4, script: 0x5b, flags: 0x0},
+ 164: {region: 0x166, script: 0x5b, flags: 0x0},
+ 165: {region: 0x35, script: 0xe, flags: 0x0},
+ 166: {region: 0x166, script: 0x5b, flags: 0x0},
+ 167: {region: 0x166, script: 0x5b, flags: 0x0},
+ 168: {region: 0x166, script: 0x5b, flags: 0x0},
+ 169: {region: 0x53, script: 0xef, flags: 0x0},
+ 170: {region: 0x166, script: 0x5b, flags: 0x0},
+ 171: {region: 0x166, script: 0x5b, flags: 0x0},
+ 172: {region: 0x166, script: 0x5b, flags: 0x0},
+ 173: {region: 0x9a, script: 0xe, flags: 0x0},
+ 174: {region: 0x166, script: 0x5b, flags: 0x0},
+ 175: {region: 0x9d, script: 0x5, flags: 0x0},
+ 176: {region: 0x166, script: 0x5b, flags: 0x0},
+ 177: {region: 0x4f, script: 0x5b, flags: 0x0},
+ 178: {region: 0x79, script: 0x5b, flags: 0x0},
+ 179: {region: 0x9a, script: 0x22, flags: 0x0},
+ 180: {region: 0xe9, script: 0x5, flags: 0x0},
+ 181: {region: 0x9a, script: 0x22, flags: 0x0},
+ 182: {region: 0x166, script: 0x5b, flags: 0x0},
+ 183: {region: 0x33, script: 0x5b, flags: 0x0},
+ 184: {region: 0x166, script: 0x5b, flags: 0x0},
+ 185: {region: 0xb5, script: 0xc, flags: 0x0},
+ 186: {region: 0x52, script: 0x5b, flags: 0x0},
+ 187: {region: 0x166, script: 0x2c, flags: 0x0},
+ 188: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 189: {region: 0x166, script: 0x5b, flags: 0x0},
+ 190: {region: 0xe9, script: 0x22, flags: 0x0},
+ 191: {region: 0x107, script: 0x20, flags: 0x0},
+ 192: {region: 0x160, script: 0x5b, flags: 0x0},
+ 193: {region: 0x166, script: 0x5b, flags: 0x0},
+ 194: {region: 0x96, script: 0x5b, flags: 0x0},
+ 195: {region: 0x166, script: 0x5b, flags: 0x0},
+ 196: {region: 0x52, script: 0x5b, flags: 0x0},
+ 197: {region: 0x166, script: 0x5b, flags: 0x0},
+ 198: {region: 0x166, script: 0x5b, flags: 0x0},
+ 199: {region: 0x166, script: 0x5b, flags: 0x0},
+ 200: {region: 0x87, script: 0x5b, flags: 0x0},
+ 201: {region: 0x166, script: 0x5b, flags: 0x0},
+ 202: {region: 0x166, script: 0x5b, flags: 0x0},
+ 203: {region: 0x166, script: 0x5b, flags: 0x0},
+ 204: {region: 0x166, script: 0x5b, flags: 0x0},
+ 205: {region: 0x6e, script: 0x2c, flags: 0x0},
+ 206: {region: 0x166, script: 0x5b, flags: 0x0},
+ 207: {region: 0x166, script: 0x5b, flags: 0x0},
+ 208: {region: 0x52, script: 0x5b, flags: 0x0},
+ 209: {region: 0x166, script: 0x5b, flags: 0x0},
+ 210: {region: 0x166, script: 0x5b, flags: 0x0},
+ 211: {region: 0xc4, script: 0x5b, flags: 0x0},
+ 212: {region: 0x166, script: 0x5b, flags: 0x0},
+ 213: {region: 0x166, script: 0x5b, flags: 0x0},
+ 214: {region: 0x166, script: 0x5b, flags: 0x0},
+ 215: {region: 0x6f, script: 0x5b, flags: 0x0},
+ 216: {region: 0x166, script: 0x5b, flags: 0x0},
+ 217: {region: 0x166, script: 0x5b, flags: 0x0},
+ 218: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 219: {region: 0x35, script: 0x16, flags: 0x0},
+ 220: {region: 0x107, script: 0x20, flags: 0x0},
+ 221: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 222: {region: 0x166, script: 0x5b, flags: 0x0},
+ 223: {region: 0x132, script: 0x5b, flags: 0x0},
+ 224: {region: 0x8b, script: 0x5b, flags: 0x0},
+ 225: {region: 0x76, script: 0x5b, flags: 0x0},
+ 226: {region: 0x107, script: 0x20, flags: 0x0},
+ 227: {region: 0x136, script: 0x5b, flags: 0x0},
+ 228: {region: 0x49, script: 0x5b, flags: 0x0},
+ 229: {region: 0x136, script: 0x1a, flags: 0x0},
+ 230: {region: 0xa7, script: 0x5, flags: 0x0},
+ 231: {region: 0x13f, script: 0x19, flags: 0x0},
+ 232: {region: 0x166, script: 0x5b, flags: 0x0},
+ 233: {region: 0x9c, script: 0x5, flags: 0x0},
+ 234: {region: 0x166, script: 0x5b, flags: 0x0},
+ 235: {region: 0x166, script: 0x5b, flags: 0x0},
+ 236: {region: 0x166, script: 0x5b, flags: 0x0},
+ 237: {region: 0x166, script: 0x5b, flags: 0x0},
+ 238: {region: 0x166, script: 0x5b, flags: 0x0},
+ 239: {region: 0xc6, script: 0xda, flags: 0x0},
+ 240: {region: 0x79, script: 0x5b, flags: 0x0},
+ 241: {region: 0x6c, script: 0x1d, flags: 0x0},
+ 242: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 243: {region: 0x49, script: 0x17, flags: 0x0},
+ 244: {region: 0x131, script: 0x20, flags: 0x0},
+ 245: {region: 0x49, script: 0x17, flags: 0x0},
+ 246: {region: 0x49, script: 0x17, flags: 0x0},
+ 247: {region: 0x49, script: 0x17, flags: 0x0},
+ 248: {region: 0x49, script: 0x17, flags: 0x0},
+ 249: {region: 0x10b, script: 0x5b, flags: 0x0},
+ 250: {region: 0x5f, script: 0x5b, flags: 0x0},
+ 251: {region: 0xea, script: 0x5b, flags: 0x0},
+ 252: {region: 0x49, script: 0x17, flags: 0x0},
+ 253: {region: 0xc5, script: 0x88, flags: 0x0},
+ 254: {region: 0x8, script: 0x2, flags: 0x1},
+ 255: {region: 0x107, script: 0x20, flags: 0x0},
+ 256: {region: 0x7c, script: 0x5b, flags: 0x0},
+ 257: {region: 0x64, script: 0x5b, flags: 0x0},
+ 258: {region: 0x166, script: 0x5b, flags: 0x0},
+ 259: {region: 0x166, script: 0x5b, flags: 0x0},
+ 260: {region: 0x166, script: 0x5b, flags: 0x0},
+ 261: {region: 0x166, script: 0x5b, flags: 0x0},
+ 262: {region: 0x136, script: 0x5b, flags: 0x0},
+ 263: {region: 0x107, script: 0x20, flags: 0x0},
+ 264: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 265: {region: 0x166, script: 0x5b, flags: 0x0},
+ 266: {region: 0x166, script: 0x5b, flags: 0x0},
+ 267: {region: 0x9a, script: 0x5, flags: 0x0},
+ 268: {region: 0x166, script: 0x5b, flags: 0x0},
+ 269: {region: 0x61, script: 0x5b, flags: 0x0},
+ 270: {region: 0x166, script: 0x5b, flags: 0x0},
+ 271: {region: 0x49, script: 0x5b, flags: 0x0},
+ 272: {region: 0x166, script: 0x5b, flags: 0x0},
+ 273: {region: 0x166, script: 0x5b, flags: 0x0},
+ 274: {region: 0x166, script: 0x5b, flags: 0x0},
+ 275: {region: 0x166, script: 0x5, flags: 0x0},
+ 276: {region: 0x49, script: 0x5b, flags: 0x0},
+ 277: {region: 0x166, script: 0x5b, flags: 0x0},
+ 278: {region: 0x166, script: 0x5b, flags: 0x0},
+ 279: {region: 0xd5, script: 0x5b, flags: 0x0},
+ 280: {region: 0x4f, script: 0x5b, flags: 0x0},
+ 281: {region: 0x166, script: 0x5b, flags: 0x0},
+ 282: {region: 0x9a, script: 0x5, flags: 0x0},
+ 283: {region: 0x166, script: 0x5b, flags: 0x0},
+ 284: {region: 0x166, script: 0x5b, flags: 0x0},
+ 285: {region: 0x166, script: 0x5b, flags: 0x0},
+ 286: {region: 0x166, script: 0x2c, flags: 0x0},
+ 287: {region: 0x61, script: 0x5b, flags: 0x0},
+ 288: {region: 0xc4, script: 0x5b, flags: 0x0},
+ 289: {region: 0xd1, script: 0x5b, flags: 0x0},
+ 290: {region: 0x166, script: 0x5b, flags: 0x0},
+ 291: {region: 0xdc, script: 0x22, flags: 0x0},
+ 292: {region: 0x52, script: 0x5b, flags: 0x0},
+ 293: {region: 0x166, script: 0x5b, flags: 0x0},
+ 294: {region: 0x166, script: 0x5b, flags: 0x0},
+ 295: {region: 0x166, script: 0x5b, flags: 0x0},
+ 296: {region: 0xce, script: 0xed, flags: 0x0},
+ 297: {region: 0x166, script: 0x5b, flags: 0x0},
+ 298: {region: 0x166, script: 0x5b, flags: 0x0},
+ 299: {region: 0x115, script: 0x5b, flags: 0x0},
+ 300: {region: 0x37, script: 0x5b, flags: 0x0},
+ 301: {region: 0x43, script: 0xef, flags: 0x0},
+ 302: {region: 0x166, script: 0x5b, flags: 0x0},
+ 303: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 304: {region: 0x81, script: 0x5b, flags: 0x0},
+ 305: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 306: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 307: {region: 0x6c, script: 0x29, flags: 0x0},
+ 308: {region: 0x166, script: 0x5b, flags: 0x0},
+ 309: {region: 0xc5, script: 0x4b, flags: 0x0},
+ 310: {region: 0x88, script: 0x34, flags: 0x0},
+ 311: {region: 0x166, script: 0x5b, flags: 0x0},
+ 312: {region: 0x166, script: 0x5b, flags: 0x0},
+ 313: {region: 0xa, script: 0x2, flags: 0x1},
+ 314: {region: 0x166, script: 0x5b, flags: 0x0},
+ 315: {region: 0x166, script: 0x5b, flags: 0x0},
+ 316: {region: 0x1, script: 0x5b, flags: 0x0},
+ 317: {region: 0x166, script: 0x5b, flags: 0x0},
+ 318: {region: 0x6f, script: 0x5b, flags: 0x0},
+ 319: {region: 0x136, script: 0x5b, flags: 0x0},
+ 320: {region: 0x6b, script: 0x5b, flags: 0x0},
+ 321: {region: 0x166, script: 0x5b, flags: 0x0},
+ 322: {region: 0x9f, script: 0x46, flags: 0x0},
+ 323: {region: 0x166, script: 0x5b, flags: 0x0},
+ 324: {region: 0x166, script: 0x5b, flags: 0x0},
+ 325: {region: 0x6f, script: 0x5b, flags: 0x0},
+ 326: {region: 0x52, script: 0x5b, flags: 0x0},
+ 327: {region: 0x6f, script: 0x5b, flags: 0x0},
+ 328: {region: 0x9d, script: 0x5, flags: 0x0},
+ 329: {region: 0x166, script: 0x5b, flags: 0x0},
+ 330: {region: 0x166, script: 0x5b, flags: 0x0},
+ 331: {region: 0x166, script: 0x5b, flags: 0x0},
+ 332: {region: 0x166, script: 0x5b, flags: 0x0},
+ 333: {region: 0x87, script: 0x5b, flags: 0x0},
+ 334: {region: 0xc, script: 0x2, flags: 0x1},
+ 335: {region: 0x166, script: 0x5b, flags: 0x0},
+ 336: {region: 0xc4, script: 0x5b, flags: 0x0},
+ 337: {region: 0x73, script: 0x5b, flags: 0x0},
+ 338: {region: 0x10c, script: 0x5, flags: 0x0},
+ 339: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 340: {region: 0x10d, script: 0x5b, flags: 0x0},
+ 341: {region: 0x74, script: 0x5b, flags: 0x0},
+ 342: {region: 0x166, script: 0x5b, flags: 0x0},
+ 343: {region: 0x166, script: 0x5b, flags: 0x0},
+ 344: {region: 0x77, script: 0x5b, flags: 0x0},
+ 345: {region: 0x166, script: 0x5b, flags: 0x0},
+ 346: {region: 0x3b, script: 0x5b, flags: 0x0},
+ 347: {region: 0x166, script: 0x5b, flags: 0x0},
+ 348: {region: 0x166, script: 0x5b, flags: 0x0},
+ 349: {region: 0x166, script: 0x5b, flags: 0x0},
+ 350: {region: 0x79, script: 0x5b, flags: 0x0},
+ 351: {region: 0x136, script: 0x5b, flags: 0x0},
+ 352: {region: 0x79, script: 0x5b, flags: 0x0},
+ 353: {region: 0x61, script: 0x5b, flags: 0x0},
+ 354: {region: 0x61, script: 0x5b, flags: 0x0},
+ 355: {region: 0x52, script: 0x5, flags: 0x0},
+ 356: {region: 0x141, script: 0x5b, flags: 0x0},
+ 357: {region: 0x166, script: 0x5b, flags: 0x0},
+ 358: {region: 0x85, script: 0x5b, flags: 0x0},
+ 359: {region: 0x166, script: 0x5b, flags: 0x0},
+ 360: {region: 0xd5, script: 0x5b, flags: 0x0},
+ 361: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 362: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 363: {region: 0x166, script: 0x5b, flags: 0x0},
+ 364: {region: 0x10c, script: 0x5b, flags: 0x0},
+ 365: {region: 0xda, script: 0x5b, flags: 0x0},
+ 366: {region: 0x97, script: 0x5b, flags: 0x0},
+ 367: {region: 0x81, script: 0x5b, flags: 0x0},
+ 368: {region: 0x166, script: 0x5b, flags: 0x0},
+ 369: {region: 0xbd, script: 0x5b, flags: 0x0},
+ 370: {region: 0x166, script: 0x5b, flags: 0x0},
+ 371: {region: 0x166, script: 0x5b, flags: 0x0},
+ 372: {region: 0x166, script: 0x5b, flags: 0x0},
+ 373: {region: 0x53, script: 0x3b, flags: 0x0},
+ 374: {region: 0x166, script: 0x5b, flags: 0x0},
+ 375: {region: 0x96, script: 0x5b, flags: 0x0},
+ 376: {region: 0x166, script: 0x5b, flags: 0x0},
+ 377: {region: 0x166, script: 0x5b, flags: 0x0},
+ 378: {region: 0x9a, script: 0x22, flags: 0x0},
+ 379: {region: 0x166, script: 0x5b, flags: 0x0},
+ 380: {region: 0x9d, script: 0x5, flags: 0x0},
+ 381: {region: 0x7f, script: 0x5b, flags: 0x0},
+ 382: {region: 0x7c, script: 0x5b, flags: 0x0},
+ 383: {region: 0x166, script: 0x5b, flags: 0x0},
+ 384: {region: 0x166, script: 0x5b, flags: 0x0},
+ 385: {region: 0x166, script: 0x5b, flags: 0x0},
+ 386: {region: 0x166, script: 0x5b, flags: 0x0},
+ 387: {region: 0x166, script: 0x5b, flags: 0x0},
+ 388: {region: 0x166, script: 0x5b, flags: 0x0},
+ 389: {region: 0x70, script: 0x2c, flags: 0x0},
+ 390: {region: 0x166, script: 0x5b, flags: 0x0},
+ 391: {region: 0xdc, script: 0x22, flags: 0x0},
+ 392: {region: 0x166, script: 0x5b, flags: 0x0},
+ 393: {region: 0xa8, script: 0x5b, flags: 0x0},
+ 394: {region: 0x166, script: 0x5b, flags: 0x0},
+ 395: {region: 0xe9, script: 0x5, flags: 0x0},
+ 396: {region: 0x166, script: 0x5b, flags: 0x0},
+ 397: {region: 0xe9, script: 0x5, flags: 0x0},
+ 398: {region: 0x166, script: 0x5b, flags: 0x0},
+ 399: {region: 0x166, script: 0x5b, flags: 0x0},
+ 400: {region: 0x6f, script: 0x5b, flags: 0x0},
+ 401: {region: 0x9d, script: 0x5, flags: 0x0},
+ 402: {region: 0x166, script: 0x5b, flags: 0x0},
+ 403: {region: 0x166, script: 0x2c, flags: 0x0},
+ 404: {region: 0xf2, script: 0x5b, flags: 0x0},
+ 405: {region: 0x166, script: 0x5b, flags: 0x0},
+ 406: {region: 0x166, script: 0x5b, flags: 0x0},
+ 407: {region: 0x166, script: 0x5b, flags: 0x0},
+ 408: {region: 0x166, script: 0x2c, flags: 0x0},
+ 409: {region: 0x166, script: 0x5b, flags: 0x0},
+ 410: {region: 0x9a, script: 0x22, flags: 0x0},
+ 411: {region: 0x9a, script: 0xe9, flags: 0x0},
+ 412: {region: 0x96, script: 0x5b, flags: 0x0},
+ 413: {region: 0xda, script: 0x5b, flags: 0x0},
+ 414: {region: 0x131, script: 0x32, flags: 0x0},
+ 415: {region: 0x166, script: 0x5b, flags: 0x0},
+ 416: {region: 0xe, script: 0x2, flags: 0x1},
+ 417: {region: 0x9a, script: 0xe, flags: 0x0},
+ 418: {region: 0x166, script: 0x5b, flags: 0x0},
+ 419: {region: 0x4e, script: 0x5b, flags: 0x0},
+ 420: {region: 0x9a, script: 0x35, flags: 0x0},
+ 421: {region: 0x41, script: 0x5b, flags: 0x0},
+ 422: {region: 0x54, script: 0x5b, flags: 0x0},
+ 423: {region: 0x166, script: 0x5b, flags: 0x0},
+ 424: {region: 0x81, script: 0x5b, flags: 0x0},
+ 425: {region: 0x166, script: 0x5b, flags: 0x0},
+ 426: {region: 0x166, script: 0x5b, flags: 0x0},
+ 427: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 428: {region: 0x99, script: 0x5b, flags: 0x0},
+ 429: {region: 0x166, script: 0x5b, flags: 0x0},
+ 430: {region: 0xdc, script: 0x22, flags: 0x0},
+ 431: {region: 0x166, script: 0x5b, flags: 0x0},
+ 432: {region: 0x166, script: 0x5, flags: 0x0},
+ 433: {region: 0x49, script: 0x5b, flags: 0x0},
+ 434: {region: 0x166, script: 0x5, flags: 0x0},
+ 435: {region: 0x166, script: 0x5b, flags: 0x0},
+ 436: {region: 0x10, script: 0x3, flags: 0x1},
+ 437: {region: 0x166, script: 0x5b, flags: 0x0},
+ 438: {region: 0x53, script: 0x3b, flags: 0x0},
+ 439: {region: 0x166, script: 0x5b, flags: 0x0},
+ 440: {region: 0x136, script: 0x5b, flags: 0x0},
+ 441: {region: 0x24, script: 0x5, flags: 0x0},
+ 442: {region: 0x166, script: 0x5b, flags: 0x0},
+ 443: {region: 0x166, script: 0x2c, flags: 0x0},
+ 444: {region: 0x98, script: 0x3e, flags: 0x0},
+ 445: {region: 0x166, script: 0x5b, flags: 0x0},
+ 446: {region: 0x9a, script: 0x22, flags: 0x0},
+ 447: {region: 0x166, script: 0x5b, flags: 0x0},
+ 448: {region: 0x74, script: 0x5b, flags: 0x0},
+ 449: {region: 0x166, script: 0x5b, flags: 0x0},
+ 450: {region: 0x166, script: 0x5b, flags: 0x0},
+ 451: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 452: {region: 0x166, script: 0x5b, flags: 0x0},
+ 453: {region: 0x12c, script: 0x40, flags: 0x0},
+ 454: {region: 0x53, script: 0x92, flags: 0x0},
+ 455: {region: 0x166, script: 0x5b, flags: 0x0},
+ 456: {region: 0xe9, script: 0x5, flags: 0x0},
+ 457: {region: 0x9a, script: 0x22, flags: 0x0},
+ 458: {region: 0xb0, script: 0x41, flags: 0x0},
+ 459: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 460: {region: 0xe9, script: 0x5, flags: 0x0},
+ 461: {region: 0xe7, script: 0x5b, flags: 0x0},
+ 462: {region: 0x9a, script: 0x22, flags: 0x0},
+ 463: {region: 0x9a, script: 0x22, flags: 0x0},
+ 464: {region: 0x166, script: 0x5b, flags: 0x0},
+ 465: {region: 0x91, script: 0x5b, flags: 0x0},
+ 466: {region: 0x61, script: 0x5b, flags: 0x0},
+ 467: {region: 0x53, script: 0x3b, flags: 0x0},
+ 468: {region: 0x92, script: 0x5b, flags: 0x0},
+ 469: {region: 0x93, script: 0x5b, flags: 0x0},
+ 470: {region: 0x166, script: 0x5b, flags: 0x0},
+ 471: {region: 0x28, script: 0x8, flags: 0x0},
+ 472: {region: 0xd3, script: 0x5b, flags: 0x0},
+ 473: {region: 0x79, script: 0x5b, flags: 0x0},
+ 474: {region: 0x166, script: 0x5b, flags: 0x0},
+ 475: {region: 0x166, script: 0x5b, flags: 0x0},
+ 476: {region: 0xd1, script: 0x5b, flags: 0x0},
+ 477: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 478: {region: 0x166, script: 0x5b, flags: 0x0},
+ 479: {region: 0x166, script: 0x5b, flags: 0x0},
+ 480: {region: 0x166, script: 0x5b, flags: 0x0},
+ 481: {region: 0x96, script: 0x5b, flags: 0x0},
+ 482: {region: 0x166, script: 0x5b, flags: 0x0},
+ 483: {region: 0x166, script: 0x5b, flags: 0x0},
+ 484: {region: 0x166, script: 0x5b, flags: 0x0},
+ 486: {region: 0x123, script: 0x5b, flags: 0x0},
+ 487: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 488: {region: 0x166, script: 0x5b, flags: 0x0},
+ 489: {region: 0x166, script: 0x5b, flags: 0x0},
+ 490: {region: 0x53, script: 0xfd, flags: 0x0},
+ 491: {region: 0x166, script: 0x5b, flags: 0x0},
+ 492: {region: 0x136, script: 0x5b, flags: 0x0},
+ 493: {region: 0x166, script: 0x5b, flags: 0x0},
+ 494: {region: 0x49, script: 0x5b, flags: 0x0},
+ 495: {region: 0x166, script: 0x5b, flags: 0x0},
+ 496: {region: 0x166, script: 0x5b, flags: 0x0},
+ 497: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 498: {region: 0x166, script: 0x5b, flags: 0x0},
+ 499: {region: 0x96, script: 0x5b, flags: 0x0},
+ 500: {region: 0x107, script: 0x20, flags: 0x0},
+ 501: {region: 0x1, script: 0x5b, flags: 0x0},
+ 502: {region: 0x166, script: 0x5b, flags: 0x0},
+ 503: {region: 0x166, script: 0x5b, flags: 0x0},
+ 504: {region: 0x9e, script: 0x5b, flags: 0x0},
+ 505: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 506: {region: 0x49, script: 0x17, flags: 0x0},
+ 507: {region: 0x98, script: 0x3e, flags: 0x0},
+ 508: {region: 0x166, script: 0x5b, flags: 0x0},
+ 509: {region: 0x166, script: 0x5b, flags: 0x0},
+ 510: {region: 0x107, script: 0x5b, flags: 0x0},
+ 511: {region: 0x166, script: 0x5b, flags: 0x0},
+ 512: {region: 0xa3, script: 0x49, flags: 0x0},
+ 513: {region: 0x166, script: 0x5b, flags: 0x0},
+ 514: {region: 0xa1, script: 0x5b, flags: 0x0},
+ 515: {region: 0x1, script: 0x5b, flags: 0x0},
+ 516: {region: 0x166, script: 0x5b, flags: 0x0},
+ 517: {region: 0x166, script: 0x5b, flags: 0x0},
+ 518: {region: 0x166, script: 0x5b, flags: 0x0},
+ 519: {region: 0x52, script: 0x5b, flags: 0x0},
+ 520: {region: 0x131, script: 0x3e, flags: 0x0},
+ 521: {region: 0x166, script: 0x5b, flags: 0x0},
+ 522: {region: 0x130, script: 0x5b, flags: 0x0},
+ 523: {region: 0xdc, script: 0x22, flags: 0x0},
+ 524: {region: 0x166, script: 0x5b, flags: 0x0},
+ 525: {region: 0x64, script: 0x5b, flags: 0x0},
+ 526: {region: 0x96, script: 0x5b, flags: 0x0},
+ 527: {region: 0x96, script: 0x5b, flags: 0x0},
+ 528: {region: 0x7e, script: 0x2e, flags: 0x0},
+ 529: {region: 0x138, script: 0x20, flags: 0x0},
+ 530: {region: 0x68, script: 0x5b, flags: 0x0},
+ 531: {region: 0xc5, script: 0x5b, flags: 0x0},
+ 532: {region: 0x166, script: 0x5b, flags: 0x0},
+ 533: {region: 0x166, script: 0x5b, flags: 0x0},
+ 534: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 535: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 536: {region: 0xc4, script: 0x5b, flags: 0x0},
+ 537: {region: 0x107, script: 0x20, flags: 0x0},
+ 538: {region: 0x166, script: 0x5b, flags: 0x0},
+ 539: {region: 0x166, script: 0x5b, flags: 0x0},
+ 540: {region: 0x166, script: 0x5b, flags: 0x0},
+ 541: {region: 0x166, script: 0x5b, flags: 0x0},
+ 542: {region: 0xd5, script: 0x5, flags: 0x0},
+ 543: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 544: {region: 0x165, script: 0x5b, flags: 0x0},
+ 545: {region: 0x166, script: 0x5b, flags: 0x0},
+ 546: {region: 0x166, script: 0x5b, flags: 0x0},
+ 547: {region: 0x130, script: 0x5b, flags: 0x0},
+ 548: {region: 0x123, script: 0x5, flags: 0x0},
+ 549: {region: 0x166, script: 0x5b, flags: 0x0},
+ 550: {region: 0x124, script: 0xee, flags: 0x0},
+ 551: {region: 0x5b, script: 0x5b, flags: 0x0},
+ 552: {region: 0x52, script: 0x5b, flags: 0x0},
+ 553: {region: 0x166, script: 0x5b, flags: 0x0},
+ 554: {region: 0x4f, script: 0x5b, flags: 0x0},
+ 555: {region: 0x9a, script: 0x22, flags: 0x0},
+ 556: {region: 0x9a, script: 0x22, flags: 0x0},
+ 557: {region: 0x4b, script: 0x5b, flags: 0x0},
+ 558: {region: 0x96, script: 0x5b, flags: 0x0},
+ 559: {region: 0x166, script: 0x5b, flags: 0x0},
+ 560: {region: 0x41, script: 0x5b, flags: 0x0},
+ 561: {region: 0x9a, script: 0x5b, flags: 0x0},
+ 562: {region: 0x53, script: 0xe5, flags: 0x0},
+ 563: {region: 0x9a, script: 0x22, flags: 0x0},
+ 564: {region: 0xc4, script: 0x5b, flags: 0x0},
+ 565: {region: 0x166, script: 0x5b, flags: 0x0},
+ 566: {region: 0x9a, script: 0x76, flags: 0x0},
+ 567: {region: 0xe9, script: 0x5, flags: 0x0},
+ 568: {region: 0x166, script: 0x5b, flags: 0x0},
+ 569: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 570: {region: 0x166, script: 0x5b, flags: 0x0},
+ 571: {region: 0x12c, script: 0x5b, flags: 0x0},
+ 572: {region: 0x166, script: 0x5b, flags: 0x0},
+ 573: {region: 0xd3, script: 0x5b, flags: 0x0},
+ 574: {region: 0x166, script: 0x5b, flags: 0x0},
+ 575: {region: 0xb0, script: 0x58, flags: 0x0},
+ 576: {region: 0x166, script: 0x5b, flags: 0x0},
+ 577: {region: 0x166, script: 0x5b, flags: 0x0},
+ 578: {region: 0x13, script: 0x6, flags: 0x1},
+ 579: {region: 0x166, script: 0x5b, flags: 0x0},
+ 580: {region: 0x52, script: 0x5b, flags: 0x0},
+ 581: {region: 0x83, script: 0x5b, flags: 0x0},
+ 582: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 583: {region: 0x166, script: 0x5b, flags: 0x0},
+ 584: {region: 0x166, script: 0x5b, flags: 0x0},
+ 585: {region: 0x166, script: 0x5b, flags: 0x0},
+ 586: {region: 0xa7, script: 0x4f, flags: 0x0},
+ 587: {region: 0x2a, script: 0x5b, flags: 0x0},
+ 588: {region: 0x166, script: 0x5b, flags: 0x0},
+ 589: {region: 0x166, script: 0x5b, flags: 0x0},
+ 590: {region: 0x166, script: 0x5b, flags: 0x0},
+ 591: {region: 0x166, script: 0x5b, flags: 0x0},
+ 592: {region: 0x166, script: 0x5b, flags: 0x0},
+ 593: {region: 0x9a, script: 0x53, flags: 0x0},
+ 594: {region: 0x8c, script: 0x5b, flags: 0x0},
+ 595: {region: 0x166, script: 0x5b, flags: 0x0},
+ 596: {region: 0xac, script: 0x54, flags: 0x0},
+ 597: {region: 0x107, script: 0x20, flags: 0x0},
+ 598: {region: 0x9a, script: 0x22, flags: 0x0},
+ 599: {region: 0x166, script: 0x5b, flags: 0x0},
+ 600: {region: 0x76, script: 0x5b, flags: 0x0},
+ 601: {region: 0x166, script: 0x5b, flags: 0x0},
+ 602: {region: 0xb5, script: 0x5b, flags: 0x0},
+ 603: {region: 0x166, script: 0x5b, flags: 0x0},
+ 604: {region: 0x166, script: 0x5b, flags: 0x0},
+ 605: {region: 0x166, script: 0x5b, flags: 0x0},
+ 606: {region: 0x166, script: 0x5b, flags: 0x0},
+ 607: {region: 0x166, script: 0x5b, flags: 0x0},
+ 608: {region: 0x166, script: 0x5b, flags: 0x0},
+ 609: {region: 0x166, script: 0x5b, flags: 0x0},
+ 610: {region: 0x166, script: 0x2c, flags: 0x0},
+ 611: {region: 0x166, script: 0x5b, flags: 0x0},
+ 612: {region: 0x107, script: 0x20, flags: 0x0},
+ 613: {region: 0x113, script: 0x5b, flags: 0x0},
+ 614: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 615: {region: 0x107, script: 0x5b, flags: 0x0},
+ 616: {region: 0x166, script: 0x5b, flags: 0x0},
+ 617: {region: 0x9a, script: 0x22, flags: 0x0},
+ 618: {region: 0x9a, script: 0x5, flags: 0x0},
+ 619: {region: 0x130, script: 0x5b, flags: 0x0},
+ 620: {region: 0x166, script: 0x5b, flags: 0x0},
+ 621: {region: 0x52, script: 0x5b, flags: 0x0},
+ 622: {region: 0x61, script: 0x5b, flags: 0x0},
+ 623: {region: 0x166, script: 0x5b, flags: 0x0},
+ 624: {region: 0x166, script: 0x5b, flags: 0x0},
+ 625: {region: 0x166, script: 0x2c, flags: 0x0},
+ 626: {region: 0x166, script: 0x5b, flags: 0x0},
+ 627: {region: 0x166, script: 0x5b, flags: 0x0},
+ 628: {region: 0x19, script: 0x3, flags: 0x1},
+ 629: {region: 0x166, script: 0x5b, flags: 0x0},
+ 630: {region: 0x166, script: 0x5b, flags: 0x0},
+ 631: {region: 0x166, script: 0x5b, flags: 0x0},
+ 632: {region: 0x166, script: 0x5b, flags: 0x0},
+ 633: {region: 0x107, script: 0x20, flags: 0x0},
+ 634: {region: 0x166, script: 0x5b, flags: 0x0},
+ 635: {region: 0x166, script: 0x5b, flags: 0x0},
+ 636: {region: 0x166, script: 0x5b, flags: 0x0},
+ 637: {region: 0x107, script: 0x20, flags: 0x0},
+ 638: {region: 0x166, script: 0x5b, flags: 0x0},
+ 639: {region: 0x96, script: 0x5b, flags: 0x0},
+ 640: {region: 0xe9, script: 0x5, flags: 0x0},
+ 641: {region: 0x7c, script: 0x5b, flags: 0x0},
+ 642: {region: 0x166, script: 0x5b, flags: 0x0},
+ 643: {region: 0x166, script: 0x5b, flags: 0x0},
+ 644: {region: 0x166, script: 0x5b, flags: 0x0},
+ 645: {region: 0x166, script: 0x2c, flags: 0x0},
+ 646: {region: 0x124, script: 0xee, flags: 0x0},
+ 647: {region: 0xe9, script: 0x5, flags: 0x0},
+ 648: {region: 0x166, script: 0x5b, flags: 0x0},
+ 649: {region: 0x166, script: 0x5b, flags: 0x0},
+ 650: {region: 0x1c, script: 0x5, flags: 0x1},
+ 651: {region: 0x166, script: 0x5b, flags: 0x0},
+ 652: {region: 0x166, script: 0x5b, flags: 0x0},
+ 653: {region: 0x166, script: 0x5b, flags: 0x0},
+ 654: {region: 0x139, script: 0x5b, flags: 0x0},
+ 655: {region: 0x88, script: 0x5f, flags: 0x0},
+ 656: {region: 0x98, script: 0x3e, flags: 0x0},
+ 657: {region: 0x130, script: 0x5b, flags: 0x0},
+ 658: {region: 0xe9, script: 0x5, flags: 0x0},
+ 659: {region: 0x132, script: 0x5b, flags: 0x0},
+ 660: {region: 0x166, script: 0x5b, flags: 0x0},
+ 661: {region: 0xb8, script: 0x5b, flags: 0x0},
+ 662: {region: 0x107, script: 0x20, flags: 0x0},
+ 663: {region: 0x166, script: 0x5b, flags: 0x0},
+ 664: {region: 0x96, script: 0x5b, flags: 0x0},
+ 665: {region: 0x166, script: 0x5b, flags: 0x0},
+ 666: {region: 0x53, script: 0xee, flags: 0x0},
+ 667: {region: 0x166, script: 0x5b, flags: 0x0},
+ 668: {region: 0x166, script: 0x5b, flags: 0x0},
+ 669: {region: 0x166, script: 0x5b, flags: 0x0},
+ 670: {region: 0x166, script: 0x5b, flags: 0x0},
+ 671: {region: 0x9a, script: 0x5d, flags: 0x0},
+ 672: {region: 0x166, script: 0x5b, flags: 0x0},
+ 673: {region: 0x166, script: 0x5b, flags: 0x0},
+ 674: {region: 0x107, script: 0x20, flags: 0x0},
+ 675: {region: 0x132, script: 0x5b, flags: 0x0},
+ 676: {region: 0x166, script: 0x5b, flags: 0x0},
+ 677: {region: 0xda, script: 0x5b, flags: 0x0},
+ 678: {region: 0x166, script: 0x5b, flags: 0x0},
+ 679: {region: 0x166, script: 0x5b, flags: 0x0},
+ 680: {region: 0x21, script: 0x2, flags: 0x1},
+ 681: {region: 0x166, script: 0x5b, flags: 0x0},
+ 682: {region: 0x166, script: 0x5b, flags: 0x0},
+ 683: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 684: {region: 0x53, script: 0x61, flags: 0x0},
+ 685: {region: 0x96, script: 0x5b, flags: 0x0},
+ 686: {region: 0x9d, script: 0x5, flags: 0x0},
+ 687: {region: 0x136, script: 0x5b, flags: 0x0},
+ 688: {region: 0x166, script: 0x5b, flags: 0x0},
+ 689: {region: 0x166, script: 0x5b, flags: 0x0},
+ 690: {region: 0x9a, script: 0xe9, flags: 0x0},
+ 691: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 692: {region: 0x166, script: 0x5b, flags: 0x0},
+ 693: {region: 0x4b, script: 0x5b, flags: 0x0},
+ 694: {region: 0x166, script: 0x5b, flags: 0x0},
+ 695: {region: 0x166, script: 0x5b, flags: 0x0},
+ 696: {region: 0xb0, script: 0x58, flags: 0x0},
+ 697: {region: 0x166, script: 0x5b, flags: 0x0},
+ 698: {region: 0x166, script: 0x5b, flags: 0x0},
+ 699: {region: 0x4b, script: 0x5b, flags: 0x0},
+ 700: {region: 0x166, script: 0x5b, flags: 0x0},
+ 701: {region: 0x166, script: 0x5b, flags: 0x0},
+ 702: {region: 0x163, script: 0x5b, flags: 0x0},
+ 703: {region: 0x9d, script: 0x5, flags: 0x0},
+ 704: {region: 0xb7, script: 0x5b, flags: 0x0},
+ 705: {region: 0xb9, script: 0x5b, flags: 0x0},
+ 706: {region: 0x4b, script: 0x5b, flags: 0x0},
+ 707: {region: 0x4b, script: 0x5b, flags: 0x0},
+ 708: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 709: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 710: {region: 0x9d, script: 0x5, flags: 0x0},
+ 711: {region: 0xb9, script: 0x5b, flags: 0x0},
+ 712: {region: 0x124, script: 0xee, flags: 0x0},
+ 713: {region: 0x53, script: 0x3b, flags: 0x0},
+ 714: {region: 0x12c, script: 0x5b, flags: 0x0},
+ 715: {region: 0x96, script: 0x5b, flags: 0x0},
+ 716: {region: 0x52, script: 0x5b, flags: 0x0},
+ 717: {region: 0x9a, script: 0x22, flags: 0x0},
+ 718: {region: 0x9a, script: 0x22, flags: 0x0},
+ 719: {region: 0x96, script: 0x5b, flags: 0x0},
+ 720: {region: 0x23, script: 0x3, flags: 0x1},
+ 721: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 722: {region: 0x166, script: 0x5b, flags: 0x0},
+ 723: {region: 0xd0, script: 0x5b, flags: 0x0},
+ 724: {region: 0x166, script: 0x5b, flags: 0x0},
+ 725: {region: 0x166, script: 0x5b, flags: 0x0},
+ 726: {region: 0x166, script: 0x5b, flags: 0x0},
+ 727: {region: 0x166, script: 0x5b, flags: 0x0},
+ 728: {region: 0x166, script: 0x5b, flags: 0x0},
+ 729: {region: 0x166, script: 0x5b, flags: 0x0},
+ 730: {region: 0x166, script: 0x5b, flags: 0x0},
+ 731: {region: 0x166, script: 0x5b, flags: 0x0},
+ 732: {region: 0x166, script: 0x5b, flags: 0x0},
+ 733: {region: 0x166, script: 0x5b, flags: 0x0},
+ 734: {region: 0x166, script: 0x5b, flags: 0x0},
+ 735: {region: 0x166, script: 0x5, flags: 0x0},
+ 736: {region: 0x107, script: 0x20, flags: 0x0},
+ 737: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 738: {region: 0x166, script: 0x5b, flags: 0x0},
+ 739: {region: 0x96, script: 0x5b, flags: 0x0},
+ 740: {region: 0x166, script: 0x2c, flags: 0x0},
+ 741: {region: 0x166, script: 0x5b, flags: 0x0},
+ 742: {region: 0x166, script: 0x5b, flags: 0x0},
+ 743: {region: 0x166, script: 0x5b, flags: 0x0},
+ 744: {region: 0x113, script: 0x5b, flags: 0x0},
+ 745: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 746: {region: 0x166, script: 0x5b, flags: 0x0},
+ 747: {region: 0x166, script: 0x5b, flags: 0x0},
+ 748: {region: 0x124, script: 0x5, flags: 0x0},
+ 749: {region: 0xcd, script: 0x5b, flags: 0x0},
+ 750: {region: 0x166, script: 0x5b, flags: 0x0},
+ 751: {region: 0x166, script: 0x5b, flags: 0x0},
+ 752: {region: 0x166, script: 0x5b, flags: 0x0},
+ 753: {region: 0xc0, script: 0x5b, flags: 0x0},
+ 754: {region: 0xd2, script: 0x5b, flags: 0x0},
+ 755: {region: 0x166, script: 0x5b, flags: 0x0},
+ 756: {region: 0x52, script: 0x5b, flags: 0x0},
+ 757: {region: 0xdc, script: 0x22, flags: 0x0},
+ 758: {region: 0x130, script: 0x5b, flags: 0x0},
+ 759: {region: 0xc1, script: 0x5b, flags: 0x0},
+ 760: {region: 0x166, script: 0x5b, flags: 0x0},
+ 761: {region: 0x166, script: 0x5b, flags: 0x0},
+ 762: {region: 0xe1, script: 0x5b, flags: 0x0},
+ 763: {region: 0x166, script: 0x5b, flags: 0x0},
+ 764: {region: 0x96, script: 0x5b, flags: 0x0},
+ 765: {region: 0x9c, script: 0x3d, flags: 0x0},
+ 766: {region: 0x166, script: 0x5b, flags: 0x0},
+ 767: {region: 0xc3, script: 0x20, flags: 0x0},
+ 768: {region: 0x166, script: 0x5, flags: 0x0},
+ 769: {region: 0x166, script: 0x5b, flags: 0x0},
+ 770: {region: 0x166, script: 0x5b, flags: 0x0},
+ 771: {region: 0x166, script: 0x5b, flags: 0x0},
+ 772: {region: 0x9a, script: 0x6f, flags: 0x0},
+ 773: {region: 0x166, script: 0x5b, flags: 0x0},
+ 774: {region: 0x166, script: 0x5b, flags: 0x0},
+ 775: {region: 0x10c, script: 0x5b, flags: 0x0},
+ 776: {region: 0x166, script: 0x5b, flags: 0x0},
+ 777: {region: 0x166, script: 0x5b, flags: 0x0},
+ 778: {region: 0x166, script: 0x5b, flags: 0x0},
+ 779: {region: 0x26, script: 0x3, flags: 0x1},
+ 780: {region: 0x166, script: 0x5b, flags: 0x0},
+ 781: {region: 0x166, script: 0x5b, flags: 0x0},
+ 782: {region: 0x9a, script: 0xe, flags: 0x0},
+ 783: {region: 0xc5, script: 0x76, flags: 0x0},
+ 785: {region: 0x166, script: 0x5b, flags: 0x0},
+ 786: {region: 0x49, script: 0x5b, flags: 0x0},
+ 787: {region: 0x49, script: 0x5b, flags: 0x0},
+ 788: {region: 0x37, script: 0x5b, flags: 0x0},
+ 789: {region: 0x166, script: 0x5b, flags: 0x0},
+ 790: {region: 0x166, script: 0x5b, flags: 0x0},
+ 791: {region: 0x166, script: 0x5b, flags: 0x0},
+ 792: {region: 0x166, script: 0x5b, flags: 0x0},
+ 793: {region: 0x166, script: 0x5b, flags: 0x0},
+ 794: {region: 0x166, script: 0x5b, flags: 0x0},
+ 795: {region: 0x9a, script: 0x22, flags: 0x0},
+ 796: {region: 0xdc, script: 0x22, flags: 0x0},
+ 797: {region: 0x107, script: 0x20, flags: 0x0},
+ 798: {region: 0x35, script: 0x73, flags: 0x0},
+ 799: {region: 0x29, script: 0x3, flags: 0x1},
+ 800: {region: 0xcc, script: 0x5b, flags: 0x0},
+ 801: {region: 0x166, script: 0x5b, flags: 0x0},
+ 802: {region: 0x166, script: 0x5b, flags: 0x0},
+ 803: {region: 0x166, script: 0x5b, flags: 0x0},
+ 804: {region: 0x9a, script: 0x22, flags: 0x0},
+ 805: {region: 0x52, script: 0x5b, flags: 0x0},
+ 807: {region: 0x166, script: 0x5b, flags: 0x0},
+ 808: {region: 0x136, script: 0x5b, flags: 0x0},
+ 809: {region: 0x166, script: 0x5b, flags: 0x0},
+ 810: {region: 0x166, script: 0x5b, flags: 0x0},
+ 811: {region: 0xe9, script: 0x5, flags: 0x0},
+ 812: {region: 0xc4, script: 0x5b, flags: 0x0},
+ 813: {region: 0x9a, script: 0x22, flags: 0x0},
+ 814: {region: 0x96, script: 0x5b, flags: 0x0},
+ 815: {region: 0x165, script: 0x5b, flags: 0x0},
+ 816: {region: 0x166, script: 0x5b, flags: 0x0},
+ 817: {region: 0xc5, script: 0x76, flags: 0x0},
+ 818: {region: 0x166, script: 0x5b, flags: 0x0},
+ 819: {region: 0x166, script: 0x2c, flags: 0x0},
+ 820: {region: 0x107, script: 0x20, flags: 0x0},
+ 821: {region: 0x166, script: 0x5b, flags: 0x0},
+ 822: {region: 0x132, script: 0x5b, flags: 0x0},
+ 823: {region: 0x9d, script: 0x67, flags: 0x0},
+ 824: {region: 0x166, script: 0x5b, flags: 0x0},
+ 825: {region: 0x166, script: 0x5b, flags: 0x0},
+ 826: {region: 0x9d, script: 0x5, flags: 0x0},
+ 827: {region: 0x166, script: 0x5b, flags: 0x0},
+ 828: {region: 0x166, script: 0x5b, flags: 0x0},
+ 829: {region: 0x166, script: 0x5b, flags: 0x0},
+ 830: {region: 0xde, script: 0x5b, flags: 0x0},
+ 831: {region: 0x166, script: 0x5b, flags: 0x0},
+ 832: {region: 0x166, script: 0x5b, flags: 0x0},
+ 834: {region: 0x166, script: 0x5b, flags: 0x0},
+ 835: {region: 0x53, script: 0x3b, flags: 0x0},
+ 836: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 837: {region: 0xd3, script: 0x5b, flags: 0x0},
+ 838: {region: 0x166, script: 0x5b, flags: 0x0},
+ 839: {region: 0xdb, script: 0x5b, flags: 0x0},
+ 840: {region: 0x166, script: 0x5b, flags: 0x0},
+ 841: {region: 0x166, script: 0x5b, flags: 0x0},
+ 842: {region: 0x166, script: 0x5b, flags: 0x0},
+ 843: {region: 0xd0, script: 0x5b, flags: 0x0},
+ 844: {region: 0x166, script: 0x5b, flags: 0x0},
+ 845: {region: 0x166, script: 0x5b, flags: 0x0},
+ 846: {region: 0x165, script: 0x5b, flags: 0x0},
+ 847: {region: 0xd2, script: 0x5b, flags: 0x0},
+ 848: {region: 0x61, script: 0x5b, flags: 0x0},
+ 849: {region: 0xdc, script: 0x22, flags: 0x0},
+ 850: {region: 0x166, script: 0x5b, flags: 0x0},
+ 851: {region: 0xdc, script: 0x22, flags: 0x0},
+ 852: {region: 0x166, script: 0x5b, flags: 0x0},
+ 853: {region: 0x166, script: 0x5b, flags: 0x0},
+ 854: {region: 0xd3, script: 0x5b, flags: 0x0},
+ 855: {region: 0x166, script: 0x5b, flags: 0x0},
+ 856: {region: 0x166, script: 0x5b, flags: 0x0},
+ 857: {region: 0xd2, script: 0x5b, flags: 0x0},
+ 858: {region: 0x166, script: 0x5b, flags: 0x0},
+ 859: {region: 0xd0, script: 0x5b, flags: 0x0},
+ 860: {region: 0xd0, script: 0x5b, flags: 0x0},
+ 861: {region: 0x166, script: 0x5b, flags: 0x0},
+ 862: {region: 0x166, script: 0x5b, flags: 0x0},
+ 863: {region: 0x96, script: 0x5b, flags: 0x0},
+ 864: {region: 0x166, script: 0x5b, flags: 0x0},
+ 865: {region: 0xe0, script: 0x5b, flags: 0x0},
+ 866: {region: 0x166, script: 0x5b, flags: 0x0},
+ 867: {region: 0x166, script: 0x5b, flags: 0x0},
+ 868: {region: 0x9a, script: 0x5b, flags: 0x0},
+ 869: {region: 0x166, script: 0x5b, flags: 0x0},
+ 870: {region: 0x166, script: 0x5b, flags: 0x0},
+ 871: {region: 0xda, script: 0x5b, flags: 0x0},
+ 872: {region: 0x52, script: 0x5b, flags: 0x0},
+ 873: {region: 0x166, script: 0x5b, flags: 0x0},
+ 874: {region: 0xdb, script: 0x5b, flags: 0x0},
+ 875: {region: 0x166, script: 0x5b, flags: 0x0},
+ 876: {region: 0x52, script: 0x5b, flags: 0x0},
+ 877: {region: 0x166, script: 0x5b, flags: 0x0},
+ 878: {region: 0x166, script: 0x5b, flags: 0x0},
+ 879: {region: 0xdb, script: 0x5b, flags: 0x0},
+ 880: {region: 0x124, script: 0x57, flags: 0x0},
+ 881: {region: 0x9a, script: 0x22, flags: 0x0},
+ 882: {region: 0x10d, script: 0xcb, flags: 0x0},
+ 883: {region: 0x166, script: 0x5b, flags: 0x0},
+ 884: {region: 0x166, script: 0x5b, flags: 0x0},
+ 885: {region: 0x85, script: 0x7e, flags: 0x0},
+ 886: {region: 0x162, script: 0x5b, flags: 0x0},
+ 887: {region: 0x166, script: 0x5b, flags: 0x0},
+ 888: {region: 0x49, script: 0x17, flags: 0x0},
+ 889: {region: 0x166, script: 0x5b, flags: 0x0},
+ 890: {region: 0x162, script: 0x5b, flags: 0x0},
+ 891: {region: 0x166, script: 0x5b, flags: 0x0},
+ 892: {region: 0x166, script: 0x5b, flags: 0x0},
+ 893: {region: 0x166, script: 0x5b, flags: 0x0},
+ 894: {region: 0x166, script: 0x5b, flags: 0x0},
+ 895: {region: 0x166, script: 0x5b, flags: 0x0},
+ 896: {region: 0x118, script: 0x5b, flags: 0x0},
+ 897: {region: 0x166, script: 0x5b, flags: 0x0},
+ 898: {region: 0x166, script: 0x5b, flags: 0x0},
+ 899: {region: 0x136, script: 0x5b, flags: 0x0},
+ 900: {region: 0x166, script: 0x5b, flags: 0x0},
+ 901: {region: 0x53, script: 0x5b, flags: 0x0},
+ 902: {region: 0x166, script: 0x5b, flags: 0x0},
+ 903: {region: 0xcf, script: 0x5b, flags: 0x0},
+ 904: {region: 0x130, script: 0x5b, flags: 0x0},
+ 905: {region: 0x132, script: 0x5b, flags: 0x0},
+ 906: {region: 0x81, script: 0x5b, flags: 0x0},
+ 907: {region: 0x79, script: 0x5b, flags: 0x0},
+ 908: {region: 0x166, script: 0x5b, flags: 0x0},
+ 910: {region: 0x166, script: 0x5b, flags: 0x0},
+ 911: {region: 0x166, script: 0x5b, flags: 0x0},
+ 912: {region: 0x70, script: 0x5b, flags: 0x0},
+ 913: {region: 0x166, script: 0x5b, flags: 0x0},
+ 914: {region: 0x166, script: 0x5b, flags: 0x0},
+ 915: {region: 0x166, script: 0x5b, flags: 0x0},
+ 916: {region: 0x166, script: 0x5b, flags: 0x0},
+ 917: {region: 0x9a, script: 0x83, flags: 0x0},
+ 918: {region: 0x166, script: 0x5b, flags: 0x0},
+ 919: {region: 0x166, script: 0x5, flags: 0x0},
+ 920: {region: 0x7e, script: 0x20, flags: 0x0},
+ 921: {region: 0x136, script: 0x84, flags: 0x0},
+ 922: {region: 0x166, script: 0x5, flags: 0x0},
+ 923: {region: 0xc6, script: 0x82, flags: 0x0},
+ 924: {region: 0x166, script: 0x5b, flags: 0x0},
+ 925: {region: 0x2c, script: 0x3, flags: 0x1},
+ 926: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 927: {region: 0x2f, script: 0x2, flags: 0x1},
+ 928: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 929: {region: 0x30, script: 0x5b, flags: 0x0},
+ 930: {region: 0xf1, script: 0x5b, flags: 0x0},
+ 931: {region: 0x166, script: 0x5b, flags: 0x0},
+ 932: {region: 0x79, script: 0x5b, flags: 0x0},
+ 933: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 934: {region: 0x136, script: 0x5b, flags: 0x0},
+ 935: {region: 0x49, script: 0x5b, flags: 0x0},
+ 936: {region: 0x166, script: 0x5b, flags: 0x0},
+ 937: {region: 0x9d, script: 0xfa, flags: 0x0},
+ 938: {region: 0x166, script: 0x5b, flags: 0x0},
+ 939: {region: 0x61, script: 0x5b, flags: 0x0},
+ 940: {region: 0x166, script: 0x5, flags: 0x0},
+ 941: {region: 0xb1, script: 0x90, flags: 0x0},
+ 943: {region: 0x166, script: 0x5b, flags: 0x0},
+ 944: {region: 0x166, script: 0x5b, flags: 0x0},
+ 945: {region: 0x9a, script: 0x12, flags: 0x0},
+ 946: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 947: {region: 0xea, script: 0x5b, flags: 0x0},
+ 948: {region: 0x166, script: 0x5b, flags: 0x0},
+ 949: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 950: {region: 0x166, script: 0x5b, flags: 0x0},
+ 951: {region: 0x166, script: 0x5b, flags: 0x0},
+ 952: {region: 0x88, script: 0x34, flags: 0x0},
+ 953: {region: 0x76, script: 0x5b, flags: 0x0},
+ 954: {region: 0x166, script: 0x5b, flags: 0x0},
+ 955: {region: 0xe9, script: 0x4e, flags: 0x0},
+ 956: {region: 0x9d, script: 0x5, flags: 0x0},
+ 957: {region: 0x1, script: 0x5b, flags: 0x0},
+ 958: {region: 0x24, script: 0x5, flags: 0x0},
+ 959: {region: 0x166, script: 0x5b, flags: 0x0},
+ 960: {region: 0x41, script: 0x5b, flags: 0x0},
+ 961: {region: 0x166, script: 0x5b, flags: 0x0},
+ 962: {region: 0x7b, script: 0x5b, flags: 0x0},
+ 963: {region: 0x166, script: 0x5b, flags: 0x0},
+ 964: {region: 0xe5, script: 0x5b, flags: 0x0},
+ 965: {region: 0x8a, script: 0x5b, flags: 0x0},
+ 966: {region: 0x6a, script: 0x5b, flags: 0x0},
+ 967: {region: 0x166, script: 0x5b, flags: 0x0},
+ 968: {region: 0x9a, script: 0x22, flags: 0x0},
+ 969: {region: 0x166, script: 0x5b, flags: 0x0},
+ 970: {region: 0x103, script: 0x5b, flags: 0x0},
+ 971: {region: 0x96, script: 0x5b, flags: 0x0},
+ 972: {region: 0x166, script: 0x5b, flags: 0x0},
+ 973: {region: 0x166, script: 0x5b, flags: 0x0},
+ 974: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 975: {region: 0x166, script: 0x5, flags: 0x0},
+ 976: {region: 0x9a, script: 0x5b, flags: 0x0},
+ 977: {region: 0x31, script: 0x2, flags: 0x1},
+ 978: {region: 0xdc, script: 0x22, flags: 0x0},
+ 979: {region: 0x35, script: 0xe, flags: 0x0},
+ 980: {region: 0x4e, script: 0x5b, flags: 0x0},
+ 981: {region: 0x73, script: 0x5b, flags: 0x0},
+ 982: {region: 0x4e, script: 0x5b, flags: 0x0},
+ 983: {region: 0x9d, script: 0x5, flags: 0x0},
+ 984: {region: 0x10d, script: 0x5b, flags: 0x0},
+ 985: {region: 0x3a, script: 0x5b, flags: 0x0},
+ 986: {region: 0x166, script: 0x5b, flags: 0x0},
+ 987: {region: 0xd2, script: 0x5b, flags: 0x0},
+ 988: {region: 0x105, script: 0x5b, flags: 0x0},
+ 989: {region: 0x96, script: 0x5b, flags: 0x0},
+ 990: {region: 0x130, script: 0x5b, flags: 0x0},
+ 991: {region: 0x166, script: 0x5b, flags: 0x0},
+ 992: {region: 0x166, script: 0x5b, flags: 0x0},
+ 993: {region: 0x74, script: 0x5b, flags: 0x0},
+ 994: {region: 0x107, script: 0x20, flags: 0x0},
+ 995: {region: 0x131, script: 0x20, flags: 0x0},
+ 996: {region: 0x10a, script: 0x5b, flags: 0x0},
+ 997: {region: 0x108, script: 0x5b, flags: 0x0},
+ 998: {region: 0x130, script: 0x5b, flags: 0x0},
+ 999: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1000: {region: 0xa3, script: 0x4c, flags: 0x0},
+ 1001: {region: 0x9a, script: 0x22, flags: 0x0},
+ 1002: {region: 0x81, script: 0x5b, flags: 0x0},
+ 1003: {region: 0x107, script: 0x20, flags: 0x0},
+ 1004: {region: 0xa5, script: 0x5b, flags: 0x0},
+ 1005: {region: 0x96, script: 0x5b, flags: 0x0},
+ 1006: {region: 0x9a, script: 0x5b, flags: 0x0},
+ 1007: {region: 0x115, script: 0x5b, flags: 0x0},
+ 1008: {region: 0x9a, script: 0xcf, flags: 0x0},
+ 1009: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1010: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1011: {region: 0x130, script: 0x5b, flags: 0x0},
+ 1012: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 1013: {region: 0x9a, script: 0x22, flags: 0x0},
+ 1014: {region: 0x166, script: 0x5, flags: 0x0},
+ 1015: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 1016: {region: 0x7c, script: 0x5b, flags: 0x0},
+ 1017: {region: 0x49, script: 0x5b, flags: 0x0},
+ 1018: {region: 0x33, script: 0x4, flags: 0x1},
+ 1019: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 1020: {region: 0x9d, script: 0x5, flags: 0x0},
+ 1021: {region: 0xdb, script: 0x5b, flags: 0x0},
+ 1022: {region: 0x4f, script: 0x5b, flags: 0x0},
+ 1023: {region: 0xd2, script: 0x5b, flags: 0x0},
+ 1024: {region: 0xd0, script: 0x5b, flags: 0x0},
+ 1025: {region: 0xc4, script: 0x5b, flags: 0x0},
+ 1026: {region: 0x4c, script: 0x5b, flags: 0x0},
+ 1027: {region: 0x97, script: 0x80, flags: 0x0},
+ 1028: {region: 0xb7, script: 0x5b, flags: 0x0},
+ 1029: {region: 0x166, script: 0x2c, flags: 0x0},
+ 1030: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1032: {region: 0xbb, script: 0xeb, flags: 0x0},
+ 1033: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1034: {region: 0xc5, script: 0x76, flags: 0x0},
+ 1035: {region: 0x166, script: 0x5, flags: 0x0},
+ 1036: {region: 0xb4, script: 0xd6, flags: 0x0},
+ 1037: {region: 0x70, script: 0x5b, flags: 0x0},
+ 1038: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1039: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1040: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1041: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1042: {region: 0x112, script: 0x5b, flags: 0x0},
+ 1043: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1044: {region: 0xe9, script: 0x5, flags: 0x0},
+ 1045: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1046: {region: 0x110, script: 0x5b, flags: 0x0},
+ 1047: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1048: {region: 0xea, script: 0x5b, flags: 0x0},
+ 1049: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1050: {region: 0x96, script: 0x5b, flags: 0x0},
+ 1051: {region: 0x143, script: 0x5b, flags: 0x0},
+ 1052: {region: 0x10d, script: 0x5b, flags: 0x0},
+ 1054: {region: 0x10d, script: 0x5b, flags: 0x0},
+ 1055: {region: 0x73, script: 0x5b, flags: 0x0},
+ 1056: {region: 0x98, script: 0xcc, flags: 0x0},
+ 1057: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1058: {region: 0x73, script: 0x5b, flags: 0x0},
+ 1059: {region: 0x165, script: 0x5b, flags: 0x0},
+ 1060: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1061: {region: 0xc4, script: 0x5b, flags: 0x0},
+ 1062: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1063: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1064: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1065: {region: 0x116, script: 0x5b, flags: 0x0},
+ 1066: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1067: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1068: {region: 0x124, script: 0xee, flags: 0x0},
+ 1069: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1070: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1071: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1072: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1073: {region: 0x27, script: 0x5b, flags: 0x0},
+ 1074: {region: 0x37, script: 0x5, flags: 0x1},
+ 1075: {region: 0x9a, script: 0xd9, flags: 0x0},
+ 1076: {region: 0x117, script: 0x5b, flags: 0x0},
+ 1077: {region: 0x115, script: 0x5b, flags: 0x0},
+ 1078: {region: 0x9a, script: 0x22, flags: 0x0},
+ 1079: {region: 0x162, script: 0x5b, flags: 0x0},
+ 1080: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1081: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1082: {region: 0x6e, script: 0x5b, flags: 0x0},
+ 1083: {region: 0x162, script: 0x5b, flags: 0x0},
+ 1084: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1085: {region: 0x61, script: 0x5b, flags: 0x0},
+ 1086: {region: 0x96, script: 0x5b, flags: 0x0},
+ 1087: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1088: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1089: {region: 0x130, script: 0x5b, flags: 0x0},
+ 1090: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1091: {region: 0x85, script: 0x5b, flags: 0x0},
+ 1092: {region: 0x10d, script: 0x5b, flags: 0x0},
+ 1093: {region: 0x130, script: 0x5b, flags: 0x0},
+ 1094: {region: 0x160, script: 0x5, flags: 0x0},
+ 1095: {region: 0x4b, script: 0x5b, flags: 0x0},
+ 1096: {region: 0x61, script: 0x5b, flags: 0x0},
+ 1097: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1098: {region: 0x9a, script: 0x22, flags: 0x0},
+ 1099: {region: 0x96, script: 0x5b, flags: 0x0},
+ 1100: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1101: {region: 0x35, script: 0xe, flags: 0x0},
+ 1102: {region: 0x9c, script: 0xde, flags: 0x0},
+ 1103: {region: 0xea, script: 0x5b, flags: 0x0},
+ 1104: {region: 0x9a, script: 0xe6, flags: 0x0},
+ 1105: {region: 0xdc, script: 0x22, flags: 0x0},
+ 1106: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1107: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1108: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1109: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1110: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1111: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1112: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1113: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1114: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 1115: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1116: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1117: {region: 0x9a, script: 0x53, flags: 0x0},
+ 1118: {region: 0x53, script: 0xe4, flags: 0x0},
+ 1119: {region: 0xdc, script: 0x22, flags: 0x0},
+ 1120: {region: 0xdc, script: 0x22, flags: 0x0},
+ 1121: {region: 0x9a, script: 0xe9, flags: 0x0},
+ 1122: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1123: {region: 0x113, script: 0x5b, flags: 0x0},
+ 1124: {region: 0x132, script: 0x5b, flags: 0x0},
+ 1125: {region: 0x127, script: 0x5b, flags: 0x0},
+ 1126: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1127: {region: 0x3c, script: 0x3, flags: 0x1},
+ 1128: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1129: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1130: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1131: {region: 0x124, script: 0xee, flags: 0x0},
+ 1132: {region: 0xdc, script: 0x22, flags: 0x0},
+ 1133: {region: 0xdc, script: 0x22, flags: 0x0},
+ 1134: {region: 0xdc, script: 0x22, flags: 0x0},
+ 1135: {region: 0x70, script: 0x2c, flags: 0x0},
+ 1136: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1137: {region: 0x6e, script: 0x2c, flags: 0x0},
+ 1138: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1139: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1140: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1141: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 1142: {region: 0x128, script: 0x5b, flags: 0x0},
+ 1143: {region: 0x126, script: 0x5b, flags: 0x0},
+ 1144: {region: 0x32, script: 0x5b, flags: 0x0},
+ 1145: {region: 0xdc, script: 0x22, flags: 0x0},
+ 1146: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 1147: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1148: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1149: {region: 0x32, script: 0x5b, flags: 0x0},
+ 1150: {region: 0xd5, script: 0x5b, flags: 0x0},
+ 1151: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1152: {region: 0x162, script: 0x5b, flags: 0x0},
+ 1153: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1154: {region: 0x12a, script: 0x5b, flags: 0x0},
+ 1155: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1156: {region: 0xcf, script: 0x5b, flags: 0x0},
+ 1157: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1158: {region: 0xe7, script: 0x5b, flags: 0x0},
+ 1159: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1160: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1161: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1162: {region: 0x12c, script: 0x5b, flags: 0x0},
+ 1163: {region: 0x12c, script: 0x5b, flags: 0x0},
+ 1164: {region: 0x12f, script: 0x5b, flags: 0x0},
+ 1165: {region: 0x166, script: 0x5, flags: 0x0},
+ 1166: {region: 0x162, script: 0x5b, flags: 0x0},
+ 1167: {region: 0x88, script: 0x34, flags: 0x0},
+ 1168: {region: 0xdc, script: 0x22, flags: 0x0},
+ 1169: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 1170: {region: 0x43, script: 0xef, flags: 0x0},
+ 1171: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1172: {region: 0x107, script: 0x20, flags: 0x0},
+ 1173: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1174: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1175: {region: 0x132, script: 0x5b, flags: 0x0},
+ 1176: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1177: {region: 0x124, script: 0xee, flags: 0x0},
+ 1178: {region: 0x32, script: 0x5b, flags: 0x0},
+ 1179: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1180: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1181: {region: 0xcf, script: 0x5b, flags: 0x0},
+ 1182: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1183: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1184: {region: 0x12e, script: 0x5b, flags: 0x0},
+ 1185: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1187: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1188: {region: 0xd5, script: 0x5b, flags: 0x0},
+ 1189: {region: 0x53, script: 0xe7, flags: 0x0},
+ 1190: {region: 0xe6, script: 0x5b, flags: 0x0},
+ 1191: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1192: {region: 0x107, script: 0x20, flags: 0x0},
+ 1193: {region: 0xbb, script: 0x5b, flags: 0x0},
+ 1194: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1195: {region: 0x107, script: 0x20, flags: 0x0},
+ 1196: {region: 0x3f, script: 0x4, flags: 0x1},
+ 1197: {region: 0x11d, script: 0xf3, flags: 0x0},
+ 1198: {region: 0x131, script: 0x20, flags: 0x0},
+ 1199: {region: 0x76, script: 0x5b, flags: 0x0},
+ 1200: {region: 0x2a, script: 0x5b, flags: 0x0},
+ 1202: {region: 0x43, script: 0x3, flags: 0x1},
+ 1203: {region: 0x9a, script: 0xe, flags: 0x0},
+ 1204: {region: 0xe9, script: 0x5, flags: 0x0},
+ 1205: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1206: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1207: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1208: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1209: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1210: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1211: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1212: {region: 0x46, script: 0x4, flags: 0x1},
+ 1213: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1214: {region: 0xb5, script: 0xf4, flags: 0x0},
+ 1215: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1216: {region: 0x162, script: 0x5b, flags: 0x0},
+ 1217: {region: 0x9f, script: 0x5b, flags: 0x0},
+ 1218: {region: 0x107, script: 0x5b, flags: 0x0},
+ 1219: {region: 0x13f, script: 0x5b, flags: 0x0},
+ 1220: {region: 0x11c, script: 0x5b, flags: 0x0},
+ 1221: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1222: {region: 0x36, script: 0x5b, flags: 0x0},
+ 1223: {region: 0x61, script: 0x5b, flags: 0x0},
+ 1224: {region: 0xd2, script: 0x5b, flags: 0x0},
+ 1225: {region: 0x1, script: 0x5b, flags: 0x0},
+ 1226: {region: 0x107, script: 0x5b, flags: 0x0},
+ 1227: {region: 0x6b, script: 0x5b, flags: 0x0},
+ 1228: {region: 0x130, script: 0x5b, flags: 0x0},
+ 1229: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1230: {region: 0x36, script: 0x5b, flags: 0x0},
+ 1231: {region: 0x4e, script: 0x5b, flags: 0x0},
+ 1232: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1233: {region: 0x70, script: 0x2c, flags: 0x0},
+ 1234: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1235: {region: 0xe8, script: 0x5b, flags: 0x0},
+ 1236: {region: 0x2f, script: 0x5b, flags: 0x0},
+ 1237: {region: 0x9a, script: 0xe9, flags: 0x0},
+ 1238: {region: 0x9a, script: 0x22, flags: 0x0},
+ 1239: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1240: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1241: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1242: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1243: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1244: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1245: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1246: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1247: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1248: {region: 0x141, script: 0x5b, flags: 0x0},
+ 1249: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1250: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1251: {region: 0xa9, script: 0x5, flags: 0x0},
+ 1252: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1253: {region: 0x115, script: 0x5b, flags: 0x0},
+ 1254: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1255: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1256: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1257: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1258: {region: 0x9a, script: 0x22, flags: 0x0},
+ 1259: {region: 0x53, script: 0x3b, flags: 0x0},
+ 1260: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1261: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1262: {region: 0x41, script: 0x5b, flags: 0x0},
+ 1263: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1264: {region: 0x12c, script: 0x18, flags: 0x0},
+ 1265: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1266: {region: 0x162, script: 0x5b, flags: 0x0},
+ 1267: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1268: {region: 0x12c, script: 0x63, flags: 0x0},
+ 1269: {region: 0x12c, script: 0x64, flags: 0x0},
+ 1270: {region: 0x7e, script: 0x2e, flags: 0x0},
+ 1271: {region: 0x53, script: 0x68, flags: 0x0},
+ 1272: {region: 0x10c, script: 0x6d, flags: 0x0},
+ 1273: {region: 0x109, script: 0x79, flags: 0x0},
+ 1274: {region: 0x9a, script: 0x22, flags: 0x0},
+ 1275: {region: 0x132, script: 0x5b, flags: 0x0},
+ 1276: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1277: {region: 0x9d, script: 0x93, flags: 0x0},
+ 1278: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1279: {region: 0x15f, script: 0xce, flags: 0x0},
+ 1280: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1281: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1282: {region: 0xdc, script: 0x22, flags: 0x0},
+ 1283: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1284: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1285: {region: 0xd2, script: 0x5b, flags: 0x0},
+ 1286: {region: 0x76, script: 0x5b, flags: 0x0},
+ 1287: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1288: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1289: {region: 0x52, script: 0x5b, flags: 0x0},
+ 1290: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1291: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1292: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1293: {region: 0x52, script: 0x5b, flags: 0x0},
+ 1294: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1295: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1296: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1297: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1298: {region: 0x1, script: 0x3e, flags: 0x0},
+ 1299: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1300: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1301: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1302: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1303: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1304: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 1305: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1306: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1307: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1308: {region: 0x41, script: 0x5b, flags: 0x0},
+ 1309: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1310: {region: 0xd0, script: 0x5b, flags: 0x0},
+ 1311: {region: 0x4a, script: 0x3, flags: 0x1},
+ 1312: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1313: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1314: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1315: {region: 0x53, script: 0x5b, flags: 0x0},
+ 1316: {region: 0x10c, script: 0x5b, flags: 0x0},
+ 1318: {region: 0xa9, script: 0x5, flags: 0x0},
+ 1319: {region: 0xda, script: 0x5b, flags: 0x0},
+ 1320: {region: 0xbb, script: 0xeb, flags: 0x0},
+ 1321: {region: 0x4d, script: 0x14, flags: 0x1},
+ 1322: {region: 0x53, script: 0x7f, flags: 0x0},
+ 1323: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1324: {region: 0x123, script: 0x5b, flags: 0x0},
+ 1325: {region: 0xd1, script: 0x5b, flags: 0x0},
+ 1326: {region: 0x166, script: 0x5b, flags: 0x0},
+ 1327: {region: 0x162, script: 0x5b, flags: 0x0},
+ 1329: {region: 0x12c, script: 0x5b, flags: 0x0},
+}
+
+// likelyLangList holds lists info associated with likelyLang.
+// Size: 582 bytes, 97 elements
+var likelyLangList = [97]likelyScriptRegion{
+ 0: {region: 0x9d, script: 0x7, flags: 0x0},
+ 1: {region: 0xa2, script: 0x7a, flags: 0x2},
+ 2: {region: 0x11d, script: 0x87, flags: 0x2},
+ 3: {region: 0x32, script: 0x5b, flags: 0x0},
+ 4: {region: 0x9c, script: 0x5, flags: 0x4},
+ 5: {region: 0x9d, script: 0x5, flags: 0x4},
+ 6: {region: 0x107, script: 0x20, flags: 0x4},
+ 7: {region: 0x9d, script: 0x5, flags: 0x2},
+ 8: {region: 0x107, script: 0x20, flags: 0x0},
+ 9: {region: 0x38, script: 0x2f, flags: 0x2},
+ 10: {region: 0x136, script: 0x5b, flags: 0x0},
+ 11: {region: 0x7c, script: 0xd1, flags: 0x2},
+ 12: {region: 0x115, script: 0x5b, flags: 0x0},
+ 13: {region: 0x85, script: 0x1, flags: 0x2},
+ 14: {region: 0x5e, script: 0x1f, flags: 0x0},
+ 15: {region: 0x88, script: 0x60, flags: 0x2},
+ 16: {region: 0xd7, script: 0x5b, flags: 0x0},
+ 17: {region: 0x52, script: 0x5, flags: 0x4},
+ 18: {region: 0x10c, script: 0x5, flags: 0x4},
+ 19: {region: 0xaf, script: 0x20, flags: 0x0},
+ 20: {region: 0x24, script: 0x5, flags: 0x4},
+ 21: {region: 0x53, script: 0x5, flags: 0x4},
+ 22: {region: 0x9d, script: 0x5, flags: 0x4},
+ 23: {region: 0xc6, script: 0x5, flags: 0x4},
+ 24: {region: 0x53, script: 0x5, flags: 0x2},
+ 25: {region: 0x12c, script: 0x5b, flags: 0x0},
+ 26: {region: 0xb1, script: 0x5, flags: 0x4},
+ 27: {region: 0x9c, script: 0x5, flags: 0x2},
+ 28: {region: 0xa6, script: 0x20, flags: 0x0},
+ 29: {region: 0x53, script: 0x5, flags: 0x4},
+ 30: {region: 0x12c, script: 0x5b, flags: 0x4},
+ 31: {region: 0x53, script: 0x5, flags: 0x2},
+ 32: {region: 0x12c, script: 0x5b, flags: 0x2},
+ 33: {region: 0xdc, script: 0x22, flags: 0x0},
+ 34: {region: 0x9a, script: 0x5e, flags: 0x2},
+ 35: {region: 0x84, script: 0x5b, flags: 0x0},
+ 36: {region: 0x85, script: 0x7e, flags: 0x4},
+ 37: {region: 0x85, script: 0x7e, flags: 0x2},
+ 38: {region: 0xc6, script: 0x20, flags: 0x0},
+ 39: {region: 0x53, script: 0x71, flags: 0x4},
+ 40: {region: 0x53, script: 0x71, flags: 0x2},
+ 41: {region: 0xd1, script: 0x5b, flags: 0x0},
+ 42: {region: 0x4a, script: 0x5, flags: 0x4},
+ 43: {region: 0x96, script: 0x5, flags: 0x4},
+ 44: {region: 0x9a, script: 0x36, flags: 0x0},
+ 45: {region: 0xe9, script: 0x5, flags: 0x4},
+ 46: {region: 0xe9, script: 0x5, flags: 0x2},
+ 47: {region: 0x9d, script: 0x8d, flags: 0x0},
+ 48: {region: 0x53, script: 0x8e, flags: 0x2},
+ 49: {region: 0xbb, script: 0xeb, flags: 0x0},
+ 50: {region: 0xda, script: 0x5b, flags: 0x4},
+ 51: {region: 0xe9, script: 0x5, flags: 0x0},
+ 52: {region: 0x9a, script: 0x22, flags: 0x2},
+ 53: {region: 0x9a, script: 0x50, flags: 0x2},
+ 54: {region: 0x9a, script: 0xd5, flags: 0x2},
+ 55: {region: 0x106, script: 0x20, flags: 0x0},
+ 56: {region: 0xbe, script: 0x5b, flags: 0x4},
+ 57: {region: 0x105, script: 0x5b, flags: 0x4},
+ 58: {region: 0x107, script: 0x5b, flags: 0x4},
+ 59: {region: 0x12c, script: 0x5b, flags: 0x4},
+ 60: {region: 0x125, script: 0x20, flags: 0x0},
+ 61: {region: 0xe9, script: 0x5, flags: 0x4},
+ 62: {region: 0xe9, script: 0x5, flags: 0x2},
+ 63: {region: 0x53, script: 0x5, flags: 0x0},
+ 64: {region: 0xaf, script: 0x20, flags: 0x4},
+ 65: {region: 0xc6, script: 0x20, flags: 0x4},
+ 66: {region: 0xaf, script: 0x20, flags: 0x2},
+ 67: {region: 0x9a, script: 0xe, flags: 0x0},
+ 68: {region: 0xdc, script: 0x22, flags: 0x4},
+ 69: {region: 0xdc, script: 0x22, flags: 0x2},
+ 70: {region: 0x138, script: 0x5b, flags: 0x0},
+ 71: {region: 0x24, script: 0x5, flags: 0x4},
+ 72: {region: 0x53, script: 0x20, flags: 0x4},
+ 73: {region: 0x24, script: 0x5, flags: 0x2},
+ 74: {region: 0x8e, script: 0x3c, flags: 0x0},
+ 75: {region: 0x53, script: 0x3b, flags: 0x4},
+ 76: {region: 0x53, script: 0x3b, flags: 0x2},
+ 77: {region: 0x53, script: 0x3b, flags: 0x0},
+ 78: {region: 0x2f, script: 0x3c, flags: 0x4},
+ 79: {region: 0x3e, script: 0x3c, flags: 0x4},
+ 80: {region: 0x7c, script: 0x3c, flags: 0x4},
+ 81: {region: 0x7f, script: 0x3c, flags: 0x4},
+ 82: {region: 0x8e, script: 0x3c, flags: 0x4},
+ 83: {region: 0x96, script: 0x3c, flags: 0x4},
+ 84: {region: 0xc7, script: 0x3c, flags: 0x4},
+ 85: {region: 0xd1, script: 0x3c, flags: 0x4},
+ 86: {region: 0xe3, script: 0x3c, flags: 0x4},
+ 87: {region: 0xe6, script: 0x3c, flags: 0x4},
+ 88: {region: 0xe8, script: 0x3c, flags: 0x4},
+ 89: {region: 0x117, script: 0x3c, flags: 0x4},
+ 90: {region: 0x124, script: 0x3c, flags: 0x4},
+ 91: {region: 0x12f, script: 0x3c, flags: 0x4},
+ 92: {region: 0x136, script: 0x3c, flags: 0x4},
+ 93: {region: 0x13f, script: 0x3c, flags: 0x4},
+ 94: {region: 0x12f, script: 0x11, flags: 0x2},
+ 95: {region: 0x12f, script: 0x37, flags: 0x2},
+ 96: {region: 0x12f, script: 0x3c, flags: 0x2},
+}
+
+type likelyLangScript struct {
+ lang uint16
+ script uint16
+ flags uint8
+}
+
+// likelyRegion is a lookup table, indexed by regionID, for the most likely
+// languages and scripts given incomplete information. If more entries exist
+// for a given regionID, lang and script are the index and size respectively
+// of the list in likelyRegionList.
+// TODO: exclude containers and user-definable regions from the list.
+// Size: 2154 bytes, 359 elements
+var likelyRegion = [359]likelyLangScript{
+ 34: {lang: 0xd7, script: 0x5b, flags: 0x0},
+ 35: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 36: {lang: 0x0, script: 0x2, flags: 0x1},
+ 39: {lang: 0x2, script: 0x2, flags: 0x1},
+ 40: {lang: 0x4, script: 0x2, flags: 0x1},
+ 42: {lang: 0x3c0, script: 0x5b, flags: 0x0},
+ 43: {lang: 0x0, script: 0x5b, flags: 0x0},
+ 44: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 45: {lang: 0x41b, script: 0x5b, flags: 0x0},
+ 46: {lang: 0x10d, script: 0x5b, flags: 0x0},
+ 48: {lang: 0x367, script: 0x5b, flags: 0x0},
+ 49: {lang: 0x444, script: 0x5b, flags: 0x0},
+ 50: {lang: 0x58, script: 0x5b, flags: 0x0},
+ 51: {lang: 0x6, script: 0x2, flags: 0x1},
+ 53: {lang: 0xa5, script: 0xe, flags: 0x0},
+ 54: {lang: 0x367, script: 0x5b, flags: 0x0},
+ 55: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 56: {lang: 0x7e, script: 0x20, flags: 0x0},
+ 57: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 58: {lang: 0x3d9, script: 0x5b, flags: 0x0},
+ 59: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 60: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 62: {lang: 0x31f, script: 0x5b, flags: 0x0},
+ 63: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 64: {lang: 0x3a1, script: 0x5b, flags: 0x0},
+ 65: {lang: 0x3c0, script: 0x5b, flags: 0x0},
+ 67: {lang: 0x8, script: 0x2, flags: 0x1},
+ 69: {lang: 0x0, script: 0x5b, flags: 0x0},
+ 71: {lang: 0x71, script: 0x20, flags: 0x0},
+ 73: {lang: 0x512, script: 0x3e, flags: 0x2},
+ 74: {lang: 0x31f, script: 0x5, flags: 0x2},
+ 75: {lang: 0x445, script: 0x5b, flags: 0x0},
+ 76: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 77: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 78: {lang: 0x10d, script: 0x5b, flags: 0x0},
+ 79: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 81: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 82: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 83: {lang: 0xa, script: 0x4, flags: 0x1},
+ 84: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 85: {lang: 0x0, script: 0x5b, flags: 0x0},
+ 87: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 90: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 91: {lang: 0x3c0, script: 0x5b, flags: 0x0},
+ 92: {lang: 0x3a1, script: 0x5b, flags: 0x0},
+ 94: {lang: 0xe, script: 0x2, flags: 0x1},
+ 95: {lang: 0xfa, script: 0x5b, flags: 0x0},
+ 97: {lang: 0x10d, script: 0x5b, flags: 0x0},
+ 99: {lang: 0x1, script: 0x5b, flags: 0x0},
+ 100: {lang: 0x101, script: 0x5b, flags: 0x0},
+ 102: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 104: {lang: 0x10, script: 0x2, flags: 0x1},
+ 105: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 106: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 107: {lang: 0x140, script: 0x5b, flags: 0x0},
+ 108: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 109: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 110: {lang: 0x46f, script: 0x2c, flags: 0x0},
+ 111: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 112: {lang: 0x12, script: 0x2, flags: 0x1},
+ 114: {lang: 0x10d, script: 0x5b, flags: 0x0},
+ 115: {lang: 0x151, script: 0x5b, flags: 0x0},
+ 116: {lang: 0x1c0, script: 0x22, flags: 0x2},
+ 119: {lang: 0x158, script: 0x5b, flags: 0x0},
+ 121: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 123: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 124: {lang: 0x14, script: 0x2, flags: 0x1},
+ 126: {lang: 0x16, script: 0x3, flags: 0x1},
+ 127: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 129: {lang: 0x21, script: 0x5b, flags: 0x0},
+ 131: {lang: 0x245, script: 0x5b, flags: 0x0},
+ 133: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 134: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 135: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 136: {lang: 0x19, script: 0x2, flags: 0x1},
+ 137: {lang: 0x0, script: 0x5b, flags: 0x0},
+ 138: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 140: {lang: 0x3c0, script: 0x5b, flags: 0x0},
+ 142: {lang: 0x529, script: 0x3c, flags: 0x0},
+ 143: {lang: 0x0, script: 0x5b, flags: 0x0},
+ 144: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 145: {lang: 0x1d1, script: 0x5b, flags: 0x0},
+ 146: {lang: 0x1d4, script: 0x5b, flags: 0x0},
+ 147: {lang: 0x1d5, script: 0x5b, flags: 0x0},
+ 149: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 150: {lang: 0x1b, script: 0x2, flags: 0x1},
+ 152: {lang: 0x1bc, script: 0x3e, flags: 0x0},
+ 154: {lang: 0x1d, script: 0x3, flags: 0x1},
+ 156: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 157: {lang: 0x20, script: 0x2, flags: 0x1},
+ 158: {lang: 0x1f8, script: 0x5b, flags: 0x0},
+ 159: {lang: 0x1f9, script: 0x5b, flags: 0x0},
+ 162: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 163: {lang: 0x200, script: 0x49, flags: 0x0},
+ 165: {lang: 0x445, script: 0x5b, flags: 0x0},
+ 166: {lang: 0x28a, script: 0x20, flags: 0x0},
+ 167: {lang: 0x22, script: 0x3, flags: 0x1},
+ 169: {lang: 0x25, script: 0x2, flags: 0x1},
+ 171: {lang: 0x254, script: 0x54, flags: 0x0},
+ 172: {lang: 0x254, script: 0x54, flags: 0x0},
+ 173: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 175: {lang: 0x3e2, script: 0x20, flags: 0x0},
+ 176: {lang: 0x27, script: 0x2, flags: 0x1},
+ 177: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 179: {lang: 0x10d, script: 0x5b, flags: 0x0},
+ 180: {lang: 0x40c, script: 0xd6, flags: 0x0},
+ 182: {lang: 0x43b, script: 0x5b, flags: 0x0},
+ 183: {lang: 0x2c0, script: 0x5b, flags: 0x0},
+ 184: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 185: {lang: 0x2c7, script: 0x5b, flags: 0x0},
+ 186: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 187: {lang: 0x29, script: 0x2, flags: 0x1},
+ 188: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 189: {lang: 0x2b, script: 0x2, flags: 0x1},
+ 190: {lang: 0x432, script: 0x5b, flags: 0x0},
+ 191: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 192: {lang: 0x2f1, script: 0x5b, flags: 0x0},
+ 195: {lang: 0x2d, script: 0x2, flags: 0x1},
+ 196: {lang: 0xa0, script: 0x5b, flags: 0x0},
+ 197: {lang: 0x2f, script: 0x2, flags: 0x1},
+ 198: {lang: 0x31, script: 0x2, flags: 0x1},
+ 199: {lang: 0x33, script: 0x2, flags: 0x1},
+ 201: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 202: {lang: 0x35, script: 0x2, flags: 0x1},
+ 204: {lang: 0x320, script: 0x5b, flags: 0x0},
+ 205: {lang: 0x37, script: 0x3, flags: 0x1},
+ 206: {lang: 0x128, script: 0xed, flags: 0x0},
+ 208: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 209: {lang: 0x31f, script: 0x5b, flags: 0x0},
+ 210: {lang: 0x3c0, script: 0x5b, flags: 0x0},
+ 211: {lang: 0x16, script: 0x5b, flags: 0x0},
+ 212: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 213: {lang: 0x1b4, script: 0x5b, flags: 0x0},
+ 215: {lang: 0x1b4, script: 0x5, flags: 0x2},
+ 217: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 218: {lang: 0x367, script: 0x5b, flags: 0x0},
+ 219: {lang: 0x347, script: 0x5b, flags: 0x0},
+ 220: {lang: 0x351, script: 0x22, flags: 0x0},
+ 226: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 227: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 229: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 230: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 231: {lang: 0x486, script: 0x5b, flags: 0x0},
+ 232: {lang: 0x153, script: 0x5b, flags: 0x0},
+ 233: {lang: 0x3a, script: 0x3, flags: 0x1},
+ 234: {lang: 0x3b3, script: 0x5b, flags: 0x0},
+ 235: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 237: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 238: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 239: {lang: 0x3c0, script: 0x5b, flags: 0x0},
+ 241: {lang: 0x3a2, script: 0x5b, flags: 0x0},
+ 242: {lang: 0x194, script: 0x5b, flags: 0x0},
+ 244: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 259: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 261: {lang: 0x3d, script: 0x2, flags: 0x1},
+ 262: {lang: 0x432, script: 0x20, flags: 0x0},
+ 263: {lang: 0x3f, script: 0x2, flags: 0x1},
+ 264: {lang: 0x3e5, script: 0x5b, flags: 0x0},
+ 265: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 267: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 268: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 269: {lang: 0x41, script: 0x2, flags: 0x1},
+ 272: {lang: 0x416, script: 0x5b, flags: 0x0},
+ 273: {lang: 0x347, script: 0x5b, flags: 0x0},
+ 274: {lang: 0x43, script: 0x2, flags: 0x1},
+ 276: {lang: 0x1f9, script: 0x5b, flags: 0x0},
+ 277: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 278: {lang: 0x429, script: 0x5b, flags: 0x0},
+ 279: {lang: 0x367, script: 0x5b, flags: 0x0},
+ 281: {lang: 0x3c0, script: 0x5b, flags: 0x0},
+ 283: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 285: {lang: 0x45, script: 0x2, flags: 0x1},
+ 289: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 290: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 291: {lang: 0x47, script: 0x2, flags: 0x1},
+ 292: {lang: 0x49, script: 0x3, flags: 0x1},
+ 293: {lang: 0x4c, script: 0x2, flags: 0x1},
+ 294: {lang: 0x477, script: 0x5b, flags: 0x0},
+ 295: {lang: 0x3c0, script: 0x5b, flags: 0x0},
+ 296: {lang: 0x476, script: 0x5b, flags: 0x0},
+ 297: {lang: 0x4e, script: 0x2, flags: 0x1},
+ 298: {lang: 0x482, script: 0x5b, flags: 0x0},
+ 300: {lang: 0x50, script: 0x4, flags: 0x1},
+ 302: {lang: 0x4a0, script: 0x5b, flags: 0x0},
+ 303: {lang: 0x54, script: 0x2, flags: 0x1},
+ 304: {lang: 0x445, script: 0x5b, flags: 0x0},
+ 305: {lang: 0x56, script: 0x3, flags: 0x1},
+ 306: {lang: 0x445, script: 0x5b, flags: 0x0},
+ 310: {lang: 0x512, script: 0x3e, flags: 0x2},
+ 311: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 312: {lang: 0x4bc, script: 0x5b, flags: 0x0},
+ 313: {lang: 0x1f9, script: 0x5b, flags: 0x0},
+ 316: {lang: 0x13e, script: 0x5b, flags: 0x0},
+ 319: {lang: 0x4c3, script: 0x5b, flags: 0x0},
+ 320: {lang: 0x8a, script: 0x5b, flags: 0x0},
+ 321: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 323: {lang: 0x41b, script: 0x5b, flags: 0x0},
+ 334: {lang: 0x59, script: 0x2, flags: 0x1},
+ 351: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 352: {lang: 0x5b, script: 0x2, flags: 0x1},
+ 357: {lang: 0x423, script: 0x5b, flags: 0x0},
+}
+
+// likelyRegionList holds lists info associated with likelyRegion.
+// Size: 558 bytes, 93 elements
+var likelyRegionList = [93]likelyLangScript{
+ 0: {lang: 0x148, script: 0x5, flags: 0x0},
+ 1: {lang: 0x476, script: 0x5b, flags: 0x0},
+ 2: {lang: 0x431, script: 0x5b, flags: 0x0},
+ 3: {lang: 0x2ff, script: 0x20, flags: 0x0},
+ 4: {lang: 0x1d7, script: 0x8, flags: 0x0},
+ 5: {lang: 0x274, script: 0x5b, flags: 0x0},
+ 6: {lang: 0xb7, script: 0x5b, flags: 0x0},
+ 7: {lang: 0x432, script: 0x20, flags: 0x0},
+ 8: {lang: 0x12d, script: 0xef, flags: 0x0},
+ 9: {lang: 0x351, script: 0x22, flags: 0x0},
+ 10: {lang: 0x529, script: 0x3b, flags: 0x0},
+ 11: {lang: 0x4ac, script: 0x5, flags: 0x0},
+ 12: {lang: 0x523, script: 0x5b, flags: 0x0},
+ 13: {lang: 0x29a, script: 0xee, flags: 0x0},
+ 14: {lang: 0x136, script: 0x34, flags: 0x0},
+ 15: {lang: 0x48a, script: 0x5b, flags: 0x0},
+ 16: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 17: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 18: {lang: 0x27, script: 0x2c, flags: 0x0},
+ 19: {lang: 0x139, script: 0x5b, flags: 0x0},
+ 20: {lang: 0x26a, script: 0x5, flags: 0x2},
+ 21: {lang: 0x512, script: 0x3e, flags: 0x2},
+ 22: {lang: 0x210, script: 0x2e, flags: 0x0},
+ 23: {lang: 0x5, script: 0x20, flags: 0x0},
+ 24: {lang: 0x274, script: 0x5b, flags: 0x0},
+ 25: {lang: 0x136, script: 0x34, flags: 0x0},
+ 26: {lang: 0x2ff, script: 0x20, flags: 0x0},
+ 27: {lang: 0x1e1, script: 0x5b, flags: 0x0},
+ 28: {lang: 0x31f, script: 0x5, flags: 0x0},
+ 29: {lang: 0x1be, script: 0x22, flags: 0x0},
+ 30: {lang: 0x4b4, script: 0x5, flags: 0x0},
+ 31: {lang: 0x236, script: 0x76, flags: 0x0},
+ 32: {lang: 0x148, script: 0x5, flags: 0x0},
+ 33: {lang: 0x476, script: 0x5b, flags: 0x0},
+ 34: {lang: 0x24a, script: 0x4f, flags: 0x0},
+ 35: {lang: 0xe6, script: 0x5, flags: 0x0},
+ 36: {lang: 0x226, script: 0xee, flags: 0x0},
+ 37: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 38: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 39: {lang: 0x2b8, script: 0x58, flags: 0x0},
+ 40: {lang: 0x226, script: 0xee, flags: 0x0},
+ 41: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 42: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 43: {lang: 0x3dc, script: 0x5b, flags: 0x0},
+ 44: {lang: 0x4ae, script: 0x20, flags: 0x0},
+ 45: {lang: 0x2ff, script: 0x20, flags: 0x0},
+ 46: {lang: 0x431, script: 0x5b, flags: 0x0},
+ 47: {lang: 0x331, script: 0x76, flags: 0x0},
+ 48: {lang: 0x213, script: 0x5b, flags: 0x0},
+ 49: {lang: 0x30b, script: 0x20, flags: 0x0},
+ 50: {lang: 0x242, script: 0x5, flags: 0x0},
+ 51: {lang: 0x529, script: 0x3c, flags: 0x0},
+ 52: {lang: 0x3c0, script: 0x5b, flags: 0x0},
+ 53: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 54: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 55: {lang: 0x2ed, script: 0x5b, flags: 0x0},
+ 56: {lang: 0x4b4, script: 0x5, flags: 0x0},
+ 57: {lang: 0x88, script: 0x22, flags: 0x0},
+ 58: {lang: 0x4b4, script: 0x5, flags: 0x0},
+ 59: {lang: 0x4b4, script: 0x5, flags: 0x0},
+ 60: {lang: 0xbe, script: 0x22, flags: 0x0},
+ 61: {lang: 0x3dc, script: 0x5b, flags: 0x0},
+ 62: {lang: 0x7e, script: 0x20, flags: 0x0},
+ 63: {lang: 0x3e2, script: 0x20, flags: 0x0},
+ 64: {lang: 0x267, script: 0x5b, flags: 0x0},
+ 65: {lang: 0x444, script: 0x5b, flags: 0x0},
+ 66: {lang: 0x512, script: 0x3e, flags: 0x0},
+ 67: {lang: 0x412, script: 0x5b, flags: 0x0},
+ 68: {lang: 0x4ae, script: 0x20, flags: 0x0},
+ 69: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 70: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 71: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 72: {lang: 0x35, script: 0x5, flags: 0x0},
+ 73: {lang: 0x46b, script: 0xee, flags: 0x0},
+ 74: {lang: 0x2ec, script: 0x5, flags: 0x0},
+ 75: {lang: 0x30f, script: 0x76, flags: 0x0},
+ 76: {lang: 0x467, script: 0x20, flags: 0x0},
+ 77: {lang: 0x148, script: 0x5, flags: 0x0},
+ 78: {lang: 0x3a, script: 0x5, flags: 0x0},
+ 79: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 80: {lang: 0x48a, script: 0x5b, flags: 0x0},
+ 81: {lang: 0x58, script: 0x5, flags: 0x0},
+ 82: {lang: 0x219, script: 0x20, flags: 0x0},
+ 83: {lang: 0x81, script: 0x34, flags: 0x0},
+ 84: {lang: 0x529, script: 0x3c, flags: 0x0},
+ 85: {lang: 0x48c, script: 0x5b, flags: 0x0},
+ 86: {lang: 0x4ae, script: 0x20, flags: 0x0},
+ 87: {lang: 0x512, script: 0x3e, flags: 0x0},
+ 88: {lang: 0x3b3, script: 0x5b, flags: 0x0},
+ 89: {lang: 0x431, script: 0x5b, flags: 0x0},
+ 90: {lang: 0x432, script: 0x20, flags: 0x0},
+ 91: {lang: 0x15e, script: 0x5b, flags: 0x0},
+ 92: {lang: 0x446, script: 0x5, flags: 0x0},
+}
+
+type likelyTag struct {
+ lang uint16
+ region uint16
+ script uint16
+}
+
+// Size: 198 bytes, 33 elements
+var likelyRegionGroup = [33]likelyTag{
+ 1: {lang: 0x139, region: 0xd7, script: 0x5b},
+ 2: {lang: 0x139, region: 0x136, script: 0x5b},
+ 3: {lang: 0x3c0, region: 0x41, script: 0x5b},
+ 4: {lang: 0x139, region: 0x2f, script: 0x5b},
+ 5: {lang: 0x139, region: 0xd7, script: 0x5b},
+ 6: {lang: 0x13e, region: 0xd0, script: 0x5b},
+ 7: {lang: 0x445, region: 0x130, script: 0x5b},
+ 8: {lang: 0x3a, region: 0x6c, script: 0x5},
+ 9: {lang: 0x445, region: 0x4b, script: 0x5b},
+ 10: {lang: 0x139, region: 0x162, script: 0x5b},
+ 11: {lang: 0x139, region: 0x136, script: 0x5b},
+ 12: {lang: 0x139, region: 0x136, script: 0x5b},
+ 13: {lang: 0x13e, region: 0x5a, script: 0x5b},
+ 14: {lang: 0x529, region: 0x53, script: 0x3b},
+ 15: {lang: 0x1be, region: 0x9a, script: 0x22},
+ 16: {lang: 0x1e1, region: 0x96, script: 0x5b},
+ 17: {lang: 0x1f9, region: 0x9f, script: 0x5b},
+ 18: {lang: 0x139, region: 0x2f, script: 0x5b},
+ 19: {lang: 0x139, region: 0xe7, script: 0x5b},
+ 20: {lang: 0x139, region: 0x8b, script: 0x5b},
+ 21: {lang: 0x41b, region: 0x143, script: 0x5b},
+ 22: {lang: 0x529, region: 0x53, script: 0x3b},
+ 23: {lang: 0x4bc, region: 0x138, script: 0x5b},
+ 24: {lang: 0x3a, region: 0x109, script: 0x5},
+ 25: {lang: 0x3e2, region: 0x107, script: 0x20},
+ 26: {lang: 0x3e2, region: 0x107, script: 0x20},
+ 27: {lang: 0x139, region: 0x7c, script: 0x5b},
+ 28: {lang: 0x10d, region: 0x61, script: 0x5b},
+ 29: {lang: 0x139, region: 0xd7, script: 0x5b},
+ 30: {lang: 0x13e, region: 0x1f, script: 0x5b},
+ 31: {lang: 0x139, region: 0x9b, script: 0x5b},
+ 32: {lang: 0x139, region: 0x7c, script: 0x5b},
+}
+
+// Size: 264 bytes, 33 elements
+var regionContainment = [33]uint64{
+ // Entry 0 - 1F
+ 0x00000001ffffffff, 0x00000000200007a2, 0x0000000000003044, 0x0000000000000008,
+ 0x00000000803c0010, 0x0000000000000020, 0x0000000000000040, 0x0000000000000080,
+ 0x0000000000000100, 0x0000000000000200, 0x0000000000000400, 0x000000004000384c,
+ 0x0000000000001000, 0x0000000000002000, 0x0000000000004000, 0x0000000000008000,
+ 0x0000000000010000, 0x0000000000020000, 0x0000000000040000, 0x0000000000080000,
+ 0x0000000000100000, 0x0000000000200000, 0x0000000001c1c000, 0x0000000000800000,
+ 0x0000000001000000, 0x000000001e020000, 0x0000000004000000, 0x0000000008000000,
+ 0x0000000010000000, 0x00000000200006a0, 0x0000000040002048, 0x0000000080000000,
+ // Entry 20 - 3F
+ 0x0000000100000000,
+}
+
+// regionInclusion maps region identifiers to sets of regions in regionInclusionBits,
+// where each set holds all groupings that are directly connected in a region
+// containment graph.
+// Size: 359 bytes, 359 elements
+var regionInclusion = [359]uint8{
+ // Entry 0 - 3F
+ 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x23,
+ 0x24, 0x26, 0x27, 0x22, 0x28, 0x29, 0x2a, 0x2b,
+ 0x26, 0x2c, 0x24, 0x23, 0x26, 0x25, 0x2a, 0x2d,
+ 0x2e, 0x24, 0x2f, 0x2d, 0x26, 0x30, 0x31, 0x28,
+ // Entry 40 - 7F
+ 0x26, 0x28, 0x26, 0x25, 0x31, 0x22, 0x32, 0x33,
+ 0x34, 0x30, 0x22, 0x27, 0x27, 0x27, 0x35, 0x2d,
+ 0x29, 0x28, 0x27, 0x36, 0x28, 0x22, 0x21, 0x34,
+ 0x23, 0x21, 0x26, 0x2d, 0x26, 0x22, 0x37, 0x2e,
+ 0x35, 0x2a, 0x22, 0x2f, 0x38, 0x26, 0x26, 0x21,
+ 0x39, 0x39, 0x28, 0x38, 0x39, 0x39, 0x2f, 0x3a,
+ 0x2f, 0x20, 0x21, 0x38, 0x3b, 0x28, 0x3c, 0x2c,
+ 0x21, 0x2a, 0x35, 0x27, 0x38, 0x26, 0x24, 0x28,
+ // Entry 80 - BF
+ 0x2c, 0x2d, 0x23, 0x30, 0x2d, 0x2d, 0x26, 0x27,
+ 0x3a, 0x22, 0x34, 0x3c, 0x2d, 0x28, 0x36, 0x22,
+ 0x34, 0x3a, 0x26, 0x2e, 0x21, 0x39, 0x31, 0x38,
+ 0x24, 0x2c, 0x25, 0x22, 0x24, 0x25, 0x2c, 0x3a,
+ 0x2c, 0x26, 0x24, 0x36, 0x21, 0x2f, 0x3d, 0x31,
+ 0x3c, 0x2f, 0x26, 0x36, 0x36, 0x24, 0x26, 0x3d,
+ 0x31, 0x24, 0x26, 0x35, 0x25, 0x2d, 0x32, 0x38,
+ 0x2a, 0x38, 0x39, 0x39, 0x35, 0x33, 0x23, 0x26,
+ // Entry C0 - FF
+ 0x2f, 0x3c, 0x21, 0x23, 0x2d, 0x31, 0x36, 0x36,
+ 0x3c, 0x26, 0x2d, 0x26, 0x3a, 0x2f, 0x25, 0x2f,
+ 0x34, 0x31, 0x2f, 0x32, 0x3b, 0x2d, 0x2b, 0x2d,
+ 0x21, 0x34, 0x2a, 0x2c, 0x25, 0x21, 0x3c, 0x24,
+ 0x29, 0x2b, 0x24, 0x34, 0x21, 0x28, 0x29, 0x3b,
+ 0x31, 0x25, 0x2e, 0x30, 0x29, 0x26, 0x24, 0x3a,
+ 0x21, 0x3c, 0x28, 0x21, 0x24, 0x21, 0x21, 0x1f,
+ 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+ // Entry 100 - 13F
+ 0x21, 0x21, 0x21, 0x2f, 0x21, 0x2e, 0x23, 0x33,
+ 0x2f, 0x24, 0x3b, 0x2f, 0x39, 0x38, 0x31, 0x2d,
+ 0x3a, 0x2c, 0x2e, 0x2d, 0x23, 0x2d, 0x2f, 0x28,
+ 0x2f, 0x27, 0x33, 0x34, 0x26, 0x24, 0x32, 0x22,
+ 0x26, 0x27, 0x22, 0x2d, 0x31, 0x3d, 0x29, 0x31,
+ 0x3d, 0x39, 0x29, 0x31, 0x24, 0x26, 0x29, 0x36,
+ 0x2f, 0x33, 0x2f, 0x21, 0x22, 0x21, 0x30, 0x28,
+ 0x3d, 0x23, 0x26, 0x21, 0x28, 0x26, 0x26, 0x31,
+ // Entry 140 - 17F
+ 0x3b, 0x29, 0x21, 0x29, 0x21, 0x21, 0x21, 0x21,
+ 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x23, 0x21,
+ 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+ 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24,
+ 0x2f, 0x23, 0x32, 0x2f, 0x27, 0x2f, 0x21,
+}
+
+// regionInclusionBits is an array of bit vectors where every vector represents
+// a set of region groupings. These sets are used to compute the distance
+// between two regions for the purpose of language matching.
+// Size: 584 bytes, 73 elements
+var regionInclusionBits = [73]uint64{
+ // Entry 0 - 1F
+ 0x0000000102400813, 0x00000000200007a3, 0x0000000000003844, 0x0000000040000808,
+ 0x00000000803c0011, 0x0000000020000022, 0x0000000040000844, 0x0000000020000082,
+ 0x0000000000000102, 0x0000000020000202, 0x0000000020000402, 0x000000004000384d,
+ 0x0000000000001804, 0x0000000040002804, 0x0000000000404000, 0x0000000000408000,
+ 0x0000000000410000, 0x0000000002020000, 0x0000000000040010, 0x0000000000080010,
+ 0x0000000000100010, 0x0000000000200010, 0x0000000001c1c001, 0x0000000000c00000,
+ 0x0000000001400000, 0x000000001e020001, 0x0000000006000000, 0x000000000a000000,
+ 0x0000000012000000, 0x00000000200006a2, 0x0000000040002848, 0x0000000080000010,
+ // Entry 20 - 3F
+ 0x0000000100000001, 0x0000000000000001, 0x0000000080000000, 0x0000000000020000,
+ 0x0000000001000000, 0x0000000000008000, 0x0000000000002000, 0x0000000000000200,
+ 0x0000000000000008, 0x0000000000200000, 0x0000000110000000, 0x0000000000040000,
+ 0x0000000008000000, 0x0000000000000020, 0x0000000104000000, 0x0000000000000080,
+ 0x0000000000001000, 0x0000000000010000, 0x0000000000000400, 0x0000000004000000,
+ 0x0000000000000040, 0x0000000010000000, 0x0000000000004000, 0x0000000101000000,
+ 0x0000000108000000, 0x0000000000000100, 0x0000000100020000, 0x0000000000080000,
+ 0x0000000000100000, 0x0000000000800000, 0x00000001ffffffff, 0x0000000122400fb3,
+ // Entry 40 - 5F
+ 0x00000001827c0813, 0x000000014240385f, 0x0000000103c1c813, 0x000000011e420813,
+ 0x0000000112000001, 0x0000000106000001, 0x0000000101400001, 0x000000010a000001,
+ 0x0000000102020001,
+}
+
+// regionInclusionNext marks, for each entry in regionInclusionBits, the set of
+// all groups that are reachable from the groups set in the respective entry.
+// Size: 73 bytes, 73 elements
+var regionInclusionNext = [73]uint8{
+ // Entry 0 - 3F
+ 0x3e, 0x3f, 0x0b, 0x0b, 0x40, 0x01, 0x0b, 0x01,
+ 0x01, 0x01, 0x01, 0x41, 0x0b, 0x0b, 0x16, 0x16,
+ 0x16, 0x19, 0x04, 0x04, 0x04, 0x04, 0x42, 0x16,
+ 0x16, 0x43, 0x19, 0x19, 0x19, 0x01, 0x0b, 0x04,
+ 0x00, 0x00, 0x1f, 0x11, 0x18, 0x0f, 0x0d, 0x09,
+ 0x03, 0x15, 0x44, 0x12, 0x1b, 0x05, 0x45, 0x07,
+ 0x0c, 0x10, 0x0a, 0x1a, 0x06, 0x1c, 0x0e, 0x46,
+ 0x47, 0x08, 0x48, 0x13, 0x14, 0x17, 0x3e, 0x3e,
+ // Entry 40 - 7F
+ 0x3e, 0x3e, 0x3e, 0x3e, 0x43, 0x43, 0x42, 0x43,
+ 0x43,
+}
+
+type parentRel struct {
+ lang uint16
+ script uint16
+ maxScript uint16
+ toRegion uint16
+ fromRegion []uint16
+}
+
+// Size: 414 bytes, 5 elements
+var parents = [5]parentRel{
+ 0: {lang: 0x139, script: 0x0, maxScript: 0x5b, toRegion: 0x1, fromRegion: []uint16{0x1a, 0x25, 0x26, 0x2f, 0x34, 0x36, 0x3d, 0x42, 0x46, 0x48, 0x49, 0x4a, 0x50, 0x52, 0x5d, 0x5e, 0x62, 0x65, 0x6e, 0x74, 0x75, 0x76, 0x7c, 0x7d, 0x80, 0x81, 0x82, 0x84, 0x8d, 0x8e, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0xa0, 0xa1, 0xa5, 0xa8, 0xaa, 0xae, 0xb2, 0xb5, 0xb6, 0xc0, 0xc7, 0xcb, 0xcc, 0xcd, 0xcf, 0xd1, 0xd3, 0xd6, 0xd7, 0xde, 0xe0, 0xe1, 0xe7, 0xe8, 0xe9, 0xec, 0xf1, 0x108, 0x10a, 0x10b, 0x10c, 0x10e, 0x10f, 0x113, 0x118, 0x11c, 0x11e, 0x120, 0x126, 0x12a, 0x12d, 0x12e, 0x130, 0x132, 0x13a, 0x13d, 0x140, 0x143, 0x162, 0x163, 0x165}},
+ 1: {lang: 0x139, script: 0x0, maxScript: 0x5b, toRegion: 0x1a, fromRegion: []uint16{0x2e, 0x4e, 0x61, 0x64, 0x73, 0xda, 0x10d, 0x110}},
+ 2: {lang: 0x13e, script: 0x0, maxScript: 0x5b, toRegion: 0x1f, fromRegion: []uint16{0x2c, 0x3f, 0x41, 0x48, 0x51, 0x54, 0x57, 0x5a, 0x66, 0x6a, 0x8a, 0x90, 0xd0, 0xd9, 0xe3, 0xe5, 0xed, 0xf2, 0x11b, 0x136, 0x137, 0x13c}},
+ 3: {lang: 0x3c0, script: 0x0, maxScript: 0x5b, toRegion: 0xef, fromRegion: []uint16{0x2a, 0x4e, 0x5b, 0x87, 0x8c, 0xb8, 0xc7, 0xd2, 0x119, 0x127}},
+ 4: {lang: 0x529, script: 0x3c, maxScript: 0x3c, toRegion: 0x8e, fromRegion: []uint16{0xc7}},
+}
+
+// Total table size 30466 bytes (29KiB); checksum: 7544152B
diff --git a/vendor/golang.org/x/text/internal/language/tags.go b/vendor/golang.org/x/text/internal/language/tags.go
new file mode 100644
index 0000000..e7afd31
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/language/tags.go
@@ -0,0 +1,48 @@
+// 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 language
+
+// MustParse is like Parse, but panics if the given BCP 47 tag cannot be parsed.
+// It simplifies safe initialization of Tag values.
+func MustParse(s string) Tag {
+ t, err := Parse(s)
+ if err != nil {
+ panic(err)
+ }
+ return t
+}
+
+// MustParseBase is like ParseBase, but panics if the given base cannot be parsed.
+// It simplifies safe initialization of Base values.
+func MustParseBase(s string) Language {
+ b, err := ParseBase(s)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
+
+// MustParseScript is like ParseScript, but panics if the given script cannot be
+// parsed. It simplifies safe initialization of Script values.
+func MustParseScript(s string) Script {
+ scr, err := ParseScript(s)
+ if err != nil {
+ panic(err)
+ }
+ return scr
+}
+
+// MustParseRegion is like ParseRegion, but panics if the given region cannot be
+// parsed. It simplifies safe initialization of Region values.
+func MustParseRegion(s string) Region {
+ r, err := ParseRegion(s)
+ if err != nil {
+ panic(err)
+ }
+ return r
+}
+
+// Und is the root language.
+var Und Tag
diff --git a/vendor/golang.org/x/text/internal/match.go b/vendor/golang.org/x/text/internal/match.go
new file mode 100644
index 0000000..1cc004a
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/match.go
@@ -0,0 +1,67 @@
+// Copyright 2015 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 internal
+
+// This file contains matchers that implement CLDR inheritance.
+//
+// See https://unicode.org/reports/tr35/#Locale_Inheritance.
+//
+// Some of the inheritance described in this document is already handled by
+// the cldr package.
+
+import (
+ "golang.org/x/text/language"
+)
+
+// TODO: consider if (some of the) matching algorithm needs to be public after
+// getting some feel about what is generic and what is specific.
+
+// NewInheritanceMatcher returns a matcher that matches based on the inheritance
+// chain.
+//
+// The matcher uses canonicalization and the parent relationship to find a
+// match. The resulting match will always be either Und or a language with the
+// same language and script as the requested language. It will not match
+// languages for which there is understood to be mutual or one-directional
+// intelligibility.
+//
+// A Match will indicate an Exact match if the language matches after
+// canonicalization and High if the matched tag is a parent.
+func NewInheritanceMatcher(t []language.Tag) *InheritanceMatcher {
+ tags := &InheritanceMatcher{make(map[language.Tag]int)}
+ for i, tag := range t {
+ ct, err := language.All.Canonicalize(tag)
+ if err != nil {
+ ct = tag
+ }
+ tags.index[ct] = i
+ }
+ return tags
+}
+
+type InheritanceMatcher struct {
+ index map[language.Tag]int
+}
+
+func (m InheritanceMatcher) Match(want ...language.Tag) (language.Tag, int, language.Confidence) {
+ for _, t := range want {
+ ct, err := language.All.Canonicalize(t)
+ if err != nil {
+ ct = t
+ }
+ conf := language.Exact
+ for {
+ if index, ok := m.index[ct]; ok {
+ return ct, index, conf
+ }
+ if ct == language.Und {
+ break
+ }
+ ct = ct.Parent()
+ conf = language.High
+ }
+ }
+ return language.Und, 0, language.No
+}
diff --git a/vendor/golang.org/x/text/internal/number/common.go b/vendor/golang.org/x/text/internal/number/common.go
new file mode 100644
index 0000000..a6e9c8e
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/number/common.go
@@ -0,0 +1,55 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package number
+
+import (
+ "unicode/utf8"
+
+ "golang.org/x/text/internal/language/compact"
+)
+
+// A system identifies a CLDR numbering system.
+type system byte
+
+type systemData struct {
+ id system
+ digitSize byte // number of UTF-8 bytes per digit
+ zero [utf8.UTFMax]byte // UTF-8 sequence of zero digit.
+}
+
+// A SymbolType identifies a symbol of a specific kind.
+type SymbolType int
+
+const (
+ SymDecimal SymbolType = iota
+ SymGroup
+ SymList
+ SymPercentSign
+ SymPlusSign
+ SymMinusSign
+ SymExponential
+ SymSuperscriptingExponent
+ SymPerMille
+ SymInfinity
+ SymNan
+ SymTimeSeparator
+
+ NumSymbolTypes
+)
+
+const hasNonLatnMask = 0x8000
+
+// symOffset is an offset into altSymData if the bit indicated by hasNonLatnMask
+// is not 0 (with this bit masked out), and an offset into symIndex otherwise.
+//
+// TODO: this type can be a byte again if we use an indirection into altsymData
+// and introduce an alt -> offset slice (the length of this will be number of
+// alternatives plus 1). This also allows getting rid of the compactTag field
+// in altSymData. In total this will save about 1K.
+type symOffset uint16
+
+type altSymData struct {
+ compactTag compact.ID
+ symIndex symOffset
+ system system
+}
diff --git a/vendor/golang.org/x/text/internal/number/decimal.go b/vendor/golang.org/x/text/internal/number/decimal.go
new file mode 100644
index 0000000..e128cf3
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/number/decimal.go
@@ -0,0 +1,500 @@
+// Copyright 2017 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 stringer -type RoundingMode
+
+package number
+
+import (
+ "math"
+ "strconv"
+)
+
+// RoundingMode determines how a number is rounded to the desired precision.
+type RoundingMode byte
+
+const (
+ ToNearestEven RoundingMode = iota // towards the nearest integer, or towards an even number if equidistant.
+ ToNearestZero // towards the nearest integer, or towards zero if equidistant.
+ ToNearestAway // towards the nearest integer, or away from zero if equidistant.
+ ToPositiveInf // towards infinity
+ ToNegativeInf // towards negative infinity
+ ToZero // towards zero
+ AwayFromZero // away from zero
+ numModes
+)
+
+const maxIntDigits = 20
+
+// A Decimal represents a floating point number in decimal format.
+// Digits represents a number [0, 1.0), and the absolute value represented by
+// Decimal is Digits * 10^Exp. Leading and trailing zeros may be omitted and Exp
+// may point outside a valid position in Digits.
+//
+// Examples:
+//
+// Number Decimal
+// 12345 Digits: [1, 2, 3, 4, 5], Exp: 5
+// 12.345 Digits: [1, 2, 3, 4, 5], Exp: 2
+// 12000 Digits: [1, 2], Exp: 5
+// 12000.00 Digits: [1, 2], Exp: 5
+// 0.00123 Digits: [1, 2, 3], Exp: -2
+// 0 Digits: [], Exp: 0
+type Decimal struct {
+ digits
+
+ buf [maxIntDigits]byte
+}
+
+type digits struct {
+ Digits []byte // mantissa digits, big-endian
+ Exp int32 // exponent
+ Neg bool
+ Inf bool // Takes precedence over Digits and Exp.
+ NaN bool // Takes precedence over Inf.
+}
+
+// Digits represents a floating point number represented in digits of the
+// base in which a number is to be displayed. It is similar to Decimal, but
+// keeps track of trailing fraction zeros and the comma placement for
+// engineering notation. Digits must have at least one digit.
+//
+// Examples:
+//
+// Number Decimal
+// decimal
+// 12345 Digits: [1, 2, 3, 4, 5], Exp: 5 End: 5
+// 12.345 Digits: [1, 2, 3, 4, 5], Exp: 2 End: 5
+// 12000 Digits: [1, 2], Exp: 5 End: 5
+// 12000.00 Digits: [1, 2], Exp: 5 End: 7
+// 0.00123 Digits: [1, 2, 3], Exp: -2 End: 3
+// 0 Digits: [], Exp: 0 End: 1
+// scientific (actual exp is Exp - Comma)
+// 0e0 Digits: [0], Exp: 1, End: 1, Comma: 1
+// .0e0 Digits: [0], Exp: 0, End: 1, Comma: 0
+// 0.0e0 Digits: [0], Exp: 1, End: 2, Comma: 1
+// 1.23e4 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 1
+// .123e5 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 0
+// engineering
+// 12.3e3 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 2
+type Digits struct {
+ digits
+ // End indicates the end position of the number.
+ End int32 // For decimals Exp <= End. For scientific len(Digits) <= End.
+ // Comma is used for the comma position for scientific (always 0 or 1) and
+ // engineering notation (always 0, 1, 2, or 3).
+ Comma uint8
+ // IsScientific indicates whether this number is to be rendered as a
+ // scientific number.
+ IsScientific bool
+}
+
+func (d *Digits) NumFracDigits() int {
+ if d.Exp >= d.End {
+ return 0
+ }
+ return int(d.End - d.Exp)
+}
+
+// normalize returns a new Decimal with leading and trailing zeros removed.
+func (d *Decimal) normalize() (n Decimal) {
+ n = *d
+ b := n.Digits
+ // Strip leading zeros. Resulting number of digits is significant digits.
+ for len(b) > 0 && b[0] == 0 {
+ b = b[1:]
+ n.Exp--
+ }
+ // Strip trailing zeros
+ for len(b) > 0 && b[len(b)-1] == 0 {
+ b = b[:len(b)-1]
+ }
+ if len(b) == 0 {
+ n.Exp = 0
+ }
+ n.Digits = b
+ return n
+}
+
+func (d *Decimal) clear() {
+ b := d.Digits
+ if b == nil {
+ b = d.buf[:0]
+ }
+ *d = Decimal{}
+ d.Digits = b[:0]
+}
+
+func (x *Decimal) String() string {
+ if x.NaN {
+ return "NaN"
+ }
+ var buf []byte
+ if x.Neg {
+ buf = append(buf, '-')
+ }
+ if x.Inf {
+ buf = append(buf, "Inf"...)
+ return string(buf)
+ }
+ switch {
+ case len(x.Digits) == 0:
+ buf = append(buf, '0')
+ case x.Exp <= 0:
+ // 0.00ddd
+ buf = append(buf, "0."...)
+ buf = appendZeros(buf, -int(x.Exp))
+ buf = appendDigits(buf, x.Digits)
+
+ case /* 0 < */ int(x.Exp) < len(x.Digits):
+ // dd.ddd
+ buf = appendDigits(buf, x.Digits[:x.Exp])
+ buf = append(buf, '.')
+ buf = appendDigits(buf, x.Digits[x.Exp:])
+
+ default: // len(x.Digits) <= x.Exp
+ // ddd00
+ buf = appendDigits(buf, x.Digits)
+ buf = appendZeros(buf, int(x.Exp)-len(x.Digits))
+ }
+ return string(buf)
+}
+
+func appendDigits(buf []byte, digits []byte) []byte {
+ for _, c := range digits {
+ buf = append(buf, c+'0')
+ }
+ return buf
+}
+
+// appendZeros appends n 0 digits to buf and returns buf.
+func appendZeros(buf []byte, n int) []byte {
+ for ; n > 0; n-- {
+ buf = append(buf, '0')
+ }
+ return buf
+}
+
+func (d *digits) round(mode RoundingMode, n int) {
+ if n >= len(d.Digits) {
+ return
+ }
+ // Make rounding decision: The result mantissa is truncated ("rounded down")
+ // by default. Decide if we need to increment, or "round up", the (unsigned)
+ // mantissa.
+ inc := false
+ switch mode {
+ case ToNegativeInf:
+ inc = d.Neg
+ case ToPositiveInf:
+ inc = !d.Neg
+ case ToZero:
+ // nothing to do
+ case AwayFromZero:
+ inc = true
+ case ToNearestEven:
+ inc = d.Digits[n] > 5 || d.Digits[n] == 5 &&
+ (len(d.Digits) > n+1 || n == 0 || d.Digits[n-1]&1 != 0)
+ case ToNearestAway:
+ inc = d.Digits[n] >= 5
+ case ToNearestZero:
+ inc = d.Digits[n] > 5 || d.Digits[n] == 5 && len(d.Digits) > n+1
+ default:
+ panic("unreachable")
+ }
+ if inc {
+ d.roundUp(n)
+ } else {
+ d.roundDown(n)
+ }
+}
+
+// roundFloat rounds a floating point number.
+func (r RoundingMode) roundFloat(x float64) float64 {
+ // Make rounding decision: The result mantissa is truncated ("rounded down")
+ // by default. Decide if we need to increment, or "round up", the (unsigned)
+ // mantissa.
+ abs := x
+ if x < 0 {
+ abs = -x
+ }
+ i, f := math.Modf(abs)
+ if f == 0.0 {
+ return x
+ }
+ inc := false
+ switch r {
+ case ToNegativeInf:
+ inc = x < 0
+ case ToPositiveInf:
+ inc = x >= 0
+ case ToZero:
+ // nothing to do
+ case AwayFromZero:
+ inc = true
+ case ToNearestEven:
+ // TODO: check overflow
+ inc = f > 0.5 || f == 0.5 && int64(i)&1 != 0
+ case ToNearestAway:
+ inc = f >= 0.5
+ case ToNearestZero:
+ inc = f > 0.5
+ default:
+ panic("unreachable")
+ }
+ if inc {
+ i += 1
+ }
+ if abs != x {
+ i = -i
+ }
+ return i
+}
+
+func (x *digits) roundUp(n int) {
+ if n < 0 || n >= len(x.Digits) {
+ return // nothing to do
+ }
+ // find first digit < 9
+ for n > 0 && x.Digits[n-1] >= 9 {
+ n--
+ }
+
+ if n == 0 {
+ // all digits are 9s => round up to 1 and update exponent
+ x.Digits[0] = 1 // ok since len(x.Digits) > n
+ x.Digits = x.Digits[:1]
+ x.Exp++
+ return
+ }
+ x.Digits[n-1]++
+ x.Digits = x.Digits[:n]
+ // x already trimmed
+}
+
+func (x *digits) roundDown(n int) {
+ if n < 0 || n >= len(x.Digits) {
+ return // nothing to do
+ }
+ x.Digits = x.Digits[:n]
+ trim(x)
+}
+
+// trim cuts off any trailing zeros from x's mantissa;
+// they are meaningless for the value of x.
+func trim(x *digits) {
+ i := len(x.Digits)
+ for i > 0 && x.Digits[i-1] == 0 {
+ i--
+ }
+ x.Digits = x.Digits[:i]
+ if i == 0 {
+ x.Exp = 0
+ }
+}
+
+// A Converter converts a number into decimals according to the given rounding
+// criteria.
+type Converter interface {
+ Convert(d *Decimal, r RoundingContext)
+}
+
+const (
+ signed = true
+ unsigned = false
+)
+
+// Convert converts the given number to the decimal representation using the
+// supplied RoundingContext.
+func (d *Decimal) Convert(r RoundingContext, number interface{}) {
+ switch f := number.(type) {
+ case Converter:
+ d.clear()
+ f.Convert(d, r)
+ case float32:
+ d.ConvertFloat(r, float64(f), 32)
+ case float64:
+ d.ConvertFloat(r, f, 64)
+ case int:
+ d.ConvertInt(r, signed, uint64(f))
+ case int8:
+ d.ConvertInt(r, signed, uint64(f))
+ case int16:
+ d.ConvertInt(r, signed, uint64(f))
+ case int32:
+ d.ConvertInt(r, signed, uint64(f))
+ case int64:
+ d.ConvertInt(r, signed, uint64(f))
+ case uint:
+ d.ConvertInt(r, unsigned, uint64(f))
+ case uint8:
+ d.ConvertInt(r, unsigned, uint64(f))
+ case uint16:
+ d.ConvertInt(r, unsigned, uint64(f))
+ case uint32:
+ d.ConvertInt(r, unsigned, uint64(f))
+ case uint64:
+ d.ConvertInt(r, unsigned, f)
+
+ default:
+ d.NaN = true
+ // TODO:
+ // case string: if produced by strconv, allows for easy arbitrary pos.
+ // case reflect.Value:
+ // case big.Float
+ // case big.Int
+ // case big.Rat?
+ // catch underlyings using reflect or will this already be done by the
+ // message package?
+ }
+}
+
+// ConvertInt converts an integer to decimals.
+func (d *Decimal) ConvertInt(r RoundingContext, signed bool, x uint64) {
+ if r.Increment > 0 {
+ // TODO: if uint64 is too large, fall back to float64
+ if signed {
+ d.ConvertFloat(r, float64(int64(x)), 64)
+ } else {
+ d.ConvertFloat(r, float64(x), 64)
+ }
+ return
+ }
+ d.clear()
+ if signed && int64(x) < 0 {
+ x = uint64(-int64(x))
+ d.Neg = true
+ }
+ d.fillIntDigits(x)
+ d.Exp = int32(len(d.Digits))
+}
+
+// ConvertFloat converts a floating point number to decimals.
+func (d *Decimal) ConvertFloat(r RoundingContext, x float64, size int) {
+ d.clear()
+ if math.IsNaN(x) {
+ d.NaN = true
+ return
+ }
+ // Simple case: decimal notation
+ if r.Increment > 0 {
+ scale := int(r.IncrementScale)
+ mult := 1.0
+ if scale >= len(scales) {
+ mult = math.Pow(10, float64(scale))
+ } else {
+ mult = scales[scale]
+ }
+ // We multiply x instead of dividing inc as it gives less rounding
+ // issues.
+ x *= mult
+ x /= float64(r.Increment)
+ x = r.Mode.roundFloat(x)
+ x *= float64(r.Increment)
+ x /= mult
+ }
+
+ abs := x
+ if x < 0 {
+ d.Neg = true
+ abs = -x
+ }
+ if math.IsInf(abs, 1) {
+ d.Inf = true
+ return
+ }
+
+ // By default we get the exact decimal representation.
+ verb := byte('g')
+ prec := -1
+ // As the strconv API does not return the rounding accuracy, we can only
+ // round using ToNearestEven.
+ if r.Mode == ToNearestEven {
+ if n := r.RoundSignificantDigits(); n >= 0 {
+ prec = n
+ } else if n = r.RoundFractionDigits(); n >= 0 {
+ prec = n
+ verb = 'f'
+ }
+ } else {
+ // TODO: At this point strconv's rounding is imprecise to the point that
+ // it is not usable for this purpose.
+ // See https://github.com/golang/go/issues/21714
+ // If rounding is requested, we ask for a large number of digits and
+ // round from there to simulate rounding only once.
+ // Ideally we would have strconv export an AppendDigits that would take
+ // a rounding mode and/or return an accuracy. Something like this would
+ // work:
+ // AppendDigits(dst []byte, x float64, base, size, prec int) (digits []byte, exp, accuracy int)
+ hasPrec := r.RoundSignificantDigits() >= 0
+ hasScale := r.RoundFractionDigits() >= 0
+ if hasPrec || hasScale {
+ // prec is the number of mantissa bits plus some extra for safety.
+ // We need at least the number of mantissa bits as decimals to
+ // accurately represent the floating point without rounding, as each
+ // bit requires one more decimal to represent: 0.5, 0.25, 0.125, ...
+ prec = 60
+ }
+ }
+
+ b := strconv.AppendFloat(d.Digits[:0], abs, verb, prec, size)
+ i := 0
+ k := 0
+ beforeDot := 1
+ for i < len(b) {
+ if c := b[i]; '0' <= c && c <= '9' {
+ b[k] = c - '0'
+ k++
+ d.Exp += int32(beforeDot)
+ } else if c == '.' {
+ beforeDot = 0
+ d.Exp = int32(k)
+ } else {
+ break
+ }
+ i++
+ }
+ d.Digits = b[:k]
+ if i != len(b) {
+ i += len("e")
+ pSign := i
+ exp := 0
+ for i++; i < len(b); i++ {
+ exp *= 10
+ exp += int(b[i] - '0')
+ }
+ if b[pSign] == '-' {
+ exp = -exp
+ }
+ d.Exp = int32(exp) + 1
+ }
+}
+
+func (d *Decimal) fillIntDigits(x uint64) {
+ if cap(d.Digits) < maxIntDigits {
+ d.Digits = d.buf[:]
+ } else {
+ d.Digits = d.buf[:maxIntDigits]
+ }
+ i := 0
+ for ; x > 0; x /= 10 {
+ d.Digits[i] = byte(x % 10)
+ i++
+ }
+ d.Digits = d.Digits[:i]
+ for p := 0; p < i; p++ {
+ i--
+ d.Digits[p], d.Digits[i] = d.Digits[i], d.Digits[p]
+ }
+}
+
+var scales [70]float64
+
+func init() {
+ x := 1.0
+ for i := range scales {
+ scales[i] = x
+ x *= 10
+ }
+}
diff --git a/vendor/golang.org/x/text/internal/number/format.go b/vendor/golang.org/x/text/internal/number/format.go
new file mode 100644
index 0000000..cd94c5d
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/number/format.go
@@ -0,0 +1,535 @@
+// Copyright 2017 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 number
+
+import (
+ "strconv"
+ "unicode/utf8"
+
+ "golang.org/x/text/language"
+)
+
+// TODO:
+// - grouping of fractions
+// - allow user-defined superscript notation (such as <sup>4</sup>)
+// - same for non-breaking spaces, like &nbsp;
+
+// A VisibleDigits computes digits, comma placement and trailing zeros as they
+// will be shown to the user.
+type VisibleDigits interface {
+ Digits(buf []byte, t language.Tag, scale int) Digits
+ // TODO: Do we also need to add the verb or pass a format.State?
+}
+
+// Formatting proceeds along the following lines:
+// 0) Compose rounding information from format and context.
+// 1) Convert a number into a Decimal.
+// 2) Sanitize Decimal by adding trailing zeros, removing leading digits, and
+// (non-increment) rounding. The Decimal that results from this is suitable
+// for determining the plural form.
+// 3) Render the Decimal in the localized form.
+
+// Formatter contains all the information needed to render a number.
+type Formatter struct {
+ Pattern
+ Info
+}
+
+func (f *Formatter) init(t language.Tag, index []uint8) {
+ f.Info = InfoFromTag(t)
+ f.Pattern = formats[index[tagToID(t)]]
+}
+
+// InitPattern initializes a Formatter for the given Pattern.
+func (f *Formatter) InitPattern(t language.Tag, pat *Pattern) {
+ f.Info = InfoFromTag(t)
+ f.Pattern = *pat
+}
+
+// InitDecimal initializes a Formatter using the default Pattern for the given
+// language.
+func (f *Formatter) InitDecimal(t language.Tag) {
+ f.init(t, tagToDecimal)
+}
+
+// InitScientific initializes a Formatter using the default Pattern for the
+// given language.
+func (f *Formatter) InitScientific(t language.Tag) {
+ f.init(t, tagToScientific)
+ f.Pattern.MinFractionDigits = 0
+ f.Pattern.MaxFractionDigits = -1
+}
+
+// InitEngineering initializes a Formatter using the default Pattern for the
+// given language.
+func (f *Formatter) InitEngineering(t language.Tag) {
+ f.init(t, tagToScientific)
+ f.Pattern.MinFractionDigits = 0
+ f.Pattern.MaxFractionDigits = -1
+ f.Pattern.MaxIntegerDigits = 3
+ f.Pattern.MinIntegerDigits = 1
+}
+
+// InitPercent initializes a Formatter using the default Pattern for the given
+// language.
+func (f *Formatter) InitPercent(t language.Tag) {
+ f.init(t, tagToPercent)
+}
+
+// InitPerMille initializes a Formatter using the default Pattern for the given
+// language.
+func (f *Formatter) InitPerMille(t language.Tag) {
+ f.init(t, tagToPercent)
+ f.Pattern.DigitShift = 3
+}
+
+func (f *Formatter) Append(dst []byte, x interface{}) []byte {
+ var d Decimal
+ r := f.RoundingContext
+ d.Convert(r, x)
+ return f.Render(dst, FormatDigits(&d, r))
+}
+
+func FormatDigits(d *Decimal, r RoundingContext) Digits {
+ if r.isScientific() {
+ return scientificVisibleDigits(r, d)
+ }
+ return decimalVisibleDigits(r, d)
+}
+
+func (f *Formatter) Format(dst []byte, d *Decimal) []byte {
+ return f.Render(dst, FormatDigits(d, f.RoundingContext))
+}
+
+func (f *Formatter) Render(dst []byte, d Digits) []byte {
+ var result []byte
+ var postPrefix, preSuffix int
+ if d.IsScientific {
+ result, postPrefix, preSuffix = appendScientific(dst, f, &d)
+ } else {
+ result, postPrefix, preSuffix = appendDecimal(dst, f, &d)
+ }
+ if f.PadRune == 0 {
+ return result
+ }
+ width := int(f.FormatWidth)
+ if count := utf8.RuneCount(result); count < width {
+ insertPos := 0
+ switch f.Flags & PadMask {
+ case PadAfterPrefix:
+ insertPos = postPrefix
+ case PadBeforeSuffix:
+ insertPos = preSuffix
+ case PadAfterSuffix:
+ insertPos = len(result)
+ }
+ num := width - count
+ pad := [utf8.UTFMax]byte{' '}
+ sz := 1
+ if r := f.PadRune; r != 0 {
+ sz = utf8.EncodeRune(pad[:], r)
+ }
+ extra := sz * num
+ if n := len(result) + extra; n < cap(result) {
+ result = result[:n]
+ copy(result[insertPos+extra:], result[insertPos:])
+ } else {
+ buf := make([]byte, n)
+ copy(buf, result[:insertPos])
+ copy(buf[insertPos+extra:], result[insertPos:])
+ result = buf
+ }
+ for ; num > 0; num-- {
+ insertPos += copy(result[insertPos:], pad[:sz])
+ }
+ }
+ return result
+}
+
+// decimalVisibleDigits converts d according to the RoundingContext. Note that
+// the exponent may change as a result of this operation.
+func decimalVisibleDigits(r RoundingContext, d *Decimal) Digits {
+ if d.NaN || d.Inf {
+ return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}}
+ }
+ n := Digits{digits: d.normalize().digits}
+
+ exp := n.Exp
+ exp += int32(r.DigitShift)
+
+ // Cap integer digits. Remove *most-significant* digits.
+ if r.MaxIntegerDigits > 0 {
+ if p := int(exp) - int(r.MaxIntegerDigits); p > 0 {
+ if p > len(n.Digits) {
+ p = len(n.Digits)
+ }
+ if n.Digits = n.Digits[p:]; len(n.Digits) == 0 {
+ exp = 0
+ } else {
+ exp -= int32(p)
+ }
+ // Strip leading zeros.
+ for len(n.Digits) > 0 && n.Digits[0] == 0 {
+ n.Digits = n.Digits[1:]
+ exp--
+ }
+ }
+ }
+
+ // Rounding if not already done by Convert.
+ p := len(n.Digits)
+ if maxSig := int(r.MaxSignificantDigits); maxSig > 0 {
+ p = maxSig
+ }
+ if maxFrac := int(r.MaxFractionDigits); maxFrac >= 0 {
+ if cap := int(exp) + maxFrac; cap < p {
+ p = int(exp) + maxFrac
+ }
+ if p < 0 {
+ p = 0
+ }
+ }
+ n.round(r.Mode, p)
+
+ // set End (trailing zeros)
+ n.End = int32(len(n.Digits))
+ if n.End == 0 {
+ exp = 0
+ if r.MinFractionDigits > 0 {
+ n.End = int32(r.MinFractionDigits)
+ }
+ if p := int32(r.MinSignificantDigits) - 1; p > n.End {
+ n.End = p
+ }
+ } else {
+ if end := exp + int32(r.MinFractionDigits); end > n.End {
+ n.End = end
+ }
+ if n.End < int32(r.MinSignificantDigits) {
+ n.End = int32(r.MinSignificantDigits)
+ }
+ }
+ n.Exp = exp
+ return n
+}
+
+// appendDecimal appends a formatted number to dst. It returns two possible
+// insertion points for padding.
+func appendDecimal(dst []byte, f *Formatter, n *Digits) (b []byte, postPre, preSuf int) {
+ if dst, ok := f.renderSpecial(dst, n); ok {
+ return dst, 0, len(dst)
+ }
+ digits := n.Digits
+ exp := n.Exp
+
+ // Split in integer and fraction part.
+ var intDigits, fracDigits []byte
+ numInt := 0
+ numFrac := int(n.End - n.Exp)
+ if exp > 0 {
+ numInt = int(exp)
+ if int(exp) >= len(digits) { // ddddd | ddddd00
+ intDigits = digits
+ } else { // ddd.dd
+ intDigits = digits[:exp]
+ fracDigits = digits[exp:]
+ }
+ } else {
+ fracDigits = digits
+ }
+
+ neg := n.Neg
+ affix, suffix := f.getAffixes(neg)
+ dst = appendAffix(dst, f, affix, neg)
+ savedLen := len(dst)
+
+ minInt := int(f.MinIntegerDigits)
+ if minInt == 0 && f.MinSignificantDigits > 0 {
+ minInt = 1
+ }
+ // add leading zeros
+ for i := minInt; i > numInt; i-- {
+ dst = f.AppendDigit(dst, 0)
+ if f.needsSep(i) {
+ dst = append(dst, f.Symbol(SymGroup)...)
+ }
+ }
+ i := 0
+ for ; i < len(intDigits); i++ {
+ dst = f.AppendDigit(dst, intDigits[i])
+ if f.needsSep(numInt - i) {
+ dst = append(dst, f.Symbol(SymGroup)...)
+ }
+ }
+ for ; i < numInt; i++ {
+ dst = f.AppendDigit(dst, 0)
+ if f.needsSep(numInt - i) {
+ dst = append(dst, f.Symbol(SymGroup)...)
+ }
+ }
+
+ if numFrac > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
+ dst = append(dst, f.Symbol(SymDecimal)...)
+ }
+ // Add trailing zeros
+ i = 0
+ for n := -int(n.Exp); i < n; i++ {
+ dst = f.AppendDigit(dst, 0)
+ }
+ for _, d := range fracDigits {
+ i++
+ dst = f.AppendDigit(dst, d)
+ }
+ for ; i < numFrac; i++ {
+ dst = f.AppendDigit(dst, 0)
+ }
+ return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
+}
+
+func scientificVisibleDigits(r RoundingContext, d *Decimal) Digits {
+ if d.NaN || d.Inf {
+ return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}}
+ }
+ n := Digits{digits: d.normalize().digits, IsScientific: true}
+
+ // Normalize to have at least one digit. This simplifies engineering
+ // notation.
+ if len(n.Digits) == 0 {
+ n.Digits = append(n.Digits, 0)
+ n.Exp = 1
+ }
+
+ // Significant digits are transformed by the parser for scientific notation
+ // and do not need to be handled here.
+ maxInt, numInt := int(r.MaxIntegerDigits), int(r.MinIntegerDigits)
+ if numInt == 0 {
+ numInt = 1
+ }
+
+ // If a maximum number of integers is specified, the minimum must be 1
+ // and the exponent is grouped by this number (e.g. for engineering)
+ if maxInt > numInt {
+ // Correct the exponent to reflect a single integer digit.
+ numInt = 1
+ // engineering
+ // 0.01234 ([12345]e-1) -> 1.2345e-2 12.345e-3
+ // 12345 ([12345]e+5) -> 1.2345e4 12.345e3
+ d := int(n.Exp-1) % maxInt
+ if d < 0 {
+ d += maxInt
+ }
+ numInt += d
+ }
+
+ p := len(n.Digits)
+ if maxSig := int(r.MaxSignificantDigits); maxSig > 0 {
+ p = maxSig
+ }
+ if maxFrac := int(r.MaxFractionDigits); maxFrac >= 0 && numInt+maxFrac < p {
+ p = numInt + maxFrac
+ }
+ n.round(r.Mode, p)
+
+ n.Comma = uint8(numInt)
+ n.End = int32(len(n.Digits))
+ if minSig := int32(r.MinFractionDigits) + int32(numInt); n.End < minSig {
+ n.End = minSig
+ }
+ return n
+}
+
+// appendScientific appends a formatted number to dst. It returns two possible
+// insertion points for padding.
+func appendScientific(dst []byte, f *Formatter, n *Digits) (b []byte, postPre, preSuf int) {
+ if dst, ok := f.renderSpecial(dst, n); ok {
+ return dst, 0, 0
+ }
+ digits := n.Digits
+ numInt := int(n.Comma)
+ numFrac := int(n.End) - int(n.Comma)
+
+ var intDigits, fracDigits []byte
+ if numInt <= len(digits) {
+ intDigits = digits[:numInt]
+ fracDigits = digits[numInt:]
+ } else {
+ intDigits = digits
+ }
+ neg := n.Neg
+ affix, suffix := f.getAffixes(neg)
+ dst = appendAffix(dst, f, affix, neg)
+ savedLen := len(dst)
+
+ i := 0
+ for ; i < len(intDigits); i++ {
+ dst = f.AppendDigit(dst, intDigits[i])
+ if f.needsSep(numInt - i) {
+ dst = append(dst, f.Symbol(SymGroup)...)
+ }
+ }
+ for ; i < numInt; i++ {
+ dst = f.AppendDigit(dst, 0)
+ if f.needsSep(numInt - i) {
+ dst = append(dst, f.Symbol(SymGroup)...)
+ }
+ }
+
+ if numFrac > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
+ dst = append(dst, f.Symbol(SymDecimal)...)
+ }
+ i = 0
+ for ; i < len(fracDigits); i++ {
+ dst = f.AppendDigit(dst, fracDigits[i])
+ }
+ for ; i < numFrac; i++ {
+ dst = f.AppendDigit(dst, 0)
+ }
+
+ // exp
+ buf := [12]byte{}
+ // TODO: use exponential if superscripting is not available (no Latin
+ // numbers or no tags) and use exponential in all other cases.
+ exp := n.Exp - int32(n.Comma)
+ exponential := f.Symbol(SymExponential)
+ if exponential == "E" {
+ dst = append(dst, "\u202f"...) // NARROW NO-BREAK SPACE
+ dst = append(dst, f.Symbol(SymSuperscriptingExponent)...)
+ dst = append(dst, "\u202f"...) // NARROW NO-BREAK SPACE
+ dst = f.AppendDigit(dst, 1)
+ dst = f.AppendDigit(dst, 0)
+ switch {
+ case exp < 0:
+ dst = append(dst, superMinus...)
+ exp = -exp
+ case f.Flags&AlwaysExpSign != 0:
+ dst = append(dst, superPlus...)
+ }
+ b = strconv.AppendUint(buf[:0], uint64(exp), 10)
+ for i := len(b); i < int(f.MinExponentDigits); i++ {
+ dst = append(dst, superDigits[0]...)
+ }
+ for _, c := range b {
+ dst = append(dst, superDigits[c-'0']...)
+ }
+ } else {
+ dst = append(dst, exponential...)
+ switch {
+ case exp < 0:
+ dst = append(dst, f.Symbol(SymMinusSign)...)
+ exp = -exp
+ case f.Flags&AlwaysExpSign != 0:
+ dst = append(dst, f.Symbol(SymPlusSign)...)
+ }
+ b = strconv.AppendUint(buf[:0], uint64(exp), 10)
+ for i := len(b); i < int(f.MinExponentDigits); i++ {
+ dst = f.AppendDigit(dst, 0)
+ }
+ for _, c := range b {
+ dst = f.AppendDigit(dst, c-'0')
+ }
+ }
+ return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
+}
+
+const (
+ superMinus = "\u207B" // SUPERSCRIPT HYPHEN-MINUS
+ superPlus = "\u207A" // SUPERSCRIPT PLUS SIGN
+)
+
+var (
+ // Note: the digits are not sequential!!!
+ superDigits = []string{
+ "\u2070", // SUPERSCRIPT DIGIT ZERO
+ "\u00B9", // SUPERSCRIPT DIGIT ONE
+ "\u00B2", // SUPERSCRIPT DIGIT TWO
+ "\u00B3", // SUPERSCRIPT DIGIT THREE
+ "\u2074", // SUPERSCRIPT DIGIT FOUR
+ "\u2075", // SUPERSCRIPT DIGIT FIVE
+ "\u2076", // SUPERSCRIPT DIGIT SIX
+ "\u2077", // SUPERSCRIPT DIGIT SEVEN
+ "\u2078", // SUPERSCRIPT DIGIT EIGHT
+ "\u2079", // SUPERSCRIPT DIGIT NINE
+ }
+)
+
+func (f *Formatter) getAffixes(neg bool) (affix, suffix string) {
+ str := f.Affix
+ if str != "" {
+ if f.NegOffset > 0 {
+ if neg {
+ str = str[f.NegOffset:]
+ } else {
+ str = str[:f.NegOffset]
+ }
+ }
+ sufStart := 1 + str[0]
+ affix = str[1:sufStart]
+ suffix = str[sufStart+1:]
+ }
+ // TODO: introduce a NeedNeg sign to indicate if the left pattern already
+ // has a sign marked?
+ if f.NegOffset == 0 && (neg || f.Flags&AlwaysSign != 0) {
+ affix = "-" + affix
+ }
+ return affix, suffix
+}
+
+func (f *Formatter) renderSpecial(dst []byte, d *Digits) (b []byte, ok bool) {
+ if d.NaN {
+ return fmtNaN(dst, f), true
+ }
+ if d.Inf {
+ return fmtInfinite(dst, f, d), true
+ }
+ return dst, false
+}
+
+func fmtNaN(dst []byte, f *Formatter) []byte {
+ return append(dst, f.Symbol(SymNan)...)
+}
+
+func fmtInfinite(dst []byte, f *Formatter, d *Digits) []byte {
+ affix, suffix := f.getAffixes(d.Neg)
+ dst = appendAffix(dst, f, affix, d.Neg)
+ dst = append(dst, f.Symbol(SymInfinity)...)
+ dst = appendAffix(dst, f, suffix, d.Neg)
+ return dst
+}
+
+func appendAffix(dst []byte, f *Formatter, affix string, neg bool) []byte {
+ quoting := false
+ escaping := false
+ for _, r := range affix {
+ switch {
+ case escaping:
+ // escaping occurs both inside and outside of quotes
+ dst = append(dst, string(r)...)
+ escaping = false
+ case r == '\\':
+ escaping = true
+ case r == '\'':
+ quoting = !quoting
+ case quoting:
+ dst = append(dst, string(r)...)
+ case r == '%':
+ if f.DigitShift == 3 {
+ dst = append(dst, f.Symbol(SymPerMille)...)
+ } else {
+ dst = append(dst, f.Symbol(SymPercentSign)...)
+ }
+ case r == '-' || r == '+':
+ if neg {
+ dst = append(dst, f.Symbol(SymMinusSign)...)
+ } else if f.Flags&ElideSign == 0 {
+ dst = append(dst, f.Symbol(SymPlusSign)...)
+ } else {
+ dst = append(dst, ' ')
+ }
+ default:
+ dst = append(dst, string(r)...)
+ }
+ }
+ return dst
+}
diff --git a/vendor/golang.org/x/text/internal/number/number.go b/vendor/golang.org/x/text/internal/number/number.go
new file mode 100644
index 0000000..e1d933c
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/number/number.go
@@ -0,0 +1,152 @@
+// Copyright 2016 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 gen.go gen_common.go
+
+// Package number contains tools and data for formatting numbers.
+package number
+
+import (
+ "unicode/utf8"
+
+ "golang.org/x/text/internal/language/compact"
+ "golang.org/x/text/language"
+)
+
+// Info holds number formatting configuration data.
+type Info struct {
+ system systemData // numbering system information
+ symIndex symOffset // index to symbols
+}
+
+// InfoFromLangID returns a Info for the given compact language identifier and
+// numbering system identifier. If system is the empty string, the default
+// numbering system will be taken for that language.
+func InfoFromLangID(compactIndex compact.ID, numberSystem string) Info {
+ p := langToDefaults[compactIndex]
+ // Lookup the entry for the language.
+ pSymIndex := symOffset(0) // Default: Latin, default symbols
+ system, ok := systemMap[numberSystem]
+ if !ok {
+ // Take the value for the default numbering system. This is by far the
+ // most common case as an alternative numbering system is hardly used.
+ if p&hasNonLatnMask == 0 { // Latn digits.
+ pSymIndex = p
+ } else { // Non-Latn or multiple numbering systems.
+ // Take the first entry from the alternatives list.
+ data := langToAlt[p&^hasNonLatnMask]
+ pSymIndex = data.symIndex
+ system = data.system
+ }
+ } else {
+ langIndex := compactIndex
+ ns := system
+ outerLoop:
+ for ; ; p = langToDefaults[langIndex] {
+ if p&hasNonLatnMask == 0 {
+ if ns == 0 {
+ // The index directly points to the symbol data.
+ pSymIndex = p
+ break
+ }
+ // Move to the parent and retry.
+ langIndex = langIndex.Parent()
+ } else {
+ // The index points to a list of symbol data indexes.
+ for _, e := range langToAlt[p&^hasNonLatnMask:] {
+ if e.compactTag != langIndex {
+ if langIndex == 0 {
+ // The CLDR root defines full symbol information for
+ // all numbering systems (even though mostly by
+ // means of aliases). Fall back to the default entry
+ // for Latn if there is no data for the numbering
+ // system of this language.
+ if ns == 0 {
+ break
+ }
+ // Fall back to Latin and start from the original
+ // language. See
+ // https://unicode.org/reports/tr35/#Locale_Inheritance.
+ ns = numLatn
+ langIndex = compactIndex
+ continue outerLoop
+ }
+ // Fall back to parent.
+ langIndex = langIndex.Parent()
+ } else if e.system == ns {
+ pSymIndex = e.symIndex
+ break outerLoop
+ }
+ }
+ }
+ }
+ }
+ if int(system) >= len(numSysData) { // algorithmic
+ // Will generate ASCII digits in case the user inadvertently calls
+ // WriteDigit or Digit on it.
+ d := numSysData[0]
+ d.id = system
+ return Info{
+ system: d,
+ symIndex: pSymIndex,
+ }
+ }
+ return Info{
+ system: numSysData[system],
+ symIndex: pSymIndex,
+ }
+}
+
+// InfoFromTag returns a Info for the given language tag.
+func InfoFromTag(t language.Tag) Info {
+ return InfoFromLangID(tagToID(t), t.TypeForKey("nu"))
+}
+
+// IsDecimal reports if the numbering system can convert decimal to native
+// symbols one-to-one.
+func (n Info) IsDecimal() bool {
+ return int(n.system.id) < len(numSysData)
+}
+
+// WriteDigit writes the UTF-8 sequence for n corresponding to the given ASCII
+// digit to dst and reports the number of bytes written. dst must be large
+// enough to hold the rune (can be up to utf8.UTFMax bytes).
+func (n Info) WriteDigit(dst []byte, asciiDigit rune) int {
+ copy(dst, n.system.zero[:n.system.digitSize])
+ dst[n.system.digitSize-1] += byte(asciiDigit - '0')
+ return int(n.system.digitSize)
+}
+
+// AppendDigit appends the UTF-8 sequence for n corresponding to the given digit
+// to dst and reports the number of bytes written. dst must be large enough to
+// hold the rune (can be up to utf8.UTFMax bytes).
+func (n Info) AppendDigit(dst []byte, digit byte) []byte {
+ dst = append(dst, n.system.zero[:n.system.digitSize]...)
+ dst[len(dst)-1] += digit
+ return dst
+}
+
+// Digit returns the digit for the numbering system for the corresponding ASCII
+// value. For example, ni.Digit('3') could return '三'. Note that the argument
+// is the rune constant '3', which equals 51, not the integer constant 3.
+func (n Info) Digit(asciiDigit rune) rune {
+ var x [utf8.UTFMax]byte
+ n.WriteDigit(x[:], asciiDigit)
+ r, _ := utf8.DecodeRune(x[:])
+ return r
+}
+
+// Symbol returns the string for the given symbol type.
+func (n Info) Symbol(t SymbolType) string {
+ return symData.Elem(int(symIndex[n.symIndex][t]))
+}
+
+func formatForLang(t language.Tag, index []byte) *Pattern {
+ return &formats[index[tagToID(t)]]
+}
+
+func tagToID(t language.Tag) compact.ID {
+ id, _ := compact.RegionalID(compact.Tag(t))
+ return id
+}
diff --git a/vendor/golang.org/x/text/internal/number/pattern.go b/vendor/golang.org/x/text/internal/number/pattern.go
new file mode 100644
index 0000000..06e5955
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/number/pattern.go
@@ -0,0 +1,485 @@
+// Copyright 2015 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 number
+
+import (
+ "errors"
+ "unicode/utf8"
+)
+
+// This file contains a parser for the CLDR number patterns as described in
+// https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
+//
+// The following BNF is derived from this standard.
+//
+// pattern := subpattern (';' subpattern)?
+// subpattern := affix? number exponent? affix?
+// number := decimal | sigDigits
+// decimal := '#'* '0'* ('.' fraction)? | '#' | '0'
+// fraction := '0'* '#'*
+// sigDigits := '#'* '@' '@'* '#'*
+// exponent := 'E' '+'? '0'* '0'
+// padSpec := '*' \L
+//
+// Notes:
+// - An affix pattern may contain any runes, but runes with special meaning
+// should be escaped.
+// - Sequences of digits, '#', and '@' in decimal and sigDigits may have
+// interstitial commas.
+
+// TODO: replace special characters in affixes (-, +, ¤) with control codes.
+
+// Pattern holds information for formatting numbers. It is designed to hold
+// information from CLDR number patterns.
+//
+// This pattern is precompiled for all patterns for all languages. Even though
+// the number of patterns is not very large, we want to keep this small.
+//
+// This type is only intended for internal use.
+type Pattern struct {
+ RoundingContext
+
+ Affix string // includes prefix and suffix. First byte is prefix length.
+ Offset uint16 // Offset into Affix for prefix and suffix
+ NegOffset uint16 // Offset into Affix for negative prefix and suffix or 0.
+ PadRune rune
+ FormatWidth uint16
+
+ GroupingSize [2]uint8
+ Flags PatternFlag
+}
+
+// A RoundingContext indicates how a number should be converted to digits.
+// It contains all information needed to determine the "visible digits" as
+// required by the pluralization rules.
+type RoundingContext struct {
+ // TODO: unify these two fields so that there is a more unambiguous meaning
+ // of how precision is handled.
+ MaxSignificantDigits int16 // -1 is unlimited
+ MaxFractionDigits int16 // -1 is unlimited
+
+ Increment uint32
+ IncrementScale uint8 // May differ from printed scale.
+
+ Mode RoundingMode
+
+ DigitShift uint8 // Number of decimals to shift. Used for % and ‰.
+
+ // Number of digits.
+ MinIntegerDigits uint8
+
+ MaxIntegerDigits uint8
+ MinFractionDigits uint8
+ MinSignificantDigits uint8
+
+ MinExponentDigits uint8
+}
+
+// RoundSignificantDigits returns the number of significant digits an
+// implementation of Convert may round to or n < 0 if there is no maximum or
+// a maximum is not recommended.
+func (r *RoundingContext) RoundSignificantDigits() (n int) {
+ if r.MaxFractionDigits == 0 && r.MaxSignificantDigits > 0 {
+ return int(r.MaxSignificantDigits)
+ } else if r.isScientific() && r.MaxIntegerDigits == 1 {
+ if r.MaxSignificantDigits == 0 ||
+ int(r.MaxFractionDigits+1) == int(r.MaxSignificantDigits) {
+ // Note: don't add DigitShift: it is only used for decimals.
+ return int(r.MaxFractionDigits) + 1
+ }
+ }
+ return -1
+}
+
+// RoundFractionDigits returns the number of fraction digits an implementation
+// of Convert may round to or n < 0 if there is no maximum or a maximum is not
+// recommended.
+func (r *RoundingContext) RoundFractionDigits() (n int) {
+ if r.MinExponentDigits == 0 &&
+ r.MaxSignificantDigits == 0 &&
+ r.MaxFractionDigits >= 0 {
+ return int(r.MaxFractionDigits) + int(r.DigitShift)
+ }
+ return -1
+}
+
+// SetScale fixes the RoundingContext to a fixed number of fraction digits.
+func (r *RoundingContext) SetScale(scale int) {
+ r.MinFractionDigits = uint8(scale)
+ r.MaxFractionDigits = int16(scale)
+}
+
+func (r *RoundingContext) SetPrecision(prec int) {
+ r.MaxSignificantDigits = int16(prec)
+}
+
+func (r *RoundingContext) isScientific() bool {
+ return r.MinExponentDigits > 0
+}
+
+func (f *Pattern) needsSep(pos int) bool {
+ p := pos - 1
+ size := int(f.GroupingSize[0])
+ if size == 0 || p == 0 {
+ return false
+ }
+ if p == size {
+ return true
+ }
+ if p -= size; p < 0 {
+ return false
+ }
+ // TODO: make second groupingsize the same as first if 0 so that we can
+ // avoid this check.
+ if x := int(f.GroupingSize[1]); x != 0 {
+ size = x
+ }
+ return p%size == 0
+}
+
+// A PatternFlag is a bit mask for the flag field of a Pattern.
+type PatternFlag uint8
+
+const (
+ AlwaysSign PatternFlag = 1 << iota
+ ElideSign // Use space instead of plus sign. AlwaysSign must be true.
+ AlwaysExpSign
+ AlwaysDecimalSeparator
+ ParenthesisForNegative // Common pattern. Saves space.
+
+ PadAfterNumber
+ PadAfterAffix
+
+ PadBeforePrefix = 0 // Default
+ PadAfterPrefix = PadAfterAffix
+ PadBeforeSuffix = PadAfterNumber
+ PadAfterSuffix = PadAfterNumber | PadAfterAffix
+ PadMask = PadAfterNumber | PadAfterAffix
+)
+
+type parser struct {
+ *Pattern
+
+ leadingSharps int
+
+ pos int
+ err error
+ doNotTerminate bool
+ groupingCount uint
+ hasGroup bool
+ buf []byte
+}
+
+func (p *parser) setError(err error) {
+ if p.err == nil {
+ p.err = err
+ }
+}
+
+func (p *parser) updateGrouping() {
+ if p.hasGroup &&
+ 0 < p.groupingCount && p.groupingCount < 255 {
+ p.GroupingSize[1] = p.GroupingSize[0]
+ p.GroupingSize[0] = uint8(p.groupingCount)
+ }
+ p.groupingCount = 0
+ p.hasGroup = true
+}
+
+var (
+ // TODO: more sensible and localizeable error messages.
+ errMultiplePadSpecifiers = errors.New("format: pattern has multiple pad specifiers")
+ errInvalidPadSpecifier = errors.New("format: invalid pad specifier")
+ errInvalidQuote = errors.New("format: invalid quote")
+ errAffixTooLarge = errors.New("format: prefix or suffix exceeds maximum UTF-8 length of 256 bytes")
+ errDuplicatePercentSign = errors.New("format: duplicate percent sign")
+ errDuplicatePermilleSign = errors.New("format: duplicate permille sign")
+ errUnexpectedEnd = errors.New("format: unexpected end of pattern")
+)
+
+// ParsePattern extracts formatting information from a CLDR number pattern.
+//
+// See https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
+func ParsePattern(s string) (f *Pattern, err error) {
+ p := parser{Pattern: &Pattern{}}
+
+ s = p.parseSubPattern(s)
+
+ if s != "" {
+ // Parse negative sub pattern.
+ if s[0] != ';' {
+ p.setError(errors.New("format: error parsing first sub pattern"))
+ return nil, p.err
+ }
+ neg := parser{Pattern: &Pattern{}} // just for extracting the affixes.
+ s = neg.parseSubPattern(s[len(";"):])
+ p.NegOffset = uint16(len(p.buf))
+ p.buf = append(p.buf, neg.buf...)
+ }
+ if s != "" {
+ p.setError(errors.New("format: spurious characters at end of pattern"))
+ }
+ if p.err != nil {
+ return nil, p.err
+ }
+ if affix := string(p.buf); affix == "\x00\x00" || affix == "\x00\x00\x00\x00" {
+ // No prefix or suffixes.
+ p.NegOffset = 0
+ } else {
+ p.Affix = affix
+ }
+ if p.Increment == 0 {
+ p.IncrementScale = 0
+ }
+ return p.Pattern, nil
+}
+
+func (p *parser) parseSubPattern(s string) string {
+ s = p.parsePad(s, PadBeforePrefix)
+ s = p.parseAffix(s)
+ s = p.parsePad(s, PadAfterPrefix)
+
+ s = p.parse(p.number, s)
+ p.updateGrouping()
+
+ s = p.parsePad(s, PadBeforeSuffix)
+ s = p.parseAffix(s)
+ s = p.parsePad(s, PadAfterSuffix)
+ return s
+}
+
+func (p *parser) parsePad(s string, f PatternFlag) (tail string) {
+ if len(s) >= 2 && s[0] == '*' {
+ r, sz := utf8.DecodeRuneInString(s[1:])
+ if p.PadRune != 0 {
+ p.err = errMultiplePadSpecifiers
+ } else {
+ p.Flags |= f
+ p.PadRune = r
+ }
+ return s[1+sz:]
+ }
+ return s
+}
+
+func (p *parser) parseAffix(s string) string {
+ x := len(p.buf)
+ p.buf = append(p.buf, 0) // placeholder for affix length
+
+ s = p.parse(p.affix, s)
+
+ n := len(p.buf) - x - 1
+ if n > 0xFF {
+ p.setError(errAffixTooLarge)
+ }
+ p.buf[x] = uint8(n)
+ return s
+}
+
+// state implements a state transition. It returns the new state. A state
+// function may set an error on the parser or may simply return on an incorrect
+// token and let the next phase fail.
+type state func(r rune) state
+
+// parse repeatedly applies a state function on the given string until a
+// termination condition is reached.
+func (p *parser) parse(fn state, s string) (tail string) {
+ for i, r := range s {
+ p.doNotTerminate = false
+ if fn = fn(r); fn == nil || p.err != nil {
+ return s[i:]
+ }
+ p.FormatWidth++
+ }
+ if p.doNotTerminate {
+ p.setError(errUnexpectedEnd)
+ }
+ return ""
+}
+
+func (p *parser) affix(r rune) state {
+ switch r {
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '#', '@', '.', '*', ',', ';':
+ return nil
+ case '\'':
+ p.FormatWidth--
+ return p.escapeFirst
+ case '%':
+ if p.DigitShift != 0 {
+ p.setError(errDuplicatePercentSign)
+ }
+ p.DigitShift = 2
+ case '\u2030': // ‰ Per mille
+ if p.DigitShift != 0 {
+ p.setError(errDuplicatePermilleSign)
+ }
+ p.DigitShift = 3
+ // TODO: handle currency somehow: ¤, ¤¤, ¤¤¤, ¤¤¤¤
+ }
+ p.buf = append(p.buf, string(r)...)
+ return p.affix
+}
+
+func (p *parser) escapeFirst(r rune) state {
+ switch r {
+ case '\'':
+ p.buf = append(p.buf, "\\'"...)
+ return p.affix
+ default:
+ p.buf = append(p.buf, '\'')
+ p.buf = append(p.buf, string(r)...)
+ }
+ return p.escape
+}
+
+func (p *parser) escape(r rune) state {
+ switch r {
+ case '\'':
+ p.FormatWidth--
+ p.buf = append(p.buf, '\'')
+ return p.affix
+ default:
+ p.buf = append(p.buf, string(r)...)
+ }
+ return p.escape
+}
+
+// number parses a number. The BNF says the integer part should always have
+// a '0', but that does not appear to be the case according to the rest of the
+// documentation. We will allow having only '#' numbers.
+func (p *parser) number(r rune) state {
+ switch r {
+ case '#':
+ p.groupingCount++
+ p.leadingSharps++
+ case '@':
+ p.groupingCount++
+ p.leadingSharps = 0
+ p.MaxFractionDigits = -1
+ return p.sigDigits(r)
+ case ',':
+ if p.leadingSharps == 0 { // no leading commas
+ return nil
+ }
+ p.updateGrouping()
+ case 'E':
+ p.MaxIntegerDigits = uint8(p.leadingSharps)
+ return p.exponent
+ case '.': // allow ".##" etc.
+ p.updateGrouping()
+ return p.fraction
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return p.integer(r)
+ default:
+ return nil
+ }
+ return p.number
+}
+
+func (p *parser) integer(r rune) state {
+ if !('0' <= r && r <= '9') {
+ var next state
+ switch r {
+ case 'E':
+ if p.leadingSharps > 0 {
+ p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits
+ }
+ next = p.exponent
+ case '.':
+ next = p.fraction
+ case ',':
+ next = p.integer
+ }
+ p.updateGrouping()
+ return next
+ }
+ p.Increment = p.Increment*10 + uint32(r-'0')
+ p.groupingCount++
+ p.MinIntegerDigits++
+ return p.integer
+}
+
+func (p *parser) sigDigits(r rune) state {
+ switch r {
+ case '@':
+ p.groupingCount++
+ p.MaxSignificantDigits++
+ p.MinSignificantDigits++
+ case '#':
+ return p.sigDigitsFinal(r)
+ case 'E':
+ p.updateGrouping()
+ return p.normalizeSigDigitsWithExponent()
+ default:
+ p.updateGrouping()
+ return nil
+ }
+ return p.sigDigits
+}
+
+func (p *parser) sigDigitsFinal(r rune) state {
+ switch r {
+ case '#':
+ p.groupingCount++
+ p.MaxSignificantDigits++
+ case 'E':
+ p.updateGrouping()
+ return p.normalizeSigDigitsWithExponent()
+ default:
+ p.updateGrouping()
+ return nil
+ }
+ return p.sigDigitsFinal
+}
+
+func (p *parser) normalizeSigDigitsWithExponent() state {
+ p.MinIntegerDigits, p.MaxIntegerDigits = 1, 1
+ p.MinFractionDigits = p.MinSignificantDigits - 1
+ p.MaxFractionDigits = p.MaxSignificantDigits - 1
+ p.MinSignificantDigits, p.MaxSignificantDigits = 0, 0
+ return p.exponent
+}
+
+func (p *parser) fraction(r rune) state {
+ switch r {
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ p.Increment = p.Increment*10 + uint32(r-'0')
+ p.IncrementScale++
+ p.MinFractionDigits++
+ p.MaxFractionDigits++
+ case '#':
+ p.MaxFractionDigits++
+ case 'E':
+ if p.leadingSharps > 0 {
+ p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits
+ }
+ return p.exponent
+ default:
+ return nil
+ }
+ return p.fraction
+}
+
+func (p *parser) exponent(r rune) state {
+ switch r {
+ case '+':
+ // Set mode and check it wasn't already set.
+ if p.Flags&AlwaysExpSign != 0 || p.MinExponentDigits > 0 {
+ break
+ }
+ p.Flags |= AlwaysExpSign
+ p.doNotTerminate = true
+ return p.exponent
+ case '0':
+ p.MinExponentDigits++
+ return p.exponent
+ }
+ // termination condition
+ if p.MinExponentDigits == 0 {
+ p.setError(errors.New("format: need at least one digit"))
+ }
+ return nil
+}
diff --git a/vendor/golang.org/x/text/internal/number/roundingmode_string.go b/vendor/golang.org/x/text/internal/number/roundingmode_string.go
new file mode 100644
index 0000000..bcc2247
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/number/roundingmode_string.go
@@ -0,0 +1,30 @@
+// Code generated by "stringer -type RoundingMode"; DO NOT EDIT.
+
+package number
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[ToNearestEven-0]
+ _ = x[ToNearestZero-1]
+ _ = x[ToNearestAway-2]
+ _ = x[ToPositiveInf-3]
+ _ = x[ToNegativeInf-4]
+ _ = x[ToZero-5]
+ _ = x[AwayFromZero-6]
+ _ = x[numModes-7]
+}
+
+const _RoundingMode_name = "ToNearestEvenToNearestZeroToNearestAwayToPositiveInfToNegativeInfToZeroAwayFromZeronumModes"
+
+var _RoundingMode_index = [...]uint8{0, 13, 26, 39, 52, 65, 71, 83, 91}
+
+func (i RoundingMode) String() string {
+ if i >= RoundingMode(len(_RoundingMode_index)-1) {
+ return "RoundingMode(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _RoundingMode_name[_RoundingMode_index[i]:_RoundingMode_index[i+1]]
+}
diff --git a/vendor/golang.org/x/text/internal/number/tables.go b/vendor/golang.org/x/text/internal/number/tables.go
new file mode 100644
index 0000000..8efce81
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/number/tables.go
@@ -0,0 +1,1219 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package number
+
+import "golang.org/x/text/internal/stringset"
+
+// CLDRVersion is the CLDR version from which the tables in this package are derived.
+const CLDRVersion = "32"
+
+var numSysData = []systemData{ // 59 elements
+ 0: {id: 0x0, digitSize: 0x1, zero: [4]uint8{0x30, 0x0, 0x0, 0x0}},
+ 1: {id: 0x1, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9e, 0xa5, 0x90}},
+ 2: {id: 0x2, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x9c, 0xb0}},
+ 3: {id: 0x3, digitSize: 0x2, zero: [4]uint8{0xd9, 0xa0, 0x0, 0x0}},
+ 4: {id: 0x4, digitSize: 0x2, zero: [4]uint8{0xdb, 0xb0, 0x0, 0x0}},
+ 5: {id: 0x5, digitSize: 0x3, zero: [4]uint8{0xe1, 0xad, 0x90, 0x0}},
+ 6: {id: 0x6, digitSize: 0x3, zero: [4]uint8{0xe0, 0xa7, 0xa6, 0x0}},
+ 7: {id: 0x7, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0xb1, 0x90}},
+ 8: {id: 0x8, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x81, 0xa6}},
+ 9: {id: 0x9, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x84, 0xb6}},
+ 10: {id: 0xa, digitSize: 0x3, zero: [4]uint8{0xea, 0xa9, 0x90, 0x0}},
+ 11: {id: 0xb, digitSize: 0x3, zero: [4]uint8{0xe0, 0xa5, 0xa6, 0x0}},
+ 12: {id: 0xc, digitSize: 0x3, zero: [4]uint8{0xef, 0xbc, 0x90, 0x0}},
+ 13: {id: 0xd, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0xb5, 0x90}},
+ 14: {id: 0xe, digitSize: 0x3, zero: [4]uint8{0xe0, 0xab, 0xa6, 0x0}},
+ 15: {id: 0xf, digitSize: 0x3, zero: [4]uint8{0xe0, 0xa9, 0xa6, 0x0}},
+ 16: {id: 0x10, digitSize: 0x4, zero: [4]uint8{0xf0, 0x96, 0xad, 0x90}},
+ 17: {id: 0x11, digitSize: 0x3, zero: [4]uint8{0xea, 0xa7, 0x90, 0x0}},
+ 18: {id: 0x12, digitSize: 0x3, zero: [4]uint8{0xea, 0xa4, 0x80, 0x0}},
+ 19: {id: 0x13, digitSize: 0x3, zero: [4]uint8{0xe1, 0x9f, 0xa0, 0x0}},
+ 20: {id: 0x14, digitSize: 0x3, zero: [4]uint8{0xe0, 0xb3, 0xa6, 0x0}},
+ 21: {id: 0x15, digitSize: 0x3, zero: [4]uint8{0xe1, 0xaa, 0x80, 0x0}},
+ 22: {id: 0x16, digitSize: 0x3, zero: [4]uint8{0xe1, 0xaa, 0x90, 0x0}},
+ 23: {id: 0x17, digitSize: 0x3, zero: [4]uint8{0xe0, 0xbb, 0x90, 0x0}},
+ 24: {id: 0x18, digitSize: 0x3, zero: [4]uint8{0xe1, 0xb1, 0x80, 0x0}},
+ 25: {id: 0x19, digitSize: 0x3, zero: [4]uint8{0xe1, 0xa5, 0x86, 0x0}},
+ 26: {id: 0x1a, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9d, 0x9f, 0x8e}},
+ 27: {id: 0x1b, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9d, 0x9f, 0x98}},
+ 28: {id: 0x1c, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9d, 0x9f, 0xb6}},
+ 29: {id: 0x1d, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9d, 0x9f, 0xac}},
+ 30: {id: 0x1e, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9d, 0x9f, 0xa2}},
+ 31: {id: 0x1f, digitSize: 0x3, zero: [4]uint8{0xe0, 0xb5, 0xa6, 0x0}},
+ 32: {id: 0x20, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x99, 0x90}},
+ 33: {id: 0x21, digitSize: 0x3, zero: [4]uint8{0xe1, 0xa0, 0x90, 0x0}},
+ 34: {id: 0x22, digitSize: 0x4, zero: [4]uint8{0xf0, 0x96, 0xa9, 0xa0}},
+ 35: {id: 0x23, digitSize: 0x3, zero: [4]uint8{0xea, 0xaf, 0xb0, 0x0}},
+ 36: {id: 0x24, digitSize: 0x3, zero: [4]uint8{0xe1, 0x81, 0x80, 0x0}},
+ 37: {id: 0x25, digitSize: 0x3, zero: [4]uint8{0xe1, 0x82, 0x90, 0x0}},
+ 38: {id: 0x26, digitSize: 0x3, zero: [4]uint8{0xea, 0xa7, 0xb0, 0x0}},
+ 39: {id: 0x27, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x91, 0x90}},
+ 40: {id: 0x28, digitSize: 0x2, zero: [4]uint8{0xdf, 0x80, 0x0, 0x0}},
+ 41: {id: 0x29, digitSize: 0x3, zero: [4]uint8{0xe1, 0xb1, 0x90, 0x0}},
+ 42: {id: 0x2a, digitSize: 0x3, zero: [4]uint8{0xe0, 0xad, 0xa6, 0x0}},
+ 43: {id: 0x2b, digitSize: 0x4, zero: [4]uint8{0xf0, 0x90, 0x92, 0xa0}},
+ 44: {id: 0x2c, digitSize: 0x3, zero: [4]uint8{0xea, 0xa3, 0x90, 0x0}},
+ 45: {id: 0x2d, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x87, 0x90}},
+ 46: {id: 0x2e, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x8b, 0xb0}},
+ 47: {id: 0x2f, digitSize: 0x3, zero: [4]uint8{0xe0, 0xb7, 0xa6, 0x0}},
+ 48: {id: 0x30, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x83, 0xb0}},
+ 49: {id: 0x31, digitSize: 0x3, zero: [4]uint8{0xe1, 0xae, 0xb0, 0x0}},
+ 50: {id: 0x32, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x9b, 0x80}},
+ 51: {id: 0x33, digitSize: 0x3, zero: [4]uint8{0xe1, 0xa7, 0x90, 0x0}},
+ 52: {id: 0x34, digitSize: 0x3, zero: [4]uint8{0xe0, 0xaf, 0xa6, 0x0}},
+ 53: {id: 0x35, digitSize: 0x3, zero: [4]uint8{0xe0, 0xb1, 0xa6, 0x0}},
+ 54: {id: 0x36, digitSize: 0x3, zero: [4]uint8{0xe0, 0xb9, 0x90, 0x0}},
+ 55: {id: 0x37, digitSize: 0x3, zero: [4]uint8{0xe0, 0xbc, 0xa0, 0x0}},
+ 56: {id: 0x38, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x93, 0x90}},
+ 57: {id: 0x39, digitSize: 0x3, zero: [4]uint8{0xea, 0x98, 0xa0, 0x0}},
+ 58: {id: 0x3a, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0xa3, 0xa0}},
+} // Size: 378 bytes
+
+const (
+ numAdlm = 0x1
+ numAhom = 0x2
+ numArab = 0x3
+ numArabext = 0x4
+ numArmn = 0x3b
+ numArmnlow = 0x3c
+ numBali = 0x5
+ numBeng = 0x6
+ numBhks = 0x7
+ numBrah = 0x8
+ numCakm = 0x9
+ numCham = 0xa
+ numCyrl = 0x3d
+ numDeva = 0xb
+ numEthi = 0x3e
+ numFullwide = 0xc
+ numGeor = 0x3f
+ numGonm = 0xd
+ numGrek = 0x40
+ numGreklow = 0x41
+ numGujr = 0xe
+ numGuru = 0xf
+ numHanidays = 0x42
+ numHanidec = 0x43
+ numHans = 0x44
+ numHansfin = 0x45
+ numHant = 0x46
+ numHantfin = 0x47
+ numHebr = 0x48
+ numHmng = 0x10
+ numJava = 0x11
+ numJpan = 0x49
+ numJpanfin = 0x4a
+ numKali = 0x12
+ numKhmr = 0x13
+ numKnda = 0x14
+ numLana = 0x15
+ numLanatham = 0x16
+ numLaoo = 0x17
+ numLatn = 0x0
+ numLepc = 0x18
+ numLimb = 0x19
+ numMathbold = 0x1a
+ numMathdbl = 0x1b
+ numMathmono = 0x1c
+ numMathsanb = 0x1d
+ numMathsans = 0x1e
+ numMlym = 0x1f
+ numModi = 0x20
+ numMong = 0x21
+ numMroo = 0x22
+ numMtei = 0x23
+ numMymr = 0x24
+ numMymrshan = 0x25
+ numMymrtlng = 0x26
+ numNewa = 0x27
+ numNkoo = 0x28
+ numOlck = 0x29
+ numOrya = 0x2a
+ numOsma = 0x2b
+ numRoman = 0x4b
+ numRomanlow = 0x4c
+ numSaur = 0x2c
+ numShrd = 0x2d
+ numSind = 0x2e
+ numSinh = 0x2f
+ numSora = 0x30
+ numSund = 0x31
+ numTakr = 0x32
+ numTalu = 0x33
+ numTaml = 0x4d
+ numTamldec = 0x34
+ numTelu = 0x35
+ numThai = 0x36
+ numTibt = 0x37
+ numTirh = 0x38
+ numVaii = 0x39
+ numWara = 0x3a
+ numNumberSystems
+)
+
+var systemMap = map[string]system{
+ "adlm": numAdlm,
+ "ahom": numAhom,
+ "arab": numArab,
+ "arabext": numArabext,
+ "armn": numArmn,
+ "armnlow": numArmnlow,
+ "bali": numBali,
+ "beng": numBeng,
+ "bhks": numBhks,
+ "brah": numBrah,
+ "cakm": numCakm,
+ "cham": numCham,
+ "cyrl": numCyrl,
+ "deva": numDeva,
+ "ethi": numEthi,
+ "fullwide": numFullwide,
+ "geor": numGeor,
+ "gonm": numGonm,
+ "grek": numGrek,
+ "greklow": numGreklow,
+ "gujr": numGujr,
+ "guru": numGuru,
+ "hanidays": numHanidays,
+ "hanidec": numHanidec,
+ "hans": numHans,
+ "hansfin": numHansfin,
+ "hant": numHant,
+ "hantfin": numHantfin,
+ "hebr": numHebr,
+ "hmng": numHmng,
+ "java": numJava,
+ "jpan": numJpan,
+ "jpanfin": numJpanfin,
+ "kali": numKali,
+ "khmr": numKhmr,
+ "knda": numKnda,
+ "lana": numLana,
+ "lanatham": numLanatham,
+ "laoo": numLaoo,
+ "latn": numLatn,
+ "lepc": numLepc,
+ "limb": numLimb,
+ "mathbold": numMathbold,
+ "mathdbl": numMathdbl,
+ "mathmono": numMathmono,
+ "mathsanb": numMathsanb,
+ "mathsans": numMathsans,
+ "mlym": numMlym,
+ "modi": numModi,
+ "mong": numMong,
+ "mroo": numMroo,
+ "mtei": numMtei,
+ "mymr": numMymr,
+ "mymrshan": numMymrshan,
+ "mymrtlng": numMymrtlng,
+ "newa": numNewa,
+ "nkoo": numNkoo,
+ "olck": numOlck,
+ "orya": numOrya,
+ "osma": numOsma,
+ "roman": numRoman,
+ "romanlow": numRomanlow,
+ "saur": numSaur,
+ "shrd": numShrd,
+ "sind": numSind,
+ "sinh": numSinh,
+ "sora": numSora,
+ "sund": numSund,
+ "takr": numTakr,
+ "talu": numTalu,
+ "taml": numTaml,
+ "tamldec": numTamldec,
+ "telu": numTelu,
+ "thai": numThai,
+ "tibt": numTibt,
+ "tirh": numTirh,
+ "vaii": numVaii,
+ "wara": numWara,
+}
+
+var symIndex = [][12]uint8{ // 81 elements
+ 0: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 1: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 2: [12]uint8{0x0, 0x1, 0x2, 0xd, 0xe, 0xf, 0x6, 0x7, 0x8, 0x9, 0x10, 0xb},
+ 3: [12]uint8{0x1, 0x0, 0x2, 0xd, 0xe, 0xf, 0x6, 0x7, 0x8, 0x9, 0x10, 0xb},
+ 4: [12]uint8{0x0, 0x1, 0x2, 0x11, 0xe, 0xf, 0x6, 0x7, 0x8, 0x9, 0x10, 0xb},
+ 5: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x12, 0xb},
+ 6: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 7: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x13, 0xb},
+ 8: [12]uint8{0x0, 0x1, 0x2, 0x3, 0xe, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 9: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x0},
+ 10: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x14, 0x8, 0x9, 0xa, 0xb},
+ 11: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x14, 0x8, 0x9, 0xa, 0xb},
+ 12: [12]uint8{0x0, 0x15, 0x2, 0x3, 0x4, 0x5, 0x6, 0x14, 0x8, 0x9, 0xa, 0xb},
+ 13: [12]uint8{0x0, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 14: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x16, 0xb},
+ 15: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 16: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x17, 0x7, 0x8, 0x9, 0xa, 0x0},
+ 17: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 18: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x0},
+ 19: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x18, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 20: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x19, 0x1a, 0xa, 0xb},
+ 21: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 22: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 23: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 24: [12]uint8{0x0, 0x1, 0x2, 0x3, 0xe, 0x1c, 0x6, 0x7, 0x8, 0x9, 0x1d, 0xb},
+ 25: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0x1e, 0x0},
+ 26: [12]uint8{0x0, 0x15, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 27: [12]uint8{0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 28: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x1f, 0xb},
+ 29: [12]uint8{0x0, 0x15, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 30: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x20, 0xb},
+ 31: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x21, 0x7, 0x8, 0x9, 0x22, 0xb},
+ 32: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x23, 0xb},
+ 33: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x14, 0x8, 0x9, 0x24, 0xb},
+ 34: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x7, 0x8, 0x9, 0x24, 0xb},
+ 35: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x25, 0xb},
+ 36: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x26, 0xb},
+ 37: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x27, 0xb},
+ 38: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x28, 0xb},
+ 39: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x29, 0xb},
+ 40: [12]uint8{0x1, 0x0, 0x2, 0x3, 0xe, 0x1c, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 41: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2a, 0xb},
+ 42: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2b, 0xb},
+ 43: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x2c, 0x14, 0x8, 0x9, 0x24, 0xb},
+ 44: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x0},
+ 45: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 46: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 47: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2d, 0x0},
+ 48: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2e, 0xb},
+ 49: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2f, 0xb},
+ 50: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x30, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 51: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x31, 0xb},
+ 52: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x32, 0xb},
+ 53: [12]uint8{0x1, 0x15, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
+ 54: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x33, 0xb},
+ 55: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x34, 0xb},
+ 56: [12]uint8{0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb},
+ 57: [12]uint8{0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x7, 0x3c, 0x9, 0x3d, 0xb},
+ 58: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x3e, 0x3f, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb},
+ 59: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x39, 0x3a, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb},
+ 60: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x39, 0x40, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb},
+ 61: [12]uint8{0x35, 0x36, 0x37, 0x41, 0x3e, 0x3f, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb},
+ 62: [12]uint8{0x35, 0x36, 0x37, 0x38, 0x3e, 0x3f, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb},
+ 63: [12]uint8{0x35, 0xc, 0x37, 0x38, 0x39, 0x42, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0x0},
+ 64: [12]uint8{0x35, 0xc, 0x37, 0x38, 0x39, 0x42, 0x43, 0x7, 0x44, 0x9, 0x24, 0xb},
+ 65: [12]uint8{0x35, 0x36, 0x37, 0x38, 0x39, 0x5, 0x3b, 0x7, 0x3c, 0x9, 0x33, 0xb},
+ 66: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x45, 0x46, 0x43, 0x7, 0x3c, 0x9, 0xa, 0x35},
+ 67: [12]uint8{0x35, 0x36, 0x37, 0x11, 0xe, 0x1c, 0x43, 0x7, 0x3c, 0x9, 0x1d, 0xb},
+ 68: [12]uint8{0x35, 0x36, 0x37, 0x11, 0xe, 0x1c, 0x43, 0x7, 0x3c, 0x9, 0xa, 0x35},
+ 69: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x45, 0x5, 0x43, 0x7, 0x3c, 0x9, 0xa, 0x35},
+ 70: [12]uint8{0x1, 0xc, 0x37, 0x11, 0x45, 0x47, 0x43, 0x7, 0x3c, 0x9, 0xa, 0x0},
+ 71: [12]uint8{0x35, 0x1, 0x37, 0x11, 0x4, 0x5, 0x43, 0x7, 0x3c, 0x9, 0xa, 0x35},
+ 72: [12]uint8{0x1, 0xc, 0x37, 0x11, 0x45, 0x47, 0x43, 0x7, 0x3c, 0x9, 0x24, 0xb},
+ 73: [12]uint8{0x35, 0x36, 0x2, 0x3, 0x45, 0x46, 0x43, 0x7, 0x8, 0x9, 0xa, 0x35},
+ 74: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x4, 0x5, 0x43, 0x7, 0x3c, 0x9, 0x31, 0x35},
+ 75: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x4, 0x5, 0x43, 0x7, 0x3c, 0x9, 0x32, 0x35},
+ 76: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x48, 0x46, 0x43, 0x7, 0x3c, 0x9, 0x33, 0x35},
+ 77: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x49},
+ 78: [12]uint8{0x0, 0x1, 0x4a, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x28, 0xb},
+ 79: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x4b, 0xb},
+ 80: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x4c, 0x4d, 0xb},
+} // Size: 996 bytes
+
+var symData = stringset.Set{
+ Data: "" + // Size: 599 bytes
+ ".,;%+-E׉∞NaN:\u00a0\u200e%\u200e\u200e+\u200e-ليس\u00a0رقمًا٪NDТерхьаш" +
+ "\u00a0дац·’mnne×10^0/00INF−\u200e−ناعددepälukuՈչԹარ\u00a0არის\u00a0რიცხვ" +
+ "იZMdMсан\u00a0емес¤¤¤сан\u00a0эмесບໍ່\u200bແມ່ນ\u200bໂຕ\u200bເລກNSဂဏန်" +
+ "းမဟုတ်သောННне\u00a0числочыыһыла\u00a0буотах·10^epilohosan\u00a0dälTFЕs" +
+ "on\u00a0emasҳақиқий\u00a0сон\u00a0эмас非數值非数值٫٬؛٪\u061c\u061c+\u061c-اس؉ل" +
+ "يس\u00a0رقم\u200f+\u200f-\u200f−٪\u200f\u061c−×۱۰^؉\u200f\u200e+\u200e" +
+ "\u200e-\u200e\u200e−\u200e+\u200e:၊ཨང་མེན་གྲངས་མེདཨང་མད",
+ Index: []uint16{ // 79 elements
+ // Entry 0 - 3F
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0009, 0x000c, 0x000f, 0x0012, 0x0013, 0x0015, 0x001c, 0x0020,
+ 0x0024, 0x0036, 0x0038, 0x003a, 0x0050, 0x0052, 0x0055, 0x0058,
+ 0x0059, 0x005e, 0x0062, 0x0065, 0x0068, 0x006e, 0x0078, 0x0080,
+ 0x0086, 0x00ae, 0x00af, 0x00b2, 0x00c2, 0x00c8, 0x00d8, 0x0105,
+ 0x0107, 0x012e, 0x0132, 0x0142, 0x015e, 0x0163, 0x016a, 0x0173,
+ 0x0175, 0x0177, 0x0180, 0x01a0, 0x01a9, 0x01b2, 0x01b4, 0x01b6,
+ 0x01b8, 0x01bc, 0x01bf, 0x01c2, 0x01c6, 0x01c8, 0x01d6, 0x01da,
+ // Entry 40 - 7F
+ 0x01de, 0x01e4, 0x01e9, 0x01ee, 0x01f5, 0x01fa, 0x0201, 0x0208,
+ 0x0211, 0x0215, 0x0218, 0x021b, 0x0230, 0x0248, 0x0257,
+ },
+} // Size: 797 bytes
+
+// langToDefaults maps a compact language index to the default numbering system
+// and default symbol set
+var langToDefaults = [775]symOffset{
+ // Entry 0 - 3F
+ 0x8000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8003, 0x0002, 0x0002, 0x0002, 0x0002, 0x0003,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0003, 0x0003, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002, 0x0004,
+ 0x0002, 0x0004, 0x0002, 0x0002, 0x0002, 0x0003, 0x0002, 0x0000,
+ 0x8005, 0x0000, 0x0000, 0x0000, 0x8006, 0x0005, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000,
+ // Entry 40 - 7F
+ 0x8009, 0x0000, 0x0000, 0x800a, 0x0000, 0x0000, 0x800c, 0x0001,
+ 0x0000, 0x0000, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x800e, 0x0000, 0x0000, 0x0007,
+ 0x0007, 0x0000, 0x0000, 0x0000, 0x0000, 0x800f, 0x0008, 0x0008,
+ 0x8011, 0x0001, 0x0001, 0x0001, 0x803c, 0x0000, 0x0009, 0x0009,
+ 0x0009, 0x0000, 0x0000, 0x000a, 0x000b, 0x000a, 0x000c, 0x000a,
+ 0x000a, 0x000c, 0x000a, 0x000d, 0x000d, 0x000a, 0x000a, 0x0001,
+ 0x0001, 0x0000, 0x0001, 0x0001, 0x803f, 0x0000, 0x0000, 0x0000,
+ // Entry 80 - BF
+ 0x000e, 0x000e, 0x000e, 0x000f, 0x000f, 0x000f, 0x0000, 0x0000,
+ 0x0006, 0x0000, 0x0000, 0x0000, 0x000a, 0x0010, 0x0000, 0x0006,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0011, 0x0000, 0x000a,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x000a, 0x0000, 0x0009, 0x0000,
+ 0x0000, 0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ // Entry C0 - FF
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0013, 0x0000,
+ 0x0000, 0x000f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0015,
+ 0x0015, 0x0006, 0x0000, 0x0006, 0x0006, 0x0000, 0x0000, 0x0006,
+ 0x0006, 0x0001, 0x0000, 0x0000, 0x0006, 0x0006, 0x0006, 0x0006,
+ // Entry 100 - 13F
+ 0x0000, 0x0000, 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006,
+ 0x0000, 0x0006, 0x0000, 0x0000, 0x0006, 0x0006, 0x0016, 0x0016,
+ 0x0017, 0x0017, 0x0001, 0x0001, 0x8041, 0x0018, 0x0018, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0019, 0x0019, 0x0000, 0x0000,
+ 0x0017, 0x0017, 0x0017, 0x8044, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0006, 0x0006, 0x0001, 0x0001, 0x0001, 0x0001,
+ // Entry 140 - 17F
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0000,
+ 0x8047, 0x0000, 0x0006, 0x0006, 0x001a, 0x001a, 0x001a, 0x001a,
+ 0x804a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x804c, 0x001b, 0x0000,
+ 0x0000, 0x0006, 0x0006, 0x0006, 0x000a, 0x000a, 0x0001, 0x0001,
+ 0x001c, 0x001c, 0x0009, 0x0009, 0x804f, 0x0000, 0x0000, 0x0000,
+ // Entry 180 - 1BF
+ 0x0000, 0x0000, 0x8052, 0x0006, 0x0006, 0x001d, 0x0006, 0x0006,
+ 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006, 0x0006,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x001e, 0x001f,
+ 0x001f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0001, 0x000d, 0x000d, 0x0000, 0x0000, 0x0020, 0x0020, 0x0006,
+ 0x0006, 0x0021, 0x0021, 0x0000, 0x0000, 0x0006, 0x0006, 0x0000,
+ 0x0000, 0x8054, 0x0000, 0x0000, 0x0000, 0x0000, 0x8056, 0x001b,
+ 0x0000, 0x0000, 0x0001, 0x0001, 0x0022, 0x0022, 0x0000, 0x0000,
+ // Entry 1C0 - 1FF
+ 0x0000, 0x0023, 0x0023, 0x0000, 0x0000, 0x0006, 0x0006, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0024, 0x0024, 0x8058, 0x0000, 0x0000, 0x0016, 0x0016, 0x0006,
+ 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0025, 0x0025, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x000d, 0x000d, 0x0000, 0x0000,
+ 0x0006, 0x0006, 0x0000, 0x0000, 0x0006, 0x0006, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x805a, 0x0000, 0x0000, 0x0006, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0006, 0x0006, 0x805b, 0x0026, 0x805d,
+ // Entry 200 - 23F
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x805e, 0x0015, 0x0015, 0x0000,
+ 0x0000, 0x0006, 0x0006, 0x0006, 0x8061, 0x0000, 0x0000, 0x8062,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0001,
+ 0x0001, 0x0015, 0x0015, 0x0006, 0x0006, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0027, 0x0027, 0x0027, 0x8065, 0x8067,
+ 0x001b, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x8069, 0x0028, 0x0006, 0x0001, 0x0006, 0x0001, 0x0001, 0x0001,
+ // Entry 240 - 27F
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000,
+ 0x0006, 0x0000, 0x0000, 0x001a, 0x001a, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0000, 0x0000, 0x0029, 0x0029, 0x0029, 0x0029,
+ 0x0029, 0x0029, 0x0029, 0x0006, 0x0006, 0x0000, 0x0000, 0x002a,
+ 0x002a, 0x0000, 0x0000, 0x0000, 0x0000, 0x806b, 0x0000, 0x0000,
+ 0x002b, 0x002b, 0x002b, 0x002b, 0x0006, 0x0006, 0x000d, 0x000d,
+ 0x0006, 0x0006, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x002c, 0x002c, 0x002d, 0x002d, 0x002e, 0x002e, 0x0000, 0x0000,
+ // Entry 280 - 2BF
+ 0x0000, 0x002f, 0x002f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0000, 0x0000, 0x0000, 0x806d, 0x0022, 0x0022,
+ 0x0022, 0x0000, 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0030, 0x0030, 0x0000, 0x0000, 0x8071, 0x0031, 0x0006,
+ // Entry 2C0 - 2FF
+ 0x0006, 0x0006, 0x0000, 0x0001, 0x0001, 0x000d, 0x000d, 0x0001,
+ 0x0001, 0x0000, 0x0000, 0x0032, 0x0032, 0x8074, 0x8076, 0x001b,
+ 0x8077, 0x8079, 0x0028, 0x807b, 0x0034, 0x0033, 0x0033, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006, 0x0006, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0035, 0x0035, 0x0006, 0x0006,
+ 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0036, 0x0037, 0x0037, 0x0036, 0x0036, 0x0001,
+ 0x0001, 0x807d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
+ // Entry 300 - 33F
+ 0x0036, 0x0036, 0x0036, 0x0000, 0x0000, 0x0006, 0x0014,
+} // Size: 1550 bytes
+
+// langToAlt is a list of numbering system and symbol set pairs, sorted and
+// marked by compact language index.
+var langToAlt = []altSymData{ // 131 elements
+ 1: {compactTag: 0x0, symIndex: 0x38, system: 0x3},
+ 2: {compactTag: 0x0, symIndex: 0x42, system: 0x4},
+ 3: {compactTag: 0xa, symIndex: 0x39, system: 0x3},
+ 4: {compactTag: 0xa, symIndex: 0x2, system: 0x0},
+ 5: {compactTag: 0x28, symIndex: 0x0, system: 0x6},
+ 6: {compactTag: 0x2c, symIndex: 0x5, system: 0x0},
+ 7: {compactTag: 0x2c, symIndex: 0x3a, system: 0x3},
+ 8: {compactTag: 0x2c, symIndex: 0x42, system: 0x4},
+ 9: {compactTag: 0x40, symIndex: 0x0, system: 0x6},
+ 10: {compactTag: 0x43, symIndex: 0x0, system: 0x0},
+ 11: {compactTag: 0x43, symIndex: 0x4f, system: 0x37},
+ 12: {compactTag: 0x46, symIndex: 0x1, system: 0x0},
+ 13: {compactTag: 0x46, symIndex: 0x38, system: 0x3},
+ 14: {compactTag: 0x54, symIndex: 0x0, system: 0x9},
+ 15: {compactTag: 0x5d, symIndex: 0x3a, system: 0x3},
+ 16: {compactTag: 0x5d, symIndex: 0x8, system: 0x0},
+ 17: {compactTag: 0x60, symIndex: 0x1, system: 0x0},
+ 18: {compactTag: 0x60, symIndex: 0x38, system: 0x3},
+ 19: {compactTag: 0x60, symIndex: 0x42, system: 0x4},
+ 20: {compactTag: 0x60, symIndex: 0x0, system: 0x5},
+ 21: {compactTag: 0x60, symIndex: 0x0, system: 0x6},
+ 22: {compactTag: 0x60, symIndex: 0x0, system: 0x8},
+ 23: {compactTag: 0x60, symIndex: 0x0, system: 0x9},
+ 24: {compactTag: 0x60, symIndex: 0x0, system: 0xa},
+ 25: {compactTag: 0x60, symIndex: 0x0, system: 0xb},
+ 26: {compactTag: 0x60, symIndex: 0x0, system: 0xc},
+ 27: {compactTag: 0x60, symIndex: 0x0, system: 0xd},
+ 28: {compactTag: 0x60, symIndex: 0x0, system: 0xe},
+ 29: {compactTag: 0x60, symIndex: 0x0, system: 0xf},
+ 30: {compactTag: 0x60, symIndex: 0x0, system: 0x11},
+ 31: {compactTag: 0x60, symIndex: 0x0, system: 0x12},
+ 32: {compactTag: 0x60, symIndex: 0x0, system: 0x13},
+ 33: {compactTag: 0x60, symIndex: 0x0, system: 0x14},
+ 34: {compactTag: 0x60, symIndex: 0x0, system: 0x15},
+ 35: {compactTag: 0x60, symIndex: 0x0, system: 0x16},
+ 36: {compactTag: 0x60, symIndex: 0x0, system: 0x17},
+ 37: {compactTag: 0x60, symIndex: 0x0, system: 0x18},
+ 38: {compactTag: 0x60, symIndex: 0x0, system: 0x19},
+ 39: {compactTag: 0x60, symIndex: 0x0, system: 0x1f},
+ 40: {compactTag: 0x60, symIndex: 0x0, system: 0x21},
+ 41: {compactTag: 0x60, symIndex: 0x0, system: 0x23},
+ 42: {compactTag: 0x60, symIndex: 0x0, system: 0x24},
+ 43: {compactTag: 0x60, symIndex: 0x0, system: 0x25},
+ 44: {compactTag: 0x60, symIndex: 0x0, system: 0x28},
+ 45: {compactTag: 0x60, symIndex: 0x0, system: 0x29},
+ 46: {compactTag: 0x60, symIndex: 0x0, system: 0x2a},
+ 47: {compactTag: 0x60, symIndex: 0x0, system: 0x2b},
+ 48: {compactTag: 0x60, symIndex: 0x0, system: 0x2c},
+ 49: {compactTag: 0x60, symIndex: 0x0, system: 0x2d},
+ 50: {compactTag: 0x60, symIndex: 0x0, system: 0x30},
+ 51: {compactTag: 0x60, symIndex: 0x0, system: 0x31},
+ 52: {compactTag: 0x60, symIndex: 0x0, system: 0x32},
+ 53: {compactTag: 0x60, symIndex: 0x0, system: 0x33},
+ 54: {compactTag: 0x60, symIndex: 0x0, system: 0x34},
+ 55: {compactTag: 0x60, symIndex: 0x0, system: 0x35},
+ 56: {compactTag: 0x60, symIndex: 0x0, system: 0x36},
+ 57: {compactTag: 0x60, symIndex: 0x0, system: 0x37},
+ 58: {compactTag: 0x60, symIndex: 0x0, system: 0x39},
+ 59: {compactTag: 0x60, symIndex: 0x0, system: 0x43},
+ 60: {compactTag: 0x64, symIndex: 0x0, system: 0x0},
+ 61: {compactTag: 0x64, symIndex: 0x38, system: 0x3},
+ 62: {compactTag: 0x64, symIndex: 0x42, system: 0x4},
+ 63: {compactTag: 0x7c, symIndex: 0x50, system: 0x37},
+ 64: {compactTag: 0x7c, symIndex: 0x0, system: 0x0},
+ 65: {compactTag: 0x114, symIndex: 0x43, system: 0x4},
+ 66: {compactTag: 0x114, symIndex: 0x18, system: 0x0},
+ 67: {compactTag: 0x114, symIndex: 0x3b, system: 0x3},
+ 68: {compactTag: 0x123, symIndex: 0x1, system: 0x0},
+ 69: {compactTag: 0x123, symIndex: 0x3c, system: 0x3},
+ 70: {compactTag: 0x123, symIndex: 0x44, system: 0x4},
+ 71: {compactTag: 0x158, symIndex: 0x0, system: 0x0},
+ 72: {compactTag: 0x158, symIndex: 0x3b, system: 0x3},
+ 73: {compactTag: 0x158, symIndex: 0x45, system: 0x4},
+ 74: {compactTag: 0x160, symIndex: 0x0, system: 0x0},
+ 75: {compactTag: 0x160, symIndex: 0x38, system: 0x3},
+ 76: {compactTag: 0x16d, symIndex: 0x1b, system: 0x0},
+ 77: {compactTag: 0x16d, symIndex: 0x0, system: 0x9},
+ 78: {compactTag: 0x16d, symIndex: 0x0, system: 0xa},
+ 79: {compactTag: 0x17c, symIndex: 0x0, system: 0x0},
+ 80: {compactTag: 0x17c, symIndex: 0x3d, system: 0x3},
+ 81: {compactTag: 0x17c, symIndex: 0x42, system: 0x4},
+ 82: {compactTag: 0x182, symIndex: 0x6, system: 0x0},
+ 83: {compactTag: 0x182, symIndex: 0x38, system: 0x3},
+ 84: {compactTag: 0x1b1, symIndex: 0x0, system: 0x0},
+ 85: {compactTag: 0x1b1, symIndex: 0x3e, system: 0x3},
+ 86: {compactTag: 0x1b6, symIndex: 0x42, system: 0x4},
+ 87: {compactTag: 0x1b6, symIndex: 0x1b, system: 0x0},
+ 88: {compactTag: 0x1d2, symIndex: 0x42, system: 0x4},
+ 89: {compactTag: 0x1d2, symIndex: 0x0, system: 0x0},
+ 90: {compactTag: 0x1f3, symIndex: 0x0, system: 0xb},
+ 91: {compactTag: 0x1fd, symIndex: 0x4e, system: 0x24},
+ 92: {compactTag: 0x1fd, symIndex: 0x26, system: 0x0},
+ 93: {compactTag: 0x1ff, symIndex: 0x42, system: 0x4},
+ 94: {compactTag: 0x204, symIndex: 0x15, system: 0x0},
+ 95: {compactTag: 0x204, symIndex: 0x3f, system: 0x3},
+ 96: {compactTag: 0x204, symIndex: 0x46, system: 0x4},
+ 97: {compactTag: 0x20c, symIndex: 0x0, system: 0xb},
+ 98: {compactTag: 0x20f, symIndex: 0x6, system: 0x0},
+ 99: {compactTag: 0x20f, symIndex: 0x38, system: 0x3},
+ 100: {compactTag: 0x20f, symIndex: 0x42, system: 0x4},
+ 101: {compactTag: 0x22e, symIndex: 0x0, system: 0x0},
+ 102: {compactTag: 0x22e, symIndex: 0x47, system: 0x4},
+ 103: {compactTag: 0x22f, symIndex: 0x42, system: 0x4},
+ 104: {compactTag: 0x22f, symIndex: 0x1b, system: 0x0},
+ 105: {compactTag: 0x238, symIndex: 0x42, system: 0x4},
+ 106: {compactTag: 0x238, symIndex: 0x28, system: 0x0},
+ 107: {compactTag: 0x265, symIndex: 0x38, system: 0x3},
+ 108: {compactTag: 0x265, symIndex: 0x0, system: 0x0},
+ 109: {compactTag: 0x29d, symIndex: 0x22, system: 0x0},
+ 110: {compactTag: 0x29d, symIndex: 0x40, system: 0x3},
+ 111: {compactTag: 0x29d, symIndex: 0x48, system: 0x4},
+ 112: {compactTag: 0x29d, symIndex: 0x4d, system: 0xc},
+ 113: {compactTag: 0x2bd, symIndex: 0x31, system: 0x0},
+ 114: {compactTag: 0x2bd, symIndex: 0x3e, system: 0x3},
+ 115: {compactTag: 0x2bd, symIndex: 0x42, system: 0x4},
+ 116: {compactTag: 0x2cd, symIndex: 0x1b, system: 0x0},
+ 117: {compactTag: 0x2cd, symIndex: 0x49, system: 0x4},
+ 118: {compactTag: 0x2ce, symIndex: 0x49, system: 0x4},
+ 119: {compactTag: 0x2d0, symIndex: 0x33, system: 0x0},
+ 120: {compactTag: 0x2d0, symIndex: 0x4a, system: 0x4},
+ 121: {compactTag: 0x2d1, symIndex: 0x42, system: 0x4},
+ 122: {compactTag: 0x2d1, symIndex: 0x28, system: 0x0},
+ 123: {compactTag: 0x2d3, symIndex: 0x34, system: 0x0},
+ 124: {compactTag: 0x2d3, symIndex: 0x4b, system: 0x4},
+ 125: {compactTag: 0x2f9, symIndex: 0x0, system: 0x0},
+ 126: {compactTag: 0x2f9, symIndex: 0x38, system: 0x3},
+ 127: {compactTag: 0x2f9, symIndex: 0x42, system: 0x4},
+ 128: {compactTag: 0x2ff, symIndex: 0x36, system: 0x0},
+ 129: {compactTag: 0x2ff, symIndex: 0x41, system: 0x3},
+ 130: {compactTag: 0x2ff, symIndex: 0x4c, system: 0x4},
+} // Size: 810 bytes
+
+var tagToDecimal = []uint8{ // 775 elements
+ // Entry 0 - 3F
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry 40 - 7F
+ 0x05, 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x05, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x01, 0x01,
+ // Entry 80 - BF
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry C0 - FF
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry 100 - 13F
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry 140 - 17F
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05,
+ 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry 180 - 1BF
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x05, 0x05,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry 1C0 - 1FF
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05,
+ 0x01, 0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry 200 - 23F
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x05, 0x01,
+ 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry 240 - 27F
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry 280 - 2BF
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05,
+ 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry 2C0 - 2FF
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ // Entry 300 - 33F
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08,
+} // Size: 799 bytes
+
+var tagToScientific = []uint8{ // 775 elements
+ // Entry 0 - 3F
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 40 - 7F
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 80 - BF
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry C0 - FF
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 100 - 13F
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 140 - 17F
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c,
+ 0x0c, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 180 - 1BF
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 1C0 - 1FF
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x0c, 0x0c, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 200 - 23F
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c, 0x02,
+ 0x02, 0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 240 - 27F
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 280 - 2BF
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 2C0 - 2FF
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ // Entry 300 - 33F
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x09,
+} // Size: 799 bytes
+
+var tagToPercent = []uint8{ // 775 elements
+ // Entry 0 - 3F
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ // Entry 40 - 7F
+ 0x06, 0x06, 0x06, 0x04, 0x04, 0x04, 0x03, 0x03,
+ 0x06, 0x06, 0x03, 0x04, 0x04, 0x03, 0x03, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x03,
+ 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
+ 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x03,
+ 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03,
+ 0x03, 0x04, 0x04, 0x04, 0x07, 0x07, 0x04, 0x04,
+ // Entry 80 - BF
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x03, 0x04,
+ 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ // Entry C0 - FF
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ // Entry 100 - 13F
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04,
+ 0x0b, 0x0b, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ // Entry 140 - 17F
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06,
+ 0x06, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ // Entry 180 - 1BF
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06,
+ 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04,
+ // Entry 1C0 - 1FF
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ // Entry 200 - 23F
+ 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x06, 0x06, 0x04, 0x04, 0x04, 0x06, 0x04,
+ 0x04, 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ // Entry 240 - 27F
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04,
+ // Entry 280 - 2BF
+ 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03,
+ 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06,
+ 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x0e,
+ // Entry 2C0 - 2FF
+ 0x0e, 0x0e, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
+ 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ // Entry 300 - 33F
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0a,
+} // Size: 799 bytes
+
+var formats = []Pattern{Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x0,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x0,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 3,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x9,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x0,
+ MaxIntegerDigits: 0x1,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x1},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x3,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x00\x03\u00a0%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x7,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x00\x01%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x6,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 3,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0xc,
+ GroupingSize: [2]uint8{0x3,
+ 0x2},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x00\x01%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x9,
+ GroupingSize: [2]uint8{0x3,
+ 0x2},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x00\x03\u00a0%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0xa,
+ GroupingSize: [2]uint8{0x3,
+ 0x2},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 6,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x8,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 6,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x6,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x3},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0xd,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x4},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x00\x01%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x2,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x03%\u00a0\x00",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x7,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x0,
+ MaxIntegerDigits: 0x1,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x1},
+ Affix: "\x01[\x01]",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x5,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
+ MinIntegerDigits: 0x0,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x1,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
+ MinIntegerDigits: 0x1,
+ MaxIntegerDigits: 0x0,
+ MinFractionDigits: 0x0,
+ MinSignificantDigits: 0x0,
+ MinExponentDigits: 0x0},
+ Affix: "\x01%\x00",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x6,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0}}
+
+// Total table size 8634 bytes (8KiB); checksum: 8F23386D
diff --git a/vendor/golang.org/x/text/internal/stringset/set.go b/vendor/golang.org/x/text/internal/stringset/set.go
new file mode 100644
index 0000000..bb2fffb
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/stringset/set.go
@@ -0,0 +1,86 @@
+// Copyright 2016 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 stringset provides a way to represent a collection of strings
+// compactly.
+package stringset
+
+import "sort"
+
+// A Set holds a collection of strings that can be looked up by an index number.
+type Set struct {
+ // These fields are exported to allow for code generation.
+
+ Data string
+ Index []uint16
+}
+
+// Elem returns the string with index i. It panics if i is out of range.
+func (s *Set) Elem(i int) string {
+ return s.Data[s.Index[i]:s.Index[i+1]]
+}
+
+// Len returns the number of strings in the set.
+func (s *Set) Len() int {
+ return len(s.Index) - 1
+}
+
+// Search returns the index of the given string or -1 if it is not in the set.
+// The Set must have been created with strings in sorted order.
+func Search(s *Set, str string) int {
+ // TODO: optimize this if it gets used a lot.
+ n := len(s.Index) - 1
+ p := sort.Search(n, func(i int) bool {
+ return s.Elem(i) >= str
+ })
+ if p == n || str != s.Elem(p) {
+ return -1
+ }
+ return p
+}
+
+// A Builder constructs Sets.
+type Builder struct {
+ set Set
+ index map[string]int
+}
+
+// NewBuilder returns a new and initialized Builder.
+func NewBuilder() *Builder {
+ return &Builder{
+ set: Set{
+ Index: []uint16{0},
+ },
+ index: map[string]int{},
+ }
+}
+
+// Set creates the set created so far.
+func (b *Builder) Set() Set {
+ return b.set
+}
+
+// Index returns the index for the given string, which must have been added
+// before.
+func (b *Builder) Index(s string) int {
+ return b.index[s]
+}
+
+// Add adds a string to the index. Strings that are added by a single Add will
+// be stored together, unless they match an existing string.
+func (b *Builder) Add(ss ...string) {
+ // First check if the string already exists.
+ for _, s := range ss {
+ if _, ok := b.index[s]; ok {
+ continue
+ }
+ b.index[s] = len(b.set.Index) - 1
+ b.set.Data += s
+ x := len(b.set.Data)
+ if x > 0xFFFF {
+ panic("Index too > 0xFFFF")
+ }
+ b.set.Index = append(b.set.Index, uint16(x))
+ }
+}
diff --git a/vendor/golang.org/x/text/internal/tag/tag.go b/vendor/golang.org/x/text/internal/tag/tag.go
new file mode 100644
index 0000000..b5d3488
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/tag/tag.go
@@ -0,0 +1,100 @@
+// Copyright 2015 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 tag contains functionality handling tags and related data.
+package tag // import "golang.org/x/text/internal/tag"
+
+import "sort"
+
+// An Index converts tags to a compact numeric value.
+//
+// All elements are of size 4. Tags may be up to 4 bytes long. Excess bytes can
+// be used to store additional information about the tag.
+type Index string
+
+// Elem returns the element data at the given index.
+func (s Index) Elem(x int) string {
+ return string(s[x*4 : x*4+4])
+}
+
+// Index reports the index of the given key or -1 if it could not be found.
+// Only the first len(key) bytes from the start of the 4-byte entries will be
+// considered for the search and the first match in Index will be returned.
+func (s Index) Index(key []byte) int {
+ n := len(key)
+ // search the index of the first entry with an equal or higher value than
+ // key in s.
+ index := sort.Search(len(s)/4, func(i int) bool {
+ return cmp(s[i*4:i*4+n], key) != -1
+ })
+ i := index * 4
+ if cmp(s[i:i+len(key)], key) != 0 {
+ return -1
+ }
+ return index
+}
+
+// Next finds the next occurrence of key after index x, which must have been
+// obtained from a call to Index using the same key. It returns x+1 or -1.
+func (s Index) Next(key []byte, x int) int {
+ if x++; x*4 < len(s) && cmp(s[x*4:x*4+len(key)], key) == 0 {
+ return x
+ }
+ return -1
+}
+
+// cmp returns an integer comparing a and b lexicographically.
+func cmp(a Index, b []byte) int {
+ n := len(a)
+ if len(b) < n {
+ n = len(b)
+ }
+ for i, c := range b[:n] {
+ switch {
+ case a[i] > c:
+ return 1
+ case a[i] < c:
+ return -1
+ }
+ }
+ switch {
+ case len(a) < len(b):
+ return -1
+ case len(a) > len(b):
+ return 1
+ }
+ return 0
+}
+
+// Compare returns an integer comparing a and b lexicographically.
+func Compare(a string, b []byte) int {
+ return cmp(Index(a), b)
+}
+
+// FixCase reformats b to the same pattern of cases as form.
+// If returns false if string b is malformed.
+func FixCase(form string, b []byte) bool {
+ if len(form) != len(b) {
+ return false
+ }
+ for i, c := range b {
+ if form[i] <= 'Z' {
+ if c >= 'a' {
+ c -= 'z' - 'Z'
+ }
+ if c < 'A' || 'Z' < c {
+ return false
+ }
+ } else {
+ if c <= 'Z' {
+ c += 'z' - 'Z'
+ }
+ if c < 'a' || 'z' < c {
+ return false
+ }
+ }
+ b[i] = c
+ }
+ return true
+}
diff --git a/vendor/golang.org/x/text/language/coverage.go b/vendor/golang.org/x/text/language/coverage.go
new file mode 100644
index 0000000..a24fd1a
--- /dev/null
+++ b/vendor/golang.org/x/text/language/coverage.go
@@ -0,0 +1,187 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package language
+
+import (
+ "fmt"
+ "sort"
+
+ "golang.org/x/text/internal/language"
+)
+
+// The Coverage interface is used to define the level of coverage of an
+// internationalization service. Note that not all types are supported by all
+// services. As lists may be generated on the fly, it is recommended that users
+// of a Coverage cache the results.
+type Coverage interface {
+ // Tags returns the list of supported tags.
+ Tags() []Tag
+
+ // BaseLanguages returns the list of supported base languages.
+ BaseLanguages() []Base
+
+ // Scripts returns the list of supported scripts.
+ Scripts() []Script
+
+ // Regions returns the list of supported regions.
+ Regions() []Region
+}
+
+var (
+ // Supported defines a Coverage that lists all supported subtags. Tags
+ // always returns nil.
+ Supported Coverage = allSubtags{}
+)
+
+// TODO:
+// - Support Variants, numbering systems.
+// - CLDR coverage levels.
+// - Set of common tags defined in this package.
+
+type allSubtags struct{}
+
+// Regions returns the list of supported regions. As all regions are in a
+// consecutive range, it simply returns a slice of numbers in increasing order.
+// The "undefined" region is not returned.
+func (s allSubtags) Regions() []Region {
+ reg := make([]Region, language.NumRegions)
+ for i := range reg {
+ reg[i] = Region{language.Region(i + 1)}
+ }
+ return reg
+}
+
+// Scripts returns the list of supported scripts. As all scripts are in a
+// consecutive range, it simply returns a slice of numbers in increasing order.
+// The "undefined" script is not returned.
+func (s allSubtags) Scripts() []Script {
+ scr := make([]Script, language.NumScripts)
+ for i := range scr {
+ scr[i] = Script{language.Script(i + 1)}
+ }
+ return scr
+}
+
+// BaseLanguages returns the list of all supported base languages. It generates
+// the list by traversing the internal structures.
+func (s allSubtags) BaseLanguages() []Base {
+ bs := language.BaseLanguages()
+ base := make([]Base, len(bs))
+ for i, b := range bs {
+ base[i] = Base{b}
+ }
+ return base
+}
+
+// Tags always returns nil.
+func (s allSubtags) Tags() []Tag {
+ return nil
+}
+
+// coverage is used by NewCoverage which is used as a convenient way for
+// creating Coverage implementations for partially defined data. Very often a
+// package will only need to define a subset of slices. coverage provides a
+// convenient way to do this. Moreover, packages using NewCoverage, instead of
+// their own implementation, will not break if later new slice types are added.
+type coverage struct {
+ tags func() []Tag
+ bases func() []Base
+ scripts func() []Script
+ regions func() []Region
+}
+
+func (s *coverage) Tags() []Tag {
+ if s.tags == nil {
+ return nil
+ }
+ return s.tags()
+}
+
+// bases implements sort.Interface and is used to sort base languages.
+type bases []Base
+
+func (b bases) Len() int {
+ return len(b)
+}
+
+func (b bases) Swap(i, j int) {
+ b[i], b[j] = b[j], b[i]
+}
+
+func (b bases) Less(i, j int) bool {
+ return b[i].langID < b[j].langID
+}
+
+// BaseLanguages returns the result from calling s.bases if it is specified or
+// otherwise derives the set of supported base languages from tags.
+func (s *coverage) BaseLanguages() []Base {
+ if s.bases == nil {
+ tags := s.Tags()
+ if len(tags) == 0 {
+ return nil
+ }
+ a := make([]Base, len(tags))
+ for i, t := range tags {
+ a[i] = Base{language.Language(t.lang())}
+ }
+ sort.Sort(bases(a))
+ k := 0
+ for i := 1; i < len(a); i++ {
+ if a[k] != a[i] {
+ k++
+ a[k] = a[i]
+ }
+ }
+ return a[:k+1]
+ }
+ return s.bases()
+}
+
+func (s *coverage) Scripts() []Script {
+ if s.scripts == nil {
+ return nil
+ }
+ return s.scripts()
+}
+
+func (s *coverage) Regions() []Region {
+ if s.regions == nil {
+ return nil
+ }
+ return s.regions()
+}
+
+// NewCoverage returns a Coverage for the given lists. It is typically used by
+// packages providing internationalization services to define their level of
+// coverage. A list may be of type []T or func() []T, where T is either Tag,
+// Base, Script or Region. The returned Coverage derives the value for Bases
+// from Tags if no func or slice for []Base is specified. For other unspecified
+// types the returned Coverage will return nil for the respective methods.
+func NewCoverage(list ...interface{}) Coverage {
+ s := &coverage{}
+ for _, x := range list {
+ switch v := x.(type) {
+ case func() []Base:
+ s.bases = v
+ case func() []Script:
+ s.scripts = v
+ case func() []Region:
+ s.regions = v
+ case func() []Tag:
+ s.tags = v
+ case []Base:
+ s.bases = func() []Base { return v }
+ case []Script:
+ s.scripts = func() []Script { return v }
+ case []Region:
+ s.regions = func() []Region { return v }
+ case []Tag:
+ s.tags = func() []Tag { return v }
+ default:
+ panic(fmt.Sprintf("language: unsupported set type %T", v))
+ }
+ }
+ return s
+}
diff --git a/vendor/golang.org/x/text/language/doc.go b/vendor/golang.org/x/text/language/doc.go
new file mode 100644
index 0000000..212b77c
--- /dev/null
+++ b/vendor/golang.org/x/text/language/doc.go
@@ -0,0 +1,98 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package language implements BCP 47 language tags and related functionality.
+//
+// The most important function of package language is to match a list of
+// user-preferred languages to a list of supported languages.
+// It alleviates the developer of dealing with the complexity of this process
+// and provides the user with the best experience
+// (see https://blog.golang.org/matchlang).
+//
+// # Matching preferred against supported languages
+//
+// A Matcher for an application that supports English, Australian English,
+// Danish, and standard Mandarin can be created as follows:
+//
+// var matcher = language.NewMatcher([]language.Tag{
+// language.English, // The first language is used as fallback.
+// language.MustParse("en-AU"),
+// language.Danish,
+// language.Chinese,
+// })
+//
+// This list of supported languages is typically implied by the languages for
+// which there exists translations of the user interface.
+//
+// User-preferred languages usually come as a comma-separated list of BCP 47
+// language tags.
+// The MatchString finds best matches for such strings:
+//
+// handler(w http.ResponseWriter, r *http.Request) {
+// lang, _ := r.Cookie("lang")
+// accept := r.Header.Get("Accept-Language")
+// tag, _ := language.MatchStrings(matcher, lang.String(), accept)
+//
+// // tag should now be used for the initialization of any
+// // locale-specific service.
+// }
+//
+// The Matcher's Match method can be used to match Tags directly.
+//
+// Matchers are aware of the intricacies of equivalence between languages, such
+// as deprecated subtags, legacy tags, macro languages, mutual
+// intelligibility between scripts and languages, and transparently passing
+// BCP 47 user configuration.
+// For instance, it will know that a reader of Bokmål Danish can read Norwegian
+// and will know that Cantonese ("yue") is a good match for "zh-HK".
+//
+// # Using match results
+//
+// To guarantee a consistent user experience to the user it is important to
+// use the same language tag for the selection of any locale-specific services.
+// For example, it is utterly confusing to substitute spelled-out numbers
+// or dates in one language in text of another language.
+// More subtly confusing is using the wrong sorting order or casing
+// algorithm for a certain language.
+//
+// All the packages in x/text that provide locale-specific services
+// (e.g. collate, cases) should be initialized with the tag that was
+// obtained at the start of an interaction with the user.
+//
+// Note that Tag that is returned by Match and MatchString may differ from any
+// of the supported languages, as it may contain carried over settings from
+// the user tags.
+// This may be inconvenient when your application has some additional
+// locale-specific data for your supported languages.
+// Match and MatchString both return the index of the matched supported tag
+// to simplify associating such data with the matched tag.
+//
+// # Canonicalization
+//
+// If one uses the Matcher to compare languages one does not need to
+// worry about canonicalization.
+//
+// The meaning of a Tag varies per application. The language package
+// therefore delays canonicalization and preserves information as much
+// as possible. The Matcher, however, will always take into account that
+// two different tags may represent the same language.
+//
+// By default, only legacy and deprecated tags are converted into their
+// canonical equivalent. All other information is preserved. This approach makes
+// the confidence scores more accurate and allows matchers to distinguish
+// between variants that are otherwise lost.
+//
+// As a consequence, two tags that should be treated as identical according to
+// BCP 47 or CLDR, like "en-Latn" and "en", will be represented differently. The
+// Matcher handles such distinctions, though, and is aware of the
+// equivalence relations. The CanonType type can be used to alter the
+// canonicalization form.
+//
+// # References
+//
+// BCP 47 - Tags for Identifying Languages http://tools.ietf.org/html/bcp47
+package language // import "golang.org/x/text/language"
+
+// TODO: explanation on how to match languages for your own locale-specific
+// service.
diff --git a/vendor/golang.org/x/text/language/language.go b/vendor/golang.org/x/text/language/language.go
new file mode 100644
index 0000000..4d9c661
--- /dev/null
+++ b/vendor/golang.org/x/text/language/language.go
@@ -0,0 +1,605 @@
+// 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 gen.go -output tables.go
+
+package language
+
+// TODO: Remove above NOTE after:
+// - verifying that tables are dropped correctly (most notably matcher tables).
+
+import (
+ "strings"
+
+ "golang.org/x/text/internal/language"
+ "golang.org/x/text/internal/language/compact"
+)
+
+// Tag represents a BCP 47 language tag. It is used to specify an instance of a
+// specific language or locale. All language tag values are guaranteed to be
+// well-formed.
+type Tag compact.Tag
+
+func makeTag(t language.Tag) (tag Tag) {
+ return Tag(compact.Make(t))
+}
+
+func (t *Tag) tag() language.Tag {
+ return (*compact.Tag)(t).Tag()
+}
+
+func (t *Tag) isCompact() bool {
+ return (*compact.Tag)(t).IsCompact()
+}
+
+// TODO: improve performance.
+func (t *Tag) lang() language.Language { return t.tag().LangID }
+func (t *Tag) region() language.Region { return t.tag().RegionID }
+func (t *Tag) script() language.Script { return t.tag().ScriptID }
+
+// Make is a convenience wrapper for Parse that omits the error.
+// In case of an error, a sensible default is returned.
+func Make(s string) Tag {
+ return Default.Make(s)
+}
+
+// Make is a convenience wrapper for c.Parse that omits the error.
+// In case of an error, a sensible default is returned.
+func (c CanonType) Make(s string) Tag {
+ t, _ := c.Parse(s)
+ return t
+}
+
+// Raw returns the raw base language, script and region, without making an
+// attempt to infer their values.
+func (t Tag) Raw() (b Base, s Script, r Region) {
+ tt := t.tag()
+ return Base{tt.LangID}, Script{tt.ScriptID}, Region{tt.RegionID}
+}
+
+// IsRoot returns true if t is equal to language "und".
+func (t Tag) IsRoot() bool {
+ return compact.Tag(t).IsRoot()
+}
+
+// CanonType can be used to enable or disable various types of canonicalization.
+type CanonType int
+
+const (
+ // Replace deprecated base languages with their preferred replacements.
+ DeprecatedBase CanonType = 1 << iota
+ // Replace deprecated scripts with their preferred replacements.
+ DeprecatedScript
+ // Replace deprecated regions with their preferred replacements.
+ DeprecatedRegion
+ // Remove redundant scripts.
+ SuppressScript
+ // Normalize legacy encodings. This includes legacy languages defined in
+ // CLDR as well as bibliographic codes defined in ISO-639.
+ Legacy
+ // Map the dominant language of a macro language group to the macro language
+ // subtag. For example cmn -> zh.
+ Macro
+ // The CLDR flag should be used if full compatibility with CLDR is required.
+ // There are a few cases where language.Tag may differ from CLDR. To follow all
+ // of CLDR's suggestions, use All|CLDR.
+ CLDR
+
+ // Raw can be used to Compose or Parse without Canonicalization.
+ Raw CanonType = 0
+
+ // Replace all deprecated tags with their preferred replacements.
+ Deprecated = DeprecatedBase | DeprecatedScript | DeprecatedRegion
+
+ // All canonicalizations recommended by BCP 47.
+ BCP47 = Deprecated | SuppressScript
+
+ // All canonicalizations.
+ All = BCP47 | Legacy | Macro
+
+ // Default is the canonicalization used by Parse, Make and Compose. To
+ // preserve as much information as possible, canonicalizations that remove
+ // potentially valuable information are not included. The Matcher is
+ // designed to recognize similar tags that would be the same if
+ // they were canonicalized using All.
+ Default = Deprecated | Legacy
+
+ canonLang = DeprecatedBase | Legacy | Macro
+
+ // TODO: LikelyScript, LikelyRegion: suppress similar to ICU.
+)
+
+// canonicalize returns the canonicalized equivalent of the tag and
+// whether there was any change.
+func canonicalize(c CanonType, t language.Tag) (language.Tag, bool) {
+ if c == Raw {
+ return t, false
+ }
+ changed := false
+ if c&SuppressScript != 0 {
+ if t.LangID.SuppressScript() == t.ScriptID {
+ t.ScriptID = 0
+ changed = true
+ }
+ }
+ if c&canonLang != 0 {
+ for {
+ if l, aliasType := t.LangID.Canonicalize(); l != t.LangID {
+ switch aliasType {
+ case language.Legacy:
+ if c&Legacy != 0 {
+ if t.LangID == _sh && t.ScriptID == 0 {
+ t.ScriptID = _Latn
+ }
+ t.LangID = l
+ changed = true
+ }
+ case language.Macro:
+ if c&Macro != 0 {
+ // We deviate here from CLDR. The mapping "nb" -> "no"
+ // qualifies as a typical Macro language mapping. However,
+ // for legacy reasons, CLDR maps "no", the macro language
+ // code for Norwegian, to the dominant variant "nb". This
+ // change is currently under consideration for CLDR as well.
+ // See https://unicode.org/cldr/trac/ticket/2698 and also
+ // https://unicode.org/cldr/trac/ticket/1790 for some of the
+ // practical implications. TODO: this check could be removed
+ // if CLDR adopts this change.
+ if c&CLDR == 0 || t.LangID != _nb {
+ changed = true
+ t.LangID = l
+ }
+ }
+ case language.Deprecated:
+ if c&DeprecatedBase != 0 {
+ if t.LangID == _mo && t.RegionID == 0 {
+ t.RegionID = _MD
+ }
+ t.LangID = l
+ changed = true
+ // Other canonicalization types may still apply.
+ continue
+ }
+ }
+ } else if c&Legacy != 0 && t.LangID == _no && c&CLDR != 0 {
+ t.LangID = _nb
+ changed = true
+ }
+ break
+ }
+ }
+ if c&DeprecatedScript != 0 {
+ if t.ScriptID == _Qaai {
+ changed = true
+ t.ScriptID = _Zinh
+ }
+ }
+ if c&DeprecatedRegion != 0 {
+ if r := t.RegionID.Canonicalize(); r != t.RegionID {
+ changed = true
+ t.RegionID = r
+ }
+ }
+ return t, changed
+}
+
+// Canonicalize returns the canonicalized equivalent of the tag.
+func (c CanonType) Canonicalize(t Tag) (Tag, error) {
+ // First try fast path.
+ if t.isCompact() {
+ if _, changed := canonicalize(c, compact.Tag(t).Tag()); !changed {
+ return t, nil
+ }
+ }
+ // It is unlikely that one will canonicalize a tag after matching. So do
+ // a slow but simple approach here.
+ if tag, changed := canonicalize(c, t.tag()); changed {
+ tag.RemakeString()
+ return makeTag(tag), nil
+ }
+ return t, nil
+
+}
+
+// Confidence indicates the level of certainty for a given return value.
+// For example, Serbian may be written in Cyrillic or Latin script.
+// The confidence level indicates whether a value was explicitly specified,
+// whether it is typically the only possible value, or whether there is
+// an ambiguity.
+type Confidence int
+
+const (
+ No Confidence = iota // full confidence that there was no match
+ Low // most likely value picked out of a set of alternatives
+ High // value is generally assumed to be the correct match
+ Exact // exact match or explicitly specified value
+)
+
+var confName = []string{"No", "Low", "High", "Exact"}
+
+func (c Confidence) String() string {
+ return confName[c]
+}
+
+// String returns the canonical string representation of the language tag.
+func (t Tag) String() string {
+ return t.tag().String()
+}
+
+// MarshalText implements encoding.TextMarshaler.
+func (t Tag) MarshalText() (text []byte, err error) {
+ return t.tag().MarshalText()
+}
+
+// UnmarshalText implements encoding.TextUnmarshaler.
+func (t *Tag) UnmarshalText(text []byte) error {
+ var tag language.Tag
+ err := tag.UnmarshalText(text)
+ *t = makeTag(tag)
+ return err
+}
+
+// Base returns the base language of the language tag. If the base language is
+// unspecified, an attempt will be made to infer it from the context.
+// It uses a variant of CLDR's Add Likely Subtags algorithm. This is subject to change.
+func (t Tag) Base() (Base, Confidence) {
+ if b := t.lang(); b != 0 {
+ return Base{b}, Exact
+ }
+ tt := t.tag()
+ c := High
+ if tt.ScriptID == 0 && !tt.RegionID.IsCountry() {
+ c = Low
+ }
+ if tag, err := tt.Maximize(); err == nil && tag.LangID != 0 {
+ return Base{tag.LangID}, c
+ }
+ return Base{0}, No
+}
+
+// Script infers the script for the language tag. If it was not explicitly given, it will infer
+// a most likely candidate.
+// If more than one script is commonly used for a language, the most likely one
+// is returned with a low confidence indication. For example, it returns (Cyrl, Low)
+// for Serbian.
+// If a script cannot be inferred (Zzzz, No) is returned. We do not use Zyyy (undetermined)
+// as one would suspect from the IANA registry for BCP 47. In a Unicode context Zyyy marks
+// common characters (like 1, 2, 3, '.', etc.) and is therefore more like multiple scripts.
+// See https://www.unicode.org/reports/tr24/#Values for more details. Zzzz is also used for
+// unknown value in CLDR. (Zzzz, Exact) is returned if Zzzz was explicitly specified.
+// Note that an inferred script is never guaranteed to be the correct one. Latin is
+// almost exclusively used for Afrikaans, but Arabic has been used for some texts
+// in the past. Also, the script that is commonly used may change over time.
+// It uses a variant of CLDR's Add Likely Subtags algorithm. This is subject to change.
+func (t Tag) Script() (Script, Confidence) {
+ if scr := t.script(); scr != 0 {
+ return Script{scr}, Exact
+ }
+ tt := t.tag()
+ sc, c := language.Script(_Zzzz), No
+ if scr := tt.LangID.SuppressScript(); scr != 0 {
+ // Note: it is not always the case that a language with a suppress
+ // script value is only written in one script (e.g. kk, ms, pa).
+ if tt.RegionID == 0 {
+ return Script{scr}, High
+ }
+ sc, c = scr, High
+ }
+ if tag, err := tt.Maximize(); err == nil {
+ if tag.ScriptID != sc {
+ sc, c = tag.ScriptID, Low
+ }
+ } else {
+ tt, _ = canonicalize(Deprecated|Macro, tt)
+ if tag, err := tt.Maximize(); err == nil && tag.ScriptID != sc {
+ sc, c = tag.ScriptID, Low
+ }
+ }
+ return Script{sc}, c
+}
+
+// Region returns the region for the language tag. If it was not explicitly given, it will
+// infer a most likely candidate from the context.
+// It uses a variant of CLDR's Add Likely Subtags algorithm. This is subject to change.
+func (t Tag) Region() (Region, Confidence) {
+ if r := t.region(); r != 0 {
+ return Region{r}, Exact
+ }
+ tt := t.tag()
+ if tt, err := tt.Maximize(); err == nil {
+ return Region{tt.RegionID}, Low // TODO: differentiate between high and low.
+ }
+ tt, _ = canonicalize(Deprecated|Macro, tt)
+ if tag, err := tt.Maximize(); err == nil {
+ return Region{tag.RegionID}, Low
+ }
+ return Region{_ZZ}, No // TODO: return world instead of undetermined?
+}
+
+// Variants returns the variants specified explicitly for this language tag.
+// or nil if no variant was specified.
+func (t Tag) Variants() []Variant {
+ if !compact.Tag(t).MayHaveVariants() {
+ return nil
+ }
+ v := []Variant{}
+ x, str := "", t.tag().Variants()
+ for str != "" {
+ x, str = nextToken(str)
+ v = append(v, Variant{x})
+ }
+ return v
+}
+
+// Parent returns the CLDR parent of t. In CLDR, missing fields in data for a
+// specific language are substituted with fields from the parent language.
+// The parent for a language may change for newer versions of CLDR.
+//
+// Parent returns a tag for a less specific language that is mutually
+// intelligible or Und if there is no such language. This may not be the same as
+// simply stripping the last BCP 47 subtag. For instance, the parent of "zh-TW"
+// is "zh-Hant", and the parent of "zh-Hant" is "und".
+func (t Tag) Parent() Tag {
+ return Tag(compact.Tag(t).Parent())
+}
+
+// nextToken returns token t and the rest of the string.
+func nextToken(s string) (t, tail string) {
+ p := strings.Index(s[1:], "-")
+ if p == -1 {
+ return s[1:], ""
+ }
+ p++
+ return s[1:p], s[p:]
+}
+
+// Extension is a single BCP 47 extension.
+type Extension struct {
+ s string
+}
+
+// String returns the string representation of the extension, including the
+// type tag.
+func (e Extension) String() string {
+ return e.s
+}
+
+// ParseExtension parses s as an extension and returns it on success.
+func ParseExtension(s string) (e Extension, err error) {
+ ext, err := language.ParseExtension(s)
+ return Extension{ext}, err
+}
+
+// Type returns the one-byte extension type of e. It returns 0 for the zero
+// exception.
+func (e Extension) Type() byte {
+ if e.s == "" {
+ return 0
+ }
+ return e.s[0]
+}
+
+// Tokens returns the list of tokens of e.
+func (e Extension) Tokens() []string {
+ return strings.Split(e.s, "-")
+}
+
+// Extension returns the extension of type x for tag t. It will return
+// false for ok if t does not have the requested extension. The returned
+// extension will be invalid in this case.
+func (t Tag) Extension(x byte) (ext Extension, ok bool) {
+ if !compact.Tag(t).MayHaveExtensions() {
+ return Extension{}, false
+ }
+ e, ok := t.tag().Extension(x)
+ return Extension{e}, ok
+}
+
+// Extensions returns all extensions of t.
+func (t Tag) Extensions() []Extension {
+ if !compact.Tag(t).MayHaveExtensions() {
+ return nil
+ }
+ e := []Extension{}
+ for _, ext := range t.tag().Extensions() {
+ e = append(e, Extension{ext})
+ }
+ return e
+}
+
+// TypeForKey returns the type associated with the given key, where key and type
+// are of the allowed values defined for the Unicode locale extension ('u') in
+// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers.
+// TypeForKey will traverse the inheritance chain to get the correct value.
+//
+// If there are multiple types associated with a key, only the first will be
+// returned. If there is no type associated with a key, it returns the empty
+// string.
+func (t Tag) TypeForKey(key string) string {
+ if !compact.Tag(t).MayHaveExtensions() {
+ if key != "rg" && key != "va" {
+ return ""
+ }
+ }
+ return t.tag().TypeForKey(key)
+}
+
+// SetTypeForKey returns a new Tag with the key set to type, where key and type
+// are of the allowed values defined for the Unicode locale extension ('u') in
+// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers.
+// An empty value removes an existing pair with the same key.
+func (t Tag) SetTypeForKey(key, value string) (Tag, error) {
+ tt, err := t.tag().SetTypeForKey(key, value)
+ return makeTag(tt), err
+}
+
+// NumCompactTags is the number of compact tags. The maximum tag is
+// NumCompactTags-1.
+const NumCompactTags = compact.NumCompactTags
+
+// CompactIndex returns an index, where 0 <= index < NumCompactTags, for tags
+// for which data exists in the text repository.The index will change over time
+// and should not be stored in persistent storage. If t does not match a compact
+// index, exact will be false and the compact index will be returned for the
+// first match after repeatedly taking the Parent of t.
+func CompactIndex(t Tag) (index int, exact bool) {
+ id, exact := compact.LanguageID(compact.Tag(t))
+ return int(id), exact
+}
+
+var root = language.Tag{}
+
+// Base is an ISO 639 language code, used for encoding the base language
+// of a language tag.
+type Base struct {
+ langID language.Language
+}
+
+// ParseBase parses a 2- or 3-letter ISO 639 code.
+// It returns a ValueError if s is a well-formed but unknown language identifier
+// or another error if another error occurred.
+func ParseBase(s string) (Base, error) {
+ l, err := language.ParseBase(s)
+ return Base{l}, err
+}
+
+// String returns the BCP 47 representation of the base language.
+func (b Base) String() string {
+ return b.langID.String()
+}
+
+// ISO3 returns the ISO 639-3 language code.
+func (b Base) ISO3() string {
+ return b.langID.ISO3()
+}
+
+// IsPrivateUse reports whether this language code is reserved for private use.
+func (b Base) IsPrivateUse() bool {
+ return b.langID.IsPrivateUse()
+}
+
+// Script is a 4-letter ISO 15924 code for representing scripts.
+// It is idiomatically represented in title case.
+type Script struct {
+ scriptID language.Script
+}
+
+// ParseScript parses a 4-letter ISO 15924 code.
+// It returns a ValueError if s is a well-formed but unknown script identifier
+// or another error if another error occurred.
+func ParseScript(s string) (Script, error) {
+ sc, err := language.ParseScript(s)
+ return Script{sc}, err
+}
+
+// String returns the script code in title case.
+// It returns "Zzzz" for an unspecified script.
+func (s Script) String() string {
+ return s.scriptID.String()
+}
+
+// IsPrivateUse reports whether this script code is reserved for private use.
+func (s Script) IsPrivateUse() bool {
+ return s.scriptID.IsPrivateUse()
+}
+
+// Region is an ISO 3166-1 or UN M.49 code for representing countries and regions.
+type Region struct {
+ regionID language.Region
+}
+
+// EncodeM49 returns the Region for the given UN M.49 code.
+// It returns an error if r is not a valid code.
+func EncodeM49(r int) (Region, error) {
+ rid, err := language.EncodeM49(r)
+ return Region{rid}, err
+}
+
+// ParseRegion parses a 2- or 3-letter ISO 3166-1 or a UN M.49 code.
+// It returns a ValueError if s is a well-formed but unknown region identifier
+// or another error if another error occurred.
+func ParseRegion(s string) (Region, error) {
+ r, err := language.ParseRegion(s)
+ return Region{r}, err
+}
+
+// String returns the BCP 47 representation for the region.
+// It returns "ZZ" for an unspecified region.
+func (r Region) String() string {
+ return r.regionID.String()
+}
+
+// ISO3 returns the 3-letter ISO code of r.
+// Note that not all regions have a 3-letter ISO code.
+// In such cases this method returns "ZZZ".
+func (r Region) ISO3() string {
+ return r.regionID.ISO3()
+}
+
+// M49 returns the UN M.49 encoding of r, or 0 if this encoding
+// is not defined for r.
+func (r Region) M49() int {
+ return r.regionID.M49()
+}
+
+// IsPrivateUse reports whether r has the ISO 3166 User-assigned status. This
+// may include private-use tags that are assigned by CLDR and used in this
+// implementation. So IsPrivateUse and IsCountry can be simultaneously true.
+func (r Region) IsPrivateUse() bool {
+ return r.regionID.IsPrivateUse()
+}
+
+// IsCountry returns whether this region is a country or autonomous area. This
+// includes non-standard definitions from CLDR.
+func (r Region) IsCountry() bool {
+ return r.regionID.IsCountry()
+}
+
+// IsGroup returns whether this region defines a collection of regions. This
+// includes non-standard definitions from CLDR.
+func (r Region) IsGroup() bool {
+ return r.regionID.IsGroup()
+}
+
+// Contains returns whether Region c is contained by Region r. It returns true
+// if c == r.
+func (r Region) Contains(c Region) bool {
+ return r.regionID.Contains(c.regionID)
+}
+
+// TLD returns the country code top-level domain (ccTLD). UK is returned for GB.
+// In all other cases it returns either the region itself or an error.
+//
+// This method may return an error for a region for which there exists a
+// canonical form with a ccTLD. To get that ccTLD canonicalize r first. The
+// region will already be canonicalized it was obtained from a Tag that was
+// obtained using any of the default methods.
+func (r Region) TLD() (Region, error) {
+ tld, err := r.regionID.TLD()
+ return Region{tld}, err
+}
+
+// Canonicalize returns the region or a possible replacement if the region is
+// deprecated. It will not return a replacement for deprecated regions that
+// are split into multiple regions.
+func (r Region) Canonicalize() Region {
+ return Region{r.regionID.Canonicalize()}
+}
+
+// Variant represents a registered variant of a language as defined by BCP 47.
+type Variant struct {
+ variant string
+}
+
+// ParseVariant parses and returns a Variant. An error is returned if s is not
+// a valid variant.
+func ParseVariant(s string) (Variant, error) {
+ v, err := language.ParseVariant(s)
+ return Variant{v.String()}, err
+}
+
+// String returns the string representation of the variant.
+func (v Variant) String() string {
+ return v.variant
+}
diff --git a/vendor/golang.org/x/text/language/match.go b/vendor/golang.org/x/text/language/match.go
new file mode 100644
index 0000000..1153baf
--- /dev/null
+++ b/vendor/golang.org/x/text/language/match.go
@@ -0,0 +1,735 @@
+// 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 language
+
+import (
+ "errors"
+ "strings"
+
+ "golang.org/x/text/internal/language"
+)
+
+// A MatchOption configures a Matcher.
+type MatchOption func(*matcher)
+
+// PreferSameScript will, in the absence of a match, result in the first
+// preferred tag with the same script as a supported tag to match this supported
+// tag. The default is currently true, but this may change in the future.
+func PreferSameScript(preferSame bool) MatchOption {
+ return func(m *matcher) { m.preferSameScript = preferSame }
+}
+
+// TODO(v1.0.0): consider making Matcher a concrete type, instead of interface.
+// There doesn't seem to be too much need for multiple types.
+// Making it a concrete type allows MatchStrings to be a method, which will
+// improve its discoverability.
+
+// MatchStrings parses and matches the given strings until one of them matches
+// the language in the Matcher. A string may be an Accept-Language header as
+// handled by ParseAcceptLanguage. The default language is returned if no
+// other language matched.
+func MatchStrings(m Matcher, lang ...string) (tag Tag, index int) {
+ for _, accept := range lang {
+ desired, _, err := ParseAcceptLanguage(accept)
+ if err != nil {
+ continue
+ }
+ if tag, index, conf := m.Match(desired...); conf != No {
+ return tag, index
+ }
+ }
+ tag, index, _ = m.Match()
+ return
+}
+
+// Matcher is the interface that wraps the Match method.
+//
+// Match returns the best match for any of the given tags, along with
+// a unique index associated with the returned tag and a confidence
+// score.
+type Matcher interface {
+ Match(t ...Tag) (tag Tag, index int, c Confidence)
+}
+
+// Comprehends reports the confidence score for a speaker of a given language
+// to being able to comprehend the written form of an alternative language.
+func Comprehends(speaker, alternative Tag) Confidence {
+ _, _, c := NewMatcher([]Tag{alternative}).Match(speaker)
+ return c
+}
+
+// NewMatcher returns a Matcher that matches an ordered list of preferred tags
+// against a list of supported tags based on written intelligibility, closeness
+// of dialect, equivalence of subtags and various other rules. It is initialized
+// with the list of supported tags. The first element is used as the default
+// value in case no match is found.
+//
+// Its Match method matches the first of the given Tags to reach a certain
+// confidence threshold. The tags passed to Match should therefore be specified
+// in order of preference. Extensions are ignored for matching.
+//
+// The index returned by the Match method corresponds to the index of the
+// matched tag in t, but is augmented with the Unicode extension ('u')of the
+// corresponding preferred tag. This allows user locale options to be passed
+// transparently.
+func NewMatcher(t []Tag, options ...MatchOption) Matcher {
+ return newMatcher(t, options)
+}
+
+func (m *matcher) Match(want ...Tag) (t Tag, index int, c Confidence) {
+ var tt language.Tag
+ match, w, c := m.getBest(want...)
+ if match != nil {
+ tt, index = match.tag, match.index
+ } else {
+ // TODO: this should be an option
+ tt = m.default_.tag
+ if m.preferSameScript {
+ outer:
+ for _, w := range want {
+ script, _ := w.Script()
+ if script.scriptID == 0 {
+ // Don't do anything if there is no script, such as with
+ // private subtags.
+ continue
+ }
+ for i, h := range m.supported {
+ if script.scriptID == h.maxScript {
+ tt, index = h.tag, i
+ break outer
+ }
+ }
+ }
+ }
+ // TODO: select first language tag based on script.
+ }
+ if w.RegionID != tt.RegionID && w.RegionID != 0 {
+ if w.RegionID != 0 && tt.RegionID != 0 && tt.RegionID.Contains(w.RegionID) {
+ tt.RegionID = w.RegionID
+ tt.RemakeString()
+ } else if r := w.RegionID.String(); len(r) == 2 {
+ // TODO: also filter macro and deprecated.
+ tt, _ = tt.SetTypeForKey("rg", strings.ToLower(r)+"zzzz")
+ }
+ }
+ // Copy options from the user-provided tag into the result tag. This is hard
+ // to do after the fact, so we do it here.
+ // TODO: add in alternative variants to -u-va-.
+ // TODO: add preferred region to -u-rg-.
+ if e := w.Extensions(); len(e) > 0 {
+ b := language.Builder{}
+ b.SetTag(tt)
+ for _, e := range e {
+ b.AddExt(e)
+ }
+ tt = b.Make()
+ }
+ return makeTag(tt), index, c
+}
+
+// ErrMissingLikelyTagsData indicates no information was available
+// to compute likely values of missing tags.
+var ErrMissingLikelyTagsData = errors.New("missing likely tags data")
+
+// func (t *Tag) setTagsFrom(id Tag) {
+// t.LangID = id.LangID
+// t.ScriptID = id.ScriptID
+// t.RegionID = id.RegionID
+// }
+
+// Tag Matching
+// CLDR defines an algorithm for finding the best match between two sets of language
+// tags. The basic algorithm defines how to score a possible match and then find
+// the match with the best score
+// (see https://www.unicode.org/reports/tr35/#LanguageMatching).
+// Using scoring has several disadvantages. The scoring obfuscates the importance of
+// the various factors considered, making the algorithm harder to understand. Using
+// scoring also requires the full score to be computed for each pair of tags.
+//
+// We will use a different algorithm which aims to have the following properties:
+// - clarity on the precedence of the various selection factors, and
+// - improved performance by allowing early termination of a comparison.
+//
+// Matching algorithm (overview)
+// Input:
+// - supported: a set of supported tags
+// - default: the default tag to return in case there is no match
+// - desired: list of desired tags, ordered by preference, starting with
+// the most-preferred.
+//
+// Algorithm:
+// 1) Set the best match to the lowest confidence level
+// 2) For each tag in "desired":
+// a) For each tag in "supported":
+// 1) compute the match between the two tags.
+// 2) if the match is better than the previous best match, replace it
+// with the new match. (see next section)
+// b) if the current best match is Exact and pin is true the result will be
+// frozen to the language found thusfar, although better matches may
+// still be found for the same language.
+// 3) If the best match so far is below a certain threshold, return "default".
+//
+// Ranking:
+// We use two phases to determine whether one pair of tags are a better match
+// than another pair of tags. First, we determine a rough confidence level. If the
+// levels are different, the one with the highest confidence wins.
+// Second, if the rough confidence levels are identical, we use a set of tie-breaker
+// rules.
+//
+// The confidence level of matching a pair of tags is determined by finding the
+// lowest confidence level of any matches of the corresponding subtags (the
+// result is deemed as good as its weakest link).
+// We define the following levels:
+// Exact - An exact match of a subtag, before adding likely subtags.
+// MaxExact - An exact match of a subtag, after adding likely subtags.
+// [See Note 2].
+// High - High level of mutual intelligibility between different subtag
+// variants.
+// Low - Low level of mutual intelligibility between different subtag
+// variants.
+// No - No mutual intelligibility.
+//
+// The following levels can occur for each type of subtag:
+// Base: Exact, MaxExact, High, Low, No
+// Script: Exact, MaxExact [see Note 3], Low, No
+// Region: Exact, MaxExact, High
+// Variant: Exact, High
+// Private: Exact, No
+//
+// Any result with a confidence level of Low or higher is deemed a possible match.
+// Once a desired tag matches any of the supported tags with a level of MaxExact
+// or higher, the next desired tag is not considered (see Step 2.b).
+// Note that CLDR provides languageMatching data that defines close equivalence
+// classes for base languages, scripts and regions.
+//
+// Tie-breaking
+// If we get the same confidence level for two matches, we apply a sequence of
+// tie-breaking rules. The first that succeeds defines the result. The rules are
+// applied in the following order.
+// 1) Original language was defined and was identical.
+// 2) Original region was defined and was identical.
+// 3) Distance between two maximized regions was the smallest.
+// 4) Original script was defined and was identical.
+// 5) Distance from want tag to have tag using the parent relation [see Note 5.]
+// If there is still no winner after these rules are applied, the first match
+// found wins.
+//
+// Notes:
+// [2] In practice, as matching of Exact is done in a separate phase from
+// matching the other levels, we reuse the Exact level to mean MaxExact in
+// the second phase. As a consequence, we only need the levels defined by
+// the Confidence type. The MaxExact confidence level is mapped to High in
+// the public API.
+// [3] We do not differentiate between maximized script values that were derived
+// from suppressScript versus most likely tag data. We determined that in
+// ranking the two, one ranks just after the other. Moreover, the two cannot
+// occur concurrently. As a consequence, they are identical for practical
+// purposes.
+// [4] In case of deprecated, macro-equivalents and legacy mappings, we assign
+// the MaxExact level to allow iw vs he to still be a closer match than
+// en-AU vs en-US, for example.
+// [5] In CLDR a locale inherits fields that are unspecified for this locale
+// from its parent. Therefore, if a locale is a parent of another locale,
+// it is a strong measure for closeness, especially when no other tie
+// breaker rule applies. One could also argue it is inconsistent, for
+// example, when pt-AO matches pt (which CLDR equates with pt-BR), even
+// though its parent is pt-PT according to the inheritance rules.
+//
+// Implementation Details:
+// There are several performance considerations worth pointing out. Most notably,
+// we preprocess as much as possible (within reason) at the time of creation of a
+// matcher. This includes:
+// - creating a per-language map, which includes data for the raw base language
+// and its canonicalized variant (if applicable),
+// - expanding entries for the equivalence classes defined in CLDR's
+// languageMatch data.
+// The per-language map ensures that typically only a very small number of tags
+// need to be considered. The pre-expansion of canonicalized subtags and
+// equivalence classes reduces the amount of map lookups that need to be done at
+// runtime.
+
+// matcher keeps a set of supported language tags, indexed by language.
+type matcher struct {
+ default_ *haveTag
+ supported []*haveTag
+ index map[language.Language]*matchHeader
+ passSettings bool
+ preferSameScript bool
+}
+
+// matchHeader has the lists of tags for exact matches and matches based on
+// maximized and canonicalized tags for a given language.
+type matchHeader struct {
+ haveTags []*haveTag
+ original bool
+}
+
+// haveTag holds a supported Tag and its maximized script and region. The maximized
+// or canonicalized language is not stored as it is not needed during matching.
+type haveTag struct {
+ tag language.Tag
+
+ // index of this tag in the original list of supported tags.
+ index int
+
+ // conf is the maximum confidence that can result from matching this haveTag.
+ // When conf < Exact this means it was inserted after applying a CLDR equivalence rule.
+ conf Confidence
+
+ // Maximized region and script.
+ maxRegion language.Region
+ maxScript language.Script
+
+ // altScript may be checked as an alternative match to maxScript. If altScript
+ // matches, the confidence level for this match is Low. Theoretically there
+ // could be multiple alternative scripts. This does not occur in practice.
+ altScript language.Script
+
+ // nextMax is the index of the next haveTag with the same maximized tags.
+ nextMax uint16
+}
+
+func makeHaveTag(tag language.Tag, index int) (haveTag, language.Language) {
+ max := tag
+ if tag.LangID != 0 || tag.RegionID != 0 || tag.ScriptID != 0 {
+ max, _ = canonicalize(All, max)
+ max, _ = max.Maximize()
+ max.RemakeString()
+ }
+ return haveTag{tag, index, Exact, max.RegionID, max.ScriptID, altScript(max.LangID, max.ScriptID), 0}, max.LangID
+}
+
+// altScript returns an alternative script that may match the given script with
+// a low confidence. At the moment, the langMatch data allows for at most one
+// script to map to another and we rely on this to keep the code simple.
+func altScript(l language.Language, s language.Script) language.Script {
+ for _, alt := range matchScript {
+ // TODO: also match cases where language is not the same.
+ if (language.Language(alt.wantLang) == l || language.Language(alt.haveLang) == l) &&
+ language.Script(alt.haveScript) == s {
+ return language.Script(alt.wantScript)
+ }
+ }
+ return 0
+}
+
+// addIfNew adds a haveTag to the list of tags only if it is a unique tag.
+// Tags that have the same maximized values are linked by index.
+func (h *matchHeader) addIfNew(n haveTag, exact bool) {
+ h.original = h.original || exact
+ // Don't add new exact matches.
+ for _, v := range h.haveTags {
+ if equalsRest(v.tag, n.tag) {
+ return
+ }
+ }
+ // Allow duplicate maximized tags, but create a linked list to allow quickly
+ // comparing the equivalents and bail out.
+ for i, v := range h.haveTags {
+ if v.maxScript == n.maxScript &&
+ v.maxRegion == n.maxRegion &&
+ v.tag.VariantOrPrivateUseTags() == n.tag.VariantOrPrivateUseTags() {
+ for h.haveTags[i].nextMax != 0 {
+ i = int(h.haveTags[i].nextMax)
+ }
+ h.haveTags[i].nextMax = uint16(len(h.haveTags))
+ break
+ }
+ }
+ h.haveTags = append(h.haveTags, &n)
+}
+
+// header returns the matchHeader for the given language. It creates one if
+// it doesn't already exist.
+func (m *matcher) header(l language.Language) *matchHeader {
+ if h := m.index[l]; h != nil {
+ return h
+ }
+ h := &matchHeader{}
+ m.index[l] = h
+ return h
+}
+
+func toConf(d uint8) Confidence {
+ if d <= 10 {
+ return High
+ }
+ if d < 30 {
+ return Low
+ }
+ return No
+}
+
+// newMatcher builds an index for the given supported tags and returns it as
+// a matcher. It also expands the index by considering various equivalence classes
+// for a given tag.
+func newMatcher(supported []Tag, options []MatchOption) *matcher {
+ m := &matcher{
+ index: make(map[language.Language]*matchHeader),
+ preferSameScript: true,
+ }
+ for _, o := range options {
+ o(m)
+ }
+ if len(supported) == 0 {
+ m.default_ = &haveTag{}
+ return m
+ }
+ // Add supported languages to the index. Add exact matches first to give
+ // them precedence.
+ for i, tag := range supported {
+ tt := tag.tag()
+ pair, _ := makeHaveTag(tt, i)
+ m.header(tt.LangID).addIfNew(pair, true)
+ m.supported = append(m.supported, &pair)
+ }
+ m.default_ = m.header(supported[0].lang()).haveTags[0]
+ // Keep these in two different loops to support the case that two equivalent
+ // languages are distinguished, such as iw and he.
+ for i, tag := range supported {
+ tt := tag.tag()
+ pair, max := makeHaveTag(tt, i)
+ if max != tt.LangID {
+ m.header(max).addIfNew(pair, true)
+ }
+ }
+
+ // update is used to add indexes in the map for equivalent languages.
+ // update will only add entries to original indexes, thus not computing any
+ // transitive relations.
+ update := func(want, have uint16, conf Confidence) {
+ if hh := m.index[language.Language(have)]; hh != nil {
+ if !hh.original {
+ return
+ }
+ hw := m.header(language.Language(want))
+ for _, ht := range hh.haveTags {
+ v := *ht
+ if conf < v.conf {
+ v.conf = conf
+ }
+ v.nextMax = 0 // this value needs to be recomputed
+ if v.altScript != 0 {
+ v.altScript = altScript(language.Language(want), v.maxScript)
+ }
+ hw.addIfNew(v, conf == Exact && hh.original)
+ }
+ }
+ }
+
+ // Add entries for languages with mutual intelligibility as defined by CLDR's
+ // languageMatch data.
+ for _, ml := range matchLang {
+ update(ml.want, ml.have, toConf(ml.distance))
+ if !ml.oneway {
+ update(ml.have, ml.want, toConf(ml.distance))
+ }
+ }
+
+ // Add entries for possible canonicalizations. This is an optimization to
+ // ensure that only one map lookup needs to be done at runtime per desired tag.
+ // First we match deprecated equivalents. If they are perfect equivalents
+ // (their canonicalization simply substitutes a different language code, but
+ // nothing else), the match confidence is Exact, otherwise it is High.
+ for i, lm := range language.AliasMap {
+ // If deprecated codes match and there is no fiddling with the script
+ // or region, we consider it an exact match.
+ conf := Exact
+ if language.AliasTypes[i] != language.Macro {
+ if !isExactEquivalent(language.Language(lm.From)) {
+ conf = High
+ }
+ update(lm.To, lm.From, conf)
+ }
+ update(lm.From, lm.To, conf)
+ }
+ return m
+}
+
+// getBest gets the best matching tag in m for any of the given tags, taking into
+// account the order of preference of the given tags.
+func (m *matcher) getBest(want ...Tag) (got *haveTag, orig language.Tag, c Confidence) {
+ best := bestMatch{}
+ for i, ww := range want {
+ w := ww.tag()
+ var max language.Tag
+ // Check for exact match first.
+ h := m.index[w.LangID]
+ if w.LangID != 0 {
+ if h == nil {
+ continue
+ }
+ // Base language is defined.
+ max, _ = canonicalize(Legacy|Deprecated|Macro, w)
+ // A region that is added through canonicalization is stronger than
+ // a maximized region: set it in the original (e.g. mo -> ro-MD).
+ if w.RegionID != max.RegionID {
+ w.RegionID = max.RegionID
+ }
+ // TODO: should we do the same for scripts?
+ // See test case: en, sr, nl ; sh ; sr
+ max, _ = max.Maximize()
+ } else {
+ // Base language is not defined.
+ if h != nil {
+ for i := range h.haveTags {
+ have := h.haveTags[i]
+ if equalsRest(have.tag, w) {
+ return have, w, Exact
+ }
+ }
+ }
+ if w.ScriptID == 0 && w.RegionID == 0 {
+ // We skip all tags matching und for approximate matching, including
+ // private tags.
+ continue
+ }
+ max, _ = w.Maximize()
+ if h = m.index[max.LangID]; h == nil {
+ continue
+ }
+ }
+ pin := true
+ for _, t := range want[i+1:] {
+ if w.LangID == t.lang() {
+ pin = false
+ break
+ }
+ }
+ // Check for match based on maximized tag.
+ for i := range h.haveTags {
+ have := h.haveTags[i]
+ best.update(have, w, max.ScriptID, max.RegionID, pin)
+ if best.conf == Exact {
+ for have.nextMax != 0 {
+ have = h.haveTags[have.nextMax]
+ best.update(have, w, max.ScriptID, max.RegionID, pin)
+ }
+ return best.have, best.want, best.conf
+ }
+ }
+ }
+ if best.conf <= No {
+ if len(want) != 0 {
+ return nil, want[0].tag(), No
+ }
+ return nil, language.Tag{}, No
+ }
+ return best.have, best.want, best.conf
+}
+
+// bestMatch accumulates the best match so far.
+type bestMatch struct {
+ have *haveTag
+ want language.Tag
+ conf Confidence
+ pinnedRegion language.Region
+ pinLanguage bool
+ sameRegionGroup bool
+ // Cached results from applying tie-breaking rules.
+ origLang bool
+ origReg bool
+ paradigmReg bool
+ regGroupDist uint8
+ origScript bool
+}
+
+// update updates the existing best match if the new pair is considered to be a
+// better match. To determine if the given pair is a better match, it first
+// computes the rough confidence level. If this surpasses the current match, it
+// will replace it and update the tie-breaker rule cache. If there is a tie, it
+// proceeds with applying a series of tie-breaker rules. If there is no
+// conclusive winner after applying the tie-breaker rules, it leaves the current
+// match as the preferred match.
+//
+// If pin is true and have and tag are a strong match, it will henceforth only
+// consider matches for this language. This corresponds to the idea that most
+// users have a strong preference for the first defined language. A user can
+// still prefer a second language over a dialect of the preferred language by
+// explicitly specifying dialects, e.g. "en, nl, en-GB". In this case pin should
+// be false.
+func (m *bestMatch) update(have *haveTag, tag language.Tag, maxScript language.Script, maxRegion language.Region, pin bool) {
+ // Bail if the maximum attainable confidence is below that of the current best match.
+ c := have.conf
+ if c < m.conf {
+ return
+ }
+ // Don't change the language once we already have found an exact match.
+ if m.pinLanguage && tag.LangID != m.want.LangID {
+ return
+ }
+ // Pin the region group if we are comparing tags for the same language.
+ if tag.LangID == m.want.LangID && m.sameRegionGroup {
+ _, sameGroup := regionGroupDist(m.pinnedRegion, have.maxRegion, have.maxScript, m.want.LangID)
+ if !sameGroup {
+ return
+ }
+ }
+ if c == Exact && have.maxScript == maxScript {
+ // If there is another language and then another entry of this language,
+ // don't pin anything, otherwise pin the language.
+ m.pinLanguage = pin
+ }
+ if equalsRest(have.tag, tag) {
+ } else if have.maxScript != maxScript {
+ // There is usually very little comprehension between different scripts.
+ // In a few cases there may still be Low comprehension. This possibility
+ // is pre-computed and stored in have.altScript.
+ if Low < m.conf || have.altScript != maxScript {
+ return
+ }
+ c = Low
+ } else if have.maxRegion != maxRegion {
+ if High < c {
+ // There is usually a small difference between languages across regions.
+ c = High
+ }
+ }
+
+ // We store the results of the computations of the tie-breaker rules along
+ // with the best match. There is no need to do the checks once we determine
+ // we have a winner, but we do still need to do the tie-breaker computations.
+ // We use "beaten" to keep track if we still need to do the checks.
+ beaten := false // true if the new pair defeats the current one.
+ if c != m.conf {
+ if c < m.conf {
+ return
+ }
+ beaten = true
+ }
+
+ // Tie-breaker rules:
+ // We prefer if the pre-maximized language was specified and identical.
+ origLang := have.tag.LangID == tag.LangID && tag.LangID != 0
+ if !beaten && m.origLang != origLang {
+ if m.origLang {
+ return
+ }
+ beaten = true
+ }
+
+ // We prefer if the pre-maximized region was specified and identical.
+ origReg := have.tag.RegionID == tag.RegionID && tag.RegionID != 0
+ if !beaten && m.origReg != origReg {
+ if m.origReg {
+ return
+ }
+ beaten = true
+ }
+
+ regGroupDist, sameGroup := regionGroupDist(have.maxRegion, maxRegion, maxScript, tag.LangID)
+ if !beaten && m.regGroupDist != regGroupDist {
+ if regGroupDist > m.regGroupDist {
+ return
+ }
+ beaten = true
+ }
+
+ paradigmReg := isParadigmLocale(tag.LangID, have.maxRegion)
+ if !beaten && m.paradigmReg != paradigmReg {
+ if !paradigmReg {
+ return
+ }
+ beaten = true
+ }
+
+ // Next we prefer if the pre-maximized script was specified and identical.
+ origScript := have.tag.ScriptID == tag.ScriptID && tag.ScriptID != 0
+ if !beaten && m.origScript != origScript {
+ if m.origScript {
+ return
+ }
+ beaten = true
+ }
+
+ // Update m to the newly found best match.
+ if beaten {
+ m.have = have
+ m.want = tag
+ m.conf = c
+ m.pinnedRegion = maxRegion
+ m.sameRegionGroup = sameGroup
+ m.origLang = origLang
+ m.origReg = origReg
+ m.paradigmReg = paradigmReg
+ m.origScript = origScript
+ m.regGroupDist = regGroupDist
+ }
+}
+
+func isParadigmLocale(lang language.Language, r language.Region) bool {
+ for _, e := range paradigmLocales {
+ if language.Language(e[0]) == lang && (r == language.Region(e[1]) || r == language.Region(e[2])) {
+ return true
+ }
+ }
+ return false
+}
+
+// regionGroupDist computes the distance between two regions based on their
+// CLDR grouping.
+func regionGroupDist(a, b language.Region, script language.Script, lang language.Language) (dist uint8, same bool) {
+ const defaultDistance = 4
+
+ aGroup := uint(regionToGroups[a]) << 1
+ bGroup := uint(regionToGroups[b]) << 1
+ for _, ri := range matchRegion {
+ if language.Language(ri.lang) == lang && (ri.script == 0 || language.Script(ri.script) == script) {
+ group := uint(1 << (ri.group &^ 0x80))
+ if 0x80&ri.group == 0 {
+ if aGroup&bGroup&group != 0 { // Both regions are in the group.
+ return ri.distance, ri.distance == defaultDistance
+ }
+ } else {
+ if (aGroup|bGroup)&group == 0 { // Both regions are not in the group.
+ return ri.distance, ri.distance == defaultDistance
+ }
+ }
+ }
+ }
+ return defaultDistance, true
+}
+
+// equalsRest compares everything except the language.
+func equalsRest(a, b language.Tag) bool {
+ // TODO: don't include extensions in this comparison. To do this efficiently,
+ // though, we should handle private tags separately.
+ return a.ScriptID == b.ScriptID && a.RegionID == b.RegionID && a.VariantOrPrivateUseTags() == b.VariantOrPrivateUseTags()
+}
+
+// isExactEquivalent returns true if canonicalizing the language will not alter
+// the script or region of a tag.
+func isExactEquivalent(l language.Language) bool {
+ for _, o := range notEquivalent {
+ if o == l {
+ return false
+ }
+ }
+ return true
+}
+
+var notEquivalent []language.Language
+
+func init() {
+ // Create a list of all languages for which canonicalization may alter the
+ // script or region.
+ for _, lm := range language.AliasMap {
+ tag := language.Tag{LangID: language.Language(lm.From)}
+ if tag, _ = canonicalize(All, tag); tag.ScriptID != 0 || tag.RegionID != 0 {
+ notEquivalent = append(notEquivalent, language.Language(lm.From))
+ }
+ }
+ // Maximize undefined regions of paradigm locales.
+ for i, v := range paradigmLocales {
+ t := language.Tag{LangID: language.Language(v[0])}
+ max, _ := t.Maximize()
+ if v[1] == 0 {
+ paradigmLocales[i][1] = uint16(max.RegionID)
+ }
+ if v[2] == 0 {
+ paradigmLocales[i][2] = uint16(max.RegionID)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/text/language/parse.go b/vendor/golang.org/x/text/language/parse.go
new file mode 100644
index 0000000..4d57222
--- /dev/null
+++ b/vendor/golang.org/x/text/language/parse.go
@@ -0,0 +1,256 @@
+// 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 language
+
+import (
+ "errors"
+ "sort"
+ "strconv"
+ "strings"
+
+ "golang.org/x/text/internal/language"
+)
+
+// ValueError is returned by any of the parsing functions when the
+// input is well-formed but the respective subtag is not recognized
+// as a valid value.
+type ValueError interface {
+ error
+
+ // Subtag returns the subtag for which the error occurred.
+ Subtag() string
+}
+
+// Parse parses the given BCP 47 string and returns a valid Tag. If parsing
+// failed it returns an error and any part of the tag that could be parsed.
+// If parsing succeeded but an unknown value was found, it returns
+// ValueError. The Tag returned in this case is just stripped of the unknown
+// value. All other values are preserved. It accepts tags in the BCP 47 format
+// and extensions to this standard defined in
+// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers.
+// The resulting tag is canonicalized using the default canonicalization type.
+func Parse(s string) (t Tag, err error) {
+ return Default.Parse(s)
+}
+
+// Parse parses the given BCP 47 string and returns a valid Tag. If parsing
+// failed it returns an error and any part of the tag that could be parsed.
+// If parsing succeeded but an unknown value was found, it returns
+// ValueError. The Tag returned in this case is just stripped of the unknown
+// value. All other values are preserved. It accepts tags in the BCP 47 format
+// and extensions to this standard defined in
+// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers.
+// The resulting tag is canonicalized using the canonicalization type c.
+func (c CanonType) Parse(s string) (t Tag, err error) {
+ defer func() {
+ if recover() != nil {
+ t = Tag{}
+ err = language.ErrSyntax
+ }
+ }()
+
+ tt, err := language.Parse(s)
+ if err != nil {
+ return makeTag(tt), err
+ }
+ tt, changed := canonicalize(c, tt)
+ if changed {
+ tt.RemakeString()
+ }
+ return makeTag(tt), err
+}
+
+// Compose creates a Tag from individual parts, which may be of type Tag, Base,
+// Script, Region, Variant, []Variant, Extension, []Extension or error. If a
+// Base, Script or Region or slice of type Variant or Extension is passed more
+// than once, the latter will overwrite the former. Variants and Extensions are
+// accumulated, but if two extensions of the same type are passed, the latter
+// will replace the former. For -u extensions, though, the key-type pairs are
+// added, where later values overwrite older ones. A Tag overwrites all former
+// values and typically only makes sense as the first argument. The resulting
+// tag is returned after canonicalizing using the Default CanonType. If one or
+// more errors are encountered, one of the errors is returned.
+func Compose(part ...interface{}) (t Tag, err error) {
+ return Default.Compose(part...)
+}
+
+// Compose creates a Tag from individual parts, which may be of type Tag, Base,
+// Script, Region, Variant, []Variant, Extension, []Extension or error. If a
+// Base, Script or Region or slice of type Variant or Extension is passed more
+// than once, the latter will overwrite the former. Variants and Extensions are
+// accumulated, but if two extensions of the same type are passed, the latter
+// will replace the former. For -u extensions, though, the key-type pairs are
+// added, where later values overwrite older ones. A Tag overwrites all former
+// values and typically only makes sense as the first argument. The resulting
+// tag is returned after canonicalizing using CanonType c. If one or more errors
+// are encountered, one of the errors is returned.
+func (c CanonType) Compose(part ...interface{}) (t Tag, err error) {
+ defer func() {
+ if recover() != nil {
+ t = Tag{}
+ err = language.ErrSyntax
+ }
+ }()
+
+ var b language.Builder
+ if err = update(&b, part...); err != nil {
+ return und, err
+ }
+ b.Tag, _ = canonicalize(c, b.Tag)
+ return makeTag(b.Make()), err
+}
+
+var errInvalidArgument = errors.New("invalid Extension or Variant")
+
+func update(b *language.Builder, part ...interface{}) (err error) {
+ for _, x := range part {
+ switch v := x.(type) {
+ case Tag:
+ b.SetTag(v.tag())
+ case Base:
+ b.Tag.LangID = v.langID
+ case Script:
+ b.Tag.ScriptID = v.scriptID
+ case Region:
+ b.Tag.RegionID = v.regionID
+ case Variant:
+ if v.variant == "" {
+ err = errInvalidArgument
+ break
+ }
+ b.AddVariant(v.variant)
+ case Extension:
+ if v.s == "" {
+ err = errInvalidArgument
+ break
+ }
+ b.SetExt(v.s)
+ case []Variant:
+ b.ClearVariants()
+ for _, v := range v {
+ b.AddVariant(v.variant)
+ }
+ case []Extension:
+ b.ClearExtensions()
+ for _, e := range v {
+ b.SetExt(e.s)
+ }
+ // TODO: support parsing of raw strings based on morphology or just extensions?
+ case error:
+ if v != nil {
+ err = v
+ }
+ }
+ }
+ return
+}
+
+var errInvalidWeight = errors.New("ParseAcceptLanguage: invalid weight")
+var errTagListTooLarge = errors.New("tag list exceeds max length")
+
+// ParseAcceptLanguage parses the contents of an Accept-Language header as
+// defined in http://www.ietf.org/rfc/rfc2616.txt and returns a list of Tags and
+// a list of corresponding quality weights. It is more permissive than RFC 2616
+// and may return non-nil slices even if the input is not valid.
+// The Tags will be sorted by highest weight first and then by first occurrence.
+// Tags with a weight of zero will be dropped. An error will be returned if the
+// input could not be parsed.
+func ParseAcceptLanguage(s string) (tag []Tag, q []float32, err error) {
+ defer func() {
+ if recover() != nil {
+ tag = nil
+ q = nil
+ err = language.ErrSyntax
+ }
+ }()
+
+ if strings.Count(s, "-") > 1000 {
+ return nil, nil, errTagListTooLarge
+ }
+
+ var entry string
+ for s != "" {
+ if entry, s = split(s, ','); entry == "" {
+ continue
+ }
+
+ entry, weight := split(entry, ';')
+
+ // Scan the language.
+ t, err := Parse(entry)
+ if err != nil {
+ id, ok := acceptFallback[entry]
+ if !ok {
+ return nil, nil, err
+ }
+ t = makeTag(language.Tag{LangID: id})
+ }
+
+ // Scan the optional weight.
+ w := 1.0
+ if weight != "" {
+ weight = consume(weight, 'q')
+ weight = consume(weight, '=')
+ // consume returns the empty string when a token could not be
+ // consumed, resulting in an error for ParseFloat.
+ if w, err = strconv.ParseFloat(weight, 32); err != nil {
+ return nil, nil, errInvalidWeight
+ }
+ // Drop tags with a quality weight of 0.
+ if w <= 0 {
+ continue
+ }
+ }
+
+ tag = append(tag, t)
+ q = append(q, float32(w))
+ }
+ sort.Stable(&tagSort{tag, q})
+ return tag, q, nil
+}
+
+// consume removes a leading token c from s and returns the result or the empty
+// string if there is no such token.
+func consume(s string, c byte) string {
+ if s == "" || s[0] != c {
+ return ""
+ }
+ return strings.TrimSpace(s[1:])
+}
+
+func split(s string, c byte) (head, tail string) {
+ if i := strings.IndexByte(s, c); i >= 0 {
+ return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+1:])
+ }
+ return strings.TrimSpace(s), ""
+}
+
+// Add hack mapping to deal with a small number of cases that occur
+// in Accept-Language (with reasonable frequency).
+var acceptFallback = map[string]language.Language{
+ "english": _en,
+ "deutsch": _de,
+ "italian": _it,
+ "french": _fr,
+ "*": _mul, // defined in the spec to match all languages.
+}
+
+type tagSort struct {
+ tag []Tag
+ q []float32
+}
+
+func (s *tagSort) Len() int {
+ return len(s.q)
+}
+
+func (s *tagSort) Less(i, j int) bool {
+ return s.q[i] > s.q[j]
+}
+
+func (s *tagSort) Swap(i, j int) {
+ s.tag[i], s.tag[j] = s.tag[j], s.tag[i]
+ s.q[i], s.q[j] = s.q[j], s.q[i]
+}
diff --git a/vendor/golang.org/x/text/language/tables.go b/vendor/golang.org/x/text/language/tables.go
new file mode 100644
index 0000000..a6573dc
--- /dev/null
+++ b/vendor/golang.org/x/text/language/tables.go
@@ -0,0 +1,298 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package language
+
+// CLDRVersion is the CLDR version from which the tables in this package are derived.
+const CLDRVersion = "32"
+
+const (
+ _de = 269
+ _en = 313
+ _fr = 350
+ _it = 505
+ _mo = 784
+ _no = 879
+ _nb = 839
+ _pt = 960
+ _sh = 1031
+ _mul = 806
+ _und = 0
+)
+const (
+ _001 = 1
+ _419 = 31
+ _BR = 65
+ _CA = 73
+ _ES = 111
+ _GB = 124
+ _MD = 189
+ _PT = 239
+ _UK = 307
+ _US = 310
+ _ZZ = 358
+ _XA = 324
+ _XC = 326
+ _XK = 334
+)
+const (
+ _Latn = 91
+ _Hani = 57
+ _Hans = 59
+ _Hant = 60
+ _Qaaa = 149
+ _Qaai = 157
+ _Qabx = 198
+ _Zinh = 255
+ _Zyyy = 260
+ _Zzzz = 261
+)
+
+var regionToGroups = []uint8{ // 359 elements
+ // Entry 0 - 3F
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x04,
+ // Entry 40 - 7F
+ 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04,
+ // Entry 80 - BF
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x04, 0x01, 0x00, 0x04, 0x02, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x04,
+ // Entry C0 - FF
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x01, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Entry 100 - 13F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x04,
+ 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x05, 0x00,
+ // Entry 140 - 17F
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+} // Size: 383 bytes
+
+var paradigmLocales = [][3]uint16{ // 3 elements
+ 0: [3]uint16{0x139, 0x0, 0x7c},
+ 1: [3]uint16{0x13e, 0x0, 0x1f},
+ 2: [3]uint16{0x3c0, 0x41, 0xef},
+} // Size: 42 bytes
+
+type mutualIntelligibility struct {
+ want uint16
+ have uint16
+ distance uint8
+ oneway bool
+}
+type scriptIntelligibility struct {
+ wantLang uint16
+ haveLang uint16
+ wantScript uint8
+ haveScript uint8
+ distance uint8
+}
+type regionIntelligibility struct {
+ lang uint16
+ script uint8
+ group uint8
+ distance uint8
+}
+
+// matchLang holds pairs of langIDs of base languages that are typically
+// mutually intelligible. Each pair is associated with a confidence and
+// whether the intelligibility goes one or both ways.
+var matchLang = []mutualIntelligibility{ // 113 elements
+ 0: {want: 0x1d1, have: 0xb7, distance: 0x4, oneway: false},
+ 1: {want: 0x407, have: 0xb7, distance: 0x4, oneway: false},
+ 2: {want: 0x407, have: 0x1d1, distance: 0x4, oneway: false},
+ 3: {want: 0x407, have: 0x432, distance: 0x4, oneway: false},
+ 4: {want: 0x43a, have: 0x1, distance: 0x4, oneway: false},
+ 5: {want: 0x1a3, have: 0x10d, distance: 0x4, oneway: true},
+ 6: {want: 0x295, have: 0x10d, distance: 0x4, oneway: true},
+ 7: {want: 0x101, have: 0x36f, distance: 0x8, oneway: false},
+ 8: {want: 0x101, have: 0x347, distance: 0x8, oneway: false},
+ 9: {want: 0x5, have: 0x3e2, distance: 0xa, oneway: true},
+ 10: {want: 0xd, have: 0x139, distance: 0xa, oneway: true},
+ 11: {want: 0x16, have: 0x367, distance: 0xa, oneway: true},
+ 12: {want: 0x21, have: 0x139, distance: 0xa, oneway: true},
+ 13: {want: 0x56, have: 0x13e, distance: 0xa, oneway: true},
+ 14: {want: 0x58, have: 0x3e2, distance: 0xa, oneway: true},
+ 15: {want: 0x71, have: 0x3e2, distance: 0xa, oneway: true},
+ 16: {want: 0x75, have: 0x139, distance: 0xa, oneway: true},
+ 17: {want: 0x82, have: 0x1be, distance: 0xa, oneway: true},
+ 18: {want: 0xa5, have: 0x139, distance: 0xa, oneway: true},
+ 19: {want: 0xb2, have: 0x15e, distance: 0xa, oneway: true},
+ 20: {want: 0xdd, have: 0x153, distance: 0xa, oneway: true},
+ 21: {want: 0xe5, have: 0x139, distance: 0xa, oneway: true},
+ 22: {want: 0xe9, have: 0x3a, distance: 0xa, oneway: true},
+ 23: {want: 0xf0, have: 0x15e, distance: 0xa, oneway: true},
+ 24: {want: 0xf9, have: 0x15e, distance: 0xa, oneway: true},
+ 25: {want: 0x100, have: 0x139, distance: 0xa, oneway: true},
+ 26: {want: 0x130, have: 0x139, distance: 0xa, oneway: true},
+ 27: {want: 0x13c, have: 0x139, distance: 0xa, oneway: true},
+ 28: {want: 0x140, have: 0x151, distance: 0xa, oneway: true},
+ 29: {want: 0x145, have: 0x13e, distance: 0xa, oneway: true},
+ 30: {want: 0x158, have: 0x101, distance: 0xa, oneway: true},
+ 31: {want: 0x16d, have: 0x367, distance: 0xa, oneway: true},
+ 32: {want: 0x16e, have: 0x139, distance: 0xa, oneway: true},
+ 33: {want: 0x16f, have: 0x139, distance: 0xa, oneway: true},
+ 34: {want: 0x17e, have: 0x139, distance: 0xa, oneway: true},
+ 35: {want: 0x190, have: 0x13e, distance: 0xa, oneway: true},
+ 36: {want: 0x194, have: 0x13e, distance: 0xa, oneway: true},
+ 37: {want: 0x1a4, have: 0x1be, distance: 0xa, oneway: true},
+ 38: {want: 0x1b4, have: 0x139, distance: 0xa, oneway: true},
+ 39: {want: 0x1b8, have: 0x139, distance: 0xa, oneway: true},
+ 40: {want: 0x1d4, have: 0x15e, distance: 0xa, oneway: true},
+ 41: {want: 0x1d7, have: 0x3e2, distance: 0xa, oneway: true},
+ 42: {want: 0x1d9, have: 0x139, distance: 0xa, oneway: true},
+ 43: {want: 0x1e7, have: 0x139, distance: 0xa, oneway: true},
+ 44: {want: 0x1f8, have: 0x139, distance: 0xa, oneway: true},
+ 45: {want: 0x20e, have: 0x1e1, distance: 0xa, oneway: true},
+ 46: {want: 0x210, have: 0x139, distance: 0xa, oneway: true},
+ 47: {want: 0x22d, have: 0x15e, distance: 0xa, oneway: true},
+ 48: {want: 0x242, have: 0x3e2, distance: 0xa, oneway: true},
+ 49: {want: 0x24a, have: 0x139, distance: 0xa, oneway: true},
+ 50: {want: 0x251, have: 0x139, distance: 0xa, oneway: true},
+ 51: {want: 0x265, have: 0x139, distance: 0xa, oneway: true},
+ 52: {want: 0x274, have: 0x48a, distance: 0xa, oneway: true},
+ 53: {want: 0x28a, have: 0x3e2, distance: 0xa, oneway: true},
+ 54: {want: 0x28e, have: 0x1f9, distance: 0xa, oneway: true},
+ 55: {want: 0x2a3, have: 0x139, distance: 0xa, oneway: true},
+ 56: {want: 0x2b5, have: 0x15e, distance: 0xa, oneway: true},
+ 57: {want: 0x2b8, have: 0x139, distance: 0xa, oneway: true},
+ 58: {want: 0x2be, have: 0x139, distance: 0xa, oneway: true},
+ 59: {want: 0x2c3, have: 0x15e, distance: 0xa, oneway: true},
+ 60: {want: 0x2ed, have: 0x139, distance: 0xa, oneway: true},
+ 61: {want: 0x2f1, have: 0x15e, distance: 0xa, oneway: true},
+ 62: {want: 0x2fa, have: 0x139, distance: 0xa, oneway: true},
+ 63: {want: 0x2ff, have: 0x7e, distance: 0xa, oneway: true},
+ 64: {want: 0x304, have: 0x139, distance: 0xa, oneway: true},
+ 65: {want: 0x30b, have: 0x3e2, distance: 0xa, oneway: true},
+ 66: {want: 0x31b, have: 0x1be, distance: 0xa, oneway: true},
+ 67: {want: 0x31f, have: 0x1e1, distance: 0xa, oneway: true},
+ 68: {want: 0x320, have: 0x139, distance: 0xa, oneway: true},
+ 69: {want: 0x331, have: 0x139, distance: 0xa, oneway: true},
+ 70: {want: 0x351, have: 0x139, distance: 0xa, oneway: true},
+ 71: {want: 0x36a, have: 0x347, distance: 0xa, oneway: false},
+ 72: {want: 0x36a, have: 0x36f, distance: 0xa, oneway: true},
+ 73: {want: 0x37a, have: 0x139, distance: 0xa, oneway: true},
+ 74: {want: 0x387, have: 0x139, distance: 0xa, oneway: true},
+ 75: {want: 0x389, have: 0x139, distance: 0xa, oneway: true},
+ 76: {want: 0x38b, have: 0x15e, distance: 0xa, oneway: true},
+ 77: {want: 0x390, have: 0x139, distance: 0xa, oneway: true},
+ 78: {want: 0x395, have: 0x139, distance: 0xa, oneway: true},
+ 79: {want: 0x39d, have: 0x139, distance: 0xa, oneway: true},
+ 80: {want: 0x3a5, have: 0x139, distance: 0xa, oneway: true},
+ 81: {want: 0x3be, have: 0x139, distance: 0xa, oneway: true},
+ 82: {want: 0x3c4, have: 0x13e, distance: 0xa, oneway: true},
+ 83: {want: 0x3d4, have: 0x10d, distance: 0xa, oneway: true},
+ 84: {want: 0x3d9, have: 0x139, distance: 0xa, oneway: true},
+ 85: {want: 0x3e5, have: 0x15e, distance: 0xa, oneway: true},
+ 86: {want: 0x3e9, have: 0x1be, distance: 0xa, oneway: true},
+ 87: {want: 0x3fa, have: 0x139, distance: 0xa, oneway: true},
+ 88: {want: 0x40c, have: 0x139, distance: 0xa, oneway: true},
+ 89: {want: 0x423, have: 0x139, distance: 0xa, oneway: true},
+ 90: {want: 0x429, have: 0x139, distance: 0xa, oneway: true},
+ 91: {want: 0x431, have: 0x139, distance: 0xa, oneway: true},
+ 92: {want: 0x43b, have: 0x139, distance: 0xa, oneway: true},
+ 93: {want: 0x43e, have: 0x1e1, distance: 0xa, oneway: true},
+ 94: {want: 0x445, have: 0x139, distance: 0xa, oneway: true},
+ 95: {want: 0x450, have: 0x139, distance: 0xa, oneway: true},
+ 96: {want: 0x461, have: 0x139, distance: 0xa, oneway: true},
+ 97: {want: 0x467, have: 0x3e2, distance: 0xa, oneway: true},
+ 98: {want: 0x46f, have: 0x139, distance: 0xa, oneway: true},
+ 99: {want: 0x476, have: 0x3e2, distance: 0xa, oneway: true},
+ 100: {want: 0x3883, have: 0x139, distance: 0xa, oneway: true},
+ 101: {want: 0x480, have: 0x139, distance: 0xa, oneway: true},
+ 102: {want: 0x482, have: 0x139, distance: 0xa, oneway: true},
+ 103: {want: 0x494, have: 0x3e2, distance: 0xa, oneway: true},
+ 104: {want: 0x49d, have: 0x139, distance: 0xa, oneway: true},
+ 105: {want: 0x4ac, have: 0x529, distance: 0xa, oneway: true},
+ 106: {want: 0x4b4, have: 0x139, distance: 0xa, oneway: true},
+ 107: {want: 0x4bc, have: 0x3e2, distance: 0xa, oneway: true},
+ 108: {want: 0x4e5, have: 0x15e, distance: 0xa, oneway: true},
+ 109: {want: 0x4f2, have: 0x139, distance: 0xa, oneway: true},
+ 110: {want: 0x512, have: 0x139, distance: 0xa, oneway: true},
+ 111: {want: 0x518, have: 0x139, distance: 0xa, oneway: true},
+ 112: {want: 0x52f, have: 0x139, distance: 0xa, oneway: true},
+} // Size: 702 bytes
+
+// matchScript holds pairs of scriptIDs where readers of one script
+// can typically also read the other. Each is associated with a confidence.
+var matchScript = []scriptIntelligibility{ // 26 elements
+ 0: {wantLang: 0x432, haveLang: 0x432, wantScript: 0x5b, haveScript: 0x20, distance: 0x5},
+ 1: {wantLang: 0x432, haveLang: 0x432, wantScript: 0x20, haveScript: 0x5b, distance: 0x5},
+ 2: {wantLang: 0x58, haveLang: 0x3e2, wantScript: 0x5b, haveScript: 0x20, distance: 0xa},
+ 3: {wantLang: 0xa5, haveLang: 0x139, wantScript: 0xe, haveScript: 0x5b, distance: 0xa},
+ 4: {wantLang: 0x1d7, haveLang: 0x3e2, wantScript: 0x8, haveScript: 0x20, distance: 0xa},
+ 5: {wantLang: 0x210, haveLang: 0x139, wantScript: 0x2e, haveScript: 0x5b, distance: 0xa},
+ 6: {wantLang: 0x24a, haveLang: 0x139, wantScript: 0x4f, haveScript: 0x5b, distance: 0xa},
+ 7: {wantLang: 0x251, haveLang: 0x139, wantScript: 0x53, haveScript: 0x5b, distance: 0xa},
+ 8: {wantLang: 0x2b8, haveLang: 0x139, wantScript: 0x58, haveScript: 0x5b, distance: 0xa},
+ 9: {wantLang: 0x304, haveLang: 0x139, wantScript: 0x6f, haveScript: 0x5b, distance: 0xa},
+ 10: {wantLang: 0x331, haveLang: 0x139, wantScript: 0x76, haveScript: 0x5b, distance: 0xa},
+ 11: {wantLang: 0x351, haveLang: 0x139, wantScript: 0x22, haveScript: 0x5b, distance: 0xa},
+ 12: {wantLang: 0x395, haveLang: 0x139, wantScript: 0x83, haveScript: 0x5b, distance: 0xa},
+ 13: {wantLang: 0x39d, haveLang: 0x139, wantScript: 0x36, haveScript: 0x5b, distance: 0xa},
+ 14: {wantLang: 0x3be, haveLang: 0x139, wantScript: 0x5, haveScript: 0x5b, distance: 0xa},
+ 15: {wantLang: 0x3fa, haveLang: 0x139, wantScript: 0x5, haveScript: 0x5b, distance: 0xa},
+ 16: {wantLang: 0x40c, haveLang: 0x139, wantScript: 0xd6, haveScript: 0x5b, distance: 0xa},
+ 17: {wantLang: 0x450, haveLang: 0x139, wantScript: 0xe6, haveScript: 0x5b, distance: 0xa},
+ 18: {wantLang: 0x461, haveLang: 0x139, wantScript: 0xe9, haveScript: 0x5b, distance: 0xa},
+ 19: {wantLang: 0x46f, haveLang: 0x139, wantScript: 0x2c, haveScript: 0x5b, distance: 0xa},
+ 20: {wantLang: 0x476, haveLang: 0x3e2, wantScript: 0x5b, haveScript: 0x20, distance: 0xa},
+ 21: {wantLang: 0x4b4, haveLang: 0x139, wantScript: 0x5, haveScript: 0x5b, distance: 0xa},
+ 22: {wantLang: 0x4bc, haveLang: 0x3e2, wantScript: 0x5b, haveScript: 0x20, distance: 0xa},
+ 23: {wantLang: 0x512, haveLang: 0x139, wantScript: 0x3e, haveScript: 0x5b, distance: 0xa},
+ 24: {wantLang: 0x529, haveLang: 0x529, wantScript: 0x3b, haveScript: 0x3c, distance: 0xf},
+ 25: {wantLang: 0x529, haveLang: 0x529, wantScript: 0x3c, haveScript: 0x3b, distance: 0x13},
+} // Size: 232 bytes
+
+var matchRegion = []regionIntelligibility{ // 15 elements
+ 0: {lang: 0x3a, script: 0x0, group: 0x4, distance: 0x4},
+ 1: {lang: 0x3a, script: 0x0, group: 0x84, distance: 0x4},
+ 2: {lang: 0x139, script: 0x0, group: 0x1, distance: 0x4},
+ 3: {lang: 0x139, script: 0x0, group: 0x81, distance: 0x4},
+ 4: {lang: 0x13e, script: 0x0, group: 0x3, distance: 0x4},
+ 5: {lang: 0x13e, script: 0x0, group: 0x83, distance: 0x4},
+ 6: {lang: 0x3c0, script: 0x0, group: 0x3, distance: 0x4},
+ 7: {lang: 0x3c0, script: 0x0, group: 0x83, distance: 0x4},
+ 8: {lang: 0x529, script: 0x3c, group: 0x2, distance: 0x4},
+ 9: {lang: 0x529, script: 0x3c, group: 0x82, distance: 0x4},
+ 10: {lang: 0x3a, script: 0x0, group: 0x80, distance: 0x5},
+ 11: {lang: 0x139, script: 0x0, group: 0x80, distance: 0x5},
+ 12: {lang: 0x13e, script: 0x0, group: 0x80, distance: 0x5},
+ 13: {lang: 0x3c0, script: 0x0, group: 0x80, distance: 0x5},
+ 14: {lang: 0x529, script: 0x3c, group: 0x80, distance: 0x5},
+} // Size: 114 bytes
+
+// Total table size 1473 bytes (1KiB); checksum: 7BB90B5C
diff --git a/vendor/golang.org/x/text/language/tags.go b/vendor/golang.org/x/text/language/tags.go
new file mode 100644
index 0000000..42ea792
--- /dev/null
+++ b/vendor/golang.org/x/text/language/tags.go
@@ -0,0 +1,145 @@
+// 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 language
+
+import "golang.org/x/text/internal/language/compact"
+
+// TODO: Various sets of commonly use tags and regions.
+
+// MustParse is like Parse, but panics if the given BCP 47 tag cannot be parsed.
+// It simplifies safe initialization of Tag values.
+func MustParse(s string) Tag {
+ t, err := Parse(s)
+ if err != nil {
+ panic(err)
+ }
+ return t
+}
+
+// MustParse is like Parse, but panics if the given BCP 47 tag cannot be parsed.
+// It simplifies safe initialization of Tag values.
+func (c CanonType) MustParse(s string) Tag {
+ t, err := c.Parse(s)
+ if err != nil {
+ panic(err)
+ }
+ return t
+}
+
+// MustParseBase is like ParseBase, but panics if the given base cannot be parsed.
+// It simplifies safe initialization of Base values.
+func MustParseBase(s string) Base {
+ b, err := ParseBase(s)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
+
+// MustParseScript is like ParseScript, but panics if the given script cannot be
+// parsed. It simplifies safe initialization of Script values.
+func MustParseScript(s string) Script {
+ scr, err := ParseScript(s)
+ if err != nil {
+ panic(err)
+ }
+ return scr
+}
+
+// MustParseRegion is like ParseRegion, but panics if the given region cannot be
+// parsed. It simplifies safe initialization of Region values.
+func MustParseRegion(s string) Region {
+ r, err := ParseRegion(s)
+ if err != nil {
+ panic(err)
+ }
+ return r
+}
+
+var (
+ und = Tag{}
+
+ Und Tag = Tag{}
+
+ Afrikaans Tag = Tag(compact.Afrikaans)
+ Amharic Tag = Tag(compact.Amharic)
+ Arabic Tag = Tag(compact.Arabic)
+ ModernStandardArabic Tag = Tag(compact.ModernStandardArabic)
+ Azerbaijani Tag = Tag(compact.Azerbaijani)
+ Bulgarian Tag = Tag(compact.Bulgarian)
+ Bengali Tag = Tag(compact.Bengali)
+ Catalan Tag = Tag(compact.Catalan)
+ Czech Tag = Tag(compact.Czech)
+ Danish Tag = Tag(compact.Danish)
+ German Tag = Tag(compact.German)
+ Greek Tag = Tag(compact.Greek)
+ English Tag = Tag(compact.English)
+ AmericanEnglish Tag = Tag(compact.AmericanEnglish)
+ BritishEnglish Tag = Tag(compact.BritishEnglish)
+ Spanish Tag = Tag(compact.Spanish)
+ EuropeanSpanish Tag = Tag(compact.EuropeanSpanish)
+ LatinAmericanSpanish Tag = Tag(compact.LatinAmericanSpanish)
+ Estonian Tag = Tag(compact.Estonian)
+ Persian Tag = Tag(compact.Persian)
+ Finnish Tag = Tag(compact.Finnish)
+ Filipino Tag = Tag(compact.Filipino)
+ French Tag = Tag(compact.French)
+ CanadianFrench Tag = Tag(compact.CanadianFrench)
+ Gujarati Tag = Tag(compact.Gujarati)
+ Hebrew Tag = Tag(compact.Hebrew)
+ Hindi Tag = Tag(compact.Hindi)
+ Croatian Tag = Tag(compact.Croatian)
+ Hungarian Tag = Tag(compact.Hungarian)
+ Armenian Tag = Tag(compact.Armenian)
+ Indonesian Tag = Tag(compact.Indonesian)
+ Icelandic Tag = Tag(compact.Icelandic)
+ Italian Tag = Tag(compact.Italian)
+ Japanese Tag = Tag(compact.Japanese)
+ Georgian Tag = Tag(compact.Georgian)
+ Kazakh Tag = Tag(compact.Kazakh)
+ Khmer Tag = Tag(compact.Khmer)
+ Kannada Tag = Tag(compact.Kannada)
+ Korean Tag = Tag(compact.Korean)
+ Kirghiz Tag = Tag(compact.Kirghiz)
+ Lao Tag = Tag(compact.Lao)
+ Lithuanian Tag = Tag(compact.Lithuanian)
+ Latvian Tag = Tag(compact.Latvian)
+ Macedonian Tag = Tag(compact.Macedonian)
+ Malayalam Tag = Tag(compact.Malayalam)
+ Mongolian Tag = Tag(compact.Mongolian)
+ Marathi Tag = Tag(compact.Marathi)
+ Malay Tag = Tag(compact.Malay)
+ Burmese Tag = Tag(compact.Burmese)
+ Nepali Tag = Tag(compact.Nepali)
+ Dutch Tag = Tag(compact.Dutch)
+ Norwegian Tag = Tag(compact.Norwegian)
+ Punjabi Tag = Tag(compact.Punjabi)
+ Polish Tag = Tag(compact.Polish)
+ Portuguese Tag = Tag(compact.Portuguese)
+ BrazilianPortuguese Tag = Tag(compact.BrazilianPortuguese)
+ EuropeanPortuguese Tag = Tag(compact.EuropeanPortuguese)
+ Romanian Tag = Tag(compact.Romanian)
+ Russian Tag = Tag(compact.Russian)
+ Sinhala Tag = Tag(compact.Sinhala)
+ Slovak Tag = Tag(compact.Slovak)
+ Slovenian Tag = Tag(compact.Slovenian)
+ Albanian Tag = Tag(compact.Albanian)
+ Serbian Tag = Tag(compact.Serbian)
+ SerbianLatin Tag = Tag(compact.SerbianLatin)
+ Swedish Tag = Tag(compact.Swedish)
+ Swahili Tag = Tag(compact.Swahili)
+ Tamil Tag = Tag(compact.Tamil)
+ Telugu Tag = Tag(compact.Telugu)
+ Thai Tag = Tag(compact.Thai)
+ Turkish Tag = Tag(compact.Turkish)
+ Ukrainian Tag = Tag(compact.Ukrainian)
+ Urdu Tag = Tag(compact.Urdu)
+ Uzbek Tag = Tag(compact.Uzbek)
+ Vietnamese Tag = Tag(compact.Vietnamese)
+ Chinese Tag = Tag(compact.Chinese)
+ SimplifiedChinese Tag = Tag(compact.SimplifiedChinese)
+ TraditionalChinese Tag = Tag(compact.TraditionalChinese)
+ Zulu Tag = Tag(compact.Zulu)
+)
diff --git a/vendor/golang.org/x/text/message/catalog.go b/vendor/golang.org/x/text/message/catalog.go
new file mode 100644
index 0000000..068271d
--- /dev/null
+++ b/vendor/golang.org/x/text/message/catalog.go
@@ -0,0 +1,36 @@
+// Copyright 2015 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 message
+
+// TODO: some types in this file will need to be made public at some time.
+// Documentation and method names will reflect this by using the exported name.
+
+import (
+ "golang.org/x/text/language"
+ "golang.org/x/text/message/catalog"
+)
+
+// MatchLanguage reports the matched tag obtained from language.MatchStrings for
+// the Matcher of the DefaultCatalog.
+func MatchLanguage(preferred ...string) language.Tag {
+ c := DefaultCatalog
+ tag, _ := language.MatchStrings(c.Matcher(), preferred...)
+ return tag
+}
+
+// DefaultCatalog is used by SetString.
+var DefaultCatalog catalog.Catalog = defaultCatalog
+
+var defaultCatalog = catalog.NewBuilder()
+
+// SetString calls SetString on the initial default Catalog.
+func SetString(tag language.Tag, key string, msg string) error {
+ return defaultCatalog.SetString(tag, key, msg)
+}
+
+// Set calls Set on the initial default Catalog.
+func Set(tag language.Tag, key string, msg ...catalog.Message) error {
+ return defaultCatalog.Set(tag, key, msg...)
+}
diff --git a/vendor/golang.org/x/text/message/catalog/catalog.go b/vendor/golang.org/x/text/message/catalog/catalog.go
new file mode 100644
index 0000000..96955d0
--- /dev/null
+++ b/vendor/golang.org/x/text/message/catalog/catalog.go
@@ -0,0 +1,365 @@
+// Copyright 2017 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 catalog defines collections of translated format strings.
+//
+// This package mostly defines types for populating catalogs with messages. The
+// catmsg package contains further definitions for creating custom message and
+// dictionary types as well as packages that use Catalogs.
+//
+// Package catalog defines various interfaces: Dictionary, Loader, and Message.
+// A Dictionary maintains a set of translations of format strings for a single
+// language. The Loader interface defines a source of dictionaries. A
+// translation of a format string is represented by a Message.
+//
+// # Catalogs
+//
+// A Catalog defines a programmatic interface for setting message translations.
+// It maintains a set of per-language dictionaries with translations for a set
+// of keys. For message translation to function properly, a translation should
+// be defined for each key for each supported language. A dictionary may be
+// underspecified, though, if there is a parent language that already defines
+// the key. For example, a Dictionary for "en-GB" could leave out entries that
+// are identical to those in a dictionary for "en".
+//
+// # Messages
+//
+// A Message is a format string which varies on the value of substitution
+// variables. For instance, to indicate the number of results one could want "no
+// results" if there are none, "1 result" if there is 1, and "%d results" for
+// any other number. Catalog is agnostic to the kind of format strings that are
+// used: for instance, messages can follow either the printf-style substitution
+// from package fmt or use templates.
+//
+// A Message does not substitute arguments in the format string. This job is
+// reserved for packages that render strings, such as message, that use Catalogs
+// to selected string. This separation of concerns allows Catalog to be used to
+// store any kind of formatting strings.
+//
+// # Selecting messages based on linguistic features of substitution arguments
+//
+// Messages may vary based on any linguistic features of the argument values.
+// The most common one is plural form, but others exist.
+//
+// Selection messages are provided in packages that provide support for a
+// specific linguistic feature. The following snippet uses plural.Selectf:
+//
+// catalog.Set(language.English, "You are %d minute(s) late.",
+// plural.Selectf(1, "",
+// plural.One, "You are 1 minute late.",
+// plural.Other, "You are %d minutes late."))
+//
+// In this example, a message is stored in the Catalog where one of two messages
+// is selected based on the first argument, a number. The first message is
+// selected if the argument is singular (identified by the selector "one") and
+// the second message is selected in all other cases. The selectors are defined
+// by the plural rules defined in CLDR. The selector "other" is special and will
+// always match. Each language always defines one of the linguistic categories
+// to be "other." For English, singular is "one" and plural is "other".
+//
+// Selects can be nested. This allows selecting sentences based on features of
+// multiple arguments or multiple linguistic properties of a single argument.
+//
+// # String interpolation
+//
+// There is often a lot of commonality between the possible variants of a
+// message. For instance, in the example above the word "minute" varies based on
+// the plural catogory of the argument, but the rest of the sentence is
+// identical. Using interpolation the above message can be rewritten as:
+//
+// catalog.Set(language.English, "You are %d minute(s) late.",
+// catalog.Var("minutes",
+// plural.Selectf(1, "", plural.One, "minute", plural.Other, "minutes")),
+// catalog.String("You are %[1]d ${minutes} late."))
+//
+// Var is defined to return the variable name if the message does not yield a
+// match. This allows us to further simplify this snippet to
+//
+// catalog.Set(language.English, "You are %d minute(s) late.",
+// catalog.Var("minutes", plural.Selectf(1, "", plural.One, "minute")),
+// catalog.String("You are %d ${minutes} late."))
+//
+// Overall this is still only a minor improvement, but things can get a lot more
+// unwieldy if more than one linguistic feature is used to determine a message
+// variant. Consider the following example:
+//
+// // argument 1: list of hosts, argument 2: list of guests
+// catalog.Set(language.English, "%[1]v invite(s) %[2]v to their party.",
+// catalog.Var("their",
+// plural.Selectf(1, ""
+// plural.One, gender.Select(1, "female", "her", "other", "his"))),
+// catalog.Var("invites", plural.Selectf(1, "", plural.One, "invite"))
+// catalog.String("%[1]v ${invites} %[2]v to ${their} party.")),
+//
+// Without variable substitution, this would have to be written as
+//
+// // argument 1: list of hosts, argument 2: list of guests
+// catalog.Set(language.English, "%[1]v invite(s) %[2]v to their party.",
+// plural.Selectf(1, "",
+// plural.One, gender.Select(1,
+// "female", "%[1]v invites %[2]v to her party."
+// "other", "%[1]v invites %[2]v to his party."),
+// plural.Other, "%[1]v invites %[2]v to their party."))
+//
+// Not necessarily shorter, but using variables there is less duplication and
+// the messages are more maintenance friendly. Moreover, languages may have up
+// to six plural forms. This makes the use of variables more welcome.
+//
+// Different messages using the same inflections can reuse variables by moving
+// them to macros. Using macros we can rewrite the message as:
+//
+// // argument 1: list of hosts, argument 2: list of guests
+// catalog.SetString(language.English, "%[1]v invite(s) %[2]v to their party.",
+// "%[1]v ${invites(1)} %[2]v to ${their(1)} party.")
+//
+// Where the following macros were defined separately.
+//
+// catalog.SetMacro(language.English, "invites", plural.Selectf(1, "",
+// plural.One, "invite"))
+// catalog.SetMacro(language.English, "their", plural.Selectf(1, "",
+// plural.One, gender.Select(1, "female", "her", "other", "his"))),
+//
+// Placeholders use parentheses and the arguments to invoke a macro.
+//
+// # Looking up messages
+//
+// Message lookup using Catalogs is typically only done by specialized packages
+// and is not something the user should be concerned with. For instance, to
+// express the tardiness of a user using the related message we defined earlier,
+// the user may use the package message like so:
+//
+// p := message.NewPrinter(language.English)
+// p.Printf("You are %d minute(s) late.", 5)
+//
+// Which would print:
+//
+// You are 5 minutes late.
+//
+// This package is UNDER CONSTRUCTION and its API may change.
+package catalog // import "golang.org/x/text/message/catalog"
+
+// TODO:
+// Some way to freeze a catalog.
+// - Locking on each lockup turns out to be about 50% of the total running time
+// for some of the benchmarks in the message package.
+// Consider these:
+// - Sequence type to support sequences in user-defined messages.
+// - Garbage collection: Remove dictionaries that can no longer be reached
+// as other dictionaries have been added that cover all possible keys.
+
+import (
+ "errors"
+ "fmt"
+
+ "golang.org/x/text/internal"
+
+ "golang.org/x/text/internal/catmsg"
+ "golang.org/x/text/language"
+)
+
+// A Catalog allows lookup of translated messages.
+type Catalog interface {
+ // Languages returns all languages for which the Catalog contains variants.
+ Languages() []language.Tag
+
+ // Matcher returns a Matcher for languages from this Catalog.
+ Matcher() language.Matcher
+
+ // A Context is used for evaluating Messages.
+ Context(tag language.Tag, r catmsg.Renderer) *Context
+
+ // This method also makes Catalog a private interface.
+ lookup(tag language.Tag, key string) (data string, ok bool)
+}
+
+// NewFromMap creates a Catalog from the given map. If a Dictionary is
+// underspecified the entry is retrieved from a parent language.
+func NewFromMap(dictionaries map[string]Dictionary, opts ...Option) (Catalog, error) {
+ options := options{}
+ for _, o := range opts {
+ o(&options)
+ }
+ c := &catalog{
+ dicts: map[language.Tag]Dictionary{},
+ }
+ _, hasFallback := dictionaries[options.fallback.String()]
+ if hasFallback {
+ // TODO: Should it be okay to not have a fallback language?
+ // Catalog generators could enforce there is always a fallback.
+ c.langs = append(c.langs, options.fallback)
+ }
+ for lang, dict := range dictionaries {
+ tag, err := language.Parse(lang)
+ if err != nil {
+ return nil, fmt.Errorf("catalog: invalid language tag %q", lang)
+ }
+ if _, ok := c.dicts[tag]; ok {
+ return nil, fmt.Errorf("catalog: duplicate entry for tag %q after normalization", tag)
+ }
+ c.dicts[tag] = dict
+ if !hasFallback || tag != options.fallback {
+ c.langs = append(c.langs, tag)
+ }
+ }
+ if hasFallback {
+ internal.SortTags(c.langs[1:])
+ } else {
+ internal.SortTags(c.langs)
+ }
+ c.matcher = language.NewMatcher(c.langs)
+ return c, nil
+}
+
+// A Dictionary is a source of translations for a single language.
+type Dictionary interface {
+ // Lookup returns a message compiled with catmsg.Compile for the given key.
+ // It returns false for ok if such a message could not be found.
+ Lookup(key string) (data string, ok bool)
+}
+
+type catalog struct {
+ langs []language.Tag
+ dicts map[language.Tag]Dictionary
+ macros store
+ matcher language.Matcher
+}
+
+func (c *catalog) Languages() []language.Tag { return c.langs }
+func (c *catalog) Matcher() language.Matcher { return c.matcher }
+
+func (c *catalog) lookup(tag language.Tag, key string) (data string, ok bool) {
+ for ; ; tag = tag.Parent() {
+ if dict, ok := c.dicts[tag]; ok {
+ if data, ok := dict.Lookup(key); ok {
+ return data, true
+ }
+ }
+ if tag == language.Und {
+ break
+ }
+ }
+ return "", false
+}
+
+// Context returns a Context for formatting messages.
+// Only one Message may be formatted per context at any given time.
+func (c *catalog) Context(tag language.Tag, r catmsg.Renderer) *Context {
+ return &Context{
+ cat: c,
+ tag: tag,
+ dec: catmsg.NewDecoder(tag, r, &dict{&c.macros, tag}),
+ }
+}
+
+// A Builder allows building a Catalog programmatically.
+type Builder struct {
+ options
+ matcher language.Matcher
+
+ index store
+ macros store
+}
+
+type options struct {
+ fallback language.Tag
+}
+
+// An Option configures Catalog behavior.
+type Option func(*options)
+
+// Fallback specifies the default fallback language. The default is Und.
+func Fallback(tag language.Tag) Option {
+ return func(o *options) { o.fallback = tag }
+}
+
+// TODO:
+// // Catalogs specifies one or more sources for a Catalog.
+// // Lookups are in order.
+// // This can be changed inserting a Catalog used for setting, which implements
+// // Loader, used for setting in the chain.
+// func Catalogs(d ...Loader) Option {
+// return nil
+// }
+//
+// func Delims(start, end string) Option {}
+//
+// func Dict(tag language.Tag, d ...Dictionary) Option
+
+// NewBuilder returns an empty mutable Catalog.
+func NewBuilder(opts ...Option) *Builder {
+ c := &Builder{}
+ for _, o := range opts {
+ o(&c.options)
+ }
+ return c
+}
+
+// SetString is shorthand for Set(tag, key, String(msg)).
+func (c *Builder) SetString(tag language.Tag, key string, msg string) error {
+ return c.set(tag, key, &c.index, String(msg))
+}
+
+// Set sets the translation for the given language and key.
+//
+// When evaluation this message, the first Message in the sequence to msgs to
+// evaluate to a string will be the message returned.
+func (c *Builder) Set(tag language.Tag, key string, msg ...Message) error {
+ return c.set(tag, key, &c.index, msg...)
+}
+
+// SetMacro defines a Message that may be substituted in another message.
+// The arguments to a macro Message are passed as arguments in the
+// placeholder the form "${foo(arg1, arg2)}".
+func (c *Builder) SetMacro(tag language.Tag, name string, msg ...Message) error {
+ return c.set(tag, name, &c.macros, msg...)
+}
+
+// ErrNotFound indicates there was no message for the given key.
+var ErrNotFound = errors.New("catalog: message not found")
+
+// String specifies a plain message string. It can be used as fallback if no
+// other strings match or as a simple standalone message.
+//
+// It is an error to pass more than one String in a message sequence.
+func String(name string) Message {
+ return catmsg.String(name)
+}
+
+// Var sets a variable that may be substituted in formatting patterns using
+// named substitution of the form "${name}". The name argument is used as a
+// fallback if the statements do not produce a match. The statement sequence may
+// not contain any Var calls.
+//
+// The name passed to a Var must be unique within message sequence.
+func Var(name string, msg ...Message) Message {
+ return &catmsg.Var{Name: name, Message: firstInSequence(msg)}
+}
+
+// Context returns a Context for formatting messages.
+// Only one Message may be formatted per context at any given time.
+func (b *Builder) Context(tag language.Tag, r catmsg.Renderer) *Context {
+ return &Context{
+ cat: b,
+ tag: tag,
+ dec: catmsg.NewDecoder(tag, r, &dict{&b.macros, tag}),
+ }
+}
+
+// A Context is used for evaluating Messages.
+// Only one Message may be formatted per context at any given time.
+type Context struct {
+ cat Catalog
+ tag language.Tag // TODO: use compact index.
+ dec *catmsg.Decoder
+}
+
+// Execute looks up and executes the message with the given key.
+// It returns ErrNotFound if no message could be found in the index.
+func (c *Context) Execute(key string) error {
+ data, ok := c.cat.lookup(c.tag, key)
+ if !ok {
+ return ErrNotFound
+ }
+ return c.dec.Execute(data)
+}
diff --git a/vendor/golang.org/x/text/message/catalog/dict.go b/vendor/golang.org/x/text/message/catalog/dict.go
new file mode 100644
index 0000000..a0eb818
--- /dev/null
+++ b/vendor/golang.org/x/text/message/catalog/dict.go
@@ -0,0 +1,129 @@
+// Copyright 2017 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 catalog
+
+import (
+ "sync"
+
+ "golang.org/x/text/internal"
+ "golang.org/x/text/internal/catmsg"
+ "golang.org/x/text/language"
+)
+
+// TODO:
+// Dictionary returns a Dictionary that returns the first Message, using the
+// given language tag, that matches:
+// 1. the last one registered by one of the Set methods
+// 2. returned by one of the Loaders
+// 3. repeat from 1. using the parent language
+// This approach allows messages to be underspecified.
+// func (c *Catalog) Dictionary(tag language.Tag) (Dictionary, error) {
+// // TODO: verify dictionary exists.
+// return &dict{&c.index, tag}, nil
+// }
+
+type dict struct {
+ s *store
+ tag language.Tag // TODO: make compact tag.
+}
+
+func (d *dict) Lookup(key string) (data string, ok bool) {
+ return d.s.lookup(d.tag, key)
+}
+
+func (b *Builder) lookup(tag language.Tag, key string) (data string, ok bool) {
+ return b.index.lookup(tag, key)
+}
+
+func (c *Builder) set(tag language.Tag, key string, s *store, msg ...Message) error {
+ data, err := catmsg.Compile(tag, &dict{&c.macros, tag}, firstInSequence(msg))
+
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
+ m := s.index[tag]
+ if m == nil {
+ m = msgMap{}
+ if s.index == nil {
+ s.index = map[language.Tag]msgMap{}
+ }
+ c.matcher = nil
+ s.index[tag] = m
+ }
+
+ m[key] = data
+ return err
+}
+
+func (c *Builder) Matcher() language.Matcher {
+ c.index.mutex.RLock()
+ m := c.matcher
+ c.index.mutex.RUnlock()
+ if m != nil {
+ return m
+ }
+
+ c.index.mutex.Lock()
+ if c.matcher == nil {
+ c.matcher = language.NewMatcher(c.unlockedLanguages())
+ }
+ m = c.matcher
+ c.index.mutex.Unlock()
+ return m
+}
+
+type store struct {
+ mutex sync.RWMutex
+ index map[language.Tag]msgMap
+}
+
+type msgMap map[string]string
+
+func (s *store) lookup(tag language.Tag, key string) (data string, ok bool) {
+ s.mutex.RLock()
+ defer s.mutex.RUnlock()
+
+ for ; ; tag = tag.Parent() {
+ if msgs, ok := s.index[tag]; ok {
+ if msg, ok := msgs[key]; ok {
+ return msg, true
+ }
+ }
+ if tag == language.Und {
+ break
+ }
+ }
+ return "", false
+}
+
+// Languages returns all languages for which the Catalog contains variants.
+func (b *Builder) Languages() []language.Tag {
+ s := &b.index
+ s.mutex.RLock()
+ defer s.mutex.RUnlock()
+
+ return b.unlockedLanguages()
+}
+
+func (b *Builder) unlockedLanguages() []language.Tag {
+ s := &b.index
+ if len(s.index) == 0 {
+ return nil
+ }
+ tags := make([]language.Tag, 0, len(s.index))
+ _, hasFallback := s.index[b.options.fallback]
+ offset := 0
+ if hasFallback {
+ tags = append(tags, b.options.fallback)
+ offset = 1
+ }
+ for t := range s.index {
+ if t != b.options.fallback {
+ tags = append(tags, t)
+ }
+ }
+ internal.SortTags(tags[offset:])
+ return tags
+}
diff --git a/vendor/golang.org/x/text/message/catalog/go19.go b/vendor/golang.org/x/text/message/catalog/go19.go
new file mode 100644
index 0000000..291a4df
--- /dev/null
+++ b/vendor/golang.org/x/text/message/catalog/go19.go
@@ -0,0 +1,15 @@
+// Copyright 2017 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:build go1.9
+
+package catalog
+
+import "golang.org/x/text/internal/catmsg"
+
+// A Message holds a collection of translations for the same phrase that may
+// vary based on the values of substitution arguments.
+type Message = catmsg.Message
+
+type firstInSequence = catmsg.FirstOf
diff --git a/vendor/golang.org/x/text/message/catalog/gopre19.go b/vendor/golang.org/x/text/message/catalog/gopre19.go
new file mode 100644
index 0000000..da44ebb
--- /dev/null
+++ b/vendor/golang.org/x/text/message/catalog/gopre19.go
@@ -0,0 +1,23 @@
+// Copyright 2017 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:build !go1.9
+
+package catalog
+
+import "golang.org/x/text/internal/catmsg"
+
+// A Message holds a collection of translations for the same phrase that may
+// vary based on the values of substitution arguments.
+type Message interface {
+ catmsg.Message
+}
+
+func firstInSequence(m []Message) catmsg.Message {
+ a := []catmsg.Message{}
+ for _, m := range m {
+ a = append(a, m)
+ }
+ return catmsg.FirstOf(a)
+}
diff --git a/vendor/golang.org/x/text/message/doc.go b/vendor/golang.org/x/text/message/doc.go
new file mode 100644
index 0000000..4bf7bdc
--- /dev/null
+++ b/vendor/golang.org/x/text/message/doc.go
@@ -0,0 +1,99 @@
+// Copyright 2017 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 message implements formatted I/O for localized strings with functions
+// analogous to the fmt's print functions. It is a drop-in replacement for fmt.
+//
+// # Localized Formatting
+//
+// A format string can be localized by replacing any of the print functions of
+// fmt with an equivalent call to a Printer.
+//
+// p := message.NewPrinter(message.MatchLanguage("en"))
+// p.Println(123456.78) // Prints 123,456.78
+//
+// p.Printf("%d ducks in a row", 4331) // Prints 4,331 ducks in a row
+//
+// p := message.NewPrinter(message.MatchLanguage("nl"))
+// p.Printf("Hoogte: %.1f meter", 1244.9) // Prints Hoogte: 1,244.9 meter
+//
+// p := message.NewPrinter(message.MatchLanguage("bn"))
+// p.Println(123456.78) // Prints ১,২৩,৪৫৬.৭৮
+//
+// Printer currently supports numbers and specialized types for which packages
+// exist in x/text. Other builtin types such as time.Time and slices are
+// planned.
+//
+// Format strings largely have the same meaning as with fmt with the following
+// notable exceptions:
+// - flag # always resorts to fmt for printing
+// - verb 'f', 'e', 'g', 'd' use localized formatting unless the '#' flag is
+// specified.
+// - verb 'm' inserts a translation of a string argument.
+//
+// See package fmt for more options.
+//
+// # Translation
+//
+// The format strings that are passed to Printf, Sprintf, Fprintf, or Errorf
+// are used as keys to look up translations for the specified languages.
+// More on how these need to be specified below.
+//
+// One can use arbitrary keys to distinguish between otherwise ambiguous
+// strings:
+//
+// p := message.NewPrinter(language.English)
+// p.Printf("archive(noun)") // Prints "archive"
+// p.Printf("archive(verb)") // Prints "archive"
+//
+// p := message.NewPrinter(language.German)
+// p.Printf("archive(noun)") // Prints "Archiv"
+// p.Printf("archive(verb)") // Prints "archivieren"
+//
+// To retain the fallback functionality, use Key:
+//
+// p.Printf(message.Key("archive(noun)", "archive"))
+// p.Printf(message.Key("archive(verb)", "archive"))
+//
+// # Translation Pipeline
+//
+// Format strings that contain text need to be translated to support different
+// locales. The first step is to extract strings that need to be translated.
+//
+// 1. Install gotext
+//
+// go get -u golang.org/x/text/cmd/gotext
+// gotext -help
+//
+// 2. Mark strings in your source to be translated by using message.Printer,
+// instead of the functions of the fmt package.
+//
+// 3. Extract the strings from your source
+//
+// gotext extract
+//
+// The output will be written to the textdata directory.
+//
+// 4. Send the files for translation
+//
+// It is planned to support multiple formats, but for now one will have to
+// rewrite the JSON output to the desired format.
+//
+// 5. Inject translations into program
+//
+// 6. Repeat from 2
+//
+// Right now this has to be done programmatically with calls to Set or
+// SetString. These functions as well as the methods defined in
+// see also package golang.org/x/text/message/catalog can be used to implement
+// either dynamic or static loading of messages.
+//
+// # Plural and Gender Forms
+//
+// Translated messages can vary based on the plural and gender forms of
+// substitution values. In general, it is up to the translators to provide
+// alternative translations for such forms. See the packages in
+// golang.org/x/text/feature and golang.org/x/text/message/catalog for more
+// information.
+package message
diff --git a/vendor/golang.org/x/text/message/format.go b/vendor/golang.org/x/text/message/format.go
new file mode 100644
index 0000000..a47d17d
--- /dev/null
+++ b/vendor/golang.org/x/text/message/format.go
@@ -0,0 +1,510 @@
+// Copyright 2017 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 message
+
+import (
+ "bytes"
+ "strconv"
+ "unicode/utf8"
+
+ "golang.org/x/text/internal/format"
+)
+
+const (
+ ldigits = "0123456789abcdefx"
+ udigits = "0123456789ABCDEFX"
+)
+
+const (
+ signed = true
+ unsigned = false
+)
+
+// A formatInfo is the raw formatter used by Printf etc.
+// It prints into a buffer that must be set up separately.
+type formatInfo struct {
+ buf *bytes.Buffer
+
+ format.Parser
+
+ // intbuf is large enough to store %b of an int64 with a sign and
+ // avoids padding at the end of the struct on 32 bit architectures.
+ intbuf [68]byte
+}
+
+func (f *formatInfo) init(buf *bytes.Buffer) {
+ f.ClearFlags()
+ f.buf = buf
+}
+
+// writePadding generates n bytes of padding.
+func (f *formatInfo) writePadding(n int) {
+ if n <= 0 { // No padding bytes needed.
+ return
+ }
+ f.buf.Grow(n)
+ // Decide which byte the padding should be filled with.
+ padByte := byte(' ')
+ if f.Zero {
+ padByte = byte('0')
+ }
+ // Fill padding with padByte.
+ for i := 0; i < n; i++ {
+ f.buf.WriteByte(padByte) // TODO: make more efficient.
+ }
+}
+
+// pad appends b to f.buf, padded on left (!f.minus) or right (f.minus).
+func (f *formatInfo) pad(b []byte) {
+ if !f.WidthPresent || f.Width == 0 {
+ f.buf.Write(b)
+ return
+ }
+ width := f.Width - utf8.RuneCount(b)
+ if !f.Minus {
+ // left padding
+ f.writePadding(width)
+ f.buf.Write(b)
+ } else {
+ // right padding
+ f.buf.Write(b)
+ f.writePadding(width)
+ }
+}
+
+// padString appends s to f.buf, padded on left (!f.minus) or right (f.minus).
+func (f *formatInfo) padString(s string) {
+ if !f.WidthPresent || f.Width == 0 {
+ f.buf.WriteString(s)
+ return
+ }
+ width := f.Width - utf8.RuneCountInString(s)
+ if !f.Minus {
+ // left padding
+ f.writePadding(width)
+ f.buf.WriteString(s)
+ } else {
+ // right padding
+ f.buf.WriteString(s)
+ f.writePadding(width)
+ }
+}
+
+// fmt_boolean formats a boolean.
+func (f *formatInfo) fmt_boolean(v bool) {
+ if v {
+ f.padString("true")
+ } else {
+ f.padString("false")
+ }
+}
+
+// fmt_unicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'".
+func (f *formatInfo) fmt_unicode(u uint64) {
+ buf := f.intbuf[0:]
+
+ // With default precision set the maximum needed buf length is 18
+ // for formatting -1 with %#U ("U+FFFFFFFFFFFFFFFF") which fits
+ // into the already allocated intbuf with a capacity of 68 bytes.
+ prec := 4
+ if f.PrecPresent && f.Prec > 4 {
+ prec = f.Prec
+ // Compute space needed for "U+" , number, " '", character, "'".
+ width := 2 + prec + 2 + utf8.UTFMax + 1
+ if width > len(buf) {
+ buf = make([]byte, width)
+ }
+ }
+
+ // Format into buf, ending at buf[i]. Formatting numbers is easier right-to-left.
+ i := len(buf)
+
+ // For %#U we want to add a space and a quoted character at the end of the buffer.
+ if f.Sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) {
+ i--
+ buf[i] = '\''
+ i -= utf8.RuneLen(rune(u))
+ utf8.EncodeRune(buf[i:], rune(u))
+ i--
+ buf[i] = '\''
+ i--
+ buf[i] = ' '
+ }
+ // Format the Unicode code point u as a hexadecimal number.
+ for u >= 16 {
+ i--
+ buf[i] = udigits[u&0xF]
+ prec--
+ u >>= 4
+ }
+ i--
+ buf[i] = udigits[u]
+ prec--
+ // Add zeros in front of the number until requested precision is reached.
+ for prec > 0 {
+ i--
+ buf[i] = '0'
+ prec--
+ }
+ // Add a leading "U+".
+ i--
+ buf[i] = '+'
+ i--
+ buf[i] = 'U'
+
+ oldZero := f.Zero
+ f.Zero = false
+ f.pad(buf[i:])
+ f.Zero = oldZero
+}
+
+// fmt_integer formats signed and unsigned integers.
+func (f *formatInfo) fmt_integer(u uint64, base int, isSigned bool, digits string) {
+ negative := isSigned && int64(u) < 0
+ if negative {
+ u = -u
+ }
+
+ buf := f.intbuf[0:]
+ // The already allocated f.intbuf with a capacity of 68 bytes
+ // is large enough for integer formatting when no precision or width is set.
+ if f.WidthPresent || f.PrecPresent {
+ // Account 3 extra bytes for possible addition of a sign and "0x".
+ width := 3 + f.Width + f.Prec // wid and prec are always positive.
+ if width > len(buf) {
+ // We're going to need a bigger boat.
+ buf = make([]byte, width)
+ }
+ }
+
+ // Two ways to ask for extra leading zero digits: %.3d or %03d.
+ // If both are specified the f.zero flag is ignored and
+ // padding with spaces is used instead.
+ prec := 0
+ if f.PrecPresent {
+ prec = f.Prec
+ // Precision of 0 and value of 0 means "print nothing" but padding.
+ if prec == 0 && u == 0 {
+ oldZero := f.Zero
+ f.Zero = false
+ f.writePadding(f.Width)
+ f.Zero = oldZero
+ return
+ }
+ } else if f.Zero && f.WidthPresent {
+ prec = f.Width
+ if negative || f.Plus || f.Space {
+ prec-- // leave room for sign
+ }
+ }
+
+ // Because printing is easier right-to-left: format u into buf, ending at buf[i].
+ // We could make things marginally faster by splitting the 32-bit case out
+ // into a separate block but it's not worth the duplication, so u has 64 bits.
+ i := len(buf)
+ // Use constants for the division and modulo for more efficient code.
+ // Switch cases ordered by popularity.
+ switch base {
+ case 10:
+ for u >= 10 {
+ i--
+ next := u / 10
+ buf[i] = byte('0' + u - next*10)
+ u = next
+ }
+ case 16:
+ for u >= 16 {
+ i--
+ buf[i] = digits[u&0xF]
+ u >>= 4
+ }
+ case 8:
+ for u >= 8 {
+ i--
+ buf[i] = byte('0' + u&7)
+ u >>= 3
+ }
+ case 2:
+ for u >= 2 {
+ i--
+ buf[i] = byte('0' + u&1)
+ u >>= 1
+ }
+ default:
+ panic("fmt: unknown base; can't happen")
+ }
+ i--
+ buf[i] = digits[u]
+ for i > 0 && prec > len(buf)-i {
+ i--
+ buf[i] = '0'
+ }
+
+ // Various prefixes: 0x, -, etc.
+ if f.Sharp {
+ switch base {
+ case 8:
+ if buf[i] != '0' {
+ i--
+ buf[i] = '0'
+ }
+ case 16:
+ // Add a leading 0x or 0X.
+ i--
+ buf[i] = digits[16]
+ i--
+ buf[i] = '0'
+ }
+ }
+
+ if negative {
+ i--
+ buf[i] = '-'
+ } else if f.Plus {
+ i--
+ buf[i] = '+'
+ } else if f.Space {
+ i--
+ buf[i] = ' '
+ }
+
+ // Left padding with zeros has already been handled like precision earlier
+ // or the f.zero flag is ignored due to an explicitly set precision.
+ oldZero := f.Zero
+ f.Zero = false
+ f.pad(buf[i:])
+ f.Zero = oldZero
+}
+
+// truncate truncates the string to the specified precision, if present.
+func (f *formatInfo) truncate(s string) string {
+ if f.PrecPresent {
+ n := f.Prec
+ for i := range s {
+ n--
+ if n < 0 {
+ return s[:i]
+ }
+ }
+ }
+ return s
+}
+
+// fmt_s formats a string.
+func (f *formatInfo) fmt_s(s string) {
+ s = f.truncate(s)
+ f.padString(s)
+}
+
+// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
+func (f *formatInfo) fmt_sbx(s string, b []byte, digits string) {
+ length := len(b)
+ if b == nil {
+ // No byte slice present. Assume string s should be encoded.
+ length = len(s)
+ }
+ // Set length to not process more bytes than the precision demands.
+ if f.PrecPresent && f.Prec < length {
+ length = f.Prec
+ }
+ // Compute width of the encoding taking into account the f.sharp and f.space flag.
+ width := 2 * length
+ if width > 0 {
+ if f.Space {
+ // Each element encoded by two hexadecimals will get a leading 0x or 0X.
+ if f.Sharp {
+ width *= 2
+ }
+ // Elements will be separated by a space.
+ width += length - 1
+ } else if f.Sharp {
+ // Only a leading 0x or 0X will be added for the whole string.
+ width += 2
+ }
+ } else { // The byte slice or string that should be encoded is empty.
+ if f.WidthPresent {
+ f.writePadding(f.Width)
+ }
+ return
+ }
+ // Handle padding to the left.
+ if f.WidthPresent && f.Width > width && !f.Minus {
+ f.writePadding(f.Width - width)
+ }
+ // Write the encoding directly into the output buffer.
+ buf := f.buf
+ if f.Sharp {
+ // Add leading 0x or 0X.
+ buf.WriteByte('0')
+ buf.WriteByte(digits[16])
+ }
+ var c byte
+ for i := 0; i < length; i++ {
+ if f.Space && i > 0 {
+ // Separate elements with a space.
+ buf.WriteByte(' ')
+ if f.Sharp {
+ // Add leading 0x or 0X for each element.
+ buf.WriteByte('0')
+ buf.WriteByte(digits[16])
+ }
+ }
+ if b != nil {
+ c = b[i] // Take a byte from the input byte slice.
+ } else {
+ c = s[i] // Take a byte from the input string.
+ }
+ // Encode each byte as two hexadecimal digits.
+ buf.WriteByte(digits[c>>4])
+ buf.WriteByte(digits[c&0xF])
+ }
+ // Handle padding to the right.
+ if f.WidthPresent && f.Width > width && f.Minus {
+ f.writePadding(f.Width - width)
+ }
+}
+
+// fmt_sx formats a string as a hexadecimal encoding of its bytes.
+func (f *formatInfo) fmt_sx(s, digits string) {
+ f.fmt_sbx(s, nil, digits)
+}
+
+// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
+func (f *formatInfo) fmt_bx(b []byte, digits string) {
+ f.fmt_sbx("", b, digits)
+}
+
+// fmt_q formats a string as a double-quoted, escaped Go string constant.
+// If f.sharp is set a raw (backquoted) string may be returned instead
+// if the string does not contain any control characters other than tab.
+func (f *formatInfo) fmt_q(s string) {
+ s = f.truncate(s)
+ if f.Sharp && strconv.CanBackquote(s) {
+ f.padString("`" + s + "`")
+ return
+ }
+ buf := f.intbuf[:0]
+ if f.Plus {
+ f.pad(strconv.AppendQuoteToASCII(buf, s))
+ } else {
+ f.pad(strconv.AppendQuote(buf, s))
+ }
+}
+
+// fmt_c formats an integer as a Unicode character.
+// If the character is not valid Unicode, it will print '\ufffd'.
+func (f *formatInfo) fmt_c(c uint64) {
+ r := rune(c)
+ if c > utf8.MaxRune {
+ r = utf8.RuneError
+ }
+ buf := f.intbuf[:0]
+ w := utf8.EncodeRune(buf[:utf8.UTFMax], r)
+ f.pad(buf[:w])
+}
+
+// fmt_qc formats an integer as a single-quoted, escaped Go character constant.
+// If the character is not valid Unicode, it will print '\ufffd'.
+func (f *formatInfo) fmt_qc(c uint64) {
+ r := rune(c)
+ if c > utf8.MaxRune {
+ r = utf8.RuneError
+ }
+ buf := f.intbuf[:0]
+ if f.Plus {
+ f.pad(strconv.AppendQuoteRuneToASCII(buf, r))
+ } else {
+ f.pad(strconv.AppendQuoteRune(buf, r))
+ }
+}
+
+// fmt_float formats a float64. It assumes that verb is a valid format specifier
+// for strconv.AppendFloat and therefore fits into a byte.
+func (f *formatInfo) fmt_float(v float64, size int, verb rune, prec int) {
+ // Explicit precision in format specifier overrules default precision.
+ if f.PrecPresent {
+ prec = f.Prec
+ }
+ // Format number, reserving space for leading + sign if needed.
+ num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size)
+ if num[1] == '-' || num[1] == '+' {
+ num = num[1:]
+ } else {
+ num[0] = '+'
+ }
+ // f.space means to add a leading space instead of a "+" sign unless
+ // the sign is explicitly asked for by f.plus.
+ if f.Space && num[0] == '+' && !f.Plus {
+ num[0] = ' '
+ }
+ // Special handling for infinities and NaN,
+ // which don't look like a number so shouldn't be padded with zeros.
+ if num[1] == 'I' || num[1] == 'N' {
+ oldZero := f.Zero
+ f.Zero = false
+ // Remove sign before NaN if not asked for.
+ if num[1] == 'N' && !f.Space && !f.Plus {
+ num = num[1:]
+ }
+ f.pad(num)
+ f.Zero = oldZero
+ return
+ }
+ // The sharp flag forces printing a decimal point for non-binary formats
+ // and retains trailing zeros, which we may need to restore.
+ if f.Sharp && verb != 'b' {
+ digits := 0
+ switch verb {
+ case 'v', 'g', 'G':
+ digits = prec
+ // If no precision is set explicitly use a precision of 6.
+ if digits == -1 {
+ digits = 6
+ }
+ }
+
+ // Buffer pre-allocated with enough room for
+ // exponent notations of the form "e+123".
+ var tailBuf [5]byte
+ tail := tailBuf[:0]
+
+ hasDecimalPoint := false
+ // Starting from i = 1 to skip sign at num[0].
+ for i := 1; i < len(num); i++ {
+ switch num[i] {
+ case '.':
+ hasDecimalPoint = true
+ case 'e', 'E':
+ tail = append(tail, num[i:]...)
+ num = num[:i]
+ default:
+ digits--
+ }
+ }
+ if !hasDecimalPoint {
+ num = append(num, '.')
+ }
+ for digits > 0 {
+ num = append(num, '0')
+ digits--
+ }
+ num = append(num, tail...)
+ }
+ // We want a sign if asked for and if the sign is not positive.
+ if f.Plus || num[0] != '+' {
+ // If we're zero padding to the left we want the sign before the leading zeros.
+ // Achieve this by writing the sign out and then padding the unsigned number.
+ if f.Zero && f.WidthPresent && f.Width > len(num) {
+ f.buf.WriteByte(num[0])
+ f.writePadding(f.Width - len(num))
+ f.buf.Write(num[1:])
+ return
+ }
+ f.pad(num)
+ return
+ }
+ // No sign to show and the number is positive; just print the unsigned number.
+ f.pad(num[1:])
+}
diff --git a/vendor/golang.org/x/text/message/message.go b/vendor/golang.org/x/text/message/message.go
new file mode 100644
index 0000000..91a9726
--- /dev/null
+++ b/vendor/golang.org/x/text/message/message.go
@@ -0,0 +1,192 @@
+// Copyright 2015 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 message // import "golang.org/x/text/message"
+
+import (
+ "io"
+ "os"
+
+ // Include features to facilitate generated catalogs.
+ _ "golang.org/x/text/feature/plural"
+
+ "golang.org/x/text/internal/number"
+ "golang.org/x/text/language"
+ "golang.org/x/text/message/catalog"
+)
+
+// A Printer implements language-specific formatted I/O analogous to the fmt
+// package.
+type Printer struct {
+ // the language
+ tag language.Tag
+
+ toDecimal number.Formatter
+ toScientific number.Formatter
+
+ cat catalog.Catalog
+}
+
+type options struct {
+ cat catalog.Catalog
+ // TODO:
+ // - allow %s to print integers in written form (tables are likely too large
+ // to enable this by default).
+ // - list behavior
+ //
+}
+
+// An Option defines an option of a Printer.
+type Option func(o *options)
+
+// Catalog defines the catalog to be used.
+func Catalog(c catalog.Catalog) Option {
+ return func(o *options) { o.cat = c }
+}
+
+// NewPrinter returns a Printer that formats messages tailored to language t.
+func NewPrinter(t language.Tag, opts ...Option) *Printer {
+ options := &options{
+ cat: DefaultCatalog,
+ }
+ for _, o := range opts {
+ o(options)
+ }
+ p := &Printer{
+ tag: t,
+ cat: options.cat,
+ }
+ p.toDecimal.InitDecimal(t)
+ p.toScientific.InitScientific(t)
+ return p
+}
+
+// Sprint is like fmt.Sprint, but using language-specific formatting.
+func (p *Printer) Sprint(a ...interface{}) string {
+ pp := newPrinter(p)
+ pp.doPrint(a)
+ s := pp.String()
+ pp.free()
+ return s
+}
+
+// Fprint is like fmt.Fprint, but using language-specific formatting.
+func (p *Printer) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
+ pp := newPrinter(p)
+ pp.doPrint(a)
+ n64, err := io.Copy(w, &pp.Buffer)
+ pp.free()
+ return int(n64), err
+}
+
+// Print is like fmt.Print, but using language-specific formatting.
+func (p *Printer) Print(a ...interface{}) (n int, err error) {
+ return p.Fprint(os.Stdout, a...)
+}
+
+// Sprintln is like fmt.Sprintln, but using language-specific formatting.
+func (p *Printer) Sprintln(a ...interface{}) string {
+ pp := newPrinter(p)
+ pp.doPrintln(a)
+ s := pp.String()
+ pp.free()
+ return s
+}
+
+// Fprintln is like fmt.Fprintln, but using language-specific formatting.
+func (p *Printer) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
+ pp := newPrinter(p)
+ pp.doPrintln(a)
+ n64, err := io.Copy(w, &pp.Buffer)
+ pp.free()
+ return int(n64), err
+}
+
+// Println is like fmt.Println, but using language-specific formatting.
+func (p *Printer) Println(a ...interface{}) (n int, err error) {
+ return p.Fprintln(os.Stdout, a...)
+}
+
+// Sprintf is like fmt.Sprintf, but using language-specific formatting.
+func (p *Printer) Sprintf(key Reference, a ...interface{}) string {
+ pp := newPrinter(p)
+ lookupAndFormat(pp, key, a)
+ s := pp.String()
+ pp.free()
+ return s
+}
+
+// Fprintf is like fmt.Fprintf, but using language-specific formatting.
+func (p *Printer) Fprintf(w io.Writer, key Reference, a ...interface{}) (n int, err error) {
+ pp := newPrinter(p)
+ lookupAndFormat(pp, key, a)
+ n, err = w.Write(pp.Bytes())
+ pp.free()
+ return n, err
+
+}
+
+// Printf is like fmt.Printf, but using language-specific formatting.
+func (p *Printer) Printf(key Reference, a ...interface{}) (n int, err error) {
+ pp := newPrinter(p)
+ lookupAndFormat(pp, key, a)
+ n, err = os.Stdout.Write(pp.Bytes())
+ pp.free()
+ return n, err
+}
+
+func lookupAndFormat(p *printer, r Reference, a []interface{}) {
+ p.fmt.Reset(a)
+ switch v := r.(type) {
+ case string:
+ if p.catContext.Execute(v) == catalog.ErrNotFound {
+ p.Render(v)
+ return
+ }
+ case key:
+ if p.catContext.Execute(v.id) == catalog.ErrNotFound &&
+ p.catContext.Execute(v.fallback) == catalog.ErrNotFound {
+ p.Render(v.fallback)
+ return
+ }
+ default:
+ panic("key argument is not a Reference")
+ }
+}
+
+type rawPrinter struct {
+ p *printer
+}
+
+func (p rawPrinter) Render(msg string) { p.p.WriteString(msg) }
+func (p rawPrinter) Arg(i int) interface{} { return nil }
+
+// Arg implements catmsg.Renderer.
+func (p *printer) Arg(i int) interface{} { // TODO, also return "ok" bool
+ i--
+ if uint(i) < uint(len(p.fmt.Args)) {
+ return p.fmt.Args[i]
+ }
+ return nil
+}
+
+// Render implements catmsg.Renderer.
+func (p *printer) Render(msg string) {
+ p.doPrintf(msg)
+}
+
+// A Reference is a string or a message reference.
+type Reference interface {
+ // TODO: also allow []string
+}
+
+// Key creates a message Reference for a message where the given id is used for
+// message lookup and the fallback is returned when no matches are found.
+func Key(id string, fallback string) Reference {
+ return key{id, fallback}
+}
+
+type key struct {
+ id, fallback string
+}
diff --git a/vendor/golang.org/x/text/message/print.go b/vendor/golang.org/x/text/message/print.go
new file mode 100644
index 0000000..da304cc
--- /dev/null
+++ b/vendor/golang.org/x/text/message/print.go
@@ -0,0 +1,984 @@
+// Copyright 2017 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 message
+
+import (
+ "bytes"
+ "fmt" // TODO: consider copying interfaces from package fmt to avoid dependency.
+ "math"
+ "reflect"
+ "sync"
+ "unicode/utf8"
+
+ "golang.org/x/text/internal/format"
+ "golang.org/x/text/internal/number"
+ "golang.org/x/text/language"
+ "golang.org/x/text/message/catalog"
+)
+
+// Strings for use with buffer.WriteString.
+// This is less overhead than using buffer.Write with byte arrays.
+const (
+ commaSpaceString = ", "
+ nilAngleString = "<nil>"
+ nilParenString = "(nil)"
+ nilString = "nil"
+ mapString = "map["
+ percentBangString = "%!"
+ missingString = "(MISSING)"
+ badIndexString = "(BADINDEX)"
+ panicString = "(PANIC="
+ extraString = "%!(EXTRA "
+ badWidthString = "%!(BADWIDTH)"
+ badPrecString = "%!(BADPREC)"
+ noVerbString = "%!(NOVERB)"
+
+ invReflectString = "<invalid reflect.Value>"
+)
+
+var printerPool = sync.Pool{
+ New: func() interface{} { return new(printer) },
+}
+
+// newPrinter allocates a new printer struct or grabs a cached one.
+func newPrinter(pp *Printer) *printer {
+ p := printerPool.Get().(*printer)
+ p.Printer = *pp
+ // TODO: cache most of the following call.
+ p.catContext = pp.cat.Context(pp.tag, p)
+
+ p.panicking = false
+ p.erroring = false
+ p.fmt.init(&p.Buffer)
+ return p
+}
+
+// free saves used printer structs in printerFree; avoids an allocation per invocation.
+func (p *printer) free() {
+ p.Buffer.Reset()
+ p.arg = nil
+ p.value = reflect.Value{}
+ printerPool.Put(p)
+}
+
+// printer is used to store a printer's state.
+// It implements "golang.org/x/text/internal/format".State.
+type printer struct {
+ Printer
+
+ // the context for looking up message translations
+ catContext *catalog.Context
+
+ // buffer for accumulating output.
+ bytes.Buffer
+
+ // arg holds the current item, as an interface{}.
+ arg interface{}
+ // value is used instead of arg for reflect values.
+ value reflect.Value
+
+ // fmt is used to format basic items such as integers or strings.
+ fmt formatInfo
+
+ // panicking is set by catchPanic to avoid infinite panic, recover, panic, ... recursion.
+ panicking bool
+ // erroring is set when printing an error string to guard against calling handleMethods.
+ erroring bool
+}
+
+// Language implements "golang.org/x/text/internal/format".State.
+func (p *printer) Language() language.Tag { return p.tag }
+
+func (p *printer) Width() (wid int, ok bool) { return p.fmt.Width, p.fmt.WidthPresent }
+
+func (p *printer) Precision() (prec int, ok bool) { return p.fmt.Prec, p.fmt.PrecPresent }
+
+func (p *printer) Flag(b int) bool {
+ switch b {
+ case '-':
+ return p.fmt.Minus
+ case '+':
+ return p.fmt.Plus || p.fmt.PlusV
+ case '#':
+ return p.fmt.Sharp || p.fmt.SharpV
+ case ' ':
+ return p.fmt.Space
+ case '0':
+ return p.fmt.Zero
+ }
+ return false
+}
+
+// getField gets the i'th field of the struct value.
+// If the field is itself is an interface, return a value for
+// the thing inside the interface, not the interface itself.
+func getField(v reflect.Value, i int) reflect.Value {
+ val := v.Field(i)
+ if val.Kind() == reflect.Interface && !val.IsNil() {
+ val = val.Elem()
+ }
+ return val
+}
+
+func (p *printer) unknownType(v reflect.Value) {
+ if !v.IsValid() {
+ p.WriteString(nilAngleString)
+ return
+ }
+ p.WriteByte('?')
+ p.WriteString(v.Type().String())
+ p.WriteByte('?')
+}
+
+func (p *printer) badVerb(verb rune) {
+ p.erroring = true
+ p.WriteString(percentBangString)
+ p.WriteRune(verb)
+ p.WriteByte('(')
+ switch {
+ case p.arg != nil:
+ p.WriteString(reflect.TypeOf(p.arg).String())
+ p.WriteByte('=')
+ p.printArg(p.arg, 'v')
+ case p.value.IsValid():
+ p.WriteString(p.value.Type().String())
+ p.WriteByte('=')
+ p.printValue(p.value, 'v', 0)
+ default:
+ p.WriteString(nilAngleString)
+ }
+ p.WriteByte(')')
+ p.erroring = false
+}
+
+func (p *printer) fmtBool(v bool, verb rune) {
+ switch verb {
+ case 't', 'v':
+ p.fmt.fmt_boolean(v)
+ default:
+ p.badVerb(verb)
+ }
+}
+
+// fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x or
+// not, as requested, by temporarily setting the sharp flag.
+func (p *printer) fmt0x64(v uint64, leading0x bool) {
+ sharp := p.fmt.Sharp
+ p.fmt.Sharp = leading0x
+ p.fmt.fmt_integer(v, 16, unsigned, ldigits)
+ p.fmt.Sharp = sharp
+}
+
+// fmtInteger formats a signed or unsigned integer.
+func (p *printer) fmtInteger(v uint64, isSigned bool, verb rune) {
+ switch verb {
+ case 'v':
+ if p.fmt.SharpV && !isSigned {
+ p.fmt0x64(v, true)
+ return
+ }
+ fallthrough
+ case 'd':
+ if p.fmt.Sharp || p.fmt.SharpV {
+ p.fmt.fmt_integer(v, 10, isSigned, ldigits)
+ } else {
+ p.fmtDecimalInt(v, isSigned)
+ }
+ case 'b':
+ p.fmt.fmt_integer(v, 2, isSigned, ldigits)
+ case 'o':
+ p.fmt.fmt_integer(v, 8, isSigned, ldigits)
+ case 'x':
+ p.fmt.fmt_integer(v, 16, isSigned, ldigits)
+ case 'X':
+ p.fmt.fmt_integer(v, 16, isSigned, udigits)
+ case 'c':
+ p.fmt.fmt_c(v)
+ case 'q':
+ if v <= utf8.MaxRune {
+ p.fmt.fmt_qc(v)
+ } else {
+ p.badVerb(verb)
+ }
+ case 'U':
+ p.fmt.fmt_unicode(v)
+ default:
+ p.badVerb(verb)
+ }
+}
+
+// fmtFloat formats a float. The default precision for each verb
+// is specified as last argument in the call to fmt_float.
+func (p *printer) fmtFloat(v float64, size int, verb rune) {
+ switch verb {
+ case 'b':
+ p.fmt.fmt_float(v, size, verb, -1)
+ case 'v':
+ verb = 'g'
+ fallthrough
+ case 'g', 'G':
+ if p.fmt.Sharp || p.fmt.SharpV {
+ p.fmt.fmt_float(v, size, verb, -1)
+ } else {
+ p.fmtVariableFloat(v, size)
+ }
+ case 'e', 'E':
+ if p.fmt.Sharp || p.fmt.SharpV {
+ p.fmt.fmt_float(v, size, verb, 6)
+ } else {
+ p.fmtScientific(v, size, 6)
+ }
+ case 'f', 'F':
+ if p.fmt.Sharp || p.fmt.SharpV {
+ p.fmt.fmt_float(v, size, verb, 6)
+ } else {
+ p.fmtDecimalFloat(v, size, 6)
+ }
+ default:
+ p.badVerb(verb)
+ }
+}
+
+func (p *printer) setFlags(f *number.Formatter) {
+ f.Flags &^= number.ElideSign
+ if p.fmt.Plus || p.fmt.Space {
+ f.Flags |= number.AlwaysSign
+ if !p.fmt.Plus {
+ f.Flags |= number.ElideSign
+ }
+ } else {
+ f.Flags &^= number.AlwaysSign
+ }
+}
+
+func (p *printer) updatePadding(f *number.Formatter) {
+ f.Flags &^= number.PadMask
+ if p.fmt.Minus {
+ f.Flags |= number.PadAfterSuffix
+ } else {
+ f.Flags |= number.PadBeforePrefix
+ }
+ f.PadRune = ' '
+ f.FormatWidth = uint16(p.fmt.Width)
+}
+
+func (p *printer) initDecimal(minFrac, maxFrac int) {
+ f := &p.toDecimal
+ f.MinIntegerDigits = 1
+ f.MaxIntegerDigits = 0
+ f.MinFractionDigits = uint8(minFrac)
+ f.MaxFractionDigits = int16(maxFrac)
+ p.setFlags(f)
+ f.PadRune = 0
+ if p.fmt.WidthPresent {
+ if p.fmt.Zero {
+ wid := p.fmt.Width
+ // Use significant integers for this.
+ // TODO: this is not the same as width, but so be it.
+ if f.MinFractionDigits > 0 {
+ wid -= 1 + int(f.MinFractionDigits)
+ }
+ if p.fmt.Plus || p.fmt.Space {
+ wid--
+ }
+ if wid > 0 && wid > int(f.MinIntegerDigits) {
+ f.MinIntegerDigits = uint8(wid)
+ }
+ }
+ p.updatePadding(f)
+ }
+}
+
+func (p *printer) initScientific(minFrac, maxFrac int) {
+ f := &p.toScientific
+ if maxFrac < 0 {
+ f.SetPrecision(maxFrac)
+ } else {
+ f.SetPrecision(maxFrac + 1)
+ f.MinFractionDigits = uint8(minFrac)
+ f.MaxFractionDigits = int16(maxFrac)
+ }
+ f.MinExponentDigits = 2
+ p.setFlags(f)
+ f.PadRune = 0
+ if p.fmt.WidthPresent {
+ f.Flags &^= number.PadMask
+ if p.fmt.Zero {
+ f.PadRune = f.Digit(0)
+ f.Flags |= number.PadAfterPrefix
+ } else {
+ f.PadRune = ' '
+ f.Flags |= number.PadBeforePrefix
+ }
+ p.updatePadding(f)
+ }
+}
+
+func (p *printer) fmtDecimalInt(v uint64, isSigned bool) {
+ var d number.Decimal
+
+ f := &p.toDecimal
+ if p.fmt.PrecPresent {
+ p.setFlags(f)
+ f.MinIntegerDigits = uint8(p.fmt.Prec)
+ f.MaxIntegerDigits = 0
+ f.MinFractionDigits = 0
+ f.MaxFractionDigits = 0
+ if p.fmt.WidthPresent {
+ p.updatePadding(f)
+ }
+ } else {
+ p.initDecimal(0, 0)
+ }
+ d.ConvertInt(p.toDecimal.RoundingContext, isSigned, v)
+
+ out := p.toDecimal.Format([]byte(nil), &d)
+ p.Buffer.Write(out)
+}
+
+func (p *printer) fmtDecimalFloat(v float64, size, prec int) {
+ var d number.Decimal
+ if p.fmt.PrecPresent {
+ prec = p.fmt.Prec
+ }
+ p.initDecimal(prec, prec)
+ d.ConvertFloat(p.toDecimal.RoundingContext, v, size)
+
+ out := p.toDecimal.Format([]byte(nil), &d)
+ p.Buffer.Write(out)
+}
+
+func (p *printer) fmtVariableFloat(v float64, size int) {
+ prec := -1
+ if p.fmt.PrecPresent {
+ prec = p.fmt.Prec
+ }
+ var d number.Decimal
+ p.initScientific(0, prec)
+ d.ConvertFloat(p.toScientific.RoundingContext, v, size)
+
+ // Copy logic of 'g' formatting from strconv. It is simplified a bit as
+ // we don't have to mind having prec > len(d.Digits).
+ shortest := prec < 0
+ ePrec := prec
+ if shortest {
+ prec = len(d.Digits)
+ ePrec = 6
+ } else if prec == 0 {
+ prec = 1
+ ePrec = 1
+ }
+ exp := int(d.Exp) - 1
+ if exp < -4 || exp >= ePrec {
+ p.initScientific(0, prec)
+
+ out := p.toScientific.Format([]byte(nil), &d)
+ p.Buffer.Write(out)
+ } else {
+ if prec > int(d.Exp) {
+ prec = len(d.Digits)
+ }
+ if prec -= int(d.Exp); prec < 0 {
+ prec = 0
+ }
+ p.initDecimal(0, prec)
+
+ out := p.toDecimal.Format([]byte(nil), &d)
+ p.Buffer.Write(out)
+ }
+}
+
+func (p *printer) fmtScientific(v float64, size, prec int) {
+ var d number.Decimal
+ if p.fmt.PrecPresent {
+ prec = p.fmt.Prec
+ }
+ p.initScientific(prec, prec)
+ rc := p.toScientific.RoundingContext
+ d.ConvertFloat(rc, v, size)
+
+ out := p.toScientific.Format([]byte(nil), &d)
+ p.Buffer.Write(out)
+
+}
+
+// fmtComplex formats a complex number v with
+// r = real(v) and j = imag(v) as (r+ji) using
+// fmtFloat for r and j formatting.
+func (p *printer) fmtComplex(v complex128, size int, verb rune) {
+ // Make sure any unsupported verbs are found before the
+ // calls to fmtFloat to not generate an incorrect error string.
+ switch verb {
+ case 'v', 'b', 'g', 'G', 'f', 'F', 'e', 'E':
+ p.WriteByte('(')
+ p.fmtFloat(real(v), size/2, verb)
+ // Imaginary part always has a sign.
+ if math.IsNaN(imag(v)) {
+ // By CLDR's rules, NaNs do not use patterns or signs. As this code
+ // relies on AlwaysSign working for imaginary parts, we need to
+ // manually handle NaNs.
+ f := &p.toScientific
+ p.setFlags(f)
+ p.updatePadding(f)
+ p.setFlags(f)
+ nan := f.Symbol(number.SymNan)
+ extra := 0
+ if w, ok := p.Width(); ok {
+ extra = w - utf8.RuneCountInString(nan) - 1
+ }
+ if f.Flags&number.PadAfterNumber == 0 {
+ for ; extra > 0; extra-- {
+ p.WriteRune(f.PadRune)
+ }
+ }
+ p.WriteString(f.Symbol(number.SymPlusSign))
+ p.WriteString(nan)
+ for ; extra > 0; extra-- {
+ p.WriteRune(f.PadRune)
+ }
+ p.WriteString("i)")
+ return
+ }
+ oldPlus := p.fmt.Plus
+ p.fmt.Plus = true
+ p.fmtFloat(imag(v), size/2, verb)
+ p.WriteString("i)") // TODO: use symbol?
+ p.fmt.Plus = oldPlus
+ default:
+ p.badVerb(verb)
+ }
+}
+
+func (p *printer) fmtString(v string, verb rune) {
+ switch verb {
+ case 'v':
+ if p.fmt.SharpV {
+ p.fmt.fmt_q(v)
+ } else {
+ p.fmt.fmt_s(v)
+ }
+ case 's':
+ p.fmt.fmt_s(v)
+ case 'x':
+ p.fmt.fmt_sx(v, ldigits)
+ case 'X':
+ p.fmt.fmt_sx(v, udigits)
+ case 'q':
+ p.fmt.fmt_q(v)
+ case 'm':
+ ctx := p.cat.Context(p.tag, rawPrinter{p})
+ if ctx.Execute(v) == catalog.ErrNotFound {
+ p.WriteString(v)
+ }
+ default:
+ p.badVerb(verb)
+ }
+}
+
+func (p *printer) fmtBytes(v []byte, verb rune, typeString string) {
+ switch verb {
+ case 'v', 'd':
+ if p.fmt.SharpV {
+ p.WriteString(typeString)
+ if v == nil {
+ p.WriteString(nilParenString)
+ return
+ }
+ p.WriteByte('{')
+ for i, c := range v {
+ if i > 0 {
+ p.WriteString(commaSpaceString)
+ }
+ p.fmt0x64(uint64(c), true)
+ }
+ p.WriteByte('}')
+ } else {
+ p.WriteByte('[')
+ for i, c := range v {
+ if i > 0 {
+ p.WriteByte(' ')
+ }
+ p.fmt.fmt_integer(uint64(c), 10, unsigned, ldigits)
+ }
+ p.WriteByte(']')
+ }
+ case 's':
+ p.fmt.fmt_s(string(v))
+ case 'x':
+ p.fmt.fmt_bx(v, ldigits)
+ case 'X':
+ p.fmt.fmt_bx(v, udigits)
+ case 'q':
+ p.fmt.fmt_q(string(v))
+ default:
+ p.printValue(reflect.ValueOf(v), verb, 0)
+ }
+}
+
+func (p *printer) fmtPointer(value reflect.Value, verb rune) {
+ var u uintptr
+ switch value.Kind() {
+ case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
+ u = value.Pointer()
+ default:
+ p.badVerb(verb)
+ return
+ }
+
+ switch verb {
+ case 'v':
+ if p.fmt.SharpV {
+ p.WriteByte('(')
+ p.WriteString(value.Type().String())
+ p.WriteString(")(")
+ if u == 0 {
+ p.WriteString(nilString)
+ } else {
+ p.fmt0x64(uint64(u), true)
+ }
+ p.WriteByte(')')
+ } else {
+ if u == 0 {
+ p.fmt.padString(nilAngleString)
+ } else {
+ p.fmt0x64(uint64(u), !p.fmt.Sharp)
+ }
+ }
+ case 'p':
+ p.fmt0x64(uint64(u), !p.fmt.Sharp)
+ case 'b', 'o', 'd', 'x', 'X':
+ if verb == 'd' {
+ p.fmt.Sharp = true // Print as standard go. TODO: does this make sense?
+ }
+ p.fmtInteger(uint64(u), unsigned, verb)
+ default:
+ p.badVerb(verb)
+ }
+}
+
+func (p *printer) catchPanic(arg interface{}, verb rune) {
+ if err := recover(); err != nil {
+ // If it's a nil pointer, just say "<nil>". The likeliest causes are a
+ // Stringer that fails to guard against nil or a nil pointer for a
+ // value receiver, and in either case, "<nil>" is a nice result.
+ if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() {
+ p.WriteString(nilAngleString)
+ return
+ }
+ // Otherwise print a concise panic message. Most of the time the panic
+ // value will print itself nicely.
+ if p.panicking {
+ // Nested panics; the recursion in printArg cannot succeed.
+ panic(err)
+ }
+
+ oldFlags := p.fmt.Parser
+ // For this output we want default behavior.
+ p.fmt.ClearFlags()
+
+ p.WriteString(percentBangString)
+ p.WriteRune(verb)
+ p.WriteString(panicString)
+ p.panicking = true
+ p.printArg(err, 'v')
+ p.panicking = false
+ p.WriteByte(')')
+
+ p.fmt.Parser = oldFlags
+ }
+}
+
+func (p *printer) handleMethods(verb rune) (handled bool) {
+ if p.erroring {
+ return
+ }
+ // Is it a Formatter?
+ if formatter, ok := p.arg.(format.Formatter); ok {
+ handled = true
+ defer p.catchPanic(p.arg, verb)
+ formatter.Format(p, verb)
+ return
+ }
+ if formatter, ok := p.arg.(fmt.Formatter); ok {
+ handled = true
+ defer p.catchPanic(p.arg, verb)
+ formatter.Format(p, verb)
+ return
+ }
+
+ // If we're doing Go syntax and the argument knows how to supply it, take care of it now.
+ if p.fmt.SharpV {
+ if stringer, ok := p.arg.(fmt.GoStringer); ok {
+ handled = true
+ defer p.catchPanic(p.arg, verb)
+ // Print the result of GoString unadorned.
+ p.fmt.fmt_s(stringer.GoString())
+ return
+ }
+ } else {
+ // If a string is acceptable according to the format, see if
+ // the value satisfies one of the string-valued interfaces.
+ // Println etc. set verb to %v, which is "stringable".
+ switch verb {
+ case 'v', 's', 'x', 'X', 'q':
+ // Is it an error or Stringer?
+ // The duplication in the bodies is necessary:
+ // setting handled and deferring catchPanic
+ // must happen before calling the method.
+ switch v := p.arg.(type) {
+ case error:
+ handled = true
+ defer p.catchPanic(p.arg, verb)
+ p.fmtString(v.Error(), verb)
+ return
+
+ case fmt.Stringer:
+ handled = true
+ defer p.catchPanic(p.arg, verb)
+ p.fmtString(v.String(), verb)
+ return
+ }
+ }
+ }
+ return false
+}
+
+func (p *printer) printArg(arg interface{}, verb rune) {
+ p.arg = arg
+ p.value = reflect.Value{}
+
+ if arg == nil {
+ switch verb {
+ case 'T', 'v':
+ p.fmt.padString(nilAngleString)
+ default:
+ p.badVerb(verb)
+ }
+ return
+ }
+
+ // Special processing considerations.
+ // %T (the value's type) and %p (its address) are special; we always do them first.
+ switch verb {
+ case 'T':
+ p.fmt.fmt_s(reflect.TypeOf(arg).String())
+ return
+ case 'p':
+ p.fmtPointer(reflect.ValueOf(arg), 'p')
+ return
+ }
+
+ // Some types can be done without reflection.
+ switch f := arg.(type) {
+ case bool:
+ p.fmtBool(f, verb)
+ case float32:
+ p.fmtFloat(float64(f), 32, verb)
+ case float64:
+ p.fmtFloat(f, 64, verb)
+ case complex64:
+ p.fmtComplex(complex128(f), 64, verb)
+ case complex128:
+ p.fmtComplex(f, 128, verb)
+ case int:
+ p.fmtInteger(uint64(f), signed, verb)
+ case int8:
+ p.fmtInteger(uint64(f), signed, verb)
+ case int16:
+ p.fmtInteger(uint64(f), signed, verb)
+ case int32:
+ p.fmtInteger(uint64(f), signed, verb)
+ case int64:
+ p.fmtInteger(uint64(f), signed, verb)
+ case uint:
+ p.fmtInteger(uint64(f), unsigned, verb)
+ case uint8:
+ p.fmtInteger(uint64(f), unsigned, verb)
+ case uint16:
+ p.fmtInteger(uint64(f), unsigned, verb)
+ case uint32:
+ p.fmtInteger(uint64(f), unsigned, verb)
+ case uint64:
+ p.fmtInteger(f, unsigned, verb)
+ case uintptr:
+ p.fmtInteger(uint64(f), unsigned, verb)
+ case string:
+ p.fmtString(f, verb)
+ case []byte:
+ p.fmtBytes(f, verb, "[]byte")
+ case reflect.Value:
+ // Handle extractable values with special methods
+ // since printValue does not handle them at depth 0.
+ if f.IsValid() && f.CanInterface() {
+ p.arg = f.Interface()
+ if p.handleMethods(verb) {
+ return
+ }
+ }
+ p.printValue(f, verb, 0)
+ default:
+ // If the type is not simple, it might have methods.
+ if !p.handleMethods(verb) {
+ // Need to use reflection, since the type had no
+ // interface methods that could be used for formatting.
+ p.printValue(reflect.ValueOf(f), verb, 0)
+ }
+ }
+}
+
+// printValue is similar to printArg but starts with a reflect value, not an interface{} value.
+// It does not handle 'p' and 'T' verbs because these should have been already handled by printArg.
+func (p *printer) printValue(value reflect.Value, verb rune, depth int) {
+ // Handle values with special methods if not already handled by printArg (depth == 0).
+ if depth > 0 && value.IsValid() && value.CanInterface() {
+ p.arg = value.Interface()
+ if p.handleMethods(verb) {
+ return
+ }
+ }
+ p.arg = nil
+ p.value = value
+
+ switch f := value; value.Kind() {
+ case reflect.Invalid:
+ if depth == 0 {
+ p.WriteString(invReflectString)
+ } else {
+ switch verb {
+ case 'v':
+ p.WriteString(nilAngleString)
+ default:
+ p.badVerb(verb)
+ }
+ }
+ case reflect.Bool:
+ p.fmtBool(f.Bool(), verb)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ p.fmtInteger(uint64(f.Int()), signed, verb)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ p.fmtInteger(f.Uint(), unsigned, verb)
+ case reflect.Float32:
+ p.fmtFloat(f.Float(), 32, verb)
+ case reflect.Float64:
+ p.fmtFloat(f.Float(), 64, verb)
+ case reflect.Complex64:
+ p.fmtComplex(f.Complex(), 64, verb)
+ case reflect.Complex128:
+ p.fmtComplex(f.Complex(), 128, verb)
+ case reflect.String:
+ p.fmtString(f.String(), verb)
+ case reflect.Map:
+ if p.fmt.SharpV {
+ p.WriteString(f.Type().String())
+ if f.IsNil() {
+ p.WriteString(nilParenString)
+ return
+ }
+ p.WriteByte('{')
+ } else {
+ p.WriteString(mapString)
+ }
+ keys := f.MapKeys()
+ for i, key := range keys {
+ if i > 0 {
+ if p.fmt.SharpV {
+ p.WriteString(commaSpaceString)
+ } else {
+ p.WriteByte(' ')
+ }
+ }
+ p.printValue(key, verb, depth+1)
+ p.WriteByte(':')
+ p.printValue(f.MapIndex(key), verb, depth+1)
+ }
+ if p.fmt.SharpV {
+ p.WriteByte('}')
+ } else {
+ p.WriteByte(']')
+ }
+ case reflect.Struct:
+ if p.fmt.SharpV {
+ p.WriteString(f.Type().String())
+ }
+ p.WriteByte('{')
+ for i := 0; i < f.NumField(); i++ {
+ if i > 0 {
+ if p.fmt.SharpV {
+ p.WriteString(commaSpaceString)
+ } else {
+ p.WriteByte(' ')
+ }
+ }
+ if p.fmt.PlusV || p.fmt.SharpV {
+ if name := f.Type().Field(i).Name; name != "" {
+ p.WriteString(name)
+ p.WriteByte(':')
+ }
+ }
+ p.printValue(getField(f, i), verb, depth+1)
+ }
+ p.WriteByte('}')
+ case reflect.Interface:
+ value := f.Elem()
+ if !value.IsValid() {
+ if p.fmt.SharpV {
+ p.WriteString(f.Type().String())
+ p.WriteString(nilParenString)
+ } else {
+ p.WriteString(nilAngleString)
+ }
+ } else {
+ p.printValue(value, verb, depth+1)
+ }
+ case reflect.Array, reflect.Slice:
+ switch verb {
+ case 's', 'q', 'x', 'X':
+ // Handle byte and uint8 slices and arrays special for the above verbs.
+ t := f.Type()
+ if t.Elem().Kind() == reflect.Uint8 {
+ var bytes []byte
+ if f.Kind() == reflect.Slice {
+ bytes = f.Bytes()
+ } else if f.CanAddr() {
+ bytes = f.Slice(0, f.Len()).Bytes()
+ } else {
+ // We have an array, but we cannot Slice() a non-addressable array,
+ // so we build a slice by hand. This is a rare case but it would be nice
+ // if reflection could help a little more.
+ bytes = make([]byte, f.Len())
+ for i := range bytes {
+ bytes[i] = byte(f.Index(i).Uint())
+ }
+ }
+ p.fmtBytes(bytes, verb, t.String())
+ return
+ }
+ }
+ if p.fmt.SharpV {
+ p.WriteString(f.Type().String())
+ if f.Kind() == reflect.Slice && f.IsNil() {
+ p.WriteString(nilParenString)
+ return
+ }
+ p.WriteByte('{')
+ for i := 0; i < f.Len(); i++ {
+ if i > 0 {
+ p.WriteString(commaSpaceString)
+ }
+ p.printValue(f.Index(i), verb, depth+1)
+ }
+ p.WriteByte('}')
+ } else {
+ p.WriteByte('[')
+ for i := 0; i < f.Len(); i++ {
+ if i > 0 {
+ p.WriteByte(' ')
+ }
+ p.printValue(f.Index(i), verb, depth+1)
+ }
+ p.WriteByte(']')
+ }
+ case reflect.Ptr:
+ // pointer to array or slice or struct? ok at top level
+ // but not embedded (avoid loops)
+ if depth == 0 && f.Pointer() != 0 {
+ switch a := f.Elem(); a.Kind() {
+ case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map:
+ p.WriteByte('&')
+ p.printValue(a, verb, depth+1)
+ return
+ }
+ }
+ fallthrough
+ case reflect.Chan, reflect.Func, reflect.UnsafePointer:
+ p.fmtPointer(f, verb)
+ default:
+ p.unknownType(f)
+ }
+}
+
+func (p *printer) badArgNum(verb rune) {
+ p.WriteString(percentBangString)
+ p.WriteRune(verb)
+ p.WriteString(badIndexString)
+}
+
+func (p *printer) missingArg(verb rune) {
+ p.WriteString(percentBangString)
+ p.WriteRune(verb)
+ p.WriteString(missingString)
+}
+
+func (p *printer) doPrintf(fmt string) {
+ for p.fmt.Parser.SetFormat(fmt); p.fmt.Scan(); {
+ switch p.fmt.Status {
+ case format.StatusText:
+ p.WriteString(p.fmt.Text())
+ case format.StatusSubstitution:
+ p.printArg(p.Arg(p.fmt.ArgNum), p.fmt.Verb)
+ case format.StatusBadWidthSubstitution:
+ p.WriteString(badWidthString)
+ p.printArg(p.Arg(p.fmt.ArgNum), p.fmt.Verb)
+ case format.StatusBadPrecSubstitution:
+ p.WriteString(badPrecString)
+ p.printArg(p.Arg(p.fmt.ArgNum), p.fmt.Verb)
+ case format.StatusNoVerb:
+ p.WriteString(noVerbString)
+ case format.StatusBadArgNum:
+ p.badArgNum(p.fmt.Verb)
+ case format.StatusMissingArg:
+ p.missingArg(p.fmt.Verb)
+ default:
+ panic("unreachable")
+ }
+ }
+
+ // Check for extra arguments, but only if there was at least one ordered
+ // argument. Note that this behavior is necessarily different from fmt:
+ // different variants of messages may opt to drop some or all of the
+ // arguments.
+ if !p.fmt.Reordered && p.fmt.ArgNum < len(p.fmt.Args) && p.fmt.ArgNum != 0 {
+ p.fmt.ClearFlags()
+ p.WriteString(extraString)
+ for i, arg := range p.fmt.Args[p.fmt.ArgNum:] {
+ if i > 0 {
+ p.WriteString(commaSpaceString)
+ }
+ if arg == nil {
+ p.WriteString(nilAngleString)
+ } else {
+ p.WriteString(reflect.TypeOf(arg).String())
+ p.WriteString("=")
+ p.printArg(arg, 'v')
+ }
+ }
+ p.WriteByte(')')
+ }
+}
+
+func (p *printer) doPrint(a []interface{}) {
+ prevString := false
+ for argNum, arg := range a {
+ isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
+ // Add a space between two non-string arguments.
+ if argNum > 0 && !isString && !prevString {
+ p.WriteByte(' ')
+ }
+ p.printArg(arg, 'v')
+ prevString = isString
+ }
+}
+
+// doPrintln is like doPrint but always adds a space between arguments
+// and a newline after the last argument.
+func (p *printer) doPrintln(a []interface{}) {
+ for argNum, arg := range a {
+ if argNum > 0 {
+ p.WriteByte(' ')
+ }
+ p.printArg(arg, 'v')
+ }
+ p.WriteByte('\n')
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
new file mode 100644
index 0000000..3ab6e67
--- /dev/null
+++ b/vendor/modules.txt
@@ -0,0 +1,19 @@
+# github.com/a-h/templ v0.2.747
+## explicit; go 1.21
+github.com/a-h/templ
+github.com/a-h/templ/runtime
+github.com/a-h/templ/safehtml
+# golang.org/x/text v0.17.0
+## explicit; go 1.18
+golang.org/x/text/feature/plural
+golang.org/x/text/internal
+golang.org/x/text/internal/catmsg
+golang.org/x/text/internal/format
+golang.org/x/text/internal/language
+golang.org/x/text/internal/language/compact
+golang.org/x/text/internal/number
+golang.org/x/text/internal/stringset
+golang.org/x/text/internal/tag
+golang.org/x/text/language
+golang.org/x/text/message
+golang.org/x/text/message/catalog