language: use new internal language tag package

More cleanup to come in separate CL.

Compact index generation currently disabled.
Will need to be enabled again as part of the
new compact index implementation.

Change-Id: I571c34b700ca3f22959ab261525827c7edfab511
Reviewed-on: https://go-review.googlesource.com/95822
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/language/Makefile b/language/Makefile
deleted file mode 100644
index 79f0057..0000000
--- a/language/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
-
-CLEANFILES+=maketables
-
-maketables: maketables.go
-	go build $^
-
-tables:	maketables
-	./maketables > tables.go
-	gofmt -w -s tables.go
-
-# Build (but do not run) maketables during testing,
-# just to make sure it still compiles.
-testshort: maketables
diff --git a/language/common.go b/language/common.go
deleted file mode 100644
index 9d86e18..0000000
--- a/language/common.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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.
-
-// langAliasType is the type of an alias in langAliasMap.
-type langAliasType int8
-
-const (
-	langDeprecated langAliasType = iota
-	langMacro
-	langLegacy
-
-	langAliasTypeUnknown langAliasType = -1
-)
diff --git a/language/coverage.go b/language/coverage.go
index 101fd23..3e7377d 100644
--- a/language/coverage.go
+++ b/language/coverage.go
@@ -7,6 +7,8 @@
 import (
 	"fmt"
 	"sort"
+
+	"golang.org/x/text/language/internal"
 )
 
 // The Coverage interface is used to define the level of coverage of an
@@ -44,9 +46,9 @@
 // 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, numRegions)
+	reg := make([]Region, language.NumRegions)
 	for i := range reg {
-		reg[i] = Region{regionID(i + 1)}
+		reg[i] = Region{language.Region(i + 1)}
 	}
 	return reg
 }
@@ -55,9 +57,9 @@
 // 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, numScripts)
+	scr := make([]Script, language.NumScripts)
 	for i := range scr {
-		scr[i] = Script{scriptID(i + 1)}
+		scr[i] = Script{language.Script(i + 1)}
 	}
 	return scr
 }
@@ -65,22 +67,10 @@
 // BaseLanguages returns the list of all supported base languages. It generates
 // the list by traversing the internal structures.
 func (s allSubtags) BaseLanguages() []Base {
-	base := make([]Base, 0, numLanguages)
-	for i := 0; i < langNoIndexOffset; i++ {
-		// We included "und" already for the value 0.
-		if i != nonCanonicalUnd {
-			base = append(base, Base{langID(i)})
-		}
-	}
-	i := langNoIndexOffset
-	for _, v := range langNoIndex {
-		for k := 0; k < 8; k++ {
-			if v&1 == 1 {
-				base = append(base, Base{langID(i)})
-			}
-			v >>= 1
-			i++
-		}
+	bs := language.BaseLanguages()
+	base := make([]Base, len(bs))
+	for i, b := range bs {
+		base[i] = Base{b}
 	}
 	return base
 }
@@ -134,7 +124,7 @@
 		}
 		a := make([]Base, len(tags))
 		for i, t := range tags {
-			a[i] = Base{langID(t.lang)}
+			a[i] = Base{language.Language(t.tag.LangID)}
 		}
 		sort.Sort(bases(a))
 		k := 0
diff --git a/language/coverage_test.go b/language/coverage_test.go
index 8e08e5c..8d59673 100644
--- a/language/coverage_test.go
+++ b/language/coverage_test.go
@@ -8,6 +8,8 @@
 	"fmt"
 	"reflect"
 	"testing"
+
+	"golang.org/x/text/language/internal"
 )
 
 func TestSupported(t *testing.T) {
@@ -15,9 +17,9 @@
 	// results is identical to the number of results on record, that all results
 	// are distinct and that all results are valid.
 	tests := map[string]int{
-		"BaseLanguages": numLanguages,
-		"Scripts":       numScripts,
-		"Regions":       numRegions,
+		"BaseLanguages": language.NumLanguages,
+		"Scripts":       language.NumScripts,
+		"Regions":       language.NumRegions,
 		"Tags":          0,
 	}
 	sup := reflect.ValueOf(Supported)
diff --git a/language/gen.go b/language/gen.go
index 302f194..5a0b393 100644
--- a/language/gen.go
+++ b/language/gen.go
@@ -10,21 +10,17 @@
 package main
 
 import (
-	"bufio"
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
-	"math"
 	"reflect"
-	"regexp"
 	"sort"
 	"strconv"
 	"strings"
 
 	"golang.org/x/text/internal/gen"
-	"golang.org/x/text/internal/tag"
+	"golang.org/x/text/language/internal"
 	"golang.org/x/text/unicode/cldr"
 )
 
@@ -39,81 +35,6 @@
 
 var comment = []string{
 	`
-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.`,
-	`
-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.`,
-	`
-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.`,
-	`
-altLangIndex is used to convert indexes in altLangISO3 to langIDs.`,
-	`
-langAliasMap maps langIDs to their suggested replacements.`,
-	`
-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.`,
-	`
-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.)`,
-	`
-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.`,
-	`
-regionTypes defines the status of a region for various standards.`,
-	`
-m49 maps regionIDs to UN.M49 codes. The first isoRegionOffset entries are
-codes indicating collections of regions.`,
-	`
-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.`,
-	`
-fromM49 contains entries to map UN.M49 codes to regions. See m49Index for details.`,
-	`
-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.`,
-	`
-altRegionIDs holds a list of regionIDs the positions of which match those
-of the 3-letter ISO codes in altRegionISO3.`,
-	`
-variantNumSpecialized is the number of specialized variants in variants.`,
-	`
-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.`,
-	`
-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.`,
-	`
-likelyLangList holds lists info associated with likelyLang.`,
-	`
-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.`,
-	`
-likelyRegionList holds lists info associated with likelyRegion.`,
-	`
-likelyScript is a lookup table, indexed by scriptID, for the most likely
-languages and regions given a script.`,
-	`
 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.`,
@@ -135,284 +56,52 @@
 all groups that are reachable from the groups set in the respective entry.`,
 }
 
-// TODO: consider changing some of these structures to tries. This can reduce
-// memory, but may increase the need for memory allocations. This could be
-// mitigated if we can piggyback on language tags for common cases.
-
-func failOnError(e error) {
-	if e != nil {
-		log.Panic(e)
-	}
-}
-
-type setType int
-
-const (
-	Indexed setType = 1 + iota // all elements must be of same size
-	Linear
-)
-
-type stringSet struct {
-	s              []string
-	sorted, frozen bool
-
-	// We often need to update values after the creation of an index is completed.
-	// We include a convenience map for keeping track of this.
-	update map[string]string
-	typ    setType // used for checking.
-}
-
-func (ss *stringSet) clone() stringSet {
-	c := *ss
-	c.s = append([]string(nil), c.s...)
-	return c
-}
-
-func (ss *stringSet) setType(t setType) {
-	if ss.typ != t && ss.typ != 0 {
-		log.Panicf("type %d cannot be assigned as it was already %d", t, ss.typ)
-	}
-}
-
-// parse parses a whitespace-separated string and initializes ss with its
-// components.
-func (ss *stringSet) parse(s string) {
-	scan := bufio.NewScanner(strings.NewReader(s))
-	scan.Split(bufio.ScanWords)
-	for scan.Scan() {
-		ss.add(scan.Text())
-	}
-}
-
-func (ss *stringSet) assertChangeable() {
-	if ss.frozen {
-		log.Panic("attempt to modify a frozen stringSet")
-	}
-}
-
-func (ss *stringSet) add(s string) {
-	ss.assertChangeable()
-	ss.s = append(ss.s, s)
-	ss.sorted = ss.frozen
-}
-
-func (ss *stringSet) freeze() {
-	ss.compact()
-	ss.frozen = true
-}
-
-func (ss *stringSet) compact() {
-	if ss.sorted {
-		return
-	}
-	a := ss.s
-	sort.Strings(a)
-	k := 0
-	for i := 1; i < len(a); i++ {
-		if a[k] != a[i] {
-			a[k+1] = a[i]
-			k++
-		}
-	}
-	ss.s = a[:k+1]
-	ss.sorted = ss.frozen
-}
-
-type funcSorter struct {
-	fn func(a, b string) bool
-	sort.StringSlice
-}
-
-func (s funcSorter) Less(i, j int) bool {
-	return s.fn(s.StringSlice[i], s.StringSlice[j])
-}
-
-func (ss *stringSet) sortFunc(f func(a, b string) bool) {
-	ss.compact()
-	sort.Sort(funcSorter{f, sort.StringSlice(ss.s)})
-}
-
-func (ss *stringSet) remove(s string) {
-	ss.assertChangeable()
-	if i, ok := ss.find(s); ok {
-		copy(ss.s[i:], ss.s[i+1:])
-		ss.s = ss.s[:len(ss.s)-1]
-	}
-}
-
-func (ss *stringSet) replace(ol, nu string) {
-	ss.s[ss.index(ol)] = nu
-	ss.sorted = ss.frozen
-}
-
-func (ss *stringSet) index(s string) int {
-	ss.setType(Indexed)
-	i, ok := ss.find(s)
-	if !ok {
-		if i < len(ss.s) {
-			log.Panicf("find: item %q is not in list. Closest match is %q.", s, ss.s[i])
-		}
-		log.Panicf("find: item %q is not in list", s)
-
-	}
-	return i
-}
-
-func (ss *stringSet) find(s string) (int, bool) {
-	ss.compact()
-	i := sort.SearchStrings(ss.s, s)
-	return i, i != len(ss.s) && ss.s[i] == s
-}
-
-func (ss *stringSet) slice() []string {
-	ss.compact()
-	return ss.s
-}
-
-func (ss *stringSet) updateLater(v, key string) {
-	if ss.update == nil {
-		ss.update = map[string]string{}
-	}
-	ss.update[v] = key
-}
-
-// join joins the string and ensures that all entries are of the same length.
-func (ss *stringSet) join() string {
-	ss.setType(Indexed)
-	n := len(ss.s[0])
-	for _, s := range ss.s {
-		if len(s) != n {
-			log.Panicf("join: not all entries are of the same length: %q", s)
-		}
-	}
-	ss.s = append(ss.s, strings.Repeat("\xff", n))
-	return strings.Join(ss.s, "")
-}
-
-// ianaEntry holds information for an entry in the IANA Language Subtag Repository.
-// All types use the same entry.
-// See http://tools.ietf.org/html/bcp47#section-5.1 for a description of the various
-// fields.
-type ianaEntry struct {
-	typ            string
-	description    []string
-	scope          string
-	added          string
-	preferred      string
-	deprecated     string
-	suppressScript string
-	macro          string
-	prefix         []string
-}
-
 type builder struct {
 	w    *gen.CodeWriter
 	hw   io.Writer // MultiWriter for w and w.Hash
 	data *cldr.CLDR
 	supp *cldr.SupplementalData
 
-	// indices
-	locale      stringSet // common locales
-	lang        stringSet // canonical language ids (2 or 3 letter ISO codes) with data
-	langNoIndex stringSet // 3-letter ISO codes with no associated data
-	script      stringSet // 4-letter ISO codes
-	region      stringSet // 2-letter ISO or 3-digit UN M49 codes
-	variant     stringSet // 4-8-alphanumeric variant code.
-
-	// Region codes that are groups with their corresponding group IDs.
-	groups map[int]index
-
-	// langInfo
-	registry map[string]*ianaEntry
+	// lang   index
+	region index
+	script index
 }
 
-type index uint
+func (b *builder) langIndex(s string) uint16 {
+	return uint16(language.MustParseBase(s))
+}
+
+type index func(s string) int
+
+func (i index) index(s string) int {
+	return i(s)
+}
 
 func newBuilder(w *gen.CodeWriter) *builder {
 	r := gen.OpenCLDRCoreZip()
 	defer r.Close()
 	d := &cldr.Decoder{}
 	data, err := d.DecodeZip(r)
-	failOnError(err)
+	if err != nil {
+		log.Fatal(err)
+	}
 	b := builder{
 		w:    w,
 		hw:   io.MultiWriter(w, w.Hash),
 		data: data,
 		supp: data.Supplemental(),
+
+		script: func(s string) int {
+			return int(language.MustParseScript(s))
+		},
+
+		region: func(s string) int {
+			return int(language.MustParseRegion(s))
+		},
 	}
-	b.parseRegistry()
 	return &b
 }
 
-func (b *builder) parseRegistry() {
-	r := gen.OpenIANAFile("assignments/language-subtag-registry")
-	defer r.Close()
-	b.registry = make(map[string]*ianaEntry)
-
-	scan := bufio.NewScanner(r)
-	scan.Split(bufio.ScanWords)
-	var record *ianaEntry
-	for more := scan.Scan(); more; {
-		key := scan.Text()
-		more = scan.Scan()
-		value := scan.Text()
-		switch key {
-		case "Type:":
-			record = &ianaEntry{typ: value}
-		case "Subtag:", "Tag:":
-			if s := strings.SplitN(value, "..", 2); len(s) > 1 {
-				for a := s[0]; a <= s[1]; a = inc(a) {
-					b.addToRegistry(a, record)
-				}
-			} else {
-				b.addToRegistry(value, record)
-			}
-		case "Suppress-Script:":
-			record.suppressScript = value
-		case "Added:":
-			record.added = value
-		case "Deprecated:":
-			record.deprecated = value
-		case "Macrolanguage:":
-			record.macro = value
-		case "Preferred-Value:":
-			record.preferred = value
-		case "Prefix:":
-			record.prefix = append(record.prefix, value)
-		case "Scope:":
-			record.scope = value
-		case "Description:":
-			buf := []byte(value)
-			for more = scan.Scan(); more; more = scan.Scan() {
-				b := scan.Bytes()
-				if b[0] == '%' || b[len(b)-1] == ':' {
-					break
-				}
-				buf = append(buf, ' ')
-				buf = append(buf, b...)
-			}
-			record.description = append(record.description, string(buf))
-			continue
-		default:
-			continue
-		}
-		more = scan.Scan()
-	}
-	if scan.Err() != nil {
-		log.Panic(scan.Err())
-	}
-}
-
-func (b *builder) addToRegistry(key string, entry *ianaEntry) {
-	if info, ok := b.registry[key]; ok {
-		if info.typ != "language" || entry.typ != "extlang" {
-			log.Fatalf("parseRegistry: tag %q already exists", key)
-		}
-	} else {
-		b.registry[key] = entry
-	}
-}
-
 var commentIndex = make(map[string]string)
 
 func init() {
@@ -481,229 +170,8 @@
 	b.p()
 }
 
-type fromTo struct {
-	from, to uint16
-}
-
-func (b *builder) writeSortedMap(name string, ss *stringSet, index func(s string) uint16) {
-	ss.sortFunc(func(a, b string) bool {
-		return index(a) < index(b)
-	})
-	m := []fromTo{}
-	for _, s := range ss.s {
-		m = append(m, fromTo{index(s), index(ss.update[s])})
-	}
-	b.writeSlice(name, m)
-}
-
-const base = 'z' - 'a' + 1
-
-func strToInt(s string) 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
-	}
-}
-
-func (b *builder) writeBitVector(name string, ss []string) {
-	vec := make([]uint8, int(math.Ceil(math.Pow(base, float64(len(ss[0])))/8)))
-	for _, s := range ss {
-		v := strToInt(s)
-		vec[v/8] |= 1 << (v % 8)
-	}
-	b.writeSlice(name, vec)
-}
-
-// TODO: convert this type into a list or two-stage trie.
-func (b *builder) writeMapFunc(name string, m map[string]string, f func(string) uint16) {
-	b.comment(name)
-	v := reflect.ValueOf(m)
-	sz := v.Len() * (2 + int(v.Type().Key().Size()))
-	for _, k := range m {
-		sz += len(k)
-	}
-	b.addSize(sz)
-	keys := []string{}
-	b.pf(`var %s = map[string]uint16{`, name)
-	for k := range m {
-		keys = append(keys, k)
-	}
-	sort.Strings(keys)
-	for _, k := range keys {
-		b.pf("\t%q: %v,", k, f(m[k]))
-	}
-	b.p("}")
-}
-
-func (b *builder) writeMap(name string, m interface{}) {
-	b.comment(name)
-	v := reflect.ValueOf(m)
-	sz := v.Len() * (2 + int(v.Type().Key().Size()) + int(v.Type().Elem().Size()))
-	b.addSize(sz)
-	f := strings.FieldsFunc(fmt.Sprintf("%#v", m), func(r rune) bool {
-		return strings.IndexRune("{}, ", r) != -1
-	})
-	sort.Strings(f[1:])
-	b.pf(`var %s = %s{`, name, f[0])
-	for _, kv := range f[1:] {
-		b.pf("\t%s,", kv)
-	}
-	b.p("}")
-}
-
-func (b *builder) langIndex(s string) uint16 {
-	if s == "und" {
-		return 0
-	}
-	if i, ok := b.lang.find(s); ok {
-		return uint16(i)
-	}
-	return uint16(strToInt(s)) + uint16(len(b.lang.s))
-}
-
-// inc advances the string to its lexicographical successor.
-func inc(s string) string {
-	const maxTagLength = 4
-	var buf [maxTagLength]byte
-	intToStr(strToInt(strings.ToLower(s))+1, buf[:len(s)])
-	for i := 0; i < len(s); i++ {
-		if s[i] <= 'Z' {
-			buf[i] -= 'a' - 'A'
-		}
-	}
-	return string(buf[:len(s)])
-}
-
-func (b *builder) parseIndices() {
-	meta := b.supp.Metadata
-
-	for k, v := range b.registry {
-		var ss *stringSet
-		switch v.typ {
-		case "language":
-			if len(k) == 2 || v.suppressScript != "" || v.scope == "special" {
-				b.lang.add(k)
-				continue
-			} else {
-				ss = &b.langNoIndex
-			}
-		case "region":
-			ss = &b.region
-		case "script":
-			ss = &b.script
-		case "variant":
-			ss = &b.variant
-		default:
-			continue
-		}
-		ss.add(k)
-	}
-	// Include any language for which there is data.
-	for _, lang := range b.data.Locales() {
-		if x := b.data.RawLDML(lang); false ||
-			x.LocaleDisplayNames != nil ||
-			x.Characters != nil ||
-			x.Delimiters != nil ||
-			x.Measurement != nil ||
-			x.Dates != nil ||
-			x.Numbers != nil ||
-			x.Units != nil ||
-			x.ListPatterns != nil ||
-			x.Collations != nil ||
-			x.Segmentations != nil ||
-			x.Rbnf != nil ||
-			x.Annotations != nil ||
-			x.Metadata != nil {
-
-			from := strings.Split(lang, "_")
-			if lang := from[0]; lang != "root" {
-				b.lang.add(lang)
-			}
-		}
-	}
-	// Include locales for plural rules, which uses a different structure.
-	for _, plurals := range b.data.Supplemental().Plurals {
-		for _, rules := range plurals.PluralRules {
-			for _, lang := range strings.Split(rules.Locales, " ") {
-				if lang = strings.Split(lang, "_")[0]; lang != "root" {
-					b.lang.add(lang)
-				}
-			}
-		}
-	}
-	// Include languages in likely subtags.
-	for _, m := range b.supp.LikelySubtags.LikelySubtag {
-		from := strings.Split(m.From, "_")
-		b.lang.add(from[0])
-	}
-	// Include ISO-639 alpha-3 bibliographic entries.
-	for _, a := range meta.Alias.LanguageAlias {
-		if a.Reason == "bibliographic" {
-			b.langNoIndex.add(a.Type)
-		}
-	}
-	// Include regions in territoryAlias (not all are in the IANA registry!)
-	for _, reg := range b.supp.Metadata.Alias.TerritoryAlias {
-		if len(reg.Type) == 2 {
-			b.region.add(reg.Type)
-		}
-	}
-
-	for _, s := range b.lang.s {
-		if len(s) == 3 {
-			b.langNoIndex.remove(s)
-		}
-	}
-	b.writeConst("numLanguages", len(b.lang.slice())+len(b.langNoIndex.slice()))
-	b.writeConst("numScripts", len(b.script.slice()))
-	b.writeConst("numRegions", len(b.region.slice()))
-
-	// Add dummy codes at the start of each list to represent "unspecified".
-	b.lang.add("---")
-	b.script.add("----")
-	b.region.add("---")
-
-	// common locales
-	b.locale.parse(meta.DefaultContent.Locales)
-}
-
 // TODO: region inclusion data will probably not be use used in future matchers.
 
-func (b *builder) computeRegionGroups() {
-	b.groups = make(map[int]index)
-
-	// Create group indices.
-	for i := 1; b.region.s[i][0] < 'A'; i++ { // Base M49 indices on regionID.
-		b.groups[i] = index(len(b.groups))
-	}
-	for _, g := range b.supp.TerritoryContainment.Group {
-		// Skip UN and EURO zone as they are flattening the containment
-		// relationship.
-		if g.Type == "EZ" || g.Type == "UN" {
-			continue
-		}
-		group := b.region.index(g.Type)
-		if _, ok := b.groups[group]; !ok {
-			b.groups[group] = index(len(b.groups))
-		}
-	}
-	if len(b.groups) > 64 {
-		log.Fatalf("only 64 groups supported, found %d", len(b.groups))
-	}
-	b.writeConst("nRegionGroups", len(b.groups))
-}
-
 var langConsts = []string{
 	"af", "am", "ar", "az", "bg", "bn", "ca", "cs", "da", "de", "el", "en", "es",
 	"et", "fa", "fi", "fil", "fr", "gu", "he", "hi", "hr", "hu", "hy", "id", "is",
@@ -717,648 +185,20 @@
 	"nn", "sfb", "vgt", "sgg", "cmn", "nan", "hsn",
 }
 
-// writeLanguage generates all tables needed for language canonicalization.
-func (b *builder) writeLanguage() {
-	meta := b.supp.Metadata
-
-	b.writeConst("nonCanonicalUnd", b.lang.index("und"))
-	b.writeConsts(func(s string) int { return int(b.langIndex(s)) }, langConsts...)
-	b.writeConst("langPrivateStart", b.langIndex("qaa"))
-	b.writeConst("langPrivateEnd", b.langIndex("qtz"))
-
-	// Get language codes that need to be mapped (overlong 3-letter codes,
-	// deprecated 2-letter codes, legacy and grandfathered tags.)
-	langAliasMap := stringSet{}
-	aliasTypeMap := map[string]langAliasType{}
-
-	// altLangISO3 get the alternative ISO3 names that need to be mapped.
-	altLangISO3 := stringSet{}
-	// Add dummy start to avoid the use of index 0.
-	altLangISO3.add("---")
-	altLangISO3.updateLater("---", "aa")
-
-	lang := b.lang.clone()
-	for _, a := range meta.Alias.LanguageAlias {
-		if a.Replacement == "" {
-			a.Replacement = "und"
-		}
-		// TODO: support mapping to tags
-		repl := strings.SplitN(a.Replacement, "_", 2)[0]
-		if a.Reason == "overlong" {
-			if len(a.Replacement) == 2 && len(a.Type) == 3 {
-				lang.updateLater(a.Replacement, a.Type)
-			}
-		} else if len(a.Type) <= 3 {
-			switch a.Reason {
-			case "macrolanguage":
-				aliasTypeMap[a.Type] = langMacro
-			case "deprecated":
-				// handled elsewhere
-				continue
-			case "bibliographic", "legacy":
-				if a.Type == "no" {
-					continue
-				}
-				aliasTypeMap[a.Type] = langLegacy
-			default:
-				log.Fatalf("new %s alias: %s", a.Reason, a.Type)
-			}
-			langAliasMap.add(a.Type)
-			langAliasMap.updateLater(a.Type, repl)
-		}
-	}
-	// Manually add the mapping of "nb" (Norwegian) to its macro language.
-	// This can be removed if CLDR adopts this change.
-	langAliasMap.add("nb")
-	langAliasMap.updateLater("nb", "no")
-	aliasTypeMap["nb"] = langMacro
-
-	for k, v := range b.registry {
-		// Also add deprecated values for 3-letter ISO codes, which CLDR omits.
-		if v.typ == "language" && v.deprecated != "" && v.preferred != "" {
-			langAliasMap.add(k)
-			langAliasMap.updateLater(k, v.preferred)
-			aliasTypeMap[k] = langDeprecated
-		}
-	}
-	// Fix CLDR mappings.
-	lang.updateLater("tl", "tgl")
-	lang.updateLater("sh", "hbs")
-	lang.updateLater("mo", "mol")
-	lang.updateLater("no", "nor")
-	lang.updateLater("tw", "twi")
-	lang.updateLater("nb", "nob")
-	lang.updateLater("ak", "aka")
-	lang.updateLater("bh", "bih")
-
-	// Ensure that each 2-letter code is matched with a 3-letter code.
-	for _, v := range lang.s[1:] {
-		s, ok := lang.update[v]
-		if !ok {
-			if s, ok = lang.update[langAliasMap.update[v]]; !ok {
-				continue
-			}
-			lang.update[v] = s
-		}
-		if v[0] != s[0] {
-			altLangISO3.add(s)
-			altLangISO3.updateLater(s, v)
-		}
-	}
-
-	// Complete canonicalized language tags.
-	lang.freeze()
-	for i, v := range lang.s {
-		// We can avoid these manual entries by using the IANA registry directly.
-		// Seems easier to update the list manually, as changes are rare.
-		// The panic in this loop will trigger if we miss an entry.
-		add := ""
-		if s, ok := lang.update[v]; ok {
-			if s[0] == v[0] {
-				add = s[1:]
-			} else {
-				add = string([]byte{0, byte(altLangISO3.index(s))})
-			}
-		} else if len(v) == 3 {
-			add = "\x00"
-		} else {
-			log.Panicf("no data for long form of %q", v)
-		}
-		lang.s[i] += add
-	}
-	b.writeConst("lang", tag.Index(lang.join()))
-
-	b.writeConst("langNoIndexOffset", len(b.lang.s))
-
-	// space of all valid 3-letter language identifiers.
-	b.writeBitVector("langNoIndex", b.langNoIndex.slice())
-
-	altLangIndex := []uint16{}
-	for i, s := range altLangISO3.slice() {
-		altLangISO3.s[i] += string([]byte{byte(len(altLangIndex))})
-		if i > 0 {
-			idx := b.lang.index(altLangISO3.update[s])
-			altLangIndex = append(altLangIndex, uint16(idx))
-		}
-	}
-	b.writeConst("altLangISO3", tag.Index(altLangISO3.join()))
-	b.writeSlice("altLangIndex", altLangIndex)
-
-	b.writeSortedMap("langAliasMap", &langAliasMap, b.langIndex)
-	types := make([]langAliasType, len(langAliasMap.s))
-	for i, s := range langAliasMap.s {
-		types[i] = aliasTypeMap[s]
-	}
-	b.writeSlice("langAliasTypes", types)
-}
-
 var scriptConsts = []string{
 	"Latn", "Hani", "Hans", "Hant", "Qaaa", "Qaai", "Qabx", "Zinh", "Zyyy",
 	"Zzzz",
 }
 
-func (b *builder) writeScript() {
-	b.writeConsts(b.script.index, scriptConsts...)
-	b.writeConst("script", tag.Index(b.script.join()))
-
-	supp := make([]uint8, len(b.lang.slice()))
-	for i, v := range b.lang.slice()[1:] {
-		if sc := b.registry[v].suppressScript; sc != "" {
-			supp[i+1] = uint8(b.script.index(sc))
-		}
-	}
-	b.writeSlice("suppressScript", supp)
-
-	// There is only one deprecated script in CLDR. This value is hard-coded.
-	// We check here if the code must be updated.
-	for _, a := range b.supp.Metadata.Alias.ScriptAlias {
-		if a.Type != "Qaai" {
-			log.Panicf("unexpected deprecated stript %q", a.Type)
-		}
-	}
-}
-
-func parseM49(s string) int16 {
-	if len(s) == 0 {
-		return 0
-	}
-	v, err := strconv.ParseUint(s, 10, 10)
-	failOnError(err)
-	return int16(v)
-}
-
 var regionConsts = []string{
 	"001", "419", "BR", "CA", "ES", "GB", "MD", "PT", "UK", "US",
 	"ZZ", "XA", "XC", "XK", // Unofficial tag for Kosovo.
 }
 
-func (b *builder) writeRegion() {
-	b.writeConsts(b.region.index, regionConsts...)
-
-	isoOffset := b.region.index("AA")
-	m49map := make([]int16, len(b.region.slice()))
-	fromM49map := make(map[int16]int)
-	altRegionISO3 := ""
-	altRegionIDs := []uint16{}
-
-	b.writeConst("isoRegionOffset", isoOffset)
-
-	// 2-letter region lookup and mapping to numeric codes.
-	regionISO := b.region.clone()
-	regionISO.s = regionISO.s[isoOffset:]
-	regionISO.sorted = false
-
-	regionTypes := make([]byte, len(b.region.s))
-
-	// Is the region valid BCP 47?
-	for s, e := range b.registry {
-		if len(s) == 2 && s == strings.ToUpper(s) {
-			i := b.region.index(s)
-			for _, d := range e.description {
-				if strings.Contains(d, "Private use") {
-					regionTypes[i] = iso3166UserAssigned
-				}
-			}
-			regionTypes[i] |= bcp47Region
-		}
-	}
-
-	// Is the region a valid ccTLD?
-	r := gen.OpenIANAFile("domains/root/db")
-	defer r.Close()
-
-	buf, err := ioutil.ReadAll(r)
-	failOnError(err)
-	re := regexp.MustCompile(`"/domains/root/db/([a-z]{2}).html"`)
-	for _, m := range re.FindAllSubmatch(buf, -1) {
-		i := b.region.index(strings.ToUpper(string(m[1])))
-		regionTypes[i] |= ccTLD
-	}
-
-	b.writeSlice("regionTypes", regionTypes)
-
-	iso3Set := make(map[string]int)
-	update := func(iso2, iso3 string) {
-		i := regionISO.index(iso2)
-		if j, ok := iso3Set[iso3]; !ok && iso3[0] == iso2[0] {
-			regionISO.s[i] += iso3[1:]
-			iso3Set[iso3] = -1
-		} else {
-			if ok && j >= 0 {
-				regionISO.s[i] += string([]byte{0, byte(j)})
-			} else {
-				iso3Set[iso3] = len(altRegionISO3)
-				regionISO.s[i] += string([]byte{0, byte(len(altRegionISO3))})
-				altRegionISO3 += iso3
-				altRegionIDs = append(altRegionIDs, uint16(isoOffset+i))
-			}
-		}
-	}
-	for _, tc := range b.supp.CodeMappings.TerritoryCodes {
-		i := regionISO.index(tc.Type) + isoOffset
-		if d := m49map[i]; d != 0 {
-			log.Panicf("%s found as a duplicate UN.M49 code of %03d", tc.Numeric, d)
-		}
-		m49 := parseM49(tc.Numeric)
-		m49map[i] = m49
-		if r := fromM49map[m49]; r == 0 {
-			fromM49map[m49] = i
-		} else if r != i {
-			dep := b.registry[regionISO.s[r-isoOffset]].deprecated
-			if t := b.registry[tc.Type]; t != nil && dep != "" && (t.deprecated == "" || t.deprecated > dep) {
-				fromM49map[m49] = i
-			}
-		}
-	}
-	for _, ta := range b.supp.Metadata.Alias.TerritoryAlias {
-		if len(ta.Type) == 3 && ta.Type[0] <= '9' && len(ta.Replacement) == 2 {
-			from := parseM49(ta.Type)
-			if r := fromM49map[from]; r == 0 {
-				fromM49map[from] = regionISO.index(ta.Replacement) + isoOffset
-			}
-		}
-	}
-	for _, tc := range b.supp.CodeMappings.TerritoryCodes {
-		if len(tc.Alpha3) == 3 {
-			update(tc.Type, tc.Alpha3)
-		}
-	}
-	// This entries are not included in territoryCodes. Mostly 3-letter variants
-	// of deleted codes and an entry for QU.
-	for _, m := range []struct{ iso2, iso3 string }{
-		{"CT", "CTE"},
-		{"DY", "DHY"},
-		{"HV", "HVO"},
-		{"JT", "JTN"},
-		{"MI", "MID"},
-		{"NH", "NHB"},
-		{"NQ", "ATN"},
-		{"PC", "PCI"},
-		{"PU", "PUS"},
-		{"PZ", "PCZ"},
-		{"RH", "RHO"},
-		{"VD", "VDR"},
-		{"WK", "WAK"},
-		// These three-letter codes are used for others as well.
-		{"FQ", "ATF"},
-	} {
-		update(m.iso2, m.iso3)
-	}
-	for i, s := range regionISO.s {
-		if len(s) != 4 {
-			regionISO.s[i] = s + "  "
-		}
-	}
-	b.writeConst("regionISO", tag.Index(regionISO.join()))
-	b.writeConst("altRegionISO3", altRegionISO3)
-	b.writeSlice("altRegionIDs", altRegionIDs)
-
-	// Create list of deprecated regions.
-	// TODO: consider inserting SF -> FI. Not included by CLDR, but is the only
-	// Transitionally-reserved mapping not included.
-	regionOldMap := stringSet{}
-	// Include regions in territoryAlias (not all are in the IANA registry!)
-	for _, reg := range b.supp.Metadata.Alias.TerritoryAlias {
-		if len(reg.Type) == 2 && reg.Reason == "deprecated" && len(reg.Replacement) == 2 {
-			regionOldMap.add(reg.Type)
-			regionOldMap.updateLater(reg.Type, reg.Replacement)
-			i, _ := regionISO.find(reg.Type)
-			j, _ := regionISO.find(reg.Replacement)
-			if k := m49map[i+isoOffset]; k == 0 {
-				m49map[i+isoOffset] = m49map[j+isoOffset]
-			}
-		}
-	}
-	b.writeSortedMap("regionOldMap", &regionOldMap, func(s string) uint16 {
-		return uint16(b.region.index(s))
-	})
-	// 3-digit region lookup, groupings.
-	for i := 1; i < isoOffset; i++ {
-		m := parseM49(b.region.s[i])
-		m49map[i] = m
-		fromM49map[m] = i
-	}
-	b.writeSlice("m49", m49map)
-
-	const (
-		searchBits = 7
-		regionBits = 9
-	)
-	if len(m49map) >= 1<<regionBits {
-		log.Fatalf("Maximum number of regions exceeded: %d > %d", len(m49map), 1<<regionBits)
-	}
-	m49Index := [9]int16{}
-	fromM49 := []uint16{}
-	m49 := []int{}
-	for k, _ := range fromM49map {
-		m49 = append(m49, int(k))
-	}
-	sort.Ints(m49)
-	for _, k := range m49[1:] {
-		val := (k & (1<<searchBits - 1)) << regionBits
-		fromM49 = append(fromM49, uint16(val|fromM49map[int16(k)]))
-		m49Index[1:][k>>searchBits] = int16(len(fromM49))
-	}
-	b.writeSlice("m49Index", m49Index)
-	b.writeSlice("fromM49", fromM49)
-}
-
-const (
-	// TODO: put these lists in regionTypes as user data? Could be used for
-	// various optimizations and refinements and could be exposed in the API.
-	iso3166Except = "AC CP DG EA EU FX IC SU TA UK"
-	iso3166Trans  = "AN BU CS NT TP YU ZR" // SF is not in our set of Regions.
-	// DY and RH are actually not deleted, but indeterminately reserved.
-	iso3166DelCLDR = "CT DD DY FQ HV JT MI NH NQ PC PU PZ RH VD WK YD"
-)
-
-const (
-	iso3166UserAssigned = 1 << iota
-	ccTLD
-	bcp47Region
-)
-
-func find(list []string, s string) int {
-	for i, t := range list {
-		if t == s {
-			return i
-		}
-	}
-	return -1
-}
-
-// writeVariants generates per-variant information and creates a map from variant
-// name to index value. We assign index values such that sorting multiple
-// variants by index value will result in the correct order.
-// There are two types of variants: specialized and general. Specialized variants
-// are only applicable to certain language or language-script pairs. Generalized
-// variants apply to any language. Generalized variants always sort after
-// specialized variants.  We will therefore always assign a higher index value
-// to a generalized variant than any other variant. Generalized variants are
-// sorted alphabetically among themselves.
-// Specialized variants may also sort after other specialized variants. Such
-// variants will be ordered after any of the variants they may follow.
-// We assume that if a variant x is followed by a variant y, then for any prefix
-// p of x, p-x is a prefix of y. This allows us to order tags based on the
-// maximum of the length of any of its prefixes.
-// TODO: it is possible to define a set of Prefix values on variants such that
-// a total order cannot be defined to the point that this algorithm breaks.
-// In other words, we cannot guarantee the same order of variants for the
-// future using the same algorithm or for non-compliant combinations of
-// variants. For this reason, consider using simple alphabetic sorting
-// of variants and ignore Prefix restrictions altogether.
-func (b *builder) writeVariant() {
-	generalized := stringSet{}
-	specialized := stringSet{}
-	specializedExtend := stringSet{}
-	// Collate the variants by type and check assumptions.
-	for _, v := range b.variant.slice() {
-		e := b.registry[v]
-		if len(e.prefix) == 0 {
-			generalized.add(v)
-			continue
-		}
-		c := strings.Split(e.prefix[0], "-")
-		hasScriptOrRegion := false
-		if len(c) > 1 {
-			_, hasScriptOrRegion = b.script.find(c[1])
-			if !hasScriptOrRegion {
-				_, hasScriptOrRegion = b.region.find(c[1])
-
-			}
-		}
-		if len(c) == 1 || len(c) == 2 && hasScriptOrRegion {
-			// Variant is preceded by a language.
-			specialized.add(v)
-			continue
-		}
-		// Variant is preceded by another variant.
-		specializedExtend.add(v)
-		prefix := c[0] + "-"
-		if hasScriptOrRegion {
-			prefix += c[1]
-		}
-		for _, p := range e.prefix {
-			// Verify that the prefix minus the last element is a prefix of the
-			// predecessor element.
-			i := strings.LastIndex(p, "-")
-			pred := b.registry[p[i+1:]]
-			if find(pred.prefix, p[:i]) < 0 {
-				log.Fatalf("prefix %q for variant %q not consistent with predecessor spec", p, v)
-			}
-			// The sorting used below does not work in the general case. It works
-			// if we assume that variants that may be followed by others only have
-			// prefixes of the same length. Verify this.
-			count := strings.Count(p[:i], "-")
-			for _, q := range pred.prefix {
-				if c := strings.Count(q, "-"); c != count {
-					log.Fatalf("variant %q preceding %q has a prefix %q of size %d; want %d", p[i+1:], v, q, c, count)
-				}
-			}
-			if !strings.HasPrefix(p, prefix) {
-				log.Fatalf("prefix %q of variant %q should start with %q", p, v, prefix)
-			}
-		}
-	}
-
-	// Sort extended variants.
-	a := specializedExtend.s
-	less := func(v, w string) bool {
-		// Sort by the maximum number of elements.
-		maxCount := func(s string) (max int) {
-			for _, p := range b.registry[s].prefix {
-				if c := strings.Count(p, "-"); c > max {
-					max = c
-				}
-			}
-			return
-		}
-		if cv, cw := maxCount(v), maxCount(w); cv != cw {
-			return cv < cw
-		}
-		// Sort by name as tie breaker.
-		return v < w
-	}
-	sort.Sort(funcSorter{less, sort.StringSlice(a)})
-	specializedExtend.frozen = true
-
-	// Create index from variant name to index.
-	variantIndex := make(map[string]uint8)
-	add := func(s []string) {
-		for _, v := range s {
-			variantIndex[v] = uint8(len(variantIndex))
-		}
-	}
-	add(specialized.slice())
-	add(specializedExtend.s)
-	numSpecialized := len(variantIndex)
-	add(generalized.slice())
-	if n := len(variantIndex); n > 255 {
-		log.Fatalf("maximum number of variants exceeded: was %d; want <= 255", n)
-	}
-	b.writeMap("variantIndex", variantIndex)
-	b.writeConst("variantNumSpecialized", numSpecialized)
-}
-
-func (b *builder) writeLanguageInfo() {
-}
-
-// writeLikelyData writes tables that are used both for finding parent relations and for
-// language matching.  Each entry contains additional bits to indicate the status of the
-// data to know when it cannot be used for parent relations.
-func (b *builder) writeLikelyData() {
-	const (
-		isList = 1 << iota
-		scriptInFrom
-		regionInFrom
-	)
-	type ( // generated types
-		likelyScriptRegion struct {
-			region uint16
-			script uint8
-			flags  uint8
-		}
-		likelyLangScript struct {
-			lang   uint16
-			script uint8
-			flags  uint8
-		}
-		likelyLangRegion struct {
-			lang   uint16
-			region uint16
-		}
-		// likelyTag is used for getting likely tags for group regions, where
-		// the likely region might be a region contained in the group.
-		likelyTag struct {
-			lang   uint16
-			region uint16
-			script uint8
-		}
-	)
-	var ( // generated variables
-		likelyRegionGroup = make([]likelyTag, len(b.groups))
-		likelyLang        = make([]likelyScriptRegion, len(b.lang.s))
-		likelyRegion      = make([]likelyLangScript, len(b.region.s))
-		likelyScript      = make([]likelyLangRegion, len(b.script.s))
-		likelyLangList    = []likelyScriptRegion{}
-		likelyRegionList  = []likelyLangScript{}
-	)
-	type fromTo struct {
-		from, to []string
-	}
-	langToOther := map[int][]fromTo{}
-	regionToOther := map[int][]fromTo{}
-	for _, m := range b.supp.LikelySubtags.LikelySubtag {
-		from := strings.Split(m.From, "_")
-		to := strings.Split(m.To, "_")
-		if len(to) != 3 {
-			log.Fatalf("invalid number of subtags in %q: found %d, want 3", m.To, len(to))
-		}
-		if len(from) > 3 {
-			log.Fatalf("invalid number of subtags: found %d, want 1-3", len(from))
-		}
-		if from[0] != to[0] && from[0] != "und" {
-			log.Fatalf("unexpected language change in expansion: %s -> %s", from, to)
-		}
-		if len(from) == 3 {
-			if from[2] != to[2] {
-				log.Fatalf("unexpected region change in expansion: %s -> %s", from, to)
-			}
-			if from[0] != "und" {
-				log.Fatalf("unexpected fully specified from tag: %s -> %s", from, to)
-			}
-		}
-		if len(from) == 1 || from[0] != "und" {
-			id := 0
-			if from[0] != "und" {
-				id = b.lang.index(from[0])
-			}
-			langToOther[id] = append(langToOther[id], fromTo{from, to})
-		} else if len(from) == 2 && len(from[1]) == 4 {
-			sid := b.script.index(from[1])
-			likelyScript[sid].lang = uint16(b.langIndex(to[0]))
-			likelyScript[sid].region = uint16(b.region.index(to[2]))
-		} else {
-			r := b.region.index(from[len(from)-1])
-			if id, ok := b.groups[r]; ok {
-				if from[0] != "und" {
-					log.Fatalf("region changed unexpectedly: %s -> %s", from, to)
-				}
-				likelyRegionGroup[id].lang = uint16(b.langIndex(to[0]))
-				likelyRegionGroup[id].script = uint8(b.script.index(to[1]))
-				likelyRegionGroup[id].region = uint16(b.region.index(to[2]))
-			} else {
-				regionToOther[r] = append(regionToOther[r], fromTo{from, to})
-			}
-		}
-	}
-	b.writeType(likelyLangRegion{})
-	b.writeSlice("likelyScript", likelyScript)
-
-	for id := range b.lang.s {
-		list := langToOther[id]
-		if len(list) == 1 {
-			likelyLang[id].region = uint16(b.region.index(list[0].to[2]))
-			likelyLang[id].script = uint8(b.script.index(list[0].to[1]))
-		} else if len(list) > 1 {
-			likelyLang[id].flags = isList
-			likelyLang[id].region = uint16(len(likelyLangList))
-			likelyLang[id].script = uint8(len(list))
-			for _, x := range list {
-				flags := uint8(0)
-				if len(x.from) > 1 {
-					if x.from[1] == x.to[2] {
-						flags = regionInFrom
-					} else {
-						flags = scriptInFrom
-					}
-				}
-				likelyLangList = append(likelyLangList, likelyScriptRegion{
-					region: uint16(b.region.index(x.to[2])),
-					script: uint8(b.script.index(x.to[1])),
-					flags:  flags,
-				})
-			}
-		}
-	}
-	// TODO: merge suppressScript data with this table.
-	b.writeType(likelyScriptRegion{})
-	b.writeSlice("likelyLang", likelyLang)
-	b.writeSlice("likelyLangList", likelyLangList)
-
-	for id := range b.region.s {
-		list := regionToOther[id]
-		if len(list) == 1 {
-			likelyRegion[id].lang = uint16(b.langIndex(list[0].to[0]))
-			likelyRegion[id].script = uint8(b.script.index(list[0].to[1]))
-			if len(list[0].from) > 2 {
-				likelyRegion[id].flags = scriptInFrom
-			}
-		} else if len(list) > 1 {
-			likelyRegion[id].flags = isList
-			likelyRegion[id].lang = uint16(len(likelyRegionList))
-			likelyRegion[id].script = uint8(len(list))
-			for i, x := range list {
-				if len(x.from) == 2 && i != 0 || i > 0 && len(x.from) != 3 {
-					log.Fatalf("unspecified script must be first in list: %v at %d", x.from, i)
-				}
-				x := likelyLangScript{
-					lang:   uint16(b.langIndex(x.to[0])),
-					script: uint8(b.script.index(x.to[1])),
-				}
-				if len(list[0].from) > 2 {
-					x.flags = scriptInFrom
-				}
-				likelyRegionList = append(likelyRegionList, x)
-			}
-		}
-	}
-	b.writeType(likelyLangScript{})
-	b.writeSlice("likelyRegion", likelyRegion)
-	b.writeSlice("likelyRegionList", likelyRegionList)
-
-	b.writeType(likelyTag{})
-	b.writeSlice("likelyRegionGroup", likelyRegionGroup)
+func (b *builder) writeConstants() {
+	b.writeConsts(func(s string) int { return int(b.langIndex(s)) }, langConsts...)
+	b.writeConsts(b.region, regionConsts...)
+	b.writeConsts(b.script, scriptConsts...)
 }
 
 type mutualIntelligibility struct {
@@ -1397,7 +237,7 @@
 		regions := strings.Split(g.Contains, " ")
 		regionHierarchy[g.Type] = append(regionHierarchy[g.Type], regions...)
 	}
-	regionToGroups := make([]uint8, len(b.region.s))
+	regionToGroups := make([]uint8, language.NumRegions)
 
 	idToIndex := map[string]uint8{}
 	for i, mv := range lm[0].MatchVariable {
@@ -1545,168 +385,15 @@
 	b.writeSlice("matchRegion", matchRegion)
 }
 
-func (b *builder) writeRegionInclusionData() {
-	var (
-		// mm holds for each group the set of groups with a distance of 1.
-		mm = make(map[int][]index)
-
-		// containment holds for each group the transitive closure of
-		// containment of other groups.
-		containment = make(map[index][]index)
-	)
-	for _, g := range b.supp.TerritoryContainment.Group {
-		// Skip UN and EURO zone as they are flattening the containment
-		// relationship.
-		if g.Type == "EZ" || g.Type == "UN" {
-			continue
-		}
-		group := b.region.index(g.Type)
-		groupIdx := b.groups[group]
-		for _, mem := range strings.Split(g.Contains, " ") {
-			r := b.region.index(mem)
-			mm[r] = append(mm[r], groupIdx)
-			if g, ok := b.groups[r]; ok {
-				mm[group] = append(mm[group], g)
-				containment[groupIdx] = append(containment[groupIdx], g)
-			}
-		}
-	}
-
-	regionContainment := make([]uint64, len(b.groups))
-	for _, g := range b.groups {
-		l := containment[g]
-
-		// Compute the transitive closure of containment.
-		for i := 0; i < len(l); i++ {
-			l = append(l, containment[l[i]]...)
-		}
-
-		// Compute the bitmask.
-		regionContainment[g] = 1 << g
-		for _, v := range l {
-			regionContainment[g] |= 1 << v
-		}
-	}
-	b.writeSlice("regionContainment", regionContainment)
-
-	regionInclusion := make([]uint8, len(b.region.s))
-	bvs := make(map[uint64]index)
-	// Make the first bitvector positions correspond with the groups.
-	for r, i := range b.groups {
-		bv := uint64(1 << i)
-		for _, g := range mm[r] {
-			bv |= 1 << g
-		}
-		bvs[bv] = i
-		regionInclusion[r] = uint8(bvs[bv])
-	}
-	for r := 1; r < len(b.region.s); r++ {
-		if _, ok := b.groups[r]; !ok {
-			bv := uint64(0)
-			for _, g := range mm[r] {
-				bv |= 1 << g
-			}
-			if bv == 0 {
-				// Pick the world for unspecified regions.
-				bv = 1 << b.groups[b.region.index("001")]
-			}
-			if _, ok := bvs[bv]; !ok {
-				bvs[bv] = index(len(bvs))
-			}
-			regionInclusion[r] = uint8(bvs[bv])
-		}
-	}
-	b.writeSlice("regionInclusion", regionInclusion)
-	regionInclusionBits := make([]uint64, len(bvs))
-	for k, v := range bvs {
-		regionInclusionBits[v] = uint64(k)
-	}
-	// Add bit vectors for increasingly large distances until a fixed point is reached.
-	regionInclusionNext := []uint8{}
-	for i := 0; i < len(regionInclusionBits); i++ {
-		bits := regionInclusionBits[i]
-		next := bits
-		for i := uint(0); i < uint(len(b.groups)); i++ {
-			if bits&(1<<i) != 0 {
-				next |= regionInclusionBits[i]
-			}
-		}
-		if _, ok := bvs[next]; !ok {
-			bvs[next] = index(len(bvs))
-			regionInclusionBits = append(regionInclusionBits, next)
-		}
-		regionInclusionNext = append(regionInclusionNext, uint8(bvs[next]))
-	}
-	b.writeSlice("regionInclusionBits", regionInclusionBits)
-	b.writeSlice("regionInclusionNext", regionInclusionNext)
-}
-
-type parentRel struct {
-	lang       uint16
-	script     uint8
-	maxScript  uint8
-	toRegion   uint16
-	fromRegion []uint16
-}
-
-func (b *builder) writeParents() {
-	b.writeType(parentRel{})
-
-	parents := []parentRel{}
-
-	// Construct parent overrides.
-	n := 0
-	for _, p := range b.data.Supplemental().ParentLocales.ParentLocale {
-		// Skipping non-standard scripts to root is implemented using addTags.
-		if p.Parent == "root" {
-			continue
-		}
-
-		sub := strings.Split(p.Parent, "_")
-		parent := parentRel{lang: b.langIndex(sub[0])}
-		if len(sub) == 2 {
-			// TODO: check that all undefined scripts are indeed Latn in these
-			// cases.
-			parent.maxScript = uint8(b.script.index("Latn"))
-			parent.toRegion = uint16(b.region.index(sub[1]))
-		} else {
-			parent.script = uint8(b.script.index(sub[1]))
-			parent.maxScript = parent.script
-			parent.toRegion = uint16(b.region.index(sub[2]))
-		}
-		for _, c := range strings.Split(p.Locales, " ") {
-			region := b.region.index(c[strings.LastIndex(c, "_")+1:])
-			parent.fromRegion = append(parent.fromRegion, uint16(region))
-		}
-		parents = append(parents, parent)
-		n += len(parent.fromRegion)
-	}
-	b.writeSliceAddSize("parents", n*2, parents)
-}
-
 func main() {
 	gen.Init()
 
-	gen.Repackage("gen_common.go", "common.go", "language")
-
 	w := gen.NewCodeWriter()
 	defer w.WriteGoFile("tables.go", "language")
 
-	fmt.Fprintln(w, `import "golang.org/x/text/internal/tag"`)
-
 	b := newBuilder(w)
 	gen.WriteCLDRVersion(w)
 
-	b.parseIndices()
-	b.writeType(fromTo{})
-	b.writeLanguage()
-	b.writeScript()
-	b.writeRegion()
-	b.writeVariant()
-	// TODO: b.writeLocale()
-	b.computeRegionGroups()
-	b.writeLikelyData()
+	b.writeConstants()
 	b.writeMatchData()
-	b.writeRegionInclusionData()
-	b.writeParents()
 }
diff --git a/language/gen_common.go b/language/gen_common.go
deleted file mode 100644
index 83ce180..0000000
--- a/language/gen_common.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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.
-
-// +build ignore
-
-package main
-
-// This file contains code common to the maketables.go and the package code.
-
-// langAliasType is the type of an alias in langAliasMap.
-type langAliasType int8
-
-const (
-	langDeprecated langAliasType = iota
-	langMacro
-	langLegacy
-
-	langAliasTypeUnknown langAliasType = -1
-)
diff --git a/language/index.go b/language/index.go
index 5311e5c..f0ed2b8 100644
--- a/language/index.go
+++ b/language/index.go
@@ -1,14 +1,15 @@
-// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
-
 package language
 
+import "golang.org/x/text/language/internal"
+
 // NumCompactTags is the number of common tags. The maximum tag is
 // NumCompactTags-1.
 const NumCompactTags = 768
 
-var specialTags = []Tag{ // 2 elements
-	0: {lang: 0xd7, region: 0x6e, script: 0x0, pVariant: 0x5, pExt: 0xe, str: "ca-ES-valencia"},
-	1: {lang: 0x139, region: 0x135, script: 0x0, pVariant: 0x5, pExt: 0x5, str: "en-US-u-va-posix"},
+// TODO: manually updated. Will be automated again in follow-up CL.
+var specialTags = []language.Tag{ // 2 elements
+	0: language.MustParse("ca-ES-valencia"),
+	1: language.MustParse("en-US-u-va-posix"),
 } // Size: 72 bytes
 
 var coreTags = map[uint32]uint16{
diff --git a/language/language.go b/language/language.go
index f81f976..ea4eb9b 100644
--- a/language/language.go
+++ b/language/language.go
@@ -2,8 +2,7 @@
 // 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
-//go:generate go run gen_index.go
+//go:generate go run gen.go -output tables.go
 
 package language
 
@@ -11,47 +10,22 @@
 // - 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
+	"golang.org/x/text/language/internal"
 )
 
 // 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 {
-	lang   langID
-	region regionID
-	// TODO: we will soon run out of positions for script. Idea: instead of
-	// storing lang, region, and script 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.
-	script   scriptID
-	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
+	tag language.Tag
 }
 
+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 {
@@ -68,25 +42,17 @@
 // 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) {
-	return Base{t.lang}, Script{t.script}, Region{t.region}
-}
-
-// equalTags compares language, script and region subtags only.
-func (t Tag) equalTags(a Tag) bool {
-	return t.lang == a.lang && t.script == a.script && t.region == a.region
+	return Base{t.tag.LangID}, Script{t.tag.ScriptID}, Region{t.tag.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)
+	return t.tag.IsRoot()
 }
 
 // private reports whether the Tag consists solely of a private use tag.
 func (t Tag) private() bool {
-	return t.str != "" && t.pVariant == 0
+	return t.tag.IsPrivateUse()
 }
 
 // CanonType can be used to enable or disable various types of canonicalization.
@@ -138,30 +104,30 @@
 
 // canonicalize returns the canonicalized equivalent of the tag and
 // whether there was any change.
-func (t Tag) canonicalize(c CanonType) (Tag, bool) {
+func canonicalize(c CanonType, t language.Tag) (language.Tag, bool) {
 	if c == Raw {
 		return t, false
 	}
 	changed := false
 	if c&SuppressScript != 0 {
-		if t.lang < langNoIndexOffset && uint8(t.script) == suppressScript[t.lang] {
-			t.script = 0
+		if t.LangID.SuppressScript() == t.ScriptID {
+			t.ScriptID = 0
 			changed = true
 		}
 	}
 	if c&canonLang != 0 {
 		for {
-			if l, aliasType := normLang(t.lang); l != t.lang {
+			if l, aliasType := t.LangID.Canonicalize(); l != t.LangID {
 				switch aliasType {
-				case langLegacy:
+				case language.Legacy:
 					if c&Legacy != 0 {
-						if t.lang == _sh && t.script == 0 {
-							t.script = _Latn
+						if t.LangID == _sh && t.ScriptID == 0 {
+							t.ScriptID = _Latn
 						}
-						t.lang = l
+						t.LangID = l
 						changed = true
 					}
-				case langMacro:
+				case language.Macro:
 					if c&Macro != 0 {
 						// We deviate here from CLDR. The mapping "nb" -> "no"
 						// qualifies as a typical Macro language mapping.  However,
@@ -172,39 +138,39 @@
 						// http://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.lang != _nb {
+						if c&CLDR == 0 || t.LangID != _nb {
 							changed = true
-							t.lang = l
+							t.LangID = l
 						}
 					}
-				case langDeprecated:
+				case language.Deprecated:
 					if c&DeprecatedBase != 0 {
-						if t.lang == _mo && t.region == 0 {
-							t.region = _MD
+						if t.LangID == _mo && t.RegionID == 0 {
+							t.RegionID = _MD
 						}
-						t.lang = l
+						t.LangID = l
 						changed = true
 						// Other canonicalization types may still apply.
 						continue
 					}
 				}
-			} else if c&Legacy != 0 && t.lang == _no && c&CLDR != 0 {
-				t.lang = _nb
+			} else if c&Legacy != 0 && t.LangID == _no && c&CLDR != 0 {
+				t.LangID = _nb
 				changed = true
 			}
 			break
 		}
 	}
 	if c&DeprecatedScript != 0 {
-		if t.script == _Qaai {
+		if t.ScriptID == _Qaai {
 			changed = true
-			t.script = _Zinh
+			t.ScriptID = _Zinh
 		}
 	}
 	if c&DeprecatedRegion != 0 {
-		if r := normRegion(t.region); r != 0 {
+		if r := t.RegionID.Canonicalize(); r != t.RegionID {
 			changed = true
-			t.region = r
+			t.RegionID = r
 		}
 	}
 	return t, changed
@@ -212,11 +178,11 @@
 
 // Canonicalize returns the canonicalized equivalent of the tag.
 func (c CanonType) Canonicalize(t Tag) (Tag, error) {
-	t, changed := t.canonicalize(c)
+	tt, changed := canonicalize(c, t.tag)
 	if changed {
-		t.remakeString()
+		tt.RemakeString()
 	}
-	return t, nil
+	return Tag{tt}, nil
 }
 
 // Confidence indicates the level of certainty for a given return value.
@@ -239,99 +205,35 @@
 	return confName[c]
 }
 
-// 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.lang.stringToBuf(buf[:])
-	if t.script != 0 {
-		n += copy(buf[n:], "-")
-		n += copy(buf[n:], t.script.String())
-	}
-	if t.region != 0 {
-		n += copy(buf[n:], "-")
-		n += copy(buf[n:], t.region.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.script == 0 && t.region == 0 {
-		return t.lang.String()
-	}
-	buf := [maxCoreSize]byte{}
-	return string(buf[:t.genCoreBytes(buf[:])])
+	return t.tag.String()
 }
 
 // MarshalText implements encoding.TextMarshaler.
 func (t Tag) MarshalText() (text []byte, err error) {
-	if t.str != "" {
-		text = append(text, t.str...)
-	} else if t.script == 0 && t.region == 0 {
-		text = append(text, t.lang.String()...)
-	} else {
-		buf := [maxCoreSize]byte{}
-		text = buf[:t.genCoreBytes(buf[:])]
-	}
-	return text, nil
+	return t.tag.MarshalText()
 }
 
 // UnmarshalText implements encoding.TextUnmarshaler.
 func (t *Tag) UnmarshalText(text []byte) error {
-	tag, err := Raw.Parse(string(text))
-	*t = tag
-	return err
+	return t.tag.UnmarshalText(text)
 }
 
 // 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 t.lang != 0 {
-		return Base{t.lang}, Exact
+	if b := t.lang(); b != 0 {
+		return Base{b}, Exact
 	}
+	tt := t.tag
 	c := High
-	if t.script == 0 && !(Region{t.region}).IsCountry() {
+	if tt.ScriptID == 0 && !tt.RegionID.IsCountry() {
 		c = Low
 	}
-	if tag, err := addTags(t); err == nil && tag.lang != 0 {
-		return Base{tag.lang}, c
+	if tag, err := tt.Maximize(); err == nil && tag.LangID != 0 {
+		return Base{tag.LangID}, c
 	}
 	return Base{0}, No
 }
@@ -351,28 +253,27 @@
 // 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 t.script != 0 {
-		return Script{t.script}, Exact
+	if t.script() != 0 {
+		return Script{t.script()}, Exact
 	}
+	tt := t.tag
 	sc, c := scriptID(_Zzzz), No
-	if t.lang < langNoIndexOffset {
-		if scr := scriptID(suppressScript[t.lang]); 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 t.region == 0 {
-				return Script{scriptID(scr)}, High
-			}
-			sc, c = scr, High
+	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 := addTags(t); err == nil {
-		if tag.script != sc {
-			sc, c = tag.script, Low
+	if tag, err := tt.Maximize(); err == nil {
+		if tag.ScriptID != sc {
+			sc, c = tag.ScriptID, Low
 		}
 	} else {
 		t, _ = (Deprecated | Macro).Canonicalize(t)
-		if tag, err := addTags(t); err == nil && tag.script != sc {
-			sc, c = tag.script, Low
+		if tag, err := t.tag.Maximize(); err == nil && tag.ScriptID != sc {
+			sc, c = tag.ScriptID, Low
 		}
 	}
 	return Script{sc}, c
@@ -382,28 +283,28 @@
 // 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 t.region != 0 {
-		return Region{t.region}, Exact
+	if t.region() != 0 {
+		return Region{t.region()}, Exact
 	}
-	if t, err := addTags(t); err == nil {
-		return Region{t.region}, Low // TODO: differentiate between high and low.
+	tt := t.tag
+	if tt, err := tt.Maximize(); err == nil {
+		return Region{tt.RegionID}, Low // TODO: differentiate between high and low.
 	}
 	t, _ = (Deprecated | Macro).Canonicalize(t)
-	if tag, err := addTags(t); err == nil {
-		return Region{tag.region}, Low
+	if tag, err := t.tag.Maximize(); err == nil {
+		return Region{tag.RegionID}, Low
 	}
 	return Region{_ZZ}, No // TODO: return world instead of undetermined?
 }
 
-// Variant returns the variants specified explicitly for this language tag.
+// Variants returns the variants specified explicitly for this language tag.
 // or nil if no variant was specified.
 func (t Tag) Variants() []Variant {
 	v := []Variant{}
-	if int(t.pVariant) < int(t.pExt) {
-		for x, str := "", t.str[t.pVariant:t.pExt]; str != ""; {
-			x, str = nextToken(str)
-			v = append(v, Variant{x})
-		}
+	x, str := "", t.tag.Variants()
+	for str != "" {
+		x, str = nextToken(str)
+		v = append(v, Variant{x})
 	}
 	return v
 }
@@ -412,56 +313,7 @@
 // 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.
-		t, _ = Raw.Compose(t.Raw())
-		if t.region == 0 && t.script != 0 && t.lang != 0 {
-			base, _ := addTags(Tag{lang: t.lang})
-			if base.script == t.script {
-				return Tag{lang: t.lang}
-			}
-		}
-		return t
-	}
-	if t.lang != 0 {
-		if t.region != 0 {
-			maxScript := t.script
-			if maxScript == 0 {
-				max, _ := addTags(t)
-				maxScript = max.script
-			}
-
-			for i := range parents {
-				if langID(parents[i].lang) == t.lang && scriptID(parents[i].maxScript) == maxScript {
-					for _, r := range parents[i].fromRegion {
-						if regionID(r) == t.region {
-							return Tag{
-								lang:   t.lang,
-								script: scriptID(parents[i].script),
-								region: regionID(parents[i].toRegion),
-							}
-						}
-					}
-				}
-			}
-
-			// Strip the script if it is the default one.
-			base, _ := addTags(Tag{lang: t.lang})
-			if base.script != maxScript {
-				return Tag{lang: t.lang, script: maxScript}
-			}
-			return Tag{lang: t.lang}
-		} else if t.script != 0 {
-			// The parent for an base-script pair with a non-default script is
-			// "und" instead of the base language.
-			base, _ := addTags(Tag{lang: t.lang})
-			if base.script != t.script {
-				return und
-			}
-			return Tag{lang: t.lang}
-		}
-	}
-	return und
+	return Tag{t.tag.Parent()}
 }
 
 // returns token t and the rest of the string.
@@ -487,17 +339,8 @@
 
 // ParseExtension parses s as an extension and returns it on success.
 func ParseExtension(s string) (e Extension, err error) {
-	scan := makeScannerString(s)
-	var end int
-	if n := len(scan.token); n != 1 {
-		return Extension{}, errSyntax
-	}
-	scan.toLower(0, len(scan.b))
-	end = parseExtension(&scan)
-	if end != len(s) {
-		return Extension{}, errSyntax
-	}
-	return Extension{string(scan.b)}, nil
+	ext, err := language.ParseExtension(s)
+	return Extension{ext}, err
 }
 
 // Type returns the one-byte extension type of e. It returns 0 for the zero
@@ -518,22 +361,14 @@
 // 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) {
-	for i := int(t.pExt); i < len(t.str)-1; {
-		var ext string
-		i, ext = getExtension(t.str, i)
-		if ext[0] == x {
-			return Extension{ext}, true
-		}
-	}
-	return Extension{}, false
+	e, ok := t.tag.Extension(x)
+	return Extension{e}, ok
 }
 
 // Extensions returns all extensions of t.
 func (t Tag) Extensions() []Extension {
 	e := []Extension{}
-	for i := int(t.pExt); i < len(t.str)-1; {
-		var ext string
-		i, ext = getExtension(t.str, i)
+	for _, ext := range t.tag.Extensions() {
 		e = append(e, Extension{ext})
 	}
 	return e
@@ -544,162 +379,16 @@
 // http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers.
 // TypeForKey will traverse the inheritance chain to get the correct value.
 func (t Tag) TypeForKey(key string) string {
-	if start, end, _ := t.findTypeForKey(key); end != start {
-		return t.str[start:end]
-	}
-	return ""
+	return t.tag.TypeForKey(key)
 }
 
-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
 // http://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.private() {
-		return t, errPrivateUse
-	}
-	if len(key) != 2 {
-		return t, errInvalidArguments
-	}
-
-	// Remove the setting if value is "".
-	if value == "" {
-		start, end, _ := t.findTypeForKey(key)
-		if start != end {
-			// Remove key tag and leading '-'.
-			start -= 4
-
-			// Remove a possible empty extension.
-			if (end == len(t.str) || t.str[end+2] == '-') && t.str[start-2] == '-' {
-				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, end, hasExt := t.findTypeForKey(key)
-		if start == end {
-			if hasExt {
-				b = b[2:]
-			}
-			t.str = fmt.Sprintf("%s-%s%s", s[:start], b, s[end:])
-		} else {
-			t.str = fmt.Sprintf("%s%s%s", s[:start], value, s[end:])
-		}
-	}
-	return t, nil
-}
-
-// findKeyAndType 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, end int, hasExt bool) {
-	p := int(t.pExt)
-	if len(key) != 2 || p == len(t.str) || p == 0 {
-		return p, p, false
-	}
-	s := t.str
-
-	// Find the correct extension.
-	for p++; s[p] != 'u'; p++ {
-		if s[p] > 'u' {
-			p--
-			return p, p, false
-		}
-		if p = nextExtension(s, p); p == len(s) {
-			return 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 {
-		// p points to the hyphen preceding the current token.
-		if p3 := p + 3; s[p3] == '-' {
-			// Found a key.
-			// Check whether we just processed the key that was requested.
-			if curKey == key {
-				return start, p, true
-			}
-			// Set to the next key and continue scanning type tokens.
-			curKey = s[p+1 : p3]
-			if curKey > key {
-				return p, p, true
-			}
-			// Start of the type token sequence.
-			start = p + 4
-			// A type is at least 3 characters long.
-			p += 7 // 4 + 3
-		} else {
-			// Attribute or type, which is at least 3 characters long.
-			p += 4
-		}
-		// p points past the third character of a type or attribute.
-		max := p + 5 // maximum length of token plus hyphen.
-		if len(s) < max {
-			max = len(s)
-		}
-		for ; p < max && s[p] != '-'; p++ {
-		}
-		// Bail if we have exhausted all tokens or if the next token starts
-		// a new extension.
-		if p == len(s) || s[p+2] == '-' {
-			if curKey == key {
-				return start, p, true
-			}
-			return p, p, true
-		}
-	}
+	tt, err := t.tag.SetTypeForKey(key, value)
+	return Tag{tt}, err
 }
 
 // CompactIndex returns an index, where 0 <= index < NumCompactTags, for tags
@@ -715,16 +404,18 @@
 
 	b, s, r := t.Raw()
 	switch {
-	case len(t.str) > 0:
-		if strings.HasPrefix(t.str, "x-") {
+	case t.tag.HasString():
+		if t.private() {
 			// We have no entries for user-defined tags.
 			return 0, false
 		}
-		if uint16(t.pVariant) != t.pExt {
-			if int(t.pExt) < len(t.str) {
+		hasExtra := false
+		if t.tag.HasVariants() {
+			if t.tag.HasExtensions() {
 				exact = false
 				t, _ = Raw.Compose(b, s, r, t.Variants())
 			}
+			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.
@@ -733,13 +424,14 @@
 			t, _ = Raw.Compose(b, s, r)
 			if variant != "" {
 				t, _ = t.SetTypeForKey("va", variant)
+				hasExtra = true
 			}
 			exact = old == t
 		}
-		if len(t.str) > 0 {
+		if hasExtra {
 			// We have some variants.
 			for i, s := range specialTags {
-				if s == t {
+				if s == t.tag {
 					return i + 1, exact
 				}
 			}
@@ -764,48 +456,66 @@
 // Base is an ISO 639 language code, used for encoding the base language
 // of a language tag.
 type Base struct {
-	langID
+	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) {
-	if n := len(s); n < 2 || 3 < n {
-		return Base{}, errSyntax
-	}
-	var buf [3]byte
-	l, err := getLangID(buf[:copy(buf[:], s)])
+	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
+	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) {
-	if len(s) != 4 {
-		return Script{}, errSyntax
-	}
-	var buf [4]byte
-	sc, err := getScriptID(script, buf[:copy(buf[:], s)])
+	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
+	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 := getRegionM49(r)
+	rid, err := language.EncodeM49(r)
 	return Region{rid}, err
 }
 
@@ -813,62 +523,54 @@
 // 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) {
-	if n := len(s); n < 2 || 3 < n {
-		return Region{}, errSyntax
-	}
-	var buf [3]byte
-	r, err := getRegionID(buf[:copy(buf[:], s)])
+	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.String()
+}
+
+// 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 {
-	if r.regionID == 0 || r.IsGroup() || r.IsPrivateUse() && r.regionID != _XK {
-		return false
-	}
-	return true
+	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 {
-	if r.regionID == 0 {
-		return false
-	}
-	return int(regionInclusion[r.regionID]) < len(regionContainment)
+	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)
+	return r.regionID.Contains(c.regionID)
 }
 
-func (r regionID) contains(c regionID) 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.
 //
@@ -877,25 +579,15 @@
 // 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.regionID == _GB {
-		r = Region{_UK}
-	}
-	if (r.typ() & ccTLD) == 0 {
-		return Region{}, errNoTLD
-	}
-	return r, nil
+	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 {
-	if cr := normRegion(r.regionID); cr != 0 {
-		return Region{cr}
-	}
-	return r
+	return Region{r.regionID.Canonicalize()}
 }
 
 // Variant represents a registered variant of a language as defined by BCP 47.
@@ -906,11 +598,8 @@
 // ParseVariant parses and returns a Variant. An error is returned if s is not
 // a valid variant.
 func ParseVariant(s string) (Variant, error) {
-	s = strings.ToLower(s)
-	if _, ok := variantIndex[s]; ok {
-		return Variant{s}, nil
-	}
-	return Variant{}, mkErrInvalid([]byte(s))
+	v, err := language.ParseVariant(s)
+	return Variant{v.String()}, err
 }
 
 // String returns the string representation of the variant.
diff --git a/language/language_test.go b/language/language_test.go
index 14bc8a7..084a86f 100644
--- a/language/language_test.go
+++ b/language/language_test.go
@@ -7,8 +7,6 @@
 import (
 	"reflect"
 	"testing"
-
-	"golang.org/x/text/internal/testtext"
 )
 
 func TestTagSize(t *testing.T) {
@@ -48,35 +46,6 @@
 	}
 }
 
-func TestMakeString(t *testing.T) {
-	tests := []struct{ in, out string }{
-		{"und", "und"},
-		{"und", "und-CW"},
-		{"nl", "nl-NL"},
-		{"de-1901", "nl-1901"},
-		{"de-1901", "de-Arab-1901"},
-		{"x-a-b", "de-Arab-x-a-b"},
-		{"x-a-b", "x-a-b"},
-	}
-	for i, tt := range tests {
-		id, _ := Parse(tt.in)
-		mod, _ := Parse(tt.out)
-		id.setTagsFrom(mod)
-		for j := 0; j < 2; j++ {
-			id.remakeString()
-			if str := id.String(); str != tt.out {
-				t.Errorf("%d:%d: found %s; want %s", i, j, id.String(), tt.out)
-			}
-		}
-		// The bytes to string conversion as used in remakeString
-		// occasionally measures as more than one alloc, breaking this test.
-		// To alleviate this we set the number of runs to more than 1.
-		if n := testtext.AllocsPerRun(8, id.remakeString); n > 1 {
-			t.Errorf("%d: # allocs got %.1f; want <= 1", i, n)
-		}
-	}
-}
-
 func TestCompactIndex(t *testing.T) {
 	tests := []struct {
 		tag   string
@@ -346,8 +315,7 @@
 		{"XK", true},
 	}
 	for i, tt := range tests {
-		reg, _ := getRegionID([]byte(tt.reg))
-		r := Region{reg}
+		r, _ := ParseRegion(tt.reg)
 		if r.IsCountry() != tt.country {
 			t.Errorf("%d: IsCountry(%s) was %v; want %v", i, tt.reg, r.IsCountry(), tt.country)
 		}
@@ -373,8 +341,7 @@
 		{"XK", false},
 	}
 	for i, tt := range tests {
-		reg, _ := getRegionID([]byte(tt.reg))
-		r := Region{reg}
+		r, _ := ParseRegion(tt.reg)
 		if r.IsGroup() != tt.group {
 			t.Errorf("%d: IsGroup(%s) was %v; want %v", i, tt.reg, r.IsGroup(), tt.group)
 		}
@@ -407,10 +374,9 @@
 		{"155", "EU", false},
 	}
 	for i, tt := range tests {
-		enc, _ := getRegionID([]byte(tt.enclosing))
-		con, _ := getRegionID([]byte(tt.contained))
-		r := Region{enc}
-		if got := r.Contains(Region{con}); got != tt.contains {
+		r := MustParseRegion(tt.enclosing)
+		con := MustParseRegion(tt.contained)
+		if got := r.Contains(con); got != tt.contains {
 			t.Errorf("%d: %s.Contains(%s) was %v; want %v", i, tt.enclosing, tt.contained, got, tt.contains)
 		}
 	}
@@ -565,9 +531,6 @@
 		if in.String() != tt.out {
 			t.Errorf("%d:%s: was %s; want %s", i, tt.in, in.String(), tt.out)
 		}
-		if int(in.pVariant) > int(in.pExt) || int(in.pExt) > len(in.str) {
-			t.Errorf("%d:%s:offsets %d <= %d <= %d must be true", i, tt.in, in.pVariant, in.pExt, len(in.str))
-		}
 	}
 	// Test idempotence.
 	for _, base := range Supported.BaseLanguages() {
@@ -597,121 +560,6 @@
 	}
 }
 
-func TestSetTypeForKey(t *testing.T) {
-	tests := []struct {
-		key, value, in, out string
-		err                 bool
-	}{
-		// replace existing value
-		{"co", "pinyin", "en-u-co-phonebk", "en-u-co-pinyin", false},
-		{"co", "pinyin", "en-u-co-phonebk-cu-xau", "en-u-co-pinyin-cu-xau", false},
-		{"co", "pinyin", "en-u-co-phonebk-v-xx", "en-u-co-pinyin-v-xx", false},
-		{"co", "pinyin", "en-u-co-phonebk-x-x", "en-u-co-pinyin-x-x", false},
-		{"nu", "arabic", "en-u-co-phonebk-nu-vaai", "en-u-co-phonebk-nu-arabic", false},
-		// add to existing -u extension
-		{"co", "pinyin", "en-u-ca-gregory", "en-u-ca-gregory-co-pinyin", false},
-		{"co", "pinyin", "en-u-ca-gregory-nu-vaai", "en-u-ca-gregory-co-pinyin-nu-vaai", false},
-		{"co", "pinyin", "en-u-ca-gregory-v-va", "en-u-ca-gregory-co-pinyin-v-va", false},
-		{"co", "pinyin", "en-u-ca-gregory-x-a", "en-u-ca-gregory-co-pinyin-x-a", false},
-		{"ca", "gregory", "en-u-co-pinyin", "en-u-ca-gregory-co-pinyin", false},
-		// remove pair
-		{"co", "", "en-u-co-phonebk", "en", false},
-		{"co", "", "en-u-ca-gregory-co-phonebk", "en-u-ca-gregory", false},
-		{"co", "", "en-u-co-phonebk-nu-arabic", "en-u-nu-arabic", false},
-		{"co", "", "en", "en", false},
-		// add -u extension
-		{"co", "pinyin", "en", "en-u-co-pinyin", false},
-		{"co", "pinyin", "und", "und-u-co-pinyin", false},
-		{"co", "pinyin", "en-a-aaa", "en-a-aaa-u-co-pinyin", false},
-		{"co", "pinyin", "en-x-aaa", "en-u-co-pinyin-x-aaa", false},
-		{"co", "pinyin", "en-v-aa", "en-u-co-pinyin-v-aa", false},
-		{"co", "pinyin", "en-a-aaa-x-x", "en-a-aaa-u-co-pinyin-x-x", false},
-		{"co", "pinyin", "en-a-aaa-v-va", "en-a-aaa-u-co-pinyin-v-va", false},
-		// error on invalid values
-		{"co", "pinyinxxx", "en", "en", true},
-		{"co", "piny.n", "en", "en", true},
-		{"co", "pinyinxxx", "en-a-aaa", "en-a-aaa", true},
-		{"co", "pinyinxxx", "en-u-aaa", "en-u-aaa", true},
-		{"co", "pinyinxxx", "en-u-aaa-co-pinyin", "en-u-aaa-co-pinyin", true},
-		{"co", "pinyi.", "en-u-aaa-co-pinyin", "en-u-aaa-co-pinyin", true},
-		{"col", "pinyin", "en", "en", true},
-		{"co", "cu", "en", "en", true},
-		// error when setting on a private use tag
-		{"co", "phonebook", "x-foo", "x-foo", true},
-	}
-	for i, tt := range tests {
-		tag := Make(tt.in)
-		if v, err := tag.SetTypeForKey(tt.key, tt.value); v.String() != tt.out {
-			t.Errorf("%d:%q[%q]=%q: was %q; want %q", i, tt.in, tt.key, tt.value, v, tt.out)
-		} else if (err != nil) != tt.err {
-			t.Errorf("%d:%q[%q]=%q: error was %v; want %v", i, tt.in, tt.key, tt.value, err != nil, tt.err)
-		} else if val := v.TypeForKey(tt.key); err == nil && val != tt.value {
-			t.Errorf("%d:%q[%q]==%q: was %v; want %v", i, tt.out, tt.key, tt.value, val, tt.value)
-		}
-		if len(tag.String()) <= 3 {
-			// Simulate a tag for which the string has not been set.
-			tag.str, tag.pExt, tag.pVariant = "", 0, 0
-			if tag, err := tag.SetTypeForKey(tt.key, tt.value); err == nil {
-				if val := tag.TypeForKey(tt.key); err == nil && val != tt.value {
-					t.Errorf("%d:%q[%q]==%q: was %v; want %v", i, tt.out, tt.key, tt.value, val, tt.value)
-				}
-			}
-		}
-	}
-}
-
-func TestFindKeyAndType(t *testing.T) {
-	// out is either the matched type in case of a match or the original
-	// string up till the insertion point.
-	tests := []struct {
-		key     string
-		hasExt  bool
-		in, out string
-	}{
-		// Don't search past a private use extension.
-		{"co", false, "en-x-foo-u-co-pinyin", "en"},
-		{"co", false, "x-foo-u-co-pinyin", ""},
-		{"co", false, "en-s-fff-x-foo", "en-s-fff"},
-		// Insertion points in absence of -u extension.
-		{"cu", false, "en", ""}, // t.str is ""
-		{"cu", false, "en-v-va", "en"},
-		{"cu", false, "en-a-va", "en-a-va"},
-		{"cu", false, "en-a-va-v-va", "en-a-va"},
-		{"cu", false, "en-x-a", "en"},
-		// Tags with the -u extension.
-		{"co", true, "en-u-co-standard", "standard"},
-		{"co", true, "yue-u-co-pinyin", "pinyin"},
-		{"co", true, "en-u-co-abc", "abc"},
-		{"co", true, "en-u-co-abc-def", "abc-def"},
-		{"co", true, "en-u-co-abc-def-x-foo", "abc-def"},
-		{"co", true, "en-u-co-standard-nu-arab", "standard"},
-		{"co", true, "yue-u-co-pinyin-nu-arab", "pinyin"},
-		// Insertion points.
-		{"cu", true, "en-u-co-standard", "en-u-co-standard"},
-		{"cu", true, "yue-u-co-pinyin-x-foo", "yue-u-co-pinyin"},
-		{"cu", true, "en-u-co-abc", "en-u-co-abc"},
-		{"cu", true, "en-u-nu-arabic", "en-u"},
-		{"cu", true, "en-u-co-abc-def-nu-arabic", "en-u-co-abc-def"},
-	}
-	for i, tt := range tests {
-		start, end, hasExt := Make(tt.in).findTypeForKey(tt.key)
-		if start != end {
-			res := tt.in[start:end]
-			if res != tt.out {
-				t.Errorf("%d:%s: was %q; want %q", i, tt.in, res, tt.out)
-			}
-		} else {
-			if hasExt != tt.hasExt {
-				t.Errorf("%d:%s: hasExt was %v; want %v", i, tt.in, hasExt, tt.hasExt)
-				continue
-			}
-			if tt.in[:start] != tt.out {
-				t.Errorf("%d:%s: insertion point was %q; want %q", i, tt.in, tt.in[:start], tt.out)
-			}
-		}
-	}
-}
-
 func TestParent(t *testing.T) {
 	tests := []struct{ in, out string }{
 		// Strip variants and extensions first
diff --git a/language/lookup.go b/language/lookup.go
index 1d80ac3..a59b7e4 100644
--- a/language/lookup.go
+++ b/language/lookup.go
@@ -5,392 +5,11 @@
 package language
 
 import (
-	"bytes"
-	"fmt"
-	"sort"
-	"strconv"
-
-	"golang.org/x/text/internal/tag"
+	"golang.org/x/text/language/internal"
 )
 
-// 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, mkErrInvalid(key)
-	}
-	return i, nil
-}
+type langID = language.Language
 
-func searchUint(imap []uint16, key uint16) int {
-	return sort.Search(len(imap), func(i int) bool {
-		return imap[i] >= key
-	})
-}
+type regionID = language.Region
 
-type langID 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) (langID, error) {
-	if len(s) == 2 {
-		return getLangISO2(s)
-	}
-	return getLangISO3(s)
-}
-
-// mapLang returns the mapped langID of id according to mapping m.
-func normLang(id langID) (langID, langAliasType) {
-	k := sort.Search(len(langAliasMap), func(i int) bool {
-		return langAliasMap[i].from >= uint16(id)
-	})
-	if k < len(langAliasMap) && langAliasMap[k].from == uint16(id) {
-		return langID(langAliasMap[k].to), langAliasTypes[k]
-	}
-	return id, langAliasTypeUnknown
-}
-
-// getLangISO2 returns the langID for the given 2-letter ISO language code
-// or unknownLang if this does not exist.
-func getLangISO2(s []byte) (langID, error) {
-	if !tag.FixCase("zz", s) {
-		return 0, errSyntax
-	}
-	if i := lang.Index(s); i != -1 && lang.Elem(i)[3] != 0 {
-		return langID(i), nil
-	}
-	return 0, mkErrInvalid(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) (langID, 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 := langID(i)
-				if id == nonCanonicalUnd {
-					return 0, nil
-				}
-				return id, nil
-			}
-		}
-		if i := altLangISO3.Index(s); i != -1 {
-			return langID(altLangIndex[altLangISO3.Elem(i)[3]]), nil
-		}
-		n := strToInt(s)
-		if langNoIndex[n/8]&(1<<(n%8)) != 0 {
-			return langID(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 langID(i), nil
-			}
-		}
-		return 0, mkErrInvalid(s)
-	}
-	return 0, errSyntax
-}
-
-// stringToBuf writes the string to b and returns the number of bytes
-// written.  cap(b) must be >= 3.
-func (id langID) 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 langID) 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 langID) 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 langID) IsPrivateUse() bool {
-	return langPrivateStart <= b && b <= langPrivateEnd
-}
-
-type regionID uint16
-
-// getRegionID returns the region id for s if s is a valid 2-letter region code
-// or unknownRegion.
-func getRegionID(s []byte) (regionID, 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) (regionID, error) {
-	i, err := findIndex(regionISO, s, "ZZ")
-	if err != nil {
-		return 0, err
-	}
-	return regionID(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) (regionID, 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 regionID(i) + isoRegionOffset, nil
-			}
-		}
-		for i := 0; i < len(altRegionISO3); i += 3 {
-			if tag.Compare(altRegionISO3[i:i+3], s) == 0 {
-				return regionID(altRegionIDs[i/3]), nil
-			}
-		}
-		return 0, mkErrInvalid(s)
-	}
-	return 0, errSyntax
-}
-
-func getRegionM49(n int) (regionID, 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 regionID(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 regionID) regionID {
-	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 regionID(m[k].to)
-	}
-	return 0
-}
-
-const (
-	iso3166UserAssigned = 1 << iota
-	ccTLD
-	bcp47Region
-)
-
-func (r regionID) typ() byte {
-	return regionTypes[r]
-}
-
-// String returns the BCP 47 representation for the region.
-// It returns "ZZ" for an unspecified region.
-func (r regionID) 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 regionID) 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 regionID) 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 regionID) IsPrivateUse() bool {
-	return r.typ()&iso3166UserAssigned != 0
-}
-
-type scriptID uint8
-
-// 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) (scriptID, error) {
-	i, err := findIndex(idx, s, "Zzzz")
-	return scriptID(i), err
-}
-
-// String returns the script code in title case.
-// It returns "Zzzz" for an unspecified script.
-func (s scriptID) 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 scriptID) 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.lang = langID(v)
-		return t, true
-	}
-	return t, false
-}
+type scriptID = language.Script
diff --git a/language/lookup_test.go b/language/lookup_test.go
deleted file mode 100644
index 9833830..0000000
--- a/language/lookup_test.go
+++ /dev/null
@@ -1,457 +0,0 @@
-// 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 (
-	"testing"
-
-	"golang.org/x/text/internal/tag"
-)
-
-func b(s string) []byte {
-	return []byte(s)
-}
-
-func TestLangID(t *testing.T) {
-	tests := []struct {
-		id, bcp47, iso3, norm string
-		err                   error
-	}{
-		{id: "", bcp47: "und", iso3: "und", err: errSyntax},
-		{id: "  ", bcp47: "und", iso3: "und", err: errSyntax},
-		{id: "   ", bcp47: "und", iso3: "und", err: errSyntax},
-		{id: "    ", bcp47: "und", iso3: "und", err: errSyntax},
-		{id: "xxx", bcp47: "und", iso3: "und", err: mkErrInvalid([]byte("xxx"))},
-		{id: "und", bcp47: "und", iso3: "und"},
-		{id: "aju", bcp47: "aju", iso3: "aju", norm: "jrb"},
-		{id: "jrb", bcp47: "jrb", iso3: "jrb"},
-		{id: "es", bcp47: "es", iso3: "spa"},
-		{id: "spa", bcp47: "es", iso3: "spa"},
-		{id: "ji", bcp47: "ji", iso3: "yid-", norm: "yi"},
-		{id: "jw", bcp47: "jw", iso3: "jav-", norm: "jv"},
-		{id: "ar", bcp47: "ar", iso3: "ara"},
-		{id: "kw", bcp47: "kw", iso3: "cor"},
-		{id: "arb", bcp47: "arb", iso3: "arb", norm: "ar"},
-		{id: "ar", bcp47: "ar", iso3: "ara"},
-		{id: "kur", bcp47: "ku", iso3: "kur"},
-		{id: "nl", bcp47: "nl", iso3: "nld"},
-		{id: "NL", bcp47: "nl", iso3: "nld"},
-		{id: "gsw", bcp47: "gsw", iso3: "gsw"},
-		{id: "gSW", bcp47: "gsw", iso3: "gsw"},
-		{id: "und", bcp47: "und", iso3: "und"},
-		{id: "sh", bcp47: "sh", iso3: "hbs", norm: "sr"},
-		{id: "hbs", bcp47: "sh", iso3: "hbs", norm: "sr"},
-		{id: "no", bcp47: "no", iso3: "nor", norm: "no"},
-		{id: "nor", bcp47: "no", iso3: "nor", norm: "no"},
-		{id: "cmn", bcp47: "cmn", iso3: "cmn", norm: "zh"},
-	}
-	for i, tt := range tests {
-		want, err := getLangID(b(tt.id))
-		if err != tt.err {
-			t.Errorf("%d:err(%s): found %q; want %q", i, tt.id, err, tt.err)
-		}
-		if err != nil {
-			continue
-		}
-		if id, _ := getLangISO2(b(tt.bcp47)); len(tt.bcp47) == 2 && want != id {
-			t.Errorf("%d:getISO2(%s): found %v; want %v", i, tt.bcp47, id, want)
-		}
-		if len(tt.iso3) == 3 {
-			if id, _ := getLangISO3(b(tt.iso3)); want != id {
-				t.Errorf("%d:getISO3(%s): found %q; want %q", i, tt.iso3, id, want)
-			}
-			if id, _ := getLangID(b(tt.iso3)); want != id {
-				t.Errorf("%d:getID3(%s): found %v; want %v", i, tt.iso3, id, want)
-			}
-		}
-		norm := want
-		if tt.norm != "" {
-			norm, _ = getLangID(b(tt.norm))
-		}
-		id, _ := normLang(want)
-		if id != norm {
-			t.Errorf("%d:norm(%s): found %v; want %v", i, tt.id, id, norm)
-		}
-		if id := want.String(); tt.bcp47 != id {
-			t.Errorf("%d:String(): found %s; want %s", i, id, tt.bcp47)
-		}
-		if id := want.ISO3(); tt.iso3[:3] != id {
-			t.Errorf("%d:iso3(): found %s; want %s", i, id, tt.iso3[:3])
-		}
-	}
-}
-
-func TestGrandfathered(t *testing.T) {
-	for _, tt := range []struct{ in, out string }{
-		{"art-lojban", "jbo"},
-		{"i-ami", "ami"},
-		{"i-bnn", "bnn"},
-		{"i-hak", "hak"},
-		{"i-klingon", "tlh"},
-		{"i-lux", "lb"},
-		{"i-navajo", "nv"},
-		{"i-pwn", "pwn"},
-		{"i-tao", "tao"},
-		{"i-tay", "tay"},
-		{"i-tsu", "tsu"},
-		{"no-bok", "nb"},
-		{"no-nyn", "nn"},
-		{"sgn-BE-FR", "sfb"},
-		{"sgn-BE-NL", "vgt"},
-		{"sgn-CH-DE", "sgg"},
-		{"sgn-ch-de", "sgg"},
-		{"zh-guoyu", "cmn"},
-		{"zh-hakka", "hak"},
-		{"zh-min-nan", "nan"},
-		{"zh-xiang", "hsn"},
-
-		// Grandfathered tags with no modern replacement will be converted as follows:
-		{"cel-gaulish", "xtg-x-cel-gaulish"},
-		{"en-GB-oed", "en-GB-oxendict"},
-		{"en-gb-oed", "en-GB-oxendict"},
-		{"i-default", "en-x-i-default"},
-		{"i-enochian", "und-x-i-enochian"},
-		{"i-mingo", "see-x-i-mingo"},
-		{"zh-min", "nan-x-zh-min"},
-
-		{"root", "und"},
-		{"en_US_POSIX", "en-US-u-va-posix"},
-		{"en_us_posix", "en-US-u-va-posix"},
-		{"en-us-posix", "en-US-u-va-posix"},
-	} {
-		got := Raw.Make(tt.in)
-		want := Raw.MustParse(tt.out)
-		if got != want {
-			t.Errorf("%s: got %q; want %q", tt.in, got, want)
-		}
-	}
-}
-
-func TestRegionID(t *testing.T) {
-	tests := []struct {
-		in, out string
-	}{
-		{"_  ", ""},
-		{"_000", ""},
-		{"419", "419"},
-		{"AA", "AA"},
-		{"ATF", "TF"},
-		{"HV", "HV"},
-		{"CT", "CT"},
-		{"DY", "DY"},
-		{"IC", "IC"},
-		{"FQ", "FQ"},
-		{"JT", "JT"},
-		{"ZZ", "ZZ"},
-		{"EU", "EU"},
-		{"QO", "QO"},
-		{"FX", "FX"},
-	}
-	for i, tt := range tests {
-		if tt.in[0] == '_' {
-			id := tt.in[1:]
-			if _, err := getRegionID(b(id)); err == nil {
-				t.Errorf("%d:err(%s): found nil; want error", i, id)
-			}
-			continue
-		}
-		want, _ := getRegionID(b(tt.in))
-		if s := want.String(); s != tt.out {
-			t.Errorf("%d:%s: found %q; want %q", i, tt.in, s, tt.out)
-		}
-		if len(tt.in) == 2 {
-			want, _ := getRegionISO2(b(tt.in))
-			if s := want.String(); s != tt.out {
-				t.Errorf("%d:getISO2(%s): found %q; want %q", i, tt.in, s, tt.out)
-			}
-		}
-	}
-}
-
-func TestRegionType(t *testing.T) {
-	for _, tt := range []struct {
-		r string
-		t byte
-	}{
-		{"NL", bcp47Region | ccTLD},
-		{"EU", bcp47Region | ccTLD}, // exceptionally reserved
-		{"AN", bcp47Region | ccTLD}, // transitionally reserved
-
-		{"DD", bcp47Region}, // deleted in ISO, deprecated in BCP 47
-		{"NT", bcp47Region}, // transitionally reserved, deprecated in BCP 47
-
-		{"XA", iso3166UserAssigned | bcp47Region},
-		{"ZZ", iso3166UserAssigned | bcp47Region},
-		{"AA", iso3166UserAssigned | bcp47Region},
-		{"QO", iso3166UserAssigned | bcp47Region},
-		{"QM", iso3166UserAssigned | bcp47Region},
-		{"XK", iso3166UserAssigned | bcp47Region},
-
-		{"CT", 0}, // deleted in ISO, not in BCP 47, canonicalized in CLDR
-	} {
-		r := MustParseRegion(tt.r)
-		if tp := r.typ(); tp != tt.t {
-			t.Errorf("Type(%s): got %x; want %x", tt.r, tp, tt.t)
-		}
-	}
-}
-
-func TestRegionISO3(t *testing.T) {
-	tests := []struct {
-		from, iso3, to string
-	}{
-		{"  ", "ZZZ", "ZZ"},
-		{"000", "ZZZ", "ZZ"},
-		{"AA", "AAA", ""},
-		{"CT", "CTE", ""},
-		{"DY", "DHY", ""},
-		{"EU", "QUU", ""},
-		{"HV", "HVO", ""},
-		{"IC", "ZZZ", "ZZ"},
-		{"JT", "JTN", ""},
-		{"PZ", "PCZ", ""},
-		{"QU", "QUU", "EU"},
-		{"QO", "QOO", ""},
-		{"YD", "YMD", ""},
-		{"FQ", "ATF", "TF"},
-		{"TF", "ATF", ""},
-		{"FX", "FXX", ""},
-		{"ZZ", "ZZZ", ""},
-		{"419", "ZZZ", "ZZ"},
-	}
-	for _, tt := range tests {
-		r, _ := getRegionID(b(tt.from))
-		if s := r.ISO3(); s != tt.iso3 {
-			t.Errorf("iso3(%q): found %q; want %q", tt.from, s, tt.iso3)
-		}
-		if tt.iso3 == "" {
-			continue
-		}
-		want := tt.to
-		if tt.to == "" {
-			want = tt.from
-		}
-		r, _ = getRegionID(b(want))
-		if id, _ := getRegionISO3(b(tt.iso3)); id != r {
-			t.Errorf("%s: found %q; want %q", tt.iso3, id, want)
-		}
-	}
-}
-
-func TestRegionM49(t *testing.T) {
-	fromTests := []struct {
-		m49 int
-		id  string
-	}{
-		{0, ""},
-		{-1, ""},
-		{1000, ""},
-		{10000, ""},
-
-		{001, "001"},
-		{104, "MM"},
-		{180, "CD"},
-		{230, "ET"},
-		{231, "ET"},
-		{249, "FX"},
-		{250, "FR"},
-		{276, "DE"},
-		{278, "DD"},
-		{280, "DE"},
-		{419, "419"},
-		{626, "TL"},
-		{736, "SD"},
-		{840, "US"},
-		{854, "BF"},
-		{891, "CS"},
-		{899, ""},
-		{958, "AA"},
-		{966, "QT"},
-		{967, "EU"},
-		{999, "ZZ"},
-	}
-	for _, tt := range fromTests {
-		id, err := getRegionM49(tt.m49)
-		if want, have := err != nil, tt.id == ""; want != have {
-			t.Errorf("error(%d): have %v; want %v", tt.m49, have, want)
-			continue
-		}
-		r, _ := getRegionID(b(tt.id))
-		if r != id {
-			t.Errorf("region(%d): have %s; want %s", tt.m49, id, r)
-		}
-	}
-
-	toTests := []struct {
-		m49 int
-		id  string
-	}{
-		{0, "000"},
-		{0, "IC"}, // Some codes don't have an ID
-
-		{001, "001"},
-		{104, "MM"},
-		{104, "BU"},
-		{180, "CD"},
-		{180, "ZR"},
-		{231, "ET"},
-		{250, "FR"},
-		{249, "FX"},
-		{276, "DE"},
-		{278, "DD"},
-		{419, "419"},
-		{626, "TL"},
-		{626, "TP"},
-		{729, "SD"},
-		{826, "GB"},
-		{840, "US"},
-		{854, "BF"},
-		{891, "YU"},
-		{891, "CS"},
-		{958, "AA"},
-		{966, "QT"},
-		{967, "EU"},
-		{967, "QU"},
-		{999, "ZZ"},
-		// For codes that don't have an M49 code use the replacement value,
-		// if available.
-		{854, "HV"}, // maps to Burkino Faso
-	}
-	for _, tt := range toTests {
-		r, _ := getRegionID(b(tt.id))
-		if r.M49() != tt.m49 {
-			t.Errorf("m49(%q): have %d; want %d", tt.id, r.M49(), tt.m49)
-		}
-	}
-}
-
-func TestRegionDeprecation(t *testing.T) {
-	tests := []struct{ in, out string }{
-		{"BU", "MM"},
-		{"BUR", "MM"},
-		{"CT", "KI"},
-		{"DD", "DE"},
-		{"DDR", "DE"},
-		{"DY", "BJ"},
-		{"FX", "FR"},
-		{"HV", "BF"},
-		{"JT", "UM"},
-		{"MI", "UM"},
-		{"NH", "VU"},
-		{"NQ", "AQ"},
-		{"PU", "UM"},
-		{"PZ", "PA"},
-		{"QU", "EU"},
-		{"RH", "ZW"},
-		{"TP", "TL"},
-		{"UK", "GB"},
-		{"VD", "VN"},
-		{"WK", "UM"},
-		{"YD", "YE"},
-		{"NL", "NL"},
-	}
-	for _, tt := range tests {
-		rIn, _ := getRegionID([]byte(tt.in))
-		rOut, _ := getRegionISO2([]byte(tt.out))
-		r := normRegion(rIn)
-		if rOut == rIn && r != 0 {
-			t.Errorf("%s: was %q; want %q", tt.in, r, tt.in)
-		}
-		if rOut != rIn && r != rOut {
-			t.Errorf("%s: was %q; want %q", tt.in, r, tt.out)
-		}
-
-	}
-}
-
-func TestGetScriptID(t *testing.T) {
-	idx := tag.Index("0000BbbbDdddEeeeZzzz\xff\xff\xff\xff")
-	tests := []struct {
-		in  string
-		out scriptID
-	}{
-		{"    ", 0},
-		{"      ", 0},
-		{"  ", 0},
-		{"", 0},
-		{"Aaaa", 0},
-		{"Bbbb", 1},
-		{"Dddd", 2},
-		{"dddd", 2},
-		{"dDDD", 2},
-		{"Eeee", 3},
-		{"Zzzz", 4},
-	}
-	for i, tt := range tests {
-		if id, err := getScriptID(idx, b(tt.in)); id != tt.out {
-			t.Errorf("%d:%s: found %d; want %d", i, tt.in, id, tt.out)
-		} else if id == 0 && err == nil {
-			t.Errorf("%d:%s: no error; expected one", i, tt.in)
-		}
-	}
-}
-
-func TestIsPrivateUse(t *testing.T) {
-	type test struct {
-		s       string
-		private bool
-	}
-	tests := []test{
-		{"en", false},
-		{"und", false},
-		{"pzn", false},
-		{"qaa", true},
-		{"qtz", true},
-		{"qua", false},
-	}
-	for i, tt := range tests {
-		x, _ := getLangID([]byte(tt.s))
-		if b := x.IsPrivateUse(); b != tt.private {
-			t.Errorf("%d: langID.IsPrivateUse(%s) was %v; want %v", i, tt.s, b, tt.private)
-		}
-	}
-	tests = []test{
-		{"001", false},
-		{"419", false},
-		{"899", false},
-		{"900", false},
-		{"957", false},
-		{"958", true},
-		{"AA", true},
-		{"AC", false},
-		{"EU", false}, // CLDR grouping, exceptionally reserved in ISO.
-		{"QU", true},  // Canonicalizes to EU, User-assigned in ISO.
-		{"QO", true},  // CLDR grouping, User-assigned in ISO.
-		{"QA", false},
-		{"QM", true},
-		{"QZ", true},
-		{"XA", true},
-		{"XK", true}, // Assigned to Kosovo in CLDR, User-assigned in ISO.
-		{"XZ", true},
-		{"ZW", false},
-		{"ZZ", true},
-	}
-	for i, tt := range tests {
-		x, _ := getRegionID([]byte(tt.s))
-		if b := x.IsPrivateUse(); b != tt.private {
-			t.Errorf("%d: regionID.IsPrivateUse(%s) was %v; want %v", i, tt.s, b, tt.private)
-		}
-	}
-	tests = []test{
-		{"Latn", false},
-		{"Laaa", false}, // invalid
-		{"Qaaa", true},
-		{"Qabx", true},
-		{"Qaby", false},
-		{"Zyyy", false},
-		{"Zzzz", false},
-	}
-	for i, tt := range tests {
-		x, _ := getScriptID(script, []byte(tt.s))
-		if b := x.IsPrivateUse(); b != tt.private {
-			t.Errorf("%d: scriptID.IsPrivateUse(%s) was %v; want %v", i, tt.s, b, tt.private)
-		}
-	}
-}
diff --git a/language/match.go b/language/match.go
index 15b74d1..33dd657 100644
--- a/language/match.go
+++ b/language/match.go
@@ -4,7 +4,11 @@
 
 package language
 
-import "errors"
+import (
+	"errors"
+
+	"golang.org/x/text/language/internal"
+)
 
 // A MatchOption configures a Matcher.
 type MatchOption func(*matcher)
@@ -74,12 +78,13 @@
 }
 
 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 {
-		t, index = match.tag, match.index
+		tt, index = match.tag, match.index
 	} else {
 		// TODO: this should be an option
-		t = m.default_.tag
+		tt = m.default_.tag
 		if m.preferSameScript {
 		outer:
 			for _, w := range want {
@@ -91,7 +96,7 @@
 				}
 				for i, h := range m.supported {
 					if script.scriptID == h.maxScript {
-						t, index = h.tag, i
+						tt, index = h.tag, i
 						break outer
 					}
 				}
@@ -99,232 +104,35 @@
 		}
 		// TODO: select first language tag based on script.
 	}
-	if w.region != 0 && t.region != 0 && t.region.contains(w.region) {
-		t, _ = Raw.Compose(t, Region{w.region})
+	if w.RegionID != 0 && tt.RegionID != 0 && tt.RegionID.Contains(w.RegionID) {
+		t, _ := Raw.Compose(Tag{tt}, Region{w.RegionID})
+		tt = t.tag
 	}
 	// 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 {
-		t, _ = Raw.Compose(t, e)
+		// TODO: improve performance.
+		ext := make([]Extension, len(e))
+		for _, ee := range e {
+			ext = append(ext, Extension{ee})
+		}
+		t, _ := Raw.Compose(Tag{tt}, ext)
+		tt = t.tag
 	}
-	return t, index, c
-}
-
-type scriptRegionFlags uint8
-
-const (
-	isList = 1 << iota
-	scriptInFrom
-	regionInFrom
-)
-
-func (t *Tag) setUndefinedLang(id langID) {
-	if t.lang == 0 {
-		t.lang = id
-	}
-}
-
-func (t *Tag) setUndefinedScript(id scriptID) {
-	if t.script == 0 {
-		t.script = id
-	}
-}
-
-func (t *Tag) setUndefinedRegion(id regionID) {
-	if t.region == 0 || t.region.contains(id) {
-		t.region = id
-	}
+	return Tag{tt}, index, c
 }
 
 // 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.region]; i < nRegionGroups {
-		x := likelyRegionGroup[i]
-		if langID(x.lang) == t.lang && scriptID(x.script) == t.script {
-			t.region = regionID(x.region)
-		}
-		return true
-	}
-	return false
-}
-
-func addTags(t Tag) (Tag, error) {
-	// We leave private use identifiers alone.
-	if t.private() {
-		return t, nil
-	}
-	if t.script != 0 && t.region != 0 {
-		if t.lang != 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.region : t.region+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 scriptID(x.script) == t.script {
-				t.setUndefinedLang(langID(x.lang))
-				return t, nil
-			}
-		}
-	}
-	if t.lang != 0 {
-		// Search matches for lang-script and lang-region, where lang != und.
-		if t.lang < langNoIndexOffset {
-			x := likelyLang[t.lang]
-			if x.flags&isList != 0 {
-				list := likelyLangList[x.region : x.region+uint16(x.script)]
-				if t.script != 0 {
-					for _, x := range list {
-						if scriptID(x.script) == t.script && x.flags&scriptInFrom != 0 {
-							t.setUndefinedRegion(regionID(x.region))
-							return t, nil
-						}
-					}
-				} else if t.region != 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.region.contains(regionID(x.region)) {
-							tt.region = regionID(x.region)
-							tt.setUndefinedScript(scriptID(x.script))
-							goodScript = goodScript && tt.script == scriptID(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.script = tt.script
-					}
-				}
-			}
-		}
-	} else {
-		// Search matches for und-script.
-		if t.script != 0 {
-			x := likelyScript[t.script]
-			if x.region != 0 {
-				t.setUndefinedRegion(regionID(x.region))
-				t.setUndefinedLang(langID(x.lang))
-				return t, nil
-			}
-		}
-		// Search matches for und-region. If und-script-region exists, it would
-		// have been found earlier.
-		if t.region != 0 {
-			if i := regionInclusion[t.region]; i < nRegionGroups {
-				x := likelyRegionGroup[i]
-				if x.region != 0 {
-					t.setUndefinedLang(langID(x.lang))
-					t.setUndefinedScript(scriptID(x.script))
-					t.region = regionID(x.region)
-				}
-			} else {
-				x := likelyRegion[t.region]
-				if x.flags&isList != 0 {
-					x = likelyRegionList[x.lang]
-				}
-				if x.script != 0 && x.flags != scriptInFrom {
-					t.setUndefinedLang(langID(x.lang))
-					t.setUndefinedScript(scriptID(x.script))
-					return t, nil
-				}
-			}
-		}
-	}
-
-	// Search matches for lang.
-	if t.lang < langNoIndexOffset {
-		x := likelyLang[t.lang]
-		if x.flags&isList != 0 {
-			x = likelyLangList[x.region]
-		}
-		if x.region != 0 {
-			t.setUndefinedScript(scriptID(x.script))
-			t.setUndefinedRegion(regionID(x.region))
-		}
-		specializeRegion(&t)
-		if t.lang == 0 {
-			t.lang = _en // default language
-		}
-		return t, nil
-	}
-	return t, ErrMissingLikelyTagsData
-}
-
-func (t *Tag) setTagsFrom(id Tag) {
-	t.lang = id.lang
-	t.script = id.script
-	t.region = id.region
-}
-
-// 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{
-		{lang: t.lang},
-		{lang: t.lang, region: t.region},
-		{lang: t.lang, script: t.script},
-	} {
-		if x, err := addTags(id); err == nil && max.equalTags(x) {
-			t.setTagsFrom(id)
-			break
-		}
-	}
-	return t, nil
-}
+// 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
@@ -456,7 +264,7 @@
 // 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 Tag
+	tag language.Tag
 
 	// index of this tag in the original list of supported tags.
 	index int
@@ -478,14 +286,14 @@
 	nextMax uint16
 }
 
-func makeHaveTag(tag Tag, index int) (haveTag, langID) {
+func makeHaveTag(tag language.Tag, index int) (haveTag, langID) {
 	max := tag
-	if tag.lang != 0 || tag.region != 0 || tag.script != 0 {
-		max, _ = max.canonicalize(All)
-		max, _ = addTags(max)
-		max.remakeString()
+	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.region, max.script, altScript(max.lang, max.script), 0}, max.lang
+	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
@@ -508,7 +316,7 @@
 	h.original = h.original || exact
 	// Don't add new exact matches.
 	for _, v := range h.haveTags {
-		if v.tag.equalsRest(n.tag) {
+		if equalsRest(v.tag, n.tag) {
 			return
 		}
 	}
@@ -517,7 +325,7 @@
 	for i, v := range h.haveTags {
 		if v.maxScript == n.maxScript &&
 			v.maxRegion == n.maxRegion &&
-			v.tag.variantOrPrivateTagStr() == n.tag.variantOrPrivateTagStr() {
+			v.tag.VariantOrPrivateTagStr() == n.tag.VariantOrPrivateTagStr() {
 			for h.haveTags[i].nextMax != 0 {
 				i = int(h.haveTags[i].nextMax)
 			}
@@ -530,7 +338,7 @@
 
 // header returns the matchHeader for the given language. It creates one if
 // it doesn't already exist.
-func (m *matcher) header(l langID) *matchHeader {
+func (m *matcher) header(l language.Language) *matchHeader {
 	if h := m.index[l]; h != nil {
 		return h
 	}
@@ -567,16 +375,16 @@
 	// Add supported languages to the index. Add exact matches first to give
 	// them precedence.
 	for i, tag := range supported {
-		pair, _ := makeHaveTag(tag, i)
-		m.header(tag.lang).addIfNew(pair, true)
+		pair, _ := makeHaveTag(tag.tag, i)
+		m.header(tag.tag.LangID).addIfNew(pair, true)
 		m.supported = append(m.supported, &pair)
 	}
-	m.default_ = m.header(supported[0].lang).haveTags[0]
+	m.default_ = m.header(supported[0].tag.LangID).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 {
-		pair, max := makeHaveTag(tag, i)
-		if max != tag.lang {
+		pair, max := makeHaveTag(tag.tag, i)
+		if max != tag.tag.LangID {
 			m.header(max).addIfNew(pair, true)
 		}
 	}
@@ -618,66 +426,67 @@
 	// 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 langAliasMap {
+	for i, lm := range language.AliasMap {
 		// If deprecated codes match and there is no fiddling with the script or
 		// or region, we consider it an exact match.
 		conf := Exact
-		if langAliasTypes[i] != langMacro {
-			if !isExactEquivalent(langID(lm.from)) {
+		if language.AliasTypes[i] != language.Macro {
+			if !isExactEquivalent(langID(lm.From)) {
 				conf = High
 			}
-			update(lm.to, lm.from, conf)
+			update(lm.To, lm.From, conf)
 		}
-		update(lm.from, lm.to, 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 Tag, c Confidence) {
+func (m *matcher) getBest(want ...Tag) (got *haveTag, orig language.Tag, c Confidence) {
 	best := bestMatch{}
-	for i, w := range want {
-		var max Tag
+	for i, ww := range want {
+		w := ww.tag
+		var max language.Tag
 		// Check for exact match first.
-		h := m.index[w.lang]
-		if w.lang != 0 {
+		h := m.index[w.LangID]
+		if w.LangID != 0 {
 			if h == nil {
 				continue
 			}
 			// Base language is defined.
-			max, _ = w.canonicalize(Legacy | Deprecated | Macro)
+			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.region != max.region {
-				w.region = max.region
+			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, _ = addTags(max)
+			max, _ = max.Maximize()
 		} else {
 			// Base language is not defined.
 			if h != nil {
 				for i := range h.haveTags {
 					have := h.haveTags[i]
-					if have.tag.equalsRest(w) {
+					if equalsRest(have.tag, w) {
 						return have, w, Exact
 					}
 				}
 			}
-			if w.script == 0 && w.region == 0 {
+			if w.ScriptID == 0 && w.RegionID == 0 {
 				// We skip all tags matching und for approximate matching, including
 				// private tags.
 				continue
 			}
-			max, _ = addTags(w)
-			if h = m.index[max.lang]; h == nil {
+			max, _ = w.Maximize()
+			if h = m.index[max.LangID]; h == nil {
 				continue
 			}
 		}
 		pin := true
 		for _, t := range want[i+1:] {
-			if w.lang == t.lang {
+			if w.LangID == t.tag.LangID {
 				pin = false
 				break
 			}
@@ -685,11 +494,11 @@
 		// Check for match based on maximized tag.
 		for i := range h.haveTags {
 			have := h.haveTags[i]
-			best.update(have, w, max.script, max.region, pin)
+			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.script, max.region, pin)
+					best.update(have, w, max.ScriptID, max.RegionID, pin)
 				}
 				return best.have, best.want, best.conf
 			}
@@ -697,9 +506,9 @@
 	}
 	if best.conf <= No {
 		if len(want) != 0 {
-			return nil, want[0], No
+			return nil, want[0].tag, No
 		}
-		return nil, Tag{}, No
+		return nil, language.Tag{}, No
 	}
 	return best.have, best.want, best.conf
 }
@@ -707,7 +516,7 @@
 // bestMatch accumulates the best match so far.
 type bestMatch struct {
 	have            *haveTag
-	want            Tag
+	want            language.Tag
 	conf            Confidence
 	pinnedRegion    regionID
 	pinLanguage     bool
@@ -734,19 +543,19 @@
 // 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 Tag, maxScript scriptID, maxRegion regionID, pin bool) {
+func (m *bestMatch) update(have *haveTag, tag language.Tag, maxScript scriptID, maxRegion regionID, 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.lang != m.want.lang {
+	if m.pinLanguage && tag.LangID != m.want.LangID {
 		return
 	}
 	// Pin the region group if we are comparing tags for the same language.
-	if tag.lang == m.want.lang && m.sameRegionGroup {
-		_, sameGroup := regionGroupDist(m.pinnedRegion, have.maxRegion, have.maxScript, m.want.lang)
+	if tag.LangID == m.want.LangID && m.sameRegionGroup {
+		_, sameGroup := regionGroupDist(m.pinnedRegion, have.maxRegion, have.maxScript, m.want.LangID)
 		if !sameGroup {
 			return
 		}
@@ -756,7 +565,7 @@
 		// don't pin anything, otherwise pin the language.
 		m.pinLanguage = pin
 	}
-	if have.tag.equalsRest(tag) {
+	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
@@ -786,7 +595,7 @@
 
 	// Tie-breaker rules:
 	// We prefer if the pre-maximized language was specified and identical.
-	origLang := have.tag.lang == tag.lang && tag.lang != 0
+	origLang := have.tag.LangID == tag.LangID && tag.LangID != 0
 	if !beaten && m.origLang != origLang {
 		if m.origLang {
 			return
@@ -795,7 +604,7 @@
 	}
 
 	// We prefer if the pre-maximized region was specified and identical.
-	origReg := have.tag.region == tag.region && tag.region != 0
+	origReg := have.tag.RegionID == tag.RegionID && tag.RegionID != 0
 	if !beaten && m.origReg != origReg {
 		if m.origReg {
 			return
@@ -803,7 +612,7 @@
 		beaten = true
 	}
 
-	regGroupDist, sameGroup := regionGroupDist(have.maxRegion, maxRegion, maxScript, tag.lang)
+	regGroupDist, sameGroup := regionGroupDist(have.maxRegion, maxRegion, maxScript, tag.LangID)
 	if !beaten && m.regGroupDist != regGroupDist {
 		if regGroupDist > m.regGroupDist {
 			return
@@ -811,7 +620,7 @@
 		beaten = true
 	}
 
-	paradigmReg := isParadigmLocale(tag.lang, have.maxRegion)
+	paradigmReg := isParadigmLocale(tag.LangID, have.maxRegion)
 	if !beaten && m.paradigmReg != paradigmReg {
 		if !paradigmReg {
 			return
@@ -820,7 +629,7 @@
 	}
 
 	// Next we prefer if the pre-maximized script was specified and identical.
-	origScript := have.tag.script == tag.script && tag.script != 0
+	origScript := have.tag.ScriptID == tag.ScriptID && tag.ScriptID != 0
 	if !beaten && m.origScript != origScript {
 		if m.origScript {
 			return
@@ -876,26 +685,11 @@
 	return defaultDistance, true
 }
 
-func (t Tag) variants() string {
-	if t.pVariant == 0 {
-		return ""
-	}
-	return t.str[t.pVariant:t.pExt]
-}
-
-// variantOrPrivateTagStr returns variants or private use tags.
-func (t Tag) variantOrPrivateTagStr() string {
-	if t.pExt > 0 {
-		return t.str[t.pVariant:t.pExt]
-	}
-	return t.str[t.pVariant:]
-}
-
 // equalsRest compares everything except the language.
-func (a Tag) equalsRest(b Tag) bool {
+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.script == b.script && a.region == b.region && a.variantOrPrivateTagStr() == b.variantOrPrivateTagStr()
+	return a.ScriptID == b.ScriptID && a.RegionID == b.RegionID && a.VariantOrPrivateTagStr() == b.VariantOrPrivateTagStr()
 }
 
 // isExactEquivalent returns true if canonicalizing the language will not alter
@@ -914,20 +708,21 @@
 func init() {
 	// Create a list of all languages for which canonicalization may alter the
 	// script or region.
-	for _, lm := range langAliasMap {
-		tag := Tag{lang: langID(lm.from)}
-		if tag, _ = tag.canonicalize(All); tag.script != 0 || tag.region != 0 {
-			notEquivalent = append(notEquivalent, langID(lm.from))
+	for _, lm := range language.AliasMap {
+		tag := language.Tag{LangID: langID(lm.From)}
+		if tag, _ = canonicalize(All, tag); tag.ScriptID != 0 || tag.RegionID != 0 {
+			notEquivalent = append(notEquivalent, langID(lm.From))
 		}
 	}
 	// Maximize undefined regions of paradigm locales.
 	for i, v := range paradigmLocales {
-		max, _ := addTags(Tag{lang: langID(v[0])})
+		t := language.Tag{LangID: langID(v[0])}
+		max, _ := t.Maximize()
 		if v[1] == 0 {
-			paradigmLocales[i][1] = uint16(max.region)
+			paradigmLocales[i][1] = uint16(max.RegionID)
 		}
 		if v[2] == 0 {
-			paradigmLocales[i][2] = uint16(max.region)
+			paradigmLocales[i][2] = uint16(max.RegionID)
 		}
 	}
 }
diff --git a/language/match_test.go b/language/match_test.go
index 8b60b07..fd36983 100644
--- a/language/match_test.go
+++ b/language/match_test.go
@@ -148,155 +148,6 @@
 	}
 }
 
-func TestAddLikelySubtags(t *testing.T) {
-	tests := []struct{ in, out string }{
-		{"aa", "aa-Latn-ET"},
-		{"aa-Latn", "aa-Latn-ET"},
-		{"aa-Arab", "aa-Arab-ET"},
-		{"aa-Arab-ER", "aa-Arab-ER"},
-		{"kk", "kk-Cyrl-KZ"},
-		{"kk-CN", "kk-Arab-CN"},
-		{"cmn", "cmn"},
-		{"zh-AU", "zh-Hant-AU"},
-		{"zh-VN", "zh-Hant-VN"},
-		{"zh-SG", "zh-Hans-SG"},
-		{"zh-Hant", "zh-Hant-TW"},
-		{"zh-Hani", "zh-Hani-CN"},
-		{"und-Hani", "zh-Hani-CN"},
-		{"und", "en-Latn-US"},
-		{"und-GB", "en-Latn-GB"},
-		{"und-CW", "pap-Latn-CW"},
-		{"und-YT", "fr-Latn-YT"},
-		{"und-Arab", "ar-Arab-EG"},
-		{"und-AM", "hy-Armn-AM"},
-		{"und-TW", "zh-Hant-TW"},
-		{"und-002", "en-Latn-NG"},
-		{"und-Latn-002", "en-Latn-NG"},
-		{"en-Latn-002", "en-Latn-NG"},
-		{"en-002", "en-Latn-NG"},
-		{"en-001", "en-Latn-US"},
-		{"und-003", "en-Latn-US"},
-		{"und-GB", "en-Latn-GB"},
-		{"Latn-001", "en-Latn-US"},
-		{"en-001", "en-Latn-US"},
-		{"es-419", "es-Latn-419"},
-		{"he-145", "he-Hebr-IL"},
-		{"ky-145", "ky-Latn-TR"},
-		{"kk", "kk-Cyrl-KZ"},
-		// Don't specialize duplicate and ambiguous matches.
-		{"kk-034", "kk-Arab-034"}, // Matches IR and AF. Both are Arab.
-		{"ku-145", "ku-Latn-TR"},  // Matches IQ, TR, and LB, but kk -> TR.
-		{"und-Arab-CC", "ms-Arab-CC"},
-		{"und-Arab-GB", "ks-Arab-GB"},
-		{"und-Hans-CC", "zh-Hans-CC"},
-		{"und-CC", "en-Latn-CC"},
-		{"sr", "sr-Cyrl-RS"},
-		{"sr-151", "sr-Latn-151"}, // Matches RO and RU.
-		// We would like addLikelySubtags to generate the same results if the input
-		// only changes by adding tags that would otherwise have been added
-		// by the expansion.
-		// In other words:
-		//     und-AA -> xx-Scrp-AA   implies und-Scrp-AA -> xx-Scrp-AA
-		//     und-AA -> xx-Scrp-AA   implies xx-AA -> xx-Scrp-AA
-		//     und-Scrp -> xx-Scrp-AA implies und-Scrp-AA -> xx-Scrp-AA
-		//     und-Scrp -> xx-Scrp-AA implies xx-Scrp -> xx-Scrp-AA
-		//     xx -> xx-Scrp-AA       implies xx-Scrp -> xx-Scrp-AA
-		//     xx -> xx-Scrp-AA       implies xx-AA -> xx-Scrp-AA
-		//
-		// The algorithm specified in
-		//   http://unicode.org/reports/tr35/tr35-9.html#Supplemental_Data,
-		// Section C.10, does not handle the first case. For example,
-		// the CLDR data contains an entry und-BJ -> fr-Latn-BJ, but not
-		// there is no rule for und-Latn-BJ.  According to spec, und-Latn-BJ
-		// would expand to en-Latn-BJ, violating the aforementioned principle.
-		// We deviate from the spec by letting und-Scrp-AA expand to xx-Scrp-AA
-		// if a rule of the form und-AA -> xx-Scrp-AA is defined.
-		// Note that as of version 23, CLDR has some explicitly specified
-		// entries that do not conform to these rules. The implementation
-		// will not correct these explicit inconsistencies. A later versions of CLDR
-		// is supposed to fix this.
-		{"und-Latn-BJ", "fr-Latn-BJ"},
-		{"und-Bugi-ID", "bug-Bugi-ID"},
-		// regions, scripts and languages without definitions
-		{"und-Arab-AA", "ar-Arab-AA"},
-		{"und-Afak-RE", "fr-Afak-RE"},
-		{"und-Arab-GB", "ks-Arab-GB"},
-		{"abp-Arab-GB", "abp-Arab-GB"},
-		// script has preference over region
-		{"und-Arab-NL", "ar-Arab-NL"},
-		{"zza", "zza-Latn-TR"},
-		// preserve variants and extensions
-		{"de-1901", "de-Latn-DE-1901"},
-		{"de-x-abc", "de-Latn-DE-x-abc"},
-		{"de-1901-x-abc", "de-Latn-DE-1901-x-abc"},
-		{"x-abc", "x-abc"}, // TODO: is this the desired behavior?
-	}
-	for i, tt := range tests {
-		in, _ := Parse(tt.in)
-		out, _ := Parse(tt.out)
-		in, _ = in.addLikelySubtags()
-		if in.String() != out.String() {
-			t.Errorf("%d: add(%s) was %s; want %s", i, tt.in, in, tt.out)
-		}
-	}
-}
-func TestMinimize(t *testing.T) {
-	tests := []struct{ in, out string }{
-		{"aa", "aa"},
-		{"aa-Latn", "aa"},
-		{"aa-Latn-ET", "aa"},
-		{"aa-ET", "aa"},
-		{"aa-Arab", "aa-Arab"},
-		{"aa-Arab-ER", "aa-Arab-ER"},
-		{"aa-Arab-ET", "aa-Arab"},
-		{"und", "und"},
-		{"und-Latn", "und"},
-		{"und-Latn-US", "und"},
-		{"en-Latn-US", "en"},
-		{"cmn", "cmn"},
-		{"cmn-Hans", "cmn-Hans"},
-		{"cmn-Hant", "cmn-Hant"},
-		{"zh-AU", "zh-AU"},
-		{"zh-VN", "zh-VN"},
-		{"zh-SG", "zh-SG"},
-		{"zh-Hant", "zh-Hant"},
-		{"zh-Hant-TW", "zh-TW"},
-		{"zh-Hans", "zh"},
-		{"zh-Hani", "zh-Hani"},
-		{"und-Hans", "und-Hans"},
-		{"und-Hani", "und-Hani"},
-
-		{"und-CW", "und-CW"},
-		{"und-YT", "und-YT"},
-		{"und-Arab", "und-Arab"},
-		{"und-AM", "und-AM"},
-		{"und-Arab-CC", "und-Arab-CC"},
-		{"und-CC", "und-CC"},
-		{"und-Latn-BJ", "und-BJ"},
-		{"und-Bugi-ID", "und-Bugi"},
-		{"bug-Bugi-ID", "bug-Bugi"},
-		// regions, scripts and languages without definitions
-		{"und-Arab-AA", "und-Arab-AA"},
-		// preserve variants and extensions
-		{"de-Latn-1901", "de-1901"},
-		{"de-Latn-x-abc", "de-x-abc"},
-		{"de-DE-1901-x-abc", "de-1901-x-abc"},
-		{"x-abc", "x-abc"}, // TODO: is this the desired behavior?
-	}
-	for i, tt := range tests {
-		in, _ := Parse(tt.in)
-		out, _ := Parse(tt.out)
-		min, _ := in.minimize()
-		if min.String() != out.String() {
-			t.Errorf("%d: min(%s) was %s; want %s", i, tt.in, min, tt.out)
-		}
-		max, _ := min.addLikelySubtags()
-		if x, _ := in.addLikelySubtags(); x.String() != max.String() {
-			t.Errorf("%d: max(min(%s)) = %s; want %s", i, tt.in, max, x)
-		}
-	}
-}
-
 func TestRegionGroups(t *testing.T) {
 	testCases := []struct {
 		a, b     string
@@ -321,7 +172,7 @@
 			t.Errorf("scripts differ: %q vs %q", aScript, bScript)
 			continue
 		}
-		d, _ := regionGroupDist(a.region, b.region, aScript.scriptID, a.lang)
+		d, _ := regionGroupDist(a.tag.RegionID, b.tag.RegionID, aScript.scriptID, a.tag.LangID)
 		if d != tc.distance {
 			t.Errorf("got %q; want %q", d, tc.distance)
 		}
@@ -338,8 +189,8 @@
 		"es-419": true,
 	}
 	for str, want := range testCases {
-		tag := Make(str)
-		got := isParadigmLocale(tag.lang, tag.region)
+		tag := Make(str).tag
+		got := isParadigmLocale(tag.LangID, tag.RegionID)
 		if got != want {
 			t.Errorf("isPL(%q) = %v; want %v", str, got, want)
 		}
diff --git a/language/parse.go b/language/parse.go
index fca2d30..3f0f4ad 100644
--- a/language/parse.go
+++ b/language/parse.go
@@ -5,216 +5,21 @@
 package language
 
 import (
-	"bytes"
 	"errors"
-	"fmt"
-	"sort"
 	"strconv"
 	"strings"
 
-	"golang.org/x/text/internal/tag"
+	"golang.org/x/text/language/internal"
 )
 
-// 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")
-
 // 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
-}
+type ValueError interface {
+	error
 
-func mkErrInvalid(s []byte) error {
-	var e ValueError
-	copy(e.v[:], s)
-	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
-		if end < cap(s.b) {
-			b := make([]byte, len(s.b)+diff)
-			copy(b, s.b[:oldStart])
-			copy(b[end:], s.b[oldEnd:])
-			s.b = b
-		} else {
-			s.b = append(s.b[end:], s.b[oldEnd:]...)
-		}
-		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.setError(errSyntax)
-	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
+	// 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
@@ -238,324 +43,15 @@
 // http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers.
 // The resulting tag is canonicalized using the the canonicalization type c.
 func (c CanonType) Parse(s string) (t Tag, err error) {
-	// TODO: consider supporting old-style locale key-value pairs.
-	if s == "" {
-		return und, errSyntax
+	tt, err := language.Parse(s)
+	if err != nil {
+		return Tag{tt}, err
 	}
-	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)
-	t, err = parse(&scan, s)
-	t, changed := t.canonicalize(c)
+	tt, changed := canonicalize(c, tt)
 	if changed {
-		t.remakeString()
+		tt.RemakeString()
 	}
-	return t, err
-}
-
-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)
-		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.
-func parseTag(scan *scanner) (t Tag, end int) {
-	var e error
-	// TODO: set an error if an unknown lang, script or region is encountered.
-	t.lang, e = getLangID(scan.token)
-	scan.setError(e)
-	scan.replace(t.lang.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>.
-		lang, e := getLangID(scan.token)
-		if lang != 0 {
-			t.lang = lang
-			copy(scan.b[langStart:], lang.String())
-			scan.b[langStart+3] = '-'
-			scan.start = langStart + 4
-		}
-		scan.gobble(e)
-		end = scan.scan()
-	}
-	if len(scan.token) == 4 && isAlpha(scan.token[0]) {
-		t.script, e = getScriptID(script, scan.token)
-		if t.script == 0 {
-			scan.gobble(e)
-		}
-		end = scan.scan()
-	}
-	if n := len(scan.token); n >= 2 && n <= 3 {
-		t.region, e = getRegionID(scan.token)
-		if t.region == 0 {
-			scan.gobble(e)
-		} else {
-			scan.replace(t.region.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(mkErrInvalid(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 [][]byte
-
-func (b bytesSort) Len() int {
-	return len(b)
-}
-
-func (b bytesSort) Swap(i, j int) {
-	b[i], b[j] = b[j], b[i]
-}
-
-func (b bytesSort) Less(i, j int) bool {
-	return bytes.Compare(b[i], b[j]) == -1
-}
-
-// 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))
-	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':
-		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))
-				copy(scan.b[p:], bytes.Join(attrs, separator))
-				break
-			}
-			last = scan.token
-			end = scan.end
-		}
-		var last, key []byte
-		for attrEnd := end; len(scan.token) == 2; last = key {
-			key = scan.token
-			keyEnd := scan.end
-			end = scan.acceptMinSize(3)
-			// TODO: check key value validity
-			if keyEnd == end || bytes.Compare(key, last) != 1 {
-				// 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, keyEnd := scan.start, scan.end
-					end = scan.acceptMinSize(3)
-					if keyEnd != end {
-						keys = append(keys, scan.b[keyStart:end])
-					} else {
-						scan.setError(errSyntax)
-						end = keyStart
-					}
-				}
-				sort.Sort(bytesSort(keys))
-				reordered := bytes.Join(keys, separator)
-				if e := p + len(reordered); e < end {
-					scan.deleteRange(e, end)
-					end = e
-				}
-				copy(scan.b[p:], bytes.Join(keys, separator))
-				break
-			}
-		}
-	case 't':
-		scan.scan()
-		if n := len(scan.token); n >= 2 && n <= 3 && isAlpha(scan.token[1]) {
-			_, end = parseTag(scan)
-			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
+	return Tag{tt}, err
 }
 
 // Compose creates a Tag from individual parts, which may be of type Tag, Base,
@@ -581,58 +77,20 @@
 // 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) {
-	var b builder
-	if err = b.update(part...); err != nil {
+	var b language.Builder
+	if err = update(&b, part...); err != nil {
 		return und, err
 	}
-	t, _ = b.tag.canonicalize(c)
-
-	if len(b.ext) > 0 || len(b.variant) > 0 {
-		sort.Sort(sortVariant(b.variant))
-		sort.Strings(b.ext)
-		if b.private != "" {
-			b.ext = append(b.ext, b.private)
-		}
-		n := maxCoreSize + tokenLen(b.variant...) + tokenLen(b.ext...)
-		buf := make([]byte, n)
-		p := t.genCoreBytes(buf)
-		t.pVariant = byte(p)
-		p += appendTokens(buf[p:], b.variant...)
-		t.pExt = uint16(p)
-		p += appendTokens(buf[p:], b.ext...)
-		t.str = string(buf[:p])
-	} else if b.private != "" {
-		t.str = b.private
-		t.remakeString()
-	}
-	return
-}
-
-type builder struct {
-	tag Tag
-
-	private string // the x extension
-	ext     []string
-	variant []string
-
-	err error
-}
-
-func (b *builder) addExt(e string) {
-	if e == "" {
-	} else if e[0] == 'x' {
-		b.private = e
-	} else {
-		b.ext = append(b.ext, e)
-	}
+	b.Tag, _ = canonicalize(c, b.Tag)
+	return Tag{b.Make()}, err
 }
 
 var errInvalidArgument = errors.New("invalid Extension or Variant")
 
-func (b *builder) update(part ...interface{}) (err error) {
+func update(b *language.Builder, part ...interface{}) (err error) {
 	replace := func(l *[]string, s string, eq func(a, b string) bool) bool {
 		if s == "" {
-			b.err = errInvalidArgument
+			b.Err = errInvalidArgument
 			return true
 		}
 		for i, v := range *l {
@@ -646,44 +104,41 @@
 	for _, x := range part {
 		switch v := x.(type) {
 		case Tag:
-			b.tag.lang = v.lang
-			b.tag.region = v.region
-			b.tag.script = v.script
-			if v.str != "" {
-				b.variant = nil
-				for x, s := "", v.str[v.pVariant:v.pExt]; s != ""; {
-					x, s = nextToken(s)
-					b.variant = append(b.variant, x)
-				}
-				b.ext, b.private = nil, ""
-				for i, e := int(v.pExt), ""; i < len(v.str); {
-					i, e = getExtension(v.str, i)
-					b.addExt(e)
-				}
+			b.Tag.LangID = v.lang()
+			b.Tag.RegionID = v.region()
+			b.Tag.ScriptID = v.script()
+			// TODO: optimize
+			b.Variant = b.Variant[:0]
+			for _, vr := range v.Variants() {
+				b.Variant = append(b.Variant, vr.String())
+			}
+			b.Ext, b.Private = b.Ext[:0], ""
+			for _, e := range v.Extensions() {
+				b.AddExt(e.String())
 			}
 		case Base:
-			b.tag.lang = v.langID
+			b.Tag.LangID = v.langID
 		case Script:
-			b.tag.script = v.scriptID
+			b.Tag.ScriptID = v.scriptID
 		case Region:
-			b.tag.region = v.regionID
+			b.Tag.RegionID = v.regionID
 		case Variant:
-			if !replace(&b.variant, v.variant, func(a, b string) bool { return a == b }) {
-				b.variant = append(b.variant, v.variant)
+			if !replace(&b.Variant, v.variant, func(a, b string) bool { return a == b }) {
+				b.Variant = append(b.Variant, v.variant)
 			}
 		case Extension:
-			if !replace(&b.ext, v.s, func(a, b string) bool { return a[0] == b[0] }) {
-				b.addExt(v.s)
+			if !replace(&b.Ext, v.s, func(a, b string) bool { return a[0] == b[0] }) {
+				b.AddExt(v.s)
 			}
 		case []Variant:
-			b.variant = nil
+			b.Variant = nil
 			for _, x := range v {
-				b.update(x)
+				update(b, x)
 			}
 		case []Extension:
-			b.ext, b.private = nil, ""
+			b.Ext, b.Private = nil, ""
 			for _, e := range v {
-				b.update(e)
+				update(b, e)
 			}
 		// TODO: support parsing of raw strings based on morphology or just extensions?
 		case error:
@@ -693,76 +148,6 @@
 	return
 }
 
-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 sortVariant []string
-
-func (s sortVariant) Len() int {
-	return len(s)
-}
-
-func (s sortVariant) Swap(i, j int) {
-	s[j], s[i] = s[i], s[j]
-}
-
-func (s sortVariant) Less(i, j int) bool {
-	return variantIndex[s[i]] < variantIndex[s[j]]
-}
-
-func findExt(list []string, x byte) int {
-	for i, e := range list {
-		if e[0] == x {
-			return i
-		}
-	}
-	return -1
-}
-
-// 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)
-}
-
 var errInvalidWeight = errors.New("ParseAcceptLanguage: invalid weight")
 
 // ParseAcceptLanguage parses the contents of an Accept-Language header as
@@ -788,7 +173,7 @@
 			if !ok {
 				return nil, nil, err
 			}
-			t = Tag{lang: id}
+			t = Tag{tag: language.Tag{LangID: id}}
 		}
 
 		// Scan the optional weight.
diff --git a/language/parse_test.go b/language/parse_test.go
index 9b40eb4..fe6bc0d 100644
--- a/language/parse_test.go
+++ b/language/parse_test.go
@@ -5,88 +5,20 @@
 package language
 
 import (
-	"bytes"
 	"strings"
 	"testing"
 
-	"golang.org/x/text/internal/tag"
+	"golang.org/x/text/language/internal"
 )
 
-type scanTest struct {
-	ok  bool // true if scanning does not result in an error
-	in  string
-	tok []string // the expected tokens
+// equalTags compares language, script and region subtags only.
+func (t Tag) equalTags(a Tag) bool {
+	return t.lang() == a.lang() &&
+		t.script() == a.script() &&
+		t.region() == a.region()
 }
 
-var tests = []scanTest{
-	{true, "", []string{}},
-	{true, "1", []string{"1"}},
-	{true, "en", []string{"en"}},
-	{true, "root", []string{"root"}},
-	{true, "maxchars", []string{"maxchars"}},
-	{false, "bad/", []string{}},
-	{false, "morethan8", []string{}},
-	{false, "-", []string{}},
-	{false, "----", []string{}},
-	{false, "_", []string{}},
-	{true, "en-US", []string{"en", "US"}},
-	{true, "en_US", []string{"en", "US"}},
-	{false, "en-US-", []string{"en", "US"}},
-	{false, "en-US--", []string{"en", "US"}},
-	{false, "en-US---", []string{"en", "US"}},
-	{false, "en--US", []string{"en", "US"}},
-	{false, "-en-US", []string{"en", "US"}},
-	{false, "-en--US-", []string{"en", "US"}},
-	{false, "-en--US-", []string{"en", "US"}},
-	{false, "en-.-US", []string{"en", "US"}},
-	{false, ".-en--US-.", []string{"en", "US"}},
-	{false, "en-u.-US", []string{"en", "US"}},
-	{true, "en-u1-US", []string{"en", "u1", "US"}},
-	{true, "maxchar1_maxchar2-maxchar3", []string{"maxchar1", "maxchar2", "maxchar3"}},
-	{false, "moreThan8-moreThan8-e", []string{"e"}},
-}
-
-func TestScan(t *testing.T) {
-	for i, tt := range tests {
-		scan := makeScannerString(tt.in)
-		for j := 0; !scan.done; j++ {
-			if j >= len(tt.tok) {
-				t.Errorf("%d: extra token %q", i, scan.token)
-			} else if tag.Compare(tt.tok[j], scan.token) != 0 {
-				t.Errorf("%d: token %d: found %q; want %q", i, j, scan.token, tt.tok[j])
-				break
-			}
-			scan.scan()
-		}
-		if s := strings.Join(tt.tok, "-"); tag.Compare(s, bytes.Replace(scan.b, b("_"), b("-"), -1)) != 0 {
-			t.Errorf("%d: input: found %q; want %q", i, scan.b, s)
-		}
-		if (scan.err == nil) != tt.ok {
-			t.Errorf("%d: ok: found %v; want %v", i, scan.err == nil, tt.ok)
-		}
-	}
-}
-
-func TestAcceptMinSize(t *testing.T) {
-	for i, tt := range tests {
-		// count number of successive tokens with a minimum size.
-		for sz := 1; sz <= 8; sz++ {
-			scan := makeScannerString(tt.in)
-			scan.end, scan.next = 0, 0
-			end := scan.acceptMinSize(sz)
-			n := 0
-			for i := 0; i < len(tt.tok) && len(tt.tok[i]) >= sz; i++ {
-				n += len(tt.tok[i])
-				if i > 0 {
-					n++
-				}
-			}
-			if end != n {
-				t.Errorf("%d:%d: found len %d; want %d", i, sz, end, n)
-			}
-		}
-	}
-}
+var errSyntax = language.ErrSyntax
 
 type parseTest struct {
 	i                    int // the index of this test
@@ -231,30 +163,6 @@
 	return tests
 }
 
-func TestParseExtensions(t *testing.T) {
-	for i, tt := range parseTests() {
-		if tt.ext == "" || tt.rewrite {
-			continue
-		}
-		scan := makeScannerString(tt.in)
-		if len(scan.b) > 1 && scan.b[1] != '-' {
-			scan.end = nextExtension(string(scan.b), 0)
-			scan.next = scan.end + 1
-			scan.scan()
-		}
-		start := scan.start
-		scan.toLower(start, len(scan.b))
-		parseExtensions(&scan)
-		ext := string(scan.b[start:])
-		if ext != tt.ext {
-			t.Errorf("%d(%s): ext was %v; want %v", i, tt.in, ext, tt.ext)
-		}
-		if changed := !strings.HasPrefix(tt.in[start:], ext); changed != tt.changed {
-			t.Errorf("%d(%s): changed was %v; want %v", i, tt.in, changed, tt.changed)
-		}
-	}
-}
-
 // partChecks runs checks for each part by calling the function returned by f.
 func partChecks(t *testing.T, f func(*parseTest) (Tag, bool)) {
 	for i, tt := range parseTests() {
@@ -262,80 +170,38 @@
 		if skip {
 			continue
 		}
-		if l, _ := getLangID(b(tt.lang)); l != tag.lang {
-			t.Errorf("%d: lang was %q; want %q", i, tag.lang, l)
+		if l, _ := language.ParseBase(tt.lang); l != tag.lang() {
+			t.Errorf("%d: lang was %q; want %q", i, tag.lang(), l)
 		}
-		if sc, _ := getScriptID(script, b(tt.script)); sc != tag.script {
-			t.Errorf("%d: script was %q; want %q", i, tag.script, sc)
+		if sc, _ := language.ParseScript(tt.script); sc != tag.script() {
+			t.Errorf("%d: script was %q; want %q", i, tag.script(), sc)
 		}
-		if r, _ := getRegionID(b(tt.region)); r != tag.region {
-			t.Errorf("%d: region was %q; want %q", i, tag.region, r)
+		if r, _ := language.ParseRegion(tt.region); r != tag.region() {
+			t.Errorf("%d: region was %q; want %q", i, tag.region(), r)
 		}
-		if tag.str == "" {
-			continue
+		v := tag.tag.Variants()
+		if v != "" {
+			v = v[1:]
 		}
-		p := int(tag.pVariant)
-		if p < int(tag.pExt) {
-			p++
+		if v != tt.variants {
+			t.Errorf("%d: variants was %q; want %q", i, v, tt.variants)
 		}
-		if s, g := tag.str[p:tag.pExt], tt.variants; s != g {
-			t.Errorf("%d: variants was %q; want %q", i, s, g)
-		}
-		p = int(tag.pExt)
-		if p > 0 && p < len(tag.str) {
-			p++
-		}
-		if s, g := (tag.str)[p:], tt.ext; s != g {
-			t.Errorf("%d: extensions were %q; want %q", i, s, g)
+		if e := strings.Join(tag.tag.Extensions(), "-"); e != tt.ext {
+			t.Errorf("%d: extensions were %q; want %q", i, e, tt.ext)
 		}
 	}
 }
 
-func TestParseTag(t *testing.T) {
-	partChecks(t, func(tt *parseTest) (id Tag, skip bool) {
-		if strings.HasPrefix(tt.in, "x-") || tt.rewrite {
-			return Tag{}, true
-		}
-		scan := makeScannerString(tt.in)
-		id, end := parseTag(&scan)
-		id.str = string(scan.b[:end])
-		tt.ext = ""
-		tt.extList = []string{}
-		return id, false
-	})
-}
-
 func TestParse(t *testing.T) {
 	partChecks(t, func(tt *parseTest) (id Tag, skip bool) {
-		id, err := Raw.Parse(tt.in)
-		ext := ""
-		if id.str != "" {
-			if strings.HasPrefix(id.str, "x-") {
-				ext = id.str
-			} else if int(id.pExt) < len(id.str) && id.pExt > 0 {
-				ext = id.str[id.pExt+1:]
-			}
-		}
-		if tag, _ := Raw.Parse(id.String()); tag.String() != id.String() {
-			t.Errorf("%d:%s: reparse was %q; want %q", tt.i, tt.in, id.String(), tag.String())
-		}
-		if ext != tt.ext {
-			t.Errorf("%d:%s: ext was %q; want %q", tt.i, tt.in, ext, tt.ext)
-		}
-		changed := id.str != "" && !strings.HasPrefix(tt.in, id.str)
-		if changed != tt.changed {
-			t.Errorf("%d:%s: changed was %v; want %v", tt.i, tt.in, changed, tt.changed)
-		}
-		if (err != nil) != tt.invalid {
-			t.Errorf("%d:%s: invalid was %v; want %v. Error: %v", tt.i, tt.in, err != nil, tt.invalid, err)
-		}
+		id, _ = Raw.Parse(tt.in)
 		return id, false
 	})
 }
 
 func TestErrors(t *testing.T) {
 	mkInvalid := func(s string) error {
-		return mkErrInvalid([]byte(s))
+		return language.NewValueError([]byte(s))
 	}
 	tests := []struct {
 		in  string
diff --git a/language/tables.go b/language/tables.go
index b738d45..cb7e1f8 100644
--- a/language/tables.go
+++ b/language/tables.go
@@ -2,23 +2,9 @@
 
 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 = 8665
-
-const numScripts = 242
-
-const numRegions = 357
-
-type fromTo struct {
-	from uint16
-	to   uint16
-}
-
-const nonCanonicalUnd = 1201
 const (
 	_af  = 22
 	_am  = 39
@@ -113,886 +99,6 @@
 	_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, 0x62,
-	0xe9, 0xbf, 0xfd, 0xbf, 0xbf, 0xf7, 0xfd, 0x77,
-	0x0f, 0xff, 0xef, 0x6f, 0xff, 0xfb, 0xdf, 0xe2,
-	0xc9, 0xf8, 0x7f, 0x7e, 0x4d, 0xb8, 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, 0x2f, 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, 0x20, 0x41, 0x00, 0x50, 0x40, 0x00, 0x80,
-	// Entry C0 - FF
-	0xfb, 0x4a, 0xf2, 0x9f, 0xb4, 0x42, 0x41, 0x96,
-	0x1b, 0x14, 0x08, 0xf2, 0x2b, 0xe7, 0x17, 0x56,
-	0x05, 0x7d, 0x0e, 0x1c, 0x37, 0x71, 0xf3, 0xef,
-	0x97, 0xff, 0x5d, 0x38, 0x64, 0x08, 0x00, 0x10,
-	0xbc, 0x85, 0xaf, 0xdf, 0xff, 0xf7, 0x73, 0x35,
-	0x3e, 0x87, 0xc7, 0xdf, 0xff, 0x00, 0x81, 0x00,
-	0xb0, 0x05, 0x80, 0x00, 0x00, 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, 0x01, 0x0c,
-	0x86, 0x00, 0xd1, 0x00, 0xf0, 0xc5, 0x67, 0x5f,
-	0x56, 0x89, 0x5e, 0xb5, 0x6c, 0xaf, 0x03, 0x00,
-	0x02, 0x00, 0x00, 0x00, 0xc0, 0x37, 0xda, 0x56,
-	0x90, 0x69, 0x01, 0x2c, 0x96, 0x69, 0x20, 0xfb,
-	// Entry 140 - 17F
-	0xff, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x08, 0x16,
-	0x01, 0x00, 0x00, 0xb0, 0x14, 0x03, 0x50, 0x06,
-	0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x09,
-	0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x10,
-	0x00, 0x00, 0x44, 0x00, 0x00, 0x10, 0x00, 0x04,
-	0x08, 0x00, 0x00, 0x04, 0x00, 0x80, 0x28, 0x04,
-	0x00, 0x00, 0x40, 0xd5, 0x2d, 0x00, 0x64, 0x35,
-	0x24, 0x52, 0xf4, 0xd4, 0xbd, 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, 0x00, 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, 0x01, 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,
-	0xcd, 0x55, 0xe7, 0x01, 0x00, 0x20, 0xb2, 0xc5,
-	0xa4, 0x45, 0x25, 0x9b, 0x02, 0xdf, 0xe0, 0xdf,
-	0x03, 0x44, 0x08, 0x10, 0x01, 0x04, 0x01, 0xe3,
-	0x92, 0x54, 0xdb, 0x28, 0xd1, 0x5f, 0xf6, 0x6d,
-	0x79, 0xed, 0x1c, 0x7d, 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, 0x38, 0x02, 0x05, 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,
-	0x11, 0x04, 0x04, 0x68, 0x00, 0x20, 0x70, 0xff,
-	0x7b, 0x7f, 0x60, 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,
-	0x08, 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, 0x91, 0x6c, 0xe2,
-	0x50, 0x27, 0x1d, 0x11, 0x29, 0x06, 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, 0x00, 0x08,
-	0xd8, 0xeb, 0xf6, 0x39, 0xc4, 0x89, 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, 0x12, 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, 0x3d, 0x1b,
-	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, 0x00,
-	0x40, 0x54, 0x9f, 0x8a, 0xd9, 0xd9, 0x0e, 0x11,
-	0x86, 0x51, 0xc0, 0xf3, 0xfb, 0x47, 0x00, 0x01,
-	0x05, 0xd1, 0x50, 0x58, 0x00, 0x00, 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, 0xbd,
-	0xcd, 0xff, 0xfb, 0xff, 0xdf, 0xd7, 0xea, 0xff,
-	0xe5, 0x5f, 0x6d, 0x0f, 0xa7, 0x51, 0x06, 0xc4,
-	// Entry 480 - 4BF
-	0x13, 0x50, 0x5d, 0xaf, 0xa6, 0xfd, 0x99, 0xfb,
-	0x63, 0x1d, 0x53, 0xff, 0xef, 0xb7, 0x35, 0x20,
-	0x14, 0x00, 0x55, 0x51, 0x82, 0x65, 0xf5, 0x41,
-	0xe2, 0xff, 0xfc, 0xdf, 0x00, 0x05, 0xc5, 0x05,
-	0x00, 0x22, 0x00, 0x74, 0x69, 0x10, 0x08, 0x04,
-	0x41, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x51, 0x20, 0x05, 0x04, 0x01, 0x00, 0x00,
-	0x06, 0x01, 0x20, 0x00, 0x18, 0x01, 0x92, 0xb1,
-	// Entry 4C0 - 4FF
-	0xfd, 0x47, 0x49, 0x06, 0x95, 0x06, 0x57, 0xed,
-	0xfb, 0x4c, 0x1c, 0x6b, 0x83, 0x04, 0x62, 0x40,
-	0x00, 0x11, 0x42, 0x00, 0x00, 0x00, 0x54, 0x83,
-	0xb8, 0x4f, 0x10, 0x8c, 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,
-	0xba, 0xcf, 0xf7, 0xaf, 0x42, 0x04, 0x84, 0x41,
-	// Entry 500 - 53F
-	0x30, 0xff, 0x79, 0x72, 0x04, 0x00, 0x00, 0x49,
-	0x2d, 0x14, 0x27, 0x57, 0xed, 0xf1, 0x3f, 0xe7,
-	0x3f, 0x00, 0x00, 0x02, 0xc6, 0xa0, 0x1e, 0xf8,
-	0xbb, 0xff, 0xfd, 0xfb, 0xb7, 0xfd, 0xe5, 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, 0x00, 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, 0x00, 0x81,
-	0xa3, 0x01, 0x50, 0x00, 0x00, 0x83, 0x11, 0x40,
-	// Entry 5C0 - 5FF
-	0x00, 0x00, 0x00, 0xf0, 0xdd, 0x7b, 0x3e, 0x02,
-	0xaa, 0x10, 0x5d, 0x98, 0x52, 0x00, 0x80, 0x20,
-	0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x02,
-	0x19, 0x00, 0x10, 0x02, 0x10, 0x61, 0x5a, 0x9d,
-	0x31, 0x00, 0x00, 0x00, 0x01, 0x10, 0x02, 0x20,
-	0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x20, 0x00,
-	0x00, 0x1f, 0xdf, 0xd2, 0xb9, 0xff, 0xfd, 0x3f,
-	0x1f, 0x98, 0xcf, 0x9c, 0xbf, 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, 0x1f,
-	0xd4, 0x77, 0xf5, 0x7d, 0xfb, 0xff, 0xeb, 0xfe,
-	0xbe, 0x5f, 0x46, 0x1b, 0xe9, 0x5f, 0x50, 0x18,
-	0x02, 0xfa, 0xf7, 0x9d, 0x15, 0x97, 0x05, 0x0f,
-	// Entry 640 - 67F
-	0x75, 0xc4, 0x7d, 0x81, 0x92, 0xf1, 0x57, 0x6c,
-	0xff, 0xe4, 0xef, 0x6f, 0xff, 0xfc, 0xdd, 0xde,
-	0xfc, 0xfd, 0x76, 0x5f, 0x7a, 0x1f, 0x00, 0x98,
-	0x02, 0xfb, 0xa3, 0xef, 0xf3, 0xd6, 0xf2, 0xff,
-	0xb9, 0xda, 0x7d, 0x50, 0x1e, 0x15, 0x7b, 0xb4,
-	0xf5, 0x3e, 0xff, 0xff, 0xf1, 0xf7, 0xff, 0xe7,
-	0x5f, 0xff, 0xff, 0x9e, 0xdb, 0xf6, 0xd7, 0xb9,
-	0xef, 0x27, 0x80, 0xbb, 0xc5, 0xff, 0xff, 0xe3,
-	// Entry 680 - 6BF
-	0x97, 0x9d, 0xbf, 0x9f, 0xf7, 0xc7, 0xfd, 0x37,
-	0xce, 0x7f, 0x04, 0x1d, 0x53, 0x7f, 0xf8, 0xda,
-	0x5d, 0xce, 0x7d, 0x06, 0xb9, 0xea, 0x69, 0xa0,
-	0x1a, 0x20, 0x00, 0x30, 0x02, 0x04, 0x24, 0x08,
-	0x04, 0x00, 0x00, 0x40, 0xd4, 0x02, 0x04, 0x00,
-	0x00, 0x04, 0x00, 0x04, 0x00, 0x20, 0x01, 0x06,
-	0x50, 0x00, 0x08, 0x00, 0x00, 0x00, 0x24, 0x00,
-	0x04, 0x00, 0x10, 0xcc, 0x58, 0xd5, 0x0d, 0x0f,
-	// Entry 6C0 - 6FF
-	0x14, 0x4d, 0xf1, 0x16, 0x44, 0xd1, 0x42, 0x08,
-	0x40, 0x00, 0x00, 0x40, 0x00, 0x08, 0x00, 0x00,
-	0x00, 0xdc, 0xfb, 0xcb, 0x0e, 0x58, 0x08, 0x41,
-	0x04, 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, 0x00, 0x00, 0x01,
-	0xdf, 0x18, 0x00, 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, 0x44,
-	0xcd, 0xf9, 0x5c, 0x00, 0x01, 0x00, 0x30, 0x04,
-	0x04, 0x55, 0x00, 0x01, 0x04, 0xf4, 0x3f, 0x4a,
-	0x01, 0x00, 0x00, 0xb0, 0x80, 0x00, 0x55, 0x55,
-	0x97, 0x7c, 0x9f, 0x31, 0xcc, 0x68, 0xd1, 0x03,
-	0xd5, 0x57, 0x27, 0x14, 0x01, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x2c, 0xf7, 0xcb, 0x1f, 0x14, 0x60,
-	// Entry 780 - 7BF
-	0x03, 0x68, 0x01, 0x10, 0x8b, 0x38, 0x8a, 0x01,
-	0x00, 0x00, 0x20, 0x00, 0x24, 0x44, 0x00, 0x00,
-	0x10, 0x03, 0x11, 0x02, 0x01, 0x00, 0x00, 0xf0,
-	0xf5, 0xff, 0xd5, 0x97, 0xbc, 0x70, 0xd6, 0x78,
-	0x78, 0x15, 0x50, 0x01, 0xa4, 0x84, 0xa9, 0x41,
-	0x00, 0x00, 0x00, 0x6b, 0x39, 0x52, 0x74, 0x00,
-	0xe8, 0x30, 0x90, 0x6a, 0x92, 0x00, 0x00, 0x02,
-	0xff, 0xef, 0xff, 0x4b, 0x85, 0x53, 0xf4, 0xed,
-	// Entry 7C0 - 7FF
-	0xdd, 0xbf, 0x72, 0x19, 0xc7, 0x0c, 0xd5, 0x42,
-	0x54, 0xdd, 0x77, 0x14, 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, 0x0a, 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, 0xd4, 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,
-	0x2e, 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, 0x3f, 0x05, 0x00, 0x12, 0x81,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02,
-	0x00, 0x00, 0x00, 0x00, 0x03, 0x30, 0x02, 0x28,
-	0x84, 0x00, 0x21, 0xc0, 0x23, 0x24, 0x00, 0x00,
-	0x00, 0xcb, 0xe4, 0x3a, 0x42, 0x88, 0x14, 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,
-}
-
-// langAliasMap maps langIDs to their suggested replacements.
-// Size: 656 bytes, 164 elements
-var langAliasMap = [164]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: 0x630, to: 0x1eb1},
-	15:  {from: 0x651, to: 0x431},
-	16:  {from: 0x662, to: 0x431},
-	17:  {from: 0x6ed, to: 0x3a},
-	18:  {from: 0x6f8, to: 0x1d7},
-	19:  {from: 0x73e, to: 0x21a1},
-	20:  {from: 0x7b3, to: 0x56},
-	21:  {from: 0x7b9, to: 0x299b},
-	22:  {from: 0x7c5, to: 0x58},
-	23:  {from: 0x7e6, to: 0x145},
-	24:  {from: 0x80c, to: 0x5a},
-	25:  {from: 0x815, to: 0x8d},
-	26:  {from: 0x87e, to: 0x810},
-	27:  {from: 0x8c3, to: 0xee3},
-	28:  {from: 0x9ef, to: 0x331},
-	29:  {from: 0xa36, to: 0x2c5},
-	30:  {from: 0xa3d, to: 0xbf},
-	31:  {from: 0xabe, to: 0x3322},
-	32:  {from: 0xb38, to: 0x529},
-	33:  {from: 0xb75, to: 0x265a},
-	34:  {from: 0xb7e, to: 0xbc3},
-	35:  {from: 0xb9b, to: 0x44e},
-	36:  {from: 0xbbc, to: 0x4229},
-	37:  {from: 0xbbf, to: 0x529},
-	38:  {from: 0xbfe, to: 0x2da7},
-	39:  {from: 0xc2e, to: 0x3181},
-	40:  {from: 0xcb9, to: 0xf3},
-	41:  {from: 0xd08, to: 0xfa},
-	42:  {from: 0xdc8, to: 0x11a},
-	43:  {from: 0xdd7, to: 0x32d},
-	44:  {from: 0xdf8, to: 0xdfb},
-	45:  {from: 0xdfe, to: 0x531},
-	46:  {from: 0xedf, to: 0x205a},
-	47:  {from: 0xeee, to: 0x2e9a},
-	48:  {from: 0xf39, to: 0x367},
-	49:  {from: 0x10d0, to: 0x140},
-	50:  {from: 0x1104, to: 0x2d0},
-	51:  {from: 0x11a0, to: 0x1ec},
-	52:  {from: 0x1279, to: 0x21},
-	53:  {from: 0x1424, to: 0x15e},
-	54:  {from: 0x1470, to: 0x14e},
-	55:  {from: 0x151f, to: 0xd9b},
-	56:  {from: 0x1523, to: 0x390},
-	57:  {from: 0x1532, to: 0x19f},
-	58:  {from: 0x1580, to: 0x210},
-	59:  {from: 0x1583, to: 0x10d},
-	60:  {from: 0x15a3, to: 0x3caf},
-	61:  {from: 0x166a, to: 0x19b},
-	62:  {from: 0x16c8, to: 0x136},
-	63:  {from: 0x1700, to: 0x29f8},
-	64:  {from: 0x1718, to: 0x194},
-	65:  {from: 0x1727, to: 0xf3f},
-	66:  {from: 0x177a, to: 0x178},
-	67:  {from: 0x1809, to: 0x17b6},
-	68:  {from: 0x1816, to: 0x18f3},
-	69:  {from: 0x188a, to: 0x436},
-	70:  {from: 0x1979, to: 0x1d01},
-	71:  {from: 0x1a74, to: 0x2bb0},
-	72:  {from: 0x1a8a, to: 0x1f8},
-	73:  {from: 0x1b5a, to: 0x1fa},
-	74:  {from: 0x1b86, to: 0x1515},
-	75:  {from: 0x1d64, to: 0x2c9b},
-	76:  {from: 0x2038, to: 0x37b1},
-	77:  {from: 0x203d, to: 0x20dd},
-	78:  {from: 0x205a, to: 0x30b},
-	79:  {from: 0x20e3, to: 0x274},
-	80:  {from: 0x20ee, to: 0x263},
-	81:  {from: 0x20f2, to: 0x22d},
-	82:  {from: 0x20f9, to: 0x256},
-	83:  {from: 0x210f, to: 0x21eb},
-	84:  {from: 0x2135, to: 0x27d},
-	85:  {from: 0x2160, to: 0x913},
-	86:  {from: 0x2199, to: 0x121},
-	87:  {from: 0x21ce, to: 0x1561},
-	88:  {from: 0x21e6, to: 0x504},
-	89:  {from: 0x21f4, to: 0x49f},
-	90:  {from: 0x222d, to: 0x121},
-	91:  {from: 0x2237, to: 0x121},
-	92:  {from: 0x2262, to: 0x92a},
-	93:  {from: 0x2316, to: 0x3226},
-	94:  {from: 0x2382, to: 0x3365},
-	95:  {from: 0x2472, to: 0x2c7},
-	96:  {from: 0x24e4, to: 0x2ff},
-	97:  {from: 0x24f0, to: 0x2fa},
-	98:  {from: 0x24fa, to: 0x31f},
-	99:  {from: 0x2550, to: 0xb5b},
-	100: {from: 0x25a9, to: 0xe2},
-	101: {from: 0x263e, to: 0x2d0},
-	102: {from: 0x26c9, to: 0x26b4},
-	103: {from: 0x26f9, to: 0x3c8},
-	104: {from: 0x2727, to: 0x3caf},
-	105: {from: 0x2765, to: 0x26b4},
-	106: {from: 0x2789, to: 0x4358},
-	107: {from: 0x28ef, to: 0x2837},
-	108: {from: 0x2914, to: 0x351},
-	109: {from: 0x2986, to: 0x2da7},
-	110: {from: 0x2b1a, to: 0x38d},
-	111: {from: 0x2bfc, to: 0x395},
-	112: {from: 0x2c3f, to: 0x3caf},
-	113: {from: 0x2cfc, to: 0x3be},
-	114: {from: 0x2d13, to: 0x597},
-	115: {from: 0x2d47, to: 0x148},
-	116: {from: 0x2d48, to: 0x148},
-	117: {from: 0x2dff, to: 0x2f1},
-	118: {from: 0x2e08, to: 0x19cc},
-	119: {from: 0x2e1a, to: 0x2d95},
-	120: {from: 0x2e21, to: 0x292},
-	121: {from: 0x2e54, to: 0x7d},
-	122: {from: 0x2e65, to: 0x2282},
-	123: {from: 0x2ea0, to: 0x2e9b},
-	124: {from: 0x2eef, to: 0x2ed7},
-	125: {from: 0x3193, to: 0x3c4},
-	126: {from: 0x3366, to: 0x338e},
-	127: {from: 0x342a, to: 0x3dc},
-	128: {from: 0x34ee, to: 0x18d0},
-	129: {from: 0x35c8, to: 0x2c9b},
-	130: {from: 0x35e6, to: 0x412},
-	131: {from: 0x3658, to: 0x246},
-	132: {from: 0x3676, to: 0x3f4},
-	133: {from: 0x36fd, to: 0x445},
-	134: {from: 0x37c0, to: 0x121},
-	135: {from: 0x3816, to: 0x38f2},
-	136: {from: 0x382b, to: 0x2c9b},
-	137: {from: 0x382f, to: 0xa9},
-	138: {from: 0x3832, to: 0x3228},
-	139: {from: 0x386c, to: 0x39a6},
-	140: {from: 0x3892, to: 0x3fc0},
-	141: {from: 0x38a5, to: 0x39d7},
-	142: {from: 0x38b4, to: 0x1fa4},
-	143: {from: 0x38b5, to: 0x2e9a},
-	144: {from: 0x395c, to: 0x47e},
-	145: {from: 0x3b4e, to: 0xd91},
-	146: {from: 0x3b78, to: 0x137},
-	147: {from: 0x3c99, to: 0x4bc},
-	148: {from: 0x3fbd, to: 0x100},
-	149: {from: 0x4208, to: 0xa91},
-	150: {from: 0x42be, to: 0x573},
-	151: {from: 0x42f9, to: 0x3f60},
-	152: {from: 0x4378, to: 0x25a},
-	153: {from: 0x43cb, to: 0x36cb},
-	154: {from: 0x43cd, to: 0x10f},
-	155: {from: 0x44af, to: 0x3322},
-	156: {from: 0x44e3, to: 0x512},
-	157: {from: 0x45ca, to: 0x2409},
-	158: {from: 0x45dd, to: 0x26dc},
-	159: {from: 0x4610, to: 0x48ae},
-	160: {from: 0x46ae, to: 0x46a0},
-	161: {from: 0x473e, to: 0x4745},
-	162: {from: 0x4916, to: 0x31f},
-	163: {from: 0x49a7, to: 0x523},
-}
-
-// Size: 164 bytes, 164 elements
-var langAliasTypes = [164]langAliasType{
-	// Entry 0 - 3F
-	1, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 1, 0, 0, 1, 2,
-	1, 1, 2, 0, 1, 0, 1, 2, 1, 1, 0, 0, 2, 1, 1, 0,
-	2, 0, 0, 1, 0, 1, 0, 0, 1, 2, 1, 1, 1, 1, 0, 0,
-	2, 1, 1, 1, 1, 2, 1, 0, 1, 1, 2, 2, 0, 1, 2, 0,
-	// Entry 40 - 7F
-	1, 0, 1, 1, 1, 1, 0, 0, 2, 1, 0, 0, 0, 0, 1, 1,
-	1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
-	2, 2, 2, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1,
-	0, 1, 0, 2, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 2,
-	// Entry 80 - BF
-	0, 0, 2, 1, 1, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
-	1, 1, 0, 1, 2, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0,
-	0, 1, 1, 1,
-}
-
-const (
-	_Latn = 87
-	_Hani = 54
-	_Hans = 56
-	_Hant = 57
-	_Qaaa = 139
-	_Qaai = 147
-	_Qabx = 188
-	_Zinh = 236
-	_Zyyy = 241
-	_Zzzz = 242
-)
-
-// 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: 976 bytes
-	"----AdlmAfakAghbAhomArabAranArmiArmnAvstBaliBamuBassBatkBengBhksBlisBopo" +
-	"BrahBraiBugiBuhdCakmCansCariChamCherCirtCoptCpmnCprtCyrlCyrsDevaDogrDsrt" +
-	"DuplEgydEgyhEgypElbaEthiGeokGeorGlagGongGonmGothGranGrekGujrGuruHanbHang" +
-	"HaniHanoHansHantHatrHebrHiraHluwHmngHmnpHrktHungIndsItalJamoJavaJpanJurc" +
-	"KaliKanaKharKhmrKhojKitlKitsKndaKoreKpelKthiLanaLaooLatfLatgLatnLekeLepc" +
-	"LimbLinaLinbLisuLomaLyciLydiMahjMakaMandManiMarcMayaMedfMendMercMeroMlym" +
-	"ModiMongMoonMrooMteiMultMymrNarbNbatNewaNkdbNkgbNkooNshuOgamOlckOrkhOrya" +
-	"OsgeOsmaPalmPaucPermPhagPhliPhlpPhlvPhnxPiqdPlrdPrtiQaaaQaabQaacQaadQaae" +
-	"QaafQaagQaahQaaiQaajQaakQaalQaamQaanQaaoQaapQaaqQaarQaasQaatQaauQaavQaaw" +
-	"QaaxQaayQaazQabaQabbQabcQabdQabeQabfQabgQabhQabiQabjQabkQablQabmQabnQabo" +
-	"QabpQabqQabrQabsQabtQabuQabvQabwQabxRjngRoroRunrSamrSaraSarbSaurSgnwShaw" +
-	"ShrdShuiSiddSindSinhSoraSoyoSundSyloSyrcSyreSyrjSyrnTagbTakrTaleTaluTaml" +
-	"TangTavtTeluTengTfngTglgThaaThaiTibtTirhUgarVaiiVispWaraWchoWoleXpeoXsux" +
-	"YiiiZanbZinhZmthZsyeZsymZxxxZyyyZzzz\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, 0x1f, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29,
-	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, 0x57, 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, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 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, 0x57,
-	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, 0x57,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x57, 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, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00,
-	// Entry 100 - 13F
-	0x57, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0xde, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00,
-	0x00, 0x57, 0x00, 0x00, 0x57, 0x00, 0x57, 0x00,
-	// Entry 140 - 17F
-	0x57, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00,
-	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x57, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00,
-	0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00,
-	0x00, 0x57, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x57, 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,
-	0x57, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x57, 0x32, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x21, 0x00,
-	// Entry 1C0 - 1FF
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x57, 0x57, 0x00, 0x57, 0x57, 0x00, 0x08,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00,
-	0x57, 0x57, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
-	// Entry 200 - 23F
-	0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x2b, 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, 0x1f, 0x00, 0x00, 0x57, 0x00, 0x00,
-	0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x4f, 0x00, 0x00, 0x50, 0x00, 0x21, 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, 0x57, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 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, 0x57, 0x00, 0x00,
-	0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	// Entry 2C0 - 2FF
-	0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 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,
-	0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
-	// Entry 300 - 33F
-	0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x57,
-	0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00,
-	// Entry 340 - 37F
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00,
-	0x57, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
-	0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x57,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x57, 0x00,
-	0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00,
-	// Entry 380 - 3BF
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x57, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
-	// Entry 3C0 - 3FF
-	0x57, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
-	0x00, 0x57, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x1f, 0x00, 0x00, 0x57, 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, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x57, 0x00,
-	0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
-	0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00,
-	// Entry 440 - 47F
-	0x00, 0x00, 0x00, 0x00, 0x57, 0x57, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0xd7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0xda, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x29,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
-	0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x57, 0x00,
-	// Entry 480 - 4BF
-	0x57, 0x00, 0x57, 0x00, 0x00, 0x00, 0x57, 0x00,
-	0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x57, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	// Entry 4C0 - 4FF
-	0x57, 0x00, 0x00, 0x57, 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, 0x57, 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, 0x3b, 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, 0x57,
-	0x00, 0x00,
-}
-
 const (
 	_001 = 1
 	_419 = 31
@@ -1009,2290 +115,21 @@
 	_XC  = 325
 	_XK  = 333
 )
+const (
+	_Latn = 87
+	_Hani = 54
+	_Hans = 56
+	_Hant = 57
+	_Qaaa = 139
+	_Qaai = 147
+	_Qabx = 188
+	_Zinh = 236
+	_Zyyy = 241
+	_Zzzz = 242
+)
 
-// 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: 358 bytes, 358 elements
-var regionTypes = [358]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, 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, 0x06,
-	// Entry 80 - BF
-	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, 0x06,
-	// Entry C0 - FF
-	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, 0x05,
-	// Entry 100 - 13F
-	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, 0x06,
-	// Entry 140 - 17F
-	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: 1308 bytes
-	"AAAAACSCADNDAEREAFFGAGTGAIIAALLBAMRMANNTAOGOAQTAARRGASSMATUTAUUSAWBWAXLA" +
-	"AZZEBAIHBBRBBDGDBEELBFFABGGRBHHRBIDIBJENBLLMBMMUBNRNBOOLBQESBRRABSHSBTTN" +
-	"BUURBVVTBWWABYLRBZLZCAANCCCKCDODCFAFCGOGCHHECIIVCKOKCLHLCMMRCNHNCOOLCPPT" +
-	"CRRICS\x00\x00CTTECUUBCVPVCWUWCXXRCYYPCZZEDDDRDEEUDGGADJJIDKNKDMMADOOMDY" +
-	"HYDZZAEA  ECCUEESTEGGYEHSHERRIESSPETTHEU\x00\x03EZ  FIINFJJIFKLKFMSMFORO" +
-	"FQ\x00\x18FRRAFXXXGAABGBBRGDRDGEEOGFUFGGGYGHHAGIIBGLRLGMMBGNINGPLPGQNQGR" +
-	"RCGS\x00\x06GTTMGUUMGWNBGYUYHKKGHMMDHNNDHRRVHTTIHUUNHVVOIC  IDDNIERLILSR" +
-	"IMMNINNDIOOTIQRQIRRNISSLITTAJEEYJMAMJOORJPPNJTTNKEENKGGZKHHMKIIRKM\x00" +
-	"\x09KNNAKP\x00\x0cKRORKWWTKY\x00\x0fKZAZLAAOLBBNLCCALIIELKKALRBRLSSOLTTU" +
-	"LUUXLVVALYBYMAARMCCOMDDAMENEMFAFMGDGMHHLMIIDMKKDMLLIMMMRMNNGMOACMPNPMQTQ" +
-	"MRRTMSSRMTLTMUUSMVDVMWWIMXEXMYYSMZOZNAAMNCCLNEERNFFKNGGANHHBNIICNLLDNOOR" +
-	"NPPLNQ\x00\x1eNRRUNTTZNUIUNZZLOMMNPAANPCCIPEERPFYFPGNGPHHLPKAKPLOLPM\x00" +
-	"\x12PNCNPRRIPSSEPTRTPUUSPWLWPYRYPZCZQAATQMMMQNNNQOOOQPPPQQQQQRRRQSSSQTTT" +
-	"QU\x00\x03QVVVQWWWQXXXQYYYQZZZREEURHHOROOURS\x00\x15RUUSRWWASAAUSBLBSCYC" +
-	"SDDNSEWESGGPSHHNSIVNSJJMSKVKSLLESMMRSNENSOOMSRURSSSDSTTPSUUNSVLVSXXMSYYR" +
-	"SZWZTAAATCCATDCDTF\x00\x18TGGOTHHATJJKTKKLTLLSTMKMTNUNTOONTPMPTRURTTTOTV" +
-	"UVTWWNTZZAUAKRUGGAUK  UMMIUN  USSAUYRYUZZBVAATVCCTVDDRVEENVGGBVIIRVNNMVU" +
-	"UTWFLFWKAKWSSMXAAAXBBBXCCCXDDDXEEEXFFFXGGGXHHHXIIIXJJJXKKKXLLLXMMMXNNNXO" +
-	"OOXPPPXQQQXRRRXSSSXTTTXUUUXVVVXWWWXXXXXYYYXZZZYDMDYEEMYT\x00\x1bYUUGZAAF" +
-	"ZMMBZRARZWWEZZZZ\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{
-	0x0057, 0x0070, 0x0088, 0x00a8, 0x00aa, 0x00ad, 0x00ea, 0x0105,
-	0x0121, 0x015f, 0x00dc,
-}
-
-// Size: 80 bytes, 20 elements
-var regionOldMap = [20]fromTo{
-	0:  {from: 0x44, to: 0xc4},
-	1:  {from: 0x58, to: 0xa7},
-	2:  {from: 0x5f, to: 0x60},
-	3:  {from: 0x66, to: 0x3b},
-	4:  {from: 0x79, to: 0x78},
-	5:  {from: 0x93, to: 0x37},
-	6:  {from: 0xa3, to: 0x133},
-	7:  {from: 0xc1, to: 0x133},
-	8:  {from: 0xd7, to: 0x13f},
-	9:  {from: 0xdc, to: 0x2b},
-	10: {from: 0xef, to: 0x133},
-	11: {from: 0xf2, to: 0xe2},
-	12: {from: 0xfc, to: 0x70},
-	13: {from: 0x103, to: 0x164},
-	14: {from: 0x12a, to: 0x126},
-	15: {from: 0x132, to: 0x7b},
-	16: {from: 0x13a, to: 0x13e},
-	17: {from: 0x141, to: 0x133},
-	18: {from: 0x15d, to: 0x15e},
-	19: {from: 0x163, to: 0x4b},
-}
-
-// m49 maps regionIDs to UN.M49 codes. The first isoRegionOffset entries are
-// codes indicating collections of regions.
-// Size: 716 bytes, 358 elements
-var m49 = [358]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, 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, 831,
-	// Entry 80 - BF
-	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, 450,
-	// Entry C0 - FF
-	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, 970,
-	// Entry 100 - 13F
-	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, 548,
-	// Entry 140 - 17F
-	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, 0x1867, 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,
-	0xac9a, 0xb509, 0xb93c, 0xc03e, 0xc838, 0xd0c4, 0xd83a, 0xe047,
-	0xe8a6, 0xf052, 0xf849, 0x085a, 0x10ad, 0x184c, 0x1c17, 0x1e18,
-	// Entry 40 - 7F
-	0x20b3, 0x2219, 0x2920, 0x2c1a, 0x2e1b, 0x3051, 0x341c, 0x361d,
-	0x3853, 0x3d2e, 0x445c, 0x4c4a, 0x5454, 0x5ca8, 0x5f5f, 0x644d,
-	0x684b, 0x7050, 0x7856, 0x7e90, 0x8059, 0x885d, 0x941e, 0x965e,
-	0x983b, 0xa063, 0xa864, 0xac65, 0xb469, 0xbd1a, 0xc486, 0xcc6f,
-	0xce6f, 0xd06d, 0xd26a, 0xd476, 0xdc74, 0xde88, 0xe473, 0xec72,
-	0xf031, 0xf279, 0xf478, 0xfc7e, 0x04e5, 0x0921, 0x0c62, 0x147a,
-	0x187d, 0x1c83, 0x26ed, 0x2860, 0x2c5f, 0x3060, 0x4080, 0x4881,
-	0x50a7, 0x5887, 0x6082, 0x687c, 0x7085, 0x788a, 0x8089, 0x8884,
-	// Entry 80 - BF
-	0x908c, 0x9891, 0x9c8e, 0xa138, 0xa88f, 0xb08d, 0xb892, 0xc09d,
-	0xc899, 0xd095, 0xd89c, 0xe09b, 0xe896, 0xf097, 0xf89e, 0x004f,
-	0x08a0, 0x10a2, 0x1cae, 0x20a1, 0x28a4, 0x30aa, 0x34ab, 0x3cac,
-	0x42a5, 0x44af, 0x461f, 0x4cb0, 0x54b5, 0x58b8, 0x5cb4, 0x64b9,
-	0x6cb2, 0x70b6, 0x74b7, 0x7cc6, 0x84bf, 0x8cce, 0x94d0, 0x9ccd,
-	0xa4c3, 0xaccb, 0xb4c8, 0xbcc9, 0xc0cc, 0xc8cf, 0xd8bb, 0xe0c5,
-	0xe4bc, 0xe6bd, 0xe8ca, 0xf0ba, 0xf8d1, 0x00e1, 0x08d2, 0x10dd,
-	0x18db, 0x20d9, 0x2429, 0x265b, 0x2a30, 0x2d1b, 0x2e40, 0x30de,
-	// Entry C0 - FF
-	0x38d3, 0x493f, 0x54e0, 0x5cd8, 0x64d4, 0x6cd6, 0x74df, 0x7cd5,
-	0x84da, 0x88c7, 0x8b33, 0x8e75, 0x90c0, 0x92f0, 0x94e8, 0x9ee2,
-	0xace6, 0xb0f1, 0xb8e4, 0xc0e7, 0xc8eb, 0xd0e9, 0xd8ee, 0xe08b,
-	0xe526, 0xecec, 0xf4f3, 0xfd02, 0x0504, 0x0706, 0x0d07, 0x183c,
-	0x1d0e, 0x26a9, 0x2826, 0x2cb1, 0x2ebe, 0x34ea, 0x3d39, 0x4513,
-	0x4d18, 0x5508, 0x5d14, 0x6105, 0x650a, 0x6d12, 0x7d0d, 0x7f11,
-	0x813e, 0x830f, 0x8515, 0x8d61, 0x9964, 0xa15d, 0xa86e, 0xb117,
-	0xb30b, 0xb86c, 0xc10b, 0xc916, 0xd110, 0xd91d, 0xe10c, 0xe84e,
-	// Entry 100 - 13F
-	0xf11c, 0xf524, 0xf923, 0x0122, 0x0925, 0x1129, 0x192c, 0x2023,
-	0x2928, 0x312b, 0x3727, 0x391f, 0x3d2d, 0x4131, 0x4930, 0x4ec2,
-	0x5519, 0x646b, 0x747b, 0x7e7f, 0x809f, 0x8298, 0x852f, 0x9135,
-	0xa53d, 0xac37, 0xb536, 0xb937, 0xbd3b, 0xd940, 0xe542, 0xed5e,
-	0xef5e, 0xf657, 0xfd62, 0x7c20, 0x7ef4, 0x80f5, 0x82f6, 0x84f7,
-	0x86f8, 0x88f9, 0x8afa, 0x8cfb, 0x8e70, 0x90fd, 0x92fe, 0x94ff,
-	0x9700, 0x9901, 0x9b43, 0x9d44, 0x9f45, 0xa146, 0xa347, 0xa548,
-	0xa749, 0xa94a, 0xab4b, 0xad4c, 0xaf4d, 0xb14e, 0xb34f, 0xb550,
-	// Entry 140 - 17F
-	0xb751, 0xb952, 0xbb53, 0xbd54, 0xbf55, 0xc156, 0xc357, 0xc558,
-	0xc759, 0xc95a, 0xcb5b, 0xcd5c, 0xcf65,
-}
-
-// Size: 1615 bytes
-var variantIndex = map[string]uint8{
-	"1606nict": 0x0,
-	"1694acad": 0x1,
-	"1901":     0x2,
-	"1959acad": 0x3,
-	"1994":     0x4d,
-	"1996":     0x4,
-	"abl1943":  0x5,
-	"akuapem":  0x6,
-	"alalc97":  0x4f,
-	"aluku":    0x7,
-	"ao1990":   0x8,
-	"arevela":  0x9,
-	"arevmda":  0xa,
-	"asante":   0xb,
-	"baku1926": 0xc,
-	"balanka":  0xd,
-	"barla":    0xe,
-	"basiceng": 0xf,
-	"bauddha":  0x10,
-	"biscayan": 0x11,
-	"biske":    0x48,
-	"bohoric":  0x12,
-	"boont":    0x13,
-	"colb1945": 0x14,
-	"cornu":    0x15,
-	"dajnko":   0x16,
-	"ekavsk":   0x17,
-	"emodeng":  0x18,
-	"fonipa":   0x50,
-	"fonnapa":  0x51,
-	"fonupa":   0x52,
-	"fonxsamp": 0x53,
-	"hepburn":  0x19,
-	"heploc":   0x4e,
-	"hognorsk": 0x1a,
-	"hsistemo": 0x1b,
-	"ijekavsk": 0x1c,
-	"itihasa":  0x1d,
-	"jauer":    0x1e,
-	"jyutping": 0x1f,
-	"kkcor":    0x20,
-	"kociewie": 0x21,
-	"kscor":    0x22,
-	"laukika":  0x23,
-	"lipaw":    0x49,
-	"luna1918": 0x24,
-	"metelko":  0x25,
-	"monoton":  0x26,
-	"ndyuka":   0x27,
-	"nedis":    0x28,
-	"newfound": 0x29,
-	"njiva":    0x4a,
-	"nulik":    0x2a,
-	"osojs":    0x4b,
-	"oxendict": 0x2b,
-	"pahawh2":  0x2c,
-	"pahawh3":  0x2d,
-	"pahawh4":  0x2e,
-	"pamaka":   0x2f,
-	"petr1708": 0x30,
-	"pinyin":   0x31,
-	"polyton":  0x32,
-	"puter":    0x33,
-	"rigik":    0x34,
-	"rozaj":    0x35,
-	"rumgr":    0x36,
-	"scotland": 0x37,
-	"scouse":   0x38,
-	"simple":   0x54,
-	"solba":    0x4c,
-	"sotav":    0x39,
-	"spanglis": 0x3a,
-	"surmiran": 0x3b,
-	"sursilv":  0x3c,
-	"sutsilv":  0x3d,
-	"tarask":   0x3e,
-	"uccor":    0x3f,
-	"ucrcor":   0x40,
-	"ulster":   0x41,
-	"unifon":   0x42,
-	"vaidika":  0x43,
-	"valencia": 0x44,
-	"vallader": 0x45,
-	"wadegile": 0x46,
-	"xsistemo": 0x47,
-}
-
-// variantNumSpecialized is the number of specialized variants in variants.
-const variantNumSpecialized = 79
-
-// 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: 976 bytes, 244 elements
-var likelyScript = [244]likelyLangRegion{
-	1:   {lang: 0x14e, region: 0x84},
-	3:   {lang: 0x2a2, region: 0x106},
-	4:   {lang: 0x1f, region: 0x99},
-	5:   {lang: 0x3a, region: 0x6b},
-	7:   {lang: 0x3b, region: 0x9c},
-	8:   {lang: 0x1d7, region: 0x28},
-	9:   {lang: 0x13, region: 0x9c},
-	10:  {lang: 0x5b, region: 0x95},
-	11:  {lang: 0x60, region: 0x52},
-	12:  {lang: 0xb9, region: 0xb4},
-	13:  {lang: 0x63, region: 0x95},
-	14:  {lang: 0xa5, region: 0x35},
-	15:  {lang: 0x3e9, region: 0x99},
-	17:  {lang: 0x529, region: 0x12e},
-	18:  {lang: 0x3b1, region: 0x99},
-	19:  {lang: 0x15e, region: 0x78},
-	20:  {lang: 0xc2, region: 0x95},
-	21:  {lang: 0x9d, region: 0xe7},
-	22:  {lang: 0xdb, region: 0x35},
-	23:  {lang: 0xf3, region: 0x49},
-	24:  {lang: 0x4f0, region: 0x12b},
-	25:  {lang: 0xe7, region: 0x13e},
-	26:  {lang: 0xe5, region: 0x135},
-	28:  {lang: 0xf1, region: 0x6b},
-	30:  {lang: 0x1a0, region: 0x5d},
-	31:  {lang: 0x3e2, region: 0x106},
-	33:  {lang: 0x1be, region: 0x99},
-	36:  {lang: 0x15e, region: 0x78},
-	39:  {lang: 0x133, region: 0x6b},
-	40:  {lang: 0x431, region: 0x27},
-	41:  {lang: 0x27, region: 0x6f},
-	43:  {lang: 0x210, region: 0x7d},
-	44:  {lang: 0xfe, region: 0x38},
-	46:  {lang: 0x19b, region: 0x99},
-	47:  {lang: 0x19e, region: 0x130},
-	48:  {lang: 0x3e9, region: 0x99},
-	49:  {lang: 0x136, region: 0x87},
-	50:  {lang: 0x1a4, region: 0x99},
-	51:  {lang: 0x39d, region: 0x99},
-	52:  {lang: 0x529, region: 0x12e},
-	53:  {lang: 0x254, region: 0xab},
-	54:  {lang: 0x529, region: 0x53},
-	55:  {lang: 0x1cb, region: 0xe7},
-	56:  {lang: 0x529, region: 0x53},
-	57:  {lang: 0x529, region: 0x12e},
-	58:  {lang: 0x2fd, region: 0x9b},
-	59:  {lang: 0x1bc, region: 0x97},
-	60:  {lang: 0x200, region: 0xa2},
-	61:  {lang: 0x1c5, region: 0x12b},
-	62:  {lang: 0x1ca, region: 0xaf},
-	65:  {lang: 0x1d5, region: 0x92},
-	67:  {lang: 0x142, region: 0x9e},
-	68:  {lang: 0x254, region: 0xab},
-	69:  {lang: 0x20e, region: 0x95},
-	70:  {lang: 0x200, region: 0xa2},
-	72:  {lang: 0x135, region: 0xc4},
-	73:  {lang: 0x200, region: 0xa2},
-	74:  {lang: 0x3bb, region: 0xe8},
-	75:  {lang: 0x24a, region: 0xa6},
-	76:  {lang: 0x3fa, region: 0x99},
-	79:  {lang: 0x251, region: 0x99},
-	80:  {lang: 0x254, region: 0xab},
-	82:  {lang: 0x88, region: 0x99},
-	83:  {lang: 0x370, region: 0x123},
-	84:  {lang: 0x2b8, region: 0xaf},
-	89:  {lang: 0x29f, region: 0x99},
-	90:  {lang: 0x2a8, region: 0x99},
-	91:  {lang: 0x28f, region: 0x87},
-	92:  {lang: 0x1a0, region: 0x87},
-	93:  {lang: 0x2ac, region: 0x53},
-	95:  {lang: 0x4f4, region: 0x12b},
-	96:  {lang: 0x4f5, region: 0x12b},
-	97:  {lang: 0x1be, region: 0x99},
-	99:  {lang: 0x337, region: 0x9c},
-	100: {lang: 0x4f7, region: 0x53},
-	101: {lang: 0xa9, region: 0x53},
-	104: {lang: 0x2e8, region: 0x112},
-	105: {lang: 0x4f8, region: 0x10b},
-	106: {lang: 0x4f8, region: 0x10b},
-	107: {lang: 0x304, region: 0x99},
-	108: {lang: 0x31b, region: 0x99},
-	109: {lang: 0x30b, region: 0x53},
-	111: {lang: 0x31e, region: 0x35},
-	112: {lang: 0x30e, region: 0x99},
-	113: {lang: 0x414, region: 0xe8},
-	114: {lang: 0x331, region: 0xc4},
-	115: {lang: 0x4f9, region: 0x108},
-	116: {lang: 0x3b, region: 0xa1},
-	117: {lang: 0x353, region: 0xdb},
-	120: {lang: 0x2d0, region: 0x84},
-	121: {lang: 0x52a, region: 0x53},
-	122: {lang: 0x403, region: 0x96},
-	123: {lang: 0x3ee, region: 0x99},
-	124: {lang: 0x39b, region: 0xc5},
-	125: {lang: 0x395, region: 0x99},
-	126: {lang: 0x399, region: 0x135},
-	127: {lang: 0x429, region: 0x115},
-	128: {lang: 0x3b, region: 0x11c},
-	129: {lang: 0xfd, region: 0xc4},
-	130: {lang: 0x27d, region: 0x106},
-	131: {lang: 0x2c9, region: 0x53},
-	132: {lang: 0x39f, region: 0x9c},
-	133: {lang: 0x39f, region: 0x53},
-	135: {lang: 0x3ad, region: 0xb0},
-	137: {lang: 0x1c6, region: 0x53},
-	138: {lang: 0x4fd, region: 0x9c},
-	189: {lang: 0x3cb, region: 0x95},
-	191: {lang: 0x372, region: 0x10c},
-	192: {lang: 0x420, region: 0x97},
-	194: {lang: 0x4ff, region: 0x15e},
-	195: {lang: 0x3f0, region: 0x99},
-	196: {lang: 0x45, region: 0x135},
-	197: {lang: 0x139, region: 0x7b},
-	198: {lang: 0x3e9, region: 0x99},
-	200: {lang: 0x3e9, region: 0x99},
-	201: {lang: 0x3fa, region: 0x99},
-	202: {lang: 0x40c, region: 0xb3},
-	203: {lang: 0x433, region: 0x99},
-	204: {lang: 0xef, region: 0xc5},
-	205: {lang: 0x43e, region: 0x95},
-	206: {lang: 0x44d, region: 0x35},
-	207: {lang: 0x44e, region: 0x9b},
-	211: {lang: 0x45a, region: 0xe7},
-	212: {lang: 0x11a, region: 0x99},
-	213: {lang: 0x45e, region: 0x53},
-	214: {lang: 0x232, region: 0x53},
-	215: {lang: 0x450, region: 0x99},
-	216: {lang: 0x4a5, region: 0x53},
-	217: {lang: 0x9f, region: 0x13e},
-	218: {lang: 0x461, region: 0x99},
-	220: {lang: 0x528, region: 0xba},
-	221: {lang: 0x153, region: 0xe7},
-	222: {lang: 0x128, region: 0xcd},
-	223: {lang: 0x46b, region: 0x123},
-	224: {lang: 0xa9, region: 0x53},
-	225: {lang: 0x2ce, region: 0x99},
-	226: {lang: 0x4ad, region: 0x11c},
-	227: {lang: 0x4be, region: 0xb4},
-	229: {lang: 0x1ce, region: 0x99},
-	232: {lang: 0x3a9, region: 0x9c},
-	233: {lang: 0x22, region: 0x9b},
-	234: {lang: 0x1ea, region: 0x53},
-	235: {lang: 0xef, region: 0xc5},
-}
-
-type likelyScriptRegion struct {
-	region uint16
-	script uint8
-	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: 5320 bytes, 1330 elements
-var likelyLang = [1330]likelyScriptRegion{
-	0:    {region: 0x135, script: 0x57, flags: 0x0},
-	1:    {region: 0x6f, script: 0x57, flags: 0x0},
-	2:    {region: 0x165, script: 0x57, flags: 0x0},
-	3:    {region: 0x165, script: 0x57, flags: 0x0},
-	4:    {region: 0x165, script: 0x57, flags: 0x0},
-	5:    {region: 0x7d, script: 0x1f, flags: 0x0},
-	6:    {region: 0x165, script: 0x57, flags: 0x0},
-	7:    {region: 0x165, script: 0x1f, flags: 0x0},
-	8:    {region: 0x80, script: 0x57, flags: 0x0},
-	9:    {region: 0x165, script: 0x57, flags: 0x0},
-	10:   {region: 0x165, script: 0x57, flags: 0x0},
-	11:   {region: 0x165, script: 0x57, flags: 0x0},
-	12:   {region: 0x95, script: 0x57, flags: 0x0},
-	13:   {region: 0x131, script: 0x57, flags: 0x0},
-	14:   {region: 0x80, script: 0x57, flags: 0x0},
-	15:   {region: 0x165, script: 0x57, flags: 0x0},
-	16:   {region: 0x165, script: 0x57, flags: 0x0},
-	17:   {region: 0x106, script: 0x1f, flags: 0x0},
-	18:   {region: 0x165, script: 0x57, flags: 0x0},
-	19:   {region: 0x9c, script: 0x9, flags: 0x0},
-	20:   {region: 0x128, script: 0x5, flags: 0x0},
-	21:   {region: 0x165, script: 0x57, flags: 0x0},
-	22:   {region: 0x161, script: 0x57, flags: 0x0},
-	23:   {region: 0x165, script: 0x57, flags: 0x0},
-	24:   {region: 0x165, script: 0x57, flags: 0x0},
-	25:   {region: 0x165, script: 0x57, flags: 0x0},
-	26:   {region: 0x165, script: 0x57, flags: 0x0},
-	27:   {region: 0x165, script: 0x57, flags: 0x0},
-	28:   {region: 0x52, script: 0x57, flags: 0x0},
-	29:   {region: 0x165, script: 0x57, flags: 0x0},
-	30:   {region: 0x165, script: 0x57, flags: 0x0},
-	31:   {region: 0x99, script: 0x4, flags: 0x0},
-	32:   {region: 0x165, script: 0x57, flags: 0x0},
-	33:   {region: 0x80, script: 0x57, flags: 0x0},
-	34:   {region: 0x9b, script: 0xe9, flags: 0x0},
-	35:   {region: 0x165, script: 0x57, flags: 0x0},
-	36:   {region: 0x165, script: 0x57, flags: 0x0},
-	37:   {region: 0x14d, script: 0x57, flags: 0x0},
-	38:   {region: 0x106, script: 0x1f, flags: 0x0},
-	39:   {region: 0x6f, script: 0x29, flags: 0x0},
-	40:   {region: 0x165, script: 0x57, flags: 0x0},
-	41:   {region: 0x165, script: 0x57, flags: 0x0},
-	42:   {region: 0xd6, script: 0x57, flags: 0x0},
-	43:   {region: 0x165, script: 0x57, flags: 0x0},
-	45:   {region: 0x165, script: 0x57, flags: 0x0},
-	46:   {region: 0x165, script: 0x57, flags: 0x0},
-	47:   {region: 0x165, script: 0x57, flags: 0x0},
-	48:   {region: 0x165, script: 0x57, flags: 0x0},
-	49:   {region: 0x165, script: 0x57, flags: 0x0},
-	50:   {region: 0x165, script: 0x57, flags: 0x0},
-	51:   {region: 0x95, script: 0x57, flags: 0x0},
-	52:   {region: 0x165, script: 0x5, flags: 0x0},
-	53:   {region: 0x122, script: 0x5, flags: 0x0},
-	54:   {region: 0x165, script: 0x57, flags: 0x0},
-	55:   {region: 0x165, script: 0x57, flags: 0x0},
-	56:   {region: 0x165, script: 0x57, flags: 0x0},
-	57:   {region: 0x165, script: 0x57, flags: 0x0},
-	58:   {region: 0x6b, script: 0x5, flags: 0x0},
-	59:   {region: 0x0, script: 0x3, flags: 0x1},
-	60:   {region: 0x165, script: 0x57, flags: 0x0},
-	61:   {region: 0x51, script: 0x57, flags: 0x0},
-	62:   {region: 0x3f, script: 0x57, flags: 0x0},
-	63:   {region: 0x67, script: 0x5, flags: 0x0},
-	65:   {region: 0xba, script: 0x5, flags: 0x0},
-	66:   {region: 0x6b, script: 0x5, flags: 0x0},
-	67:   {region: 0x99, script: 0xe, flags: 0x0},
-	68:   {region: 0x12f, script: 0x57, flags: 0x0},
-	69:   {region: 0x135, script: 0xc4, flags: 0x0},
-	70:   {region: 0x165, script: 0x57, flags: 0x0},
-	71:   {region: 0x165, script: 0x57, flags: 0x0},
-	72:   {region: 0x6e, script: 0x57, flags: 0x0},
-	73:   {region: 0x165, script: 0x57, flags: 0x0},
-	74:   {region: 0x165, script: 0x57, flags: 0x0},
-	75:   {region: 0x49, script: 0x57, flags: 0x0},
-	76:   {region: 0x165, script: 0x57, flags: 0x0},
-	77:   {region: 0x106, script: 0x1f, flags: 0x0},
-	78:   {region: 0x165, script: 0x5, flags: 0x0},
-	79:   {region: 0x165, script: 0x57, flags: 0x0},
-	80:   {region: 0x165, script: 0x57, flags: 0x0},
-	81:   {region: 0x165, script: 0x57, flags: 0x0},
-	82:   {region: 0x99, script: 0x21, flags: 0x0},
-	83:   {region: 0x165, script: 0x57, flags: 0x0},
-	84:   {region: 0x165, script: 0x57, flags: 0x0},
-	85:   {region: 0x165, script: 0x57, flags: 0x0},
-	86:   {region: 0x3f, script: 0x57, flags: 0x0},
-	87:   {region: 0x165, script: 0x57, flags: 0x0},
-	88:   {region: 0x3, script: 0x5, flags: 0x1},
-	89:   {region: 0x106, script: 0x1f, flags: 0x0},
-	90:   {region: 0xe8, script: 0x5, flags: 0x0},
-	91:   {region: 0x95, script: 0x57, flags: 0x0},
-	92:   {region: 0xdb, script: 0x21, flags: 0x0},
-	93:   {region: 0x2e, script: 0x57, flags: 0x0},
-	94:   {region: 0x52, script: 0x57, flags: 0x0},
-	95:   {region: 0x165, script: 0x57, flags: 0x0},
-	96:   {region: 0x52, script: 0xb, flags: 0x0},
-	97:   {region: 0x165, script: 0x57, flags: 0x0},
-	98:   {region: 0x165, script: 0x57, flags: 0x0},
-	99:   {region: 0x95, script: 0x57, flags: 0x0},
-	100:  {region: 0x165, script: 0x57, flags: 0x0},
-	101:  {region: 0x52, script: 0x57, flags: 0x0},
-	102:  {region: 0x165, script: 0x57, flags: 0x0},
-	103:  {region: 0x165, script: 0x57, flags: 0x0},
-	104:  {region: 0x165, script: 0x57, flags: 0x0},
-	105:  {region: 0x165, script: 0x57, flags: 0x0},
-	106:  {region: 0x4f, script: 0x57, flags: 0x0},
-	107:  {region: 0x165, script: 0x57, flags: 0x0},
-	108:  {region: 0x165, script: 0x57, flags: 0x0},
-	109:  {region: 0x165, script: 0x57, flags: 0x0},
-	110:  {region: 0x165, script: 0x29, flags: 0x0},
-	111:  {region: 0x165, script: 0x57, flags: 0x0},
-	112:  {region: 0x165, script: 0x57, flags: 0x0},
-	113:  {region: 0x47, script: 0x1f, flags: 0x0},
-	114:  {region: 0x165, script: 0x57, flags: 0x0},
-	115:  {region: 0x165, script: 0x57, flags: 0x0},
-	116:  {region: 0x10b, script: 0x5, flags: 0x0},
-	117:  {region: 0x162, script: 0x57, flags: 0x0},
-	118:  {region: 0x165, script: 0x57, flags: 0x0},
-	119:  {region: 0x95, script: 0x57, flags: 0x0},
-	120:  {region: 0x165, script: 0x57, flags: 0x0},
-	121:  {region: 0x12f, script: 0x57, flags: 0x0},
-	122:  {region: 0x52, script: 0x57, flags: 0x0},
-	123:  {region: 0x99, script: 0xd7, flags: 0x0},
-	124:  {region: 0xe8, script: 0x5, flags: 0x0},
-	125:  {region: 0x99, script: 0x21, flags: 0x0},
-	126:  {region: 0x38, script: 0x1f, flags: 0x0},
-	127:  {region: 0x99, script: 0x21, flags: 0x0},
-	128:  {region: 0xe8, script: 0x5, flags: 0x0},
-	129:  {region: 0x12b, script: 0x31, flags: 0x0},
-	131:  {region: 0x99, script: 0x21, flags: 0x0},
-	132:  {region: 0x165, script: 0x57, flags: 0x0},
-	133:  {region: 0x99, script: 0x21, flags: 0x0},
-	134:  {region: 0xe7, script: 0x57, flags: 0x0},
-	135:  {region: 0x165, script: 0x57, flags: 0x0},
-	136:  {region: 0x99, script: 0x21, flags: 0x0},
-	137:  {region: 0x165, script: 0x57, flags: 0x0},
-	138:  {region: 0x13f, script: 0x57, flags: 0x0},
-	139:  {region: 0x165, script: 0x57, flags: 0x0},
-	140:  {region: 0x165, script: 0x57, flags: 0x0},
-	141:  {region: 0xe7, script: 0x57, flags: 0x0},
-	142:  {region: 0x165, script: 0x57, flags: 0x0},
-	143:  {region: 0xd6, script: 0x57, flags: 0x0},
-	144:  {region: 0x165, script: 0x57, flags: 0x0},
-	145:  {region: 0x165, script: 0x57, flags: 0x0},
-	146:  {region: 0x165, script: 0x57, flags: 0x0},
-	147:  {region: 0x165, script: 0x29, flags: 0x0},
-	148:  {region: 0x99, script: 0x21, flags: 0x0},
-	149:  {region: 0x95, script: 0x57, flags: 0x0},
-	150:  {region: 0x165, script: 0x57, flags: 0x0},
-	151:  {region: 0x165, script: 0x57, flags: 0x0},
-	152:  {region: 0x114, script: 0x57, flags: 0x0},
-	153:  {region: 0x165, script: 0x57, flags: 0x0},
-	154:  {region: 0x165, script: 0x57, flags: 0x0},
-	155:  {region: 0x52, script: 0x57, flags: 0x0},
-	156:  {region: 0x165, script: 0x57, flags: 0x0},
-	157:  {region: 0xe7, script: 0x57, flags: 0x0},
-	158:  {region: 0x165, script: 0x57, flags: 0x0},
-	159:  {region: 0x13e, script: 0xd9, flags: 0x0},
-	160:  {region: 0xc3, script: 0x57, flags: 0x0},
-	161:  {region: 0x165, script: 0x57, flags: 0x0},
-	162:  {region: 0x165, script: 0x57, flags: 0x0},
-	163:  {region: 0xc3, script: 0x57, flags: 0x0},
-	164:  {region: 0x165, script: 0x57, flags: 0x0},
-	165:  {region: 0x35, script: 0xe, flags: 0x0},
-	166:  {region: 0x165, script: 0x57, flags: 0x0},
-	167:  {region: 0x165, script: 0x57, flags: 0x0},
-	168:  {region: 0x165, script: 0x57, flags: 0x0},
-	169:  {region: 0x53, script: 0xe0, flags: 0x0},
-	170:  {region: 0x165, script: 0x57, flags: 0x0},
-	171:  {region: 0x165, script: 0x57, flags: 0x0},
-	172:  {region: 0x165, script: 0x57, flags: 0x0},
-	173:  {region: 0x99, script: 0xe, flags: 0x0},
-	174:  {region: 0x165, script: 0x57, flags: 0x0},
-	175:  {region: 0x9c, script: 0x5, flags: 0x0},
-	176:  {region: 0x165, script: 0x57, flags: 0x0},
-	177:  {region: 0x4f, script: 0x57, flags: 0x0},
-	178:  {region: 0x78, script: 0x57, flags: 0x0},
-	179:  {region: 0x99, script: 0x21, flags: 0x0},
-	180:  {region: 0xe8, script: 0x5, flags: 0x0},
-	181:  {region: 0x99, script: 0x21, flags: 0x0},
-	182:  {region: 0x165, script: 0x57, flags: 0x0},
-	183:  {region: 0x33, script: 0x57, flags: 0x0},
-	184:  {region: 0x165, script: 0x57, flags: 0x0},
-	185:  {region: 0xb4, script: 0xc, flags: 0x0},
-	186:  {region: 0x52, script: 0x57, flags: 0x0},
-	187:  {region: 0x165, script: 0x29, flags: 0x0},
-	188:  {region: 0xe7, script: 0x57, flags: 0x0},
-	189:  {region: 0x165, script: 0x57, flags: 0x0},
-	190:  {region: 0xe8, script: 0x21, flags: 0x0},
-	191:  {region: 0x106, script: 0x1f, flags: 0x0},
-	192:  {region: 0x15f, script: 0x57, flags: 0x0},
-	193:  {region: 0x165, script: 0x57, flags: 0x0},
-	194:  {region: 0x95, script: 0x57, flags: 0x0},
-	195:  {region: 0x165, script: 0x57, flags: 0x0},
-	196:  {region: 0x52, script: 0x57, flags: 0x0},
-	197:  {region: 0x165, script: 0x57, flags: 0x0},
-	198:  {region: 0x165, script: 0x57, flags: 0x0},
-	199:  {region: 0x165, script: 0x57, flags: 0x0},
-	200:  {region: 0x86, script: 0x57, flags: 0x0},
-	201:  {region: 0x165, script: 0x57, flags: 0x0},
-	202:  {region: 0x165, script: 0x57, flags: 0x0},
-	203:  {region: 0x165, script: 0x57, flags: 0x0},
-	204:  {region: 0x165, script: 0x57, flags: 0x0},
-	205:  {region: 0x6d, script: 0x29, flags: 0x0},
-	206:  {region: 0x165, script: 0x57, flags: 0x0},
-	207:  {region: 0x165, script: 0x57, flags: 0x0},
-	208:  {region: 0x52, script: 0x57, flags: 0x0},
-	209:  {region: 0x165, script: 0x57, flags: 0x0},
-	210:  {region: 0x165, script: 0x57, flags: 0x0},
-	211:  {region: 0xc3, script: 0x57, flags: 0x0},
-	212:  {region: 0x165, script: 0x57, flags: 0x0},
-	213:  {region: 0x165, script: 0x57, flags: 0x0},
-	214:  {region: 0x165, script: 0x57, flags: 0x0},
-	215:  {region: 0x6e, script: 0x57, flags: 0x0},
-	216:  {region: 0x165, script: 0x57, flags: 0x0},
-	217:  {region: 0x165, script: 0x57, flags: 0x0},
-	218:  {region: 0xd6, script: 0x57, flags: 0x0},
-	219:  {region: 0x35, script: 0x16, flags: 0x0},
-	220:  {region: 0x106, script: 0x1f, flags: 0x0},
-	221:  {region: 0xe7, script: 0x57, flags: 0x0},
-	222:  {region: 0x165, script: 0x57, flags: 0x0},
-	223:  {region: 0x131, script: 0x57, flags: 0x0},
-	224:  {region: 0x8a, script: 0x57, flags: 0x0},
-	225:  {region: 0x75, script: 0x57, flags: 0x0},
-	226:  {region: 0x106, script: 0x1f, flags: 0x0},
-	227:  {region: 0x135, script: 0x57, flags: 0x0},
-	228:  {region: 0x49, script: 0x57, flags: 0x0},
-	229:  {region: 0x135, script: 0x1a, flags: 0x0},
-	230:  {region: 0xa6, script: 0x5, flags: 0x0},
-	231:  {region: 0x13e, script: 0x19, flags: 0x0},
-	232:  {region: 0x165, script: 0x57, flags: 0x0},
-	233:  {region: 0x9b, script: 0x5, flags: 0x0},
-	234:  {region: 0x165, script: 0x57, flags: 0x0},
-	235:  {region: 0x165, script: 0x57, flags: 0x0},
-	236:  {region: 0x165, script: 0x57, flags: 0x0},
-	237:  {region: 0x165, script: 0x57, flags: 0x0},
-	238:  {region: 0x165, script: 0x57, flags: 0x0},
-	239:  {region: 0xc5, script: 0xcc, flags: 0x0},
-	240:  {region: 0x78, script: 0x57, flags: 0x0},
-	241:  {region: 0x6b, script: 0x1c, flags: 0x0},
-	242:  {region: 0xe7, script: 0x57, flags: 0x0},
-	243:  {region: 0x49, script: 0x17, flags: 0x0},
-	244:  {region: 0x130, script: 0x1f, 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: 0x10a, script: 0x57, flags: 0x0},
-	250:  {region: 0x5e, script: 0x57, flags: 0x0},
-	251:  {region: 0xe9, script: 0x57, flags: 0x0},
-	252:  {region: 0x49, script: 0x17, flags: 0x0},
-	253:  {region: 0xc4, script: 0x81, flags: 0x0},
-	254:  {region: 0x8, script: 0x2, flags: 0x1},
-	255:  {region: 0x106, script: 0x1f, flags: 0x0},
-	256:  {region: 0x7b, script: 0x57, flags: 0x0},
-	257:  {region: 0x63, script: 0x57, flags: 0x0},
-	258:  {region: 0x165, script: 0x57, flags: 0x0},
-	259:  {region: 0x165, script: 0x57, flags: 0x0},
-	260:  {region: 0x165, script: 0x57, flags: 0x0},
-	261:  {region: 0x165, script: 0x57, flags: 0x0},
-	262:  {region: 0x135, script: 0x57, flags: 0x0},
-	263:  {region: 0x106, script: 0x1f, flags: 0x0},
-	264:  {region: 0xa4, script: 0x57, flags: 0x0},
-	265:  {region: 0x165, script: 0x57, flags: 0x0},
-	266:  {region: 0x165, script: 0x57, flags: 0x0},
-	267:  {region: 0x99, script: 0x5, flags: 0x0},
-	268:  {region: 0x165, script: 0x57, flags: 0x0},
-	269:  {region: 0x60, script: 0x57, flags: 0x0},
-	270:  {region: 0x165, script: 0x57, flags: 0x0},
-	271:  {region: 0x49, script: 0x57, flags: 0x0},
-	272:  {region: 0x165, script: 0x57, flags: 0x0},
-	273:  {region: 0x165, script: 0x57, flags: 0x0},
-	274:  {region: 0x165, script: 0x57, flags: 0x0},
-	275:  {region: 0x165, script: 0x5, flags: 0x0},
-	276:  {region: 0x49, script: 0x57, flags: 0x0},
-	277:  {region: 0x165, script: 0x57, flags: 0x0},
-	278:  {region: 0x165, script: 0x57, flags: 0x0},
-	279:  {region: 0xd4, script: 0x57, flags: 0x0},
-	280:  {region: 0x4f, script: 0x57, flags: 0x0},
-	281:  {region: 0x165, script: 0x57, flags: 0x0},
-	282:  {region: 0x99, script: 0x5, flags: 0x0},
-	283:  {region: 0x165, script: 0x57, flags: 0x0},
-	284:  {region: 0x165, script: 0x57, flags: 0x0},
-	285:  {region: 0x165, script: 0x57, flags: 0x0},
-	286:  {region: 0x165, script: 0x29, flags: 0x0},
-	287:  {region: 0x60, script: 0x57, flags: 0x0},
-	288:  {region: 0xc3, script: 0x57, flags: 0x0},
-	289:  {region: 0xd0, script: 0x57, flags: 0x0},
-	290:  {region: 0x165, script: 0x57, flags: 0x0},
-	291:  {region: 0xdb, script: 0x21, flags: 0x0},
-	292:  {region: 0x52, script: 0x57, flags: 0x0},
-	293:  {region: 0x165, script: 0x57, flags: 0x0},
-	294:  {region: 0x165, script: 0x57, flags: 0x0},
-	295:  {region: 0x165, script: 0x57, flags: 0x0},
-	296:  {region: 0xcd, script: 0xde, flags: 0x0},
-	297:  {region: 0x165, script: 0x57, flags: 0x0},
-	298:  {region: 0x165, script: 0x57, flags: 0x0},
-	299:  {region: 0x114, script: 0x57, flags: 0x0},
-	300:  {region: 0x37, script: 0x57, flags: 0x0},
-	301:  {region: 0x43, script: 0xe0, flags: 0x0},
-	302:  {region: 0x165, script: 0x57, flags: 0x0},
-	303:  {region: 0xa4, script: 0x57, flags: 0x0},
-	304:  {region: 0x80, script: 0x57, flags: 0x0},
-	305:  {region: 0xd6, script: 0x57, flags: 0x0},
-	306:  {region: 0x9e, script: 0x57, flags: 0x0},
-	307:  {region: 0x6b, script: 0x27, flags: 0x0},
-	308:  {region: 0x165, script: 0x57, flags: 0x0},
-	309:  {region: 0xc4, script: 0x48, flags: 0x0},
-	310:  {region: 0x87, script: 0x31, flags: 0x0},
-	311:  {region: 0x165, script: 0x57, flags: 0x0},
-	312:  {region: 0x165, script: 0x57, flags: 0x0},
-	313:  {region: 0xa, script: 0x2, flags: 0x1},
-	314:  {region: 0x165, script: 0x57, flags: 0x0},
-	315:  {region: 0x165, script: 0x57, flags: 0x0},
-	316:  {region: 0x1, script: 0x57, flags: 0x0},
-	317:  {region: 0x165, script: 0x57, flags: 0x0},
-	318:  {region: 0x6e, script: 0x57, flags: 0x0},
-	319:  {region: 0x135, script: 0x57, flags: 0x0},
-	320:  {region: 0x6a, script: 0x57, flags: 0x0},
-	321:  {region: 0x165, script: 0x57, flags: 0x0},
-	322:  {region: 0x9e, script: 0x43, flags: 0x0},
-	323:  {region: 0x165, script: 0x57, flags: 0x0},
-	324:  {region: 0x165, script: 0x57, flags: 0x0},
-	325:  {region: 0x6e, script: 0x57, flags: 0x0},
-	326:  {region: 0x52, script: 0x57, flags: 0x0},
-	327:  {region: 0x6e, script: 0x57, flags: 0x0},
-	328:  {region: 0x9c, script: 0x5, flags: 0x0},
-	329:  {region: 0x165, script: 0x57, flags: 0x0},
-	330:  {region: 0x165, script: 0x57, flags: 0x0},
-	331:  {region: 0x165, script: 0x57, flags: 0x0},
-	332:  {region: 0x165, script: 0x57, flags: 0x0},
-	333:  {region: 0x86, script: 0x57, flags: 0x0},
-	334:  {region: 0xc, script: 0x2, flags: 0x1},
-	335:  {region: 0x165, script: 0x57, flags: 0x0},
-	336:  {region: 0xc3, script: 0x57, flags: 0x0},
-	337:  {region: 0x72, script: 0x57, flags: 0x0},
-	338:  {region: 0x10b, script: 0x5, flags: 0x0},
-	339:  {region: 0xe7, script: 0x57, flags: 0x0},
-	340:  {region: 0x10c, script: 0x57, flags: 0x0},
-	341:  {region: 0x73, script: 0x57, flags: 0x0},
-	342:  {region: 0x165, script: 0x57, flags: 0x0},
-	343:  {region: 0x165, script: 0x57, flags: 0x0},
-	344:  {region: 0x76, script: 0x57, flags: 0x0},
-	345:  {region: 0x165, script: 0x57, flags: 0x0},
-	346:  {region: 0x3b, script: 0x57, flags: 0x0},
-	347:  {region: 0x165, script: 0x57, flags: 0x0},
-	348:  {region: 0x165, script: 0x57, flags: 0x0},
-	349:  {region: 0x165, script: 0x57, flags: 0x0},
-	350:  {region: 0x78, script: 0x57, flags: 0x0},
-	351:  {region: 0x135, script: 0x57, flags: 0x0},
-	352:  {region: 0x78, script: 0x57, flags: 0x0},
-	353:  {region: 0x60, script: 0x57, flags: 0x0},
-	354:  {region: 0x60, script: 0x57, flags: 0x0},
-	355:  {region: 0x52, script: 0x5, flags: 0x0},
-	356:  {region: 0x140, script: 0x57, flags: 0x0},
-	357:  {region: 0x165, script: 0x57, flags: 0x0},
-	358:  {region: 0x84, script: 0x57, flags: 0x0},
-	359:  {region: 0x165, script: 0x57, flags: 0x0},
-	360:  {region: 0xd4, script: 0x57, flags: 0x0},
-	361:  {region: 0x9e, script: 0x57, flags: 0x0},
-	362:  {region: 0xd6, script: 0x57, flags: 0x0},
-	363:  {region: 0x165, script: 0x57, flags: 0x0},
-	364:  {region: 0x10b, script: 0x57, flags: 0x0},
-	365:  {region: 0xd9, script: 0x57, flags: 0x0},
-	366:  {region: 0x96, script: 0x57, flags: 0x0},
-	367:  {region: 0x80, script: 0x57, flags: 0x0},
-	368:  {region: 0x165, script: 0x57, flags: 0x0},
-	369:  {region: 0xbc, script: 0x57, flags: 0x0},
-	370:  {region: 0x165, script: 0x57, flags: 0x0},
-	371:  {region: 0x165, script: 0x57, flags: 0x0},
-	372:  {region: 0x165, script: 0x57, flags: 0x0},
-	373:  {region: 0x53, script: 0x38, flags: 0x0},
-	374:  {region: 0x165, script: 0x57, flags: 0x0},
-	375:  {region: 0x95, script: 0x57, flags: 0x0},
-	376:  {region: 0x165, script: 0x57, flags: 0x0},
-	377:  {region: 0x165, script: 0x57, flags: 0x0},
-	378:  {region: 0x99, script: 0x21, flags: 0x0},
-	379:  {region: 0x165, script: 0x57, flags: 0x0},
-	380:  {region: 0x9c, script: 0x5, flags: 0x0},
-	381:  {region: 0x7e, script: 0x57, flags: 0x0},
-	382:  {region: 0x7b, script: 0x57, flags: 0x0},
-	383:  {region: 0x165, script: 0x57, flags: 0x0},
-	384:  {region: 0x165, script: 0x57, flags: 0x0},
-	385:  {region: 0x165, script: 0x57, flags: 0x0},
-	386:  {region: 0x165, script: 0x57, flags: 0x0},
-	387:  {region: 0x165, script: 0x57, flags: 0x0},
-	388:  {region: 0x165, script: 0x57, flags: 0x0},
-	389:  {region: 0x6f, script: 0x29, flags: 0x0},
-	390:  {region: 0x165, script: 0x57, flags: 0x0},
-	391:  {region: 0xdb, script: 0x21, flags: 0x0},
-	392:  {region: 0x165, script: 0x57, flags: 0x0},
-	393:  {region: 0xa7, script: 0x57, flags: 0x0},
-	394:  {region: 0x165, script: 0x57, flags: 0x0},
-	395:  {region: 0xe8, script: 0x5, flags: 0x0},
-	396:  {region: 0x165, script: 0x57, flags: 0x0},
-	397:  {region: 0xe8, script: 0x5, flags: 0x0},
-	398:  {region: 0x165, script: 0x57, flags: 0x0},
-	399:  {region: 0x165, script: 0x57, flags: 0x0},
-	400:  {region: 0x6e, script: 0x57, flags: 0x0},
-	401:  {region: 0x9c, script: 0x5, flags: 0x0},
-	402:  {region: 0x165, script: 0x57, flags: 0x0},
-	403:  {region: 0x165, script: 0x29, flags: 0x0},
-	404:  {region: 0xf1, script: 0x57, flags: 0x0},
-	405:  {region: 0x165, script: 0x57, flags: 0x0},
-	406:  {region: 0x165, script: 0x57, flags: 0x0},
-	407:  {region: 0x165, script: 0x57, flags: 0x0},
-	408:  {region: 0x165, script: 0x29, flags: 0x0},
-	409:  {region: 0x165, script: 0x57, flags: 0x0},
-	410:  {region: 0x99, script: 0x21, flags: 0x0},
-	411:  {region: 0x99, script: 0xda, flags: 0x0},
-	412:  {region: 0x95, script: 0x57, flags: 0x0},
-	413:  {region: 0xd9, script: 0x57, flags: 0x0},
-	414:  {region: 0x130, script: 0x2f, flags: 0x0},
-	415:  {region: 0x165, script: 0x57, flags: 0x0},
-	416:  {region: 0xe, script: 0x2, flags: 0x1},
-	417:  {region: 0x99, script: 0xe, flags: 0x0},
-	418:  {region: 0x165, script: 0x57, flags: 0x0},
-	419:  {region: 0x4e, script: 0x57, flags: 0x0},
-	420:  {region: 0x99, script: 0x32, flags: 0x0},
-	421:  {region: 0x41, script: 0x57, flags: 0x0},
-	422:  {region: 0x54, script: 0x57, flags: 0x0},
-	423:  {region: 0x165, script: 0x57, flags: 0x0},
-	424:  {region: 0x80, script: 0x57, flags: 0x0},
-	425:  {region: 0x165, script: 0x57, flags: 0x0},
-	426:  {region: 0x165, script: 0x57, flags: 0x0},
-	427:  {region: 0xa4, script: 0x57, flags: 0x0},
-	428:  {region: 0x98, script: 0x57, flags: 0x0},
-	429:  {region: 0x165, script: 0x57, flags: 0x0},
-	430:  {region: 0xdb, script: 0x21, flags: 0x0},
-	431:  {region: 0x165, script: 0x57, flags: 0x0},
-	432:  {region: 0x165, script: 0x5, flags: 0x0},
-	433:  {region: 0x49, script: 0x57, flags: 0x0},
-	434:  {region: 0x165, script: 0x5, flags: 0x0},
-	435:  {region: 0x165, script: 0x57, flags: 0x0},
-	436:  {region: 0x10, script: 0x3, flags: 0x1},
-	437:  {region: 0x165, script: 0x57, flags: 0x0},
-	438:  {region: 0x53, script: 0x38, flags: 0x0},
-	439:  {region: 0x165, script: 0x57, flags: 0x0},
-	440:  {region: 0x135, script: 0x57, flags: 0x0},
-	441:  {region: 0x24, script: 0x5, flags: 0x0},
-	442:  {region: 0x165, script: 0x57, flags: 0x0},
-	443:  {region: 0x165, script: 0x29, flags: 0x0},
-	444:  {region: 0x97, script: 0x3b, flags: 0x0},
-	445:  {region: 0x165, script: 0x57, flags: 0x0},
-	446:  {region: 0x99, script: 0x21, flags: 0x0},
-	447:  {region: 0x165, script: 0x57, flags: 0x0},
-	448:  {region: 0x73, script: 0x57, flags: 0x0},
-	449:  {region: 0x165, script: 0x57, flags: 0x0},
-	450:  {region: 0x165, script: 0x57, flags: 0x0},
-	451:  {region: 0xe7, script: 0x57, flags: 0x0},
-	452:  {region: 0x165, script: 0x57, flags: 0x0},
-	453:  {region: 0x12b, script: 0x3d, flags: 0x0},
-	454:  {region: 0x53, script: 0x89, flags: 0x0},
-	455:  {region: 0x165, script: 0x57, flags: 0x0},
-	456:  {region: 0xe8, script: 0x5, flags: 0x0},
-	457:  {region: 0x99, script: 0x21, flags: 0x0},
-	458:  {region: 0xaf, script: 0x3e, flags: 0x0},
-	459:  {region: 0xe7, script: 0x57, flags: 0x0},
-	460:  {region: 0xe8, script: 0x5, flags: 0x0},
-	461:  {region: 0xe6, script: 0x57, flags: 0x0},
-	462:  {region: 0x99, script: 0x21, flags: 0x0},
-	463:  {region: 0x99, script: 0x21, flags: 0x0},
-	464:  {region: 0x165, script: 0x57, flags: 0x0},
-	465:  {region: 0x90, script: 0x57, flags: 0x0},
-	466:  {region: 0x60, script: 0x57, flags: 0x0},
-	467:  {region: 0x53, script: 0x38, flags: 0x0},
-	468:  {region: 0x91, script: 0x57, flags: 0x0},
-	469:  {region: 0x92, script: 0x57, flags: 0x0},
-	470:  {region: 0x165, script: 0x57, flags: 0x0},
-	471:  {region: 0x28, script: 0x8, flags: 0x0},
-	472:  {region: 0xd2, script: 0x57, flags: 0x0},
-	473:  {region: 0x78, script: 0x57, flags: 0x0},
-	474:  {region: 0x165, script: 0x57, flags: 0x0},
-	475:  {region: 0x165, script: 0x57, flags: 0x0},
-	476:  {region: 0xd0, script: 0x57, flags: 0x0},
-	477:  {region: 0xd6, script: 0x57, flags: 0x0},
-	478:  {region: 0x165, script: 0x57, flags: 0x0},
-	479:  {region: 0x165, script: 0x57, flags: 0x0},
-	480:  {region: 0x165, script: 0x57, flags: 0x0},
-	481:  {region: 0x95, script: 0x57, flags: 0x0},
-	482:  {region: 0x165, script: 0x57, flags: 0x0},
-	483:  {region: 0x165, script: 0x57, flags: 0x0},
-	484:  {region: 0x165, script: 0x57, flags: 0x0},
-	486:  {region: 0x122, script: 0x57, flags: 0x0},
-	487:  {region: 0xd6, script: 0x57, flags: 0x0},
-	488:  {region: 0x165, script: 0x57, flags: 0x0},
-	489:  {region: 0x165, script: 0x57, flags: 0x0},
-	490:  {region: 0x53, script: 0xea, flags: 0x0},
-	491:  {region: 0x165, script: 0x57, flags: 0x0},
-	492:  {region: 0x135, script: 0x57, flags: 0x0},
-	493:  {region: 0x165, script: 0x57, flags: 0x0},
-	494:  {region: 0x49, script: 0x57, flags: 0x0},
-	495:  {region: 0x165, script: 0x57, flags: 0x0},
-	496:  {region: 0x165, script: 0x57, flags: 0x0},
-	497:  {region: 0xe7, script: 0x57, flags: 0x0},
-	498:  {region: 0x165, script: 0x57, flags: 0x0},
-	499:  {region: 0x95, script: 0x57, flags: 0x0},
-	500:  {region: 0x106, script: 0x1f, flags: 0x0},
-	501:  {region: 0x1, script: 0x57, flags: 0x0},
-	502:  {region: 0x165, script: 0x57, flags: 0x0},
-	503:  {region: 0x165, script: 0x57, flags: 0x0},
-	504:  {region: 0x9d, script: 0x57, flags: 0x0},
-	505:  {region: 0x9e, script: 0x57, flags: 0x0},
-	506:  {region: 0x49, script: 0x17, flags: 0x0},
-	507:  {region: 0x97, script: 0x3b, flags: 0x0},
-	508:  {region: 0x165, script: 0x57, flags: 0x0},
-	509:  {region: 0x165, script: 0x57, flags: 0x0},
-	510:  {region: 0x106, script: 0x57, flags: 0x0},
-	511:  {region: 0x165, script: 0x57, flags: 0x0},
-	512:  {region: 0xa2, script: 0x46, flags: 0x0},
-	513:  {region: 0x165, script: 0x57, flags: 0x0},
-	514:  {region: 0xa0, script: 0x57, flags: 0x0},
-	515:  {region: 0x1, script: 0x57, flags: 0x0},
-	516:  {region: 0x165, script: 0x57, flags: 0x0},
-	517:  {region: 0x165, script: 0x57, flags: 0x0},
-	518:  {region: 0x165, script: 0x57, flags: 0x0},
-	519:  {region: 0x52, script: 0x57, flags: 0x0},
-	520:  {region: 0x130, script: 0x3b, flags: 0x0},
-	521:  {region: 0x165, script: 0x57, flags: 0x0},
-	522:  {region: 0x12f, script: 0x57, flags: 0x0},
-	523:  {region: 0xdb, script: 0x21, flags: 0x0},
-	524:  {region: 0x165, script: 0x57, flags: 0x0},
-	525:  {region: 0x63, script: 0x57, flags: 0x0},
-	526:  {region: 0x95, script: 0x57, flags: 0x0},
-	527:  {region: 0x95, script: 0x57, flags: 0x0},
-	528:  {region: 0x7d, script: 0x2b, flags: 0x0},
-	529:  {region: 0x137, script: 0x1f, flags: 0x0},
-	530:  {region: 0x67, script: 0x57, flags: 0x0},
-	531:  {region: 0xc4, script: 0x57, flags: 0x0},
-	532:  {region: 0x165, script: 0x57, flags: 0x0},
-	533:  {region: 0x165, script: 0x57, flags: 0x0},
-	534:  {region: 0xd6, script: 0x57, flags: 0x0},
-	535:  {region: 0xa4, script: 0x57, flags: 0x0},
-	536:  {region: 0xc3, script: 0x57, flags: 0x0},
-	537:  {region: 0x106, script: 0x1f, flags: 0x0},
-	538:  {region: 0x165, script: 0x57, flags: 0x0},
-	539:  {region: 0x165, script: 0x57, flags: 0x0},
-	540:  {region: 0x165, script: 0x57, flags: 0x0},
-	541:  {region: 0x165, script: 0x57, flags: 0x0},
-	542:  {region: 0xd4, script: 0x5, flags: 0x0},
-	543:  {region: 0xd6, script: 0x57, flags: 0x0},
-	544:  {region: 0x164, script: 0x57, flags: 0x0},
-	545:  {region: 0x165, script: 0x57, flags: 0x0},
-	546:  {region: 0x165, script: 0x57, flags: 0x0},
-	547:  {region: 0x12f, script: 0x57, flags: 0x0},
-	548:  {region: 0x122, script: 0x5, flags: 0x0},
-	549:  {region: 0x165, script: 0x57, flags: 0x0},
-	550:  {region: 0x123, script: 0xdf, flags: 0x0},
-	551:  {region: 0x5a, script: 0x57, flags: 0x0},
-	552:  {region: 0x52, script: 0x57, flags: 0x0},
-	553:  {region: 0x165, script: 0x57, flags: 0x0},
-	554:  {region: 0x4f, script: 0x57, flags: 0x0},
-	555:  {region: 0x99, script: 0x21, flags: 0x0},
-	556:  {region: 0x99, script: 0x21, flags: 0x0},
-	557:  {region: 0x4b, script: 0x57, flags: 0x0},
-	558:  {region: 0x95, script: 0x57, flags: 0x0},
-	559:  {region: 0x165, script: 0x57, flags: 0x0},
-	560:  {region: 0x41, script: 0x57, flags: 0x0},
-	561:  {region: 0x99, script: 0x57, flags: 0x0},
-	562:  {region: 0x53, script: 0xd6, flags: 0x0},
-	563:  {region: 0x99, script: 0x21, flags: 0x0},
-	564:  {region: 0xc3, script: 0x57, flags: 0x0},
-	565:  {region: 0x165, script: 0x57, flags: 0x0},
-	566:  {region: 0x99, script: 0x72, flags: 0x0},
-	567:  {region: 0xe8, script: 0x5, flags: 0x0},
-	568:  {region: 0x165, script: 0x57, flags: 0x0},
-	569:  {region: 0xa4, script: 0x57, flags: 0x0},
-	570:  {region: 0x165, script: 0x57, flags: 0x0},
-	571:  {region: 0x12b, script: 0x57, flags: 0x0},
-	572:  {region: 0x165, script: 0x57, flags: 0x0},
-	573:  {region: 0xd2, script: 0x57, flags: 0x0},
-	574:  {region: 0x165, script: 0x57, flags: 0x0},
-	575:  {region: 0xaf, script: 0x54, flags: 0x0},
-	576:  {region: 0x165, script: 0x57, flags: 0x0},
-	577:  {region: 0x165, script: 0x57, flags: 0x0},
-	578:  {region: 0x13, script: 0x6, flags: 0x1},
-	579:  {region: 0x165, script: 0x57, flags: 0x0},
-	580:  {region: 0x52, script: 0x57, flags: 0x0},
-	581:  {region: 0x82, script: 0x57, flags: 0x0},
-	582:  {region: 0xa4, script: 0x57, flags: 0x0},
-	583:  {region: 0x165, script: 0x57, flags: 0x0},
-	584:  {region: 0x165, script: 0x57, flags: 0x0},
-	585:  {region: 0x165, script: 0x57, flags: 0x0},
-	586:  {region: 0xa6, script: 0x4b, flags: 0x0},
-	587:  {region: 0x2a, script: 0x57, flags: 0x0},
-	588:  {region: 0x165, script: 0x57, flags: 0x0},
-	589:  {region: 0x165, script: 0x57, flags: 0x0},
-	590:  {region: 0x165, script: 0x57, flags: 0x0},
-	591:  {region: 0x165, script: 0x57, flags: 0x0},
-	592:  {region: 0x165, script: 0x57, flags: 0x0},
-	593:  {region: 0x99, script: 0x4f, flags: 0x0},
-	594:  {region: 0x8b, script: 0x57, flags: 0x0},
-	595:  {region: 0x165, script: 0x57, flags: 0x0},
-	596:  {region: 0xab, script: 0x50, flags: 0x0},
-	597:  {region: 0x106, script: 0x1f, flags: 0x0},
-	598:  {region: 0x99, script: 0x21, flags: 0x0},
-	599:  {region: 0x165, script: 0x57, flags: 0x0},
-	600:  {region: 0x75, script: 0x57, flags: 0x0},
-	601:  {region: 0x165, script: 0x57, flags: 0x0},
-	602:  {region: 0xb4, script: 0x57, flags: 0x0},
-	603:  {region: 0x165, script: 0x57, flags: 0x0},
-	604:  {region: 0x165, script: 0x57, flags: 0x0},
-	605:  {region: 0x165, script: 0x57, flags: 0x0},
-	606:  {region: 0x165, script: 0x57, flags: 0x0},
-	607:  {region: 0x165, script: 0x57, flags: 0x0},
-	608:  {region: 0x165, script: 0x57, flags: 0x0},
-	609:  {region: 0x165, script: 0x57, flags: 0x0},
-	610:  {region: 0x165, script: 0x29, flags: 0x0},
-	611:  {region: 0x165, script: 0x57, flags: 0x0},
-	612:  {region: 0x106, script: 0x1f, flags: 0x0},
-	613:  {region: 0x112, script: 0x57, flags: 0x0},
-	614:  {region: 0xe7, script: 0x57, flags: 0x0},
-	615:  {region: 0x106, script: 0x57, flags: 0x0},
-	616:  {region: 0x165, script: 0x57, flags: 0x0},
-	617:  {region: 0x99, script: 0x21, flags: 0x0},
-	618:  {region: 0x99, script: 0x5, flags: 0x0},
-	619:  {region: 0x12f, script: 0x57, flags: 0x0},
-	620:  {region: 0x165, script: 0x57, flags: 0x0},
-	621:  {region: 0x52, script: 0x57, flags: 0x0},
-	622:  {region: 0x60, script: 0x57, flags: 0x0},
-	623:  {region: 0x165, script: 0x57, flags: 0x0},
-	624:  {region: 0x165, script: 0x57, flags: 0x0},
-	625:  {region: 0x165, script: 0x29, flags: 0x0},
-	626:  {region: 0x165, script: 0x57, flags: 0x0},
-	627:  {region: 0x165, script: 0x57, flags: 0x0},
-	628:  {region: 0x19, script: 0x3, flags: 0x1},
-	629:  {region: 0x165, script: 0x57, flags: 0x0},
-	630:  {region: 0x165, script: 0x57, flags: 0x0},
-	631:  {region: 0x165, script: 0x57, flags: 0x0},
-	632:  {region: 0x165, script: 0x57, flags: 0x0},
-	633:  {region: 0x106, script: 0x1f, flags: 0x0},
-	634:  {region: 0x165, script: 0x57, flags: 0x0},
-	635:  {region: 0x165, script: 0x57, flags: 0x0},
-	636:  {region: 0x165, script: 0x57, flags: 0x0},
-	637:  {region: 0x106, script: 0x1f, flags: 0x0},
-	638:  {region: 0x165, script: 0x57, flags: 0x0},
-	639:  {region: 0x95, script: 0x57, flags: 0x0},
-	640:  {region: 0xe8, script: 0x5, flags: 0x0},
-	641:  {region: 0x7b, script: 0x57, flags: 0x0},
-	642:  {region: 0x165, script: 0x57, flags: 0x0},
-	643:  {region: 0x165, script: 0x57, flags: 0x0},
-	644:  {region: 0x165, script: 0x57, flags: 0x0},
-	645:  {region: 0x165, script: 0x29, flags: 0x0},
-	646:  {region: 0x123, script: 0xdf, flags: 0x0},
-	647:  {region: 0xe8, script: 0x5, flags: 0x0},
-	648:  {region: 0x165, script: 0x57, flags: 0x0},
-	649:  {region: 0x165, script: 0x57, flags: 0x0},
-	650:  {region: 0x1c, script: 0x5, flags: 0x1},
-	651:  {region: 0x165, script: 0x57, flags: 0x0},
-	652:  {region: 0x165, script: 0x57, flags: 0x0},
-	653:  {region: 0x165, script: 0x57, flags: 0x0},
-	654:  {region: 0x138, script: 0x57, flags: 0x0},
-	655:  {region: 0x87, script: 0x5b, flags: 0x0},
-	656:  {region: 0x97, script: 0x3b, flags: 0x0},
-	657:  {region: 0x12f, script: 0x57, flags: 0x0},
-	658:  {region: 0xe8, script: 0x5, flags: 0x0},
-	659:  {region: 0x131, script: 0x57, flags: 0x0},
-	660:  {region: 0x165, script: 0x57, flags: 0x0},
-	661:  {region: 0xb7, script: 0x57, flags: 0x0},
-	662:  {region: 0x106, script: 0x1f, flags: 0x0},
-	663:  {region: 0x165, script: 0x57, flags: 0x0},
-	664:  {region: 0x95, script: 0x57, flags: 0x0},
-	665:  {region: 0x165, script: 0x57, flags: 0x0},
-	666:  {region: 0x53, script: 0xdf, flags: 0x0},
-	667:  {region: 0x165, script: 0x57, flags: 0x0},
-	668:  {region: 0x165, script: 0x57, flags: 0x0},
-	669:  {region: 0x165, script: 0x57, flags: 0x0},
-	670:  {region: 0x165, script: 0x57, flags: 0x0},
-	671:  {region: 0x99, script: 0x59, flags: 0x0},
-	672:  {region: 0x165, script: 0x57, flags: 0x0},
-	673:  {region: 0x165, script: 0x57, flags: 0x0},
-	674:  {region: 0x106, script: 0x1f, flags: 0x0},
-	675:  {region: 0x131, script: 0x57, flags: 0x0},
-	676:  {region: 0x165, script: 0x57, flags: 0x0},
-	677:  {region: 0xd9, script: 0x57, flags: 0x0},
-	678:  {region: 0x165, script: 0x57, flags: 0x0},
-	679:  {region: 0x165, script: 0x57, flags: 0x0},
-	680:  {region: 0x21, script: 0x2, flags: 0x1},
-	681:  {region: 0x165, script: 0x57, flags: 0x0},
-	682:  {region: 0x165, script: 0x57, flags: 0x0},
-	683:  {region: 0x9e, script: 0x57, flags: 0x0},
-	684:  {region: 0x53, script: 0x5d, flags: 0x0},
-	685:  {region: 0x95, script: 0x57, flags: 0x0},
-	686:  {region: 0x9c, script: 0x5, flags: 0x0},
-	687:  {region: 0x135, script: 0x57, flags: 0x0},
-	688:  {region: 0x165, script: 0x57, flags: 0x0},
-	689:  {region: 0x165, script: 0x57, flags: 0x0},
-	690:  {region: 0x99, script: 0xda, flags: 0x0},
-	691:  {region: 0x9e, script: 0x57, flags: 0x0},
-	692:  {region: 0x165, script: 0x57, flags: 0x0},
-	693:  {region: 0x4b, script: 0x57, flags: 0x0},
-	694:  {region: 0x165, script: 0x57, flags: 0x0},
-	695:  {region: 0x165, script: 0x57, flags: 0x0},
-	696:  {region: 0xaf, script: 0x54, flags: 0x0},
-	697:  {region: 0x165, script: 0x57, flags: 0x0},
-	698:  {region: 0x165, script: 0x57, flags: 0x0},
-	699:  {region: 0x4b, script: 0x57, flags: 0x0},
-	700:  {region: 0x165, script: 0x57, flags: 0x0},
-	701:  {region: 0x165, script: 0x57, flags: 0x0},
-	702:  {region: 0x162, script: 0x57, flags: 0x0},
-	703:  {region: 0x9c, script: 0x5, flags: 0x0},
-	704:  {region: 0xb6, script: 0x57, flags: 0x0},
-	705:  {region: 0xb8, script: 0x57, flags: 0x0},
-	706:  {region: 0x4b, script: 0x57, flags: 0x0},
-	707:  {region: 0x4b, script: 0x57, flags: 0x0},
-	708:  {region: 0xa4, script: 0x57, flags: 0x0},
-	709:  {region: 0xa4, script: 0x57, flags: 0x0},
-	710:  {region: 0x9c, script: 0x5, flags: 0x0},
-	711:  {region: 0xb8, script: 0x57, flags: 0x0},
-	712:  {region: 0x123, script: 0xdf, flags: 0x0},
-	713:  {region: 0x53, script: 0x38, flags: 0x0},
-	714:  {region: 0x12b, script: 0x57, flags: 0x0},
-	715:  {region: 0x95, script: 0x57, flags: 0x0},
-	716:  {region: 0x52, script: 0x57, flags: 0x0},
-	717:  {region: 0x99, script: 0x21, flags: 0x0},
-	718:  {region: 0x99, script: 0x21, flags: 0x0},
-	719:  {region: 0x95, script: 0x57, flags: 0x0},
-	720:  {region: 0x23, script: 0x3, flags: 0x1},
-	721:  {region: 0xa4, script: 0x57, flags: 0x0},
-	722:  {region: 0x165, script: 0x57, flags: 0x0},
-	723:  {region: 0xcf, script: 0x57, flags: 0x0},
-	724:  {region: 0x165, script: 0x57, flags: 0x0},
-	725:  {region: 0x165, script: 0x57, flags: 0x0},
-	726:  {region: 0x165, script: 0x57, flags: 0x0},
-	727:  {region: 0x165, script: 0x57, flags: 0x0},
-	728:  {region: 0x165, script: 0x57, flags: 0x0},
-	729:  {region: 0x165, script: 0x57, flags: 0x0},
-	730:  {region: 0x165, script: 0x57, flags: 0x0},
-	731:  {region: 0x165, script: 0x57, flags: 0x0},
-	732:  {region: 0x165, script: 0x57, flags: 0x0},
-	733:  {region: 0x165, script: 0x57, flags: 0x0},
-	734:  {region: 0x165, script: 0x57, flags: 0x0},
-	735:  {region: 0x165, script: 0x5, flags: 0x0},
-	736:  {region: 0x106, script: 0x1f, flags: 0x0},
-	737:  {region: 0xe7, script: 0x57, flags: 0x0},
-	738:  {region: 0x165, script: 0x57, flags: 0x0},
-	739:  {region: 0x95, script: 0x57, flags: 0x0},
-	740:  {region: 0x165, script: 0x29, flags: 0x0},
-	741:  {region: 0x165, script: 0x57, flags: 0x0},
-	742:  {region: 0x165, script: 0x57, flags: 0x0},
-	743:  {region: 0x165, script: 0x57, flags: 0x0},
-	744:  {region: 0x112, script: 0x57, flags: 0x0},
-	745:  {region: 0xa4, script: 0x57, flags: 0x0},
-	746:  {region: 0x165, script: 0x57, flags: 0x0},
-	747:  {region: 0x165, script: 0x57, flags: 0x0},
-	748:  {region: 0x123, script: 0x5, flags: 0x0},
-	749:  {region: 0xcc, script: 0x57, flags: 0x0},
-	750:  {region: 0x165, script: 0x57, flags: 0x0},
-	751:  {region: 0x165, script: 0x57, flags: 0x0},
-	752:  {region: 0x165, script: 0x57, flags: 0x0},
-	753:  {region: 0xbf, script: 0x57, flags: 0x0},
-	754:  {region: 0xd1, script: 0x57, flags: 0x0},
-	755:  {region: 0x165, script: 0x57, flags: 0x0},
-	756:  {region: 0x52, script: 0x57, flags: 0x0},
-	757:  {region: 0xdb, script: 0x21, flags: 0x0},
-	758:  {region: 0x12f, script: 0x57, flags: 0x0},
-	759:  {region: 0xc0, script: 0x57, flags: 0x0},
-	760:  {region: 0x165, script: 0x57, flags: 0x0},
-	761:  {region: 0x165, script: 0x57, flags: 0x0},
-	762:  {region: 0xe0, script: 0x57, flags: 0x0},
-	763:  {region: 0x165, script: 0x57, flags: 0x0},
-	764:  {region: 0x95, script: 0x57, flags: 0x0},
-	765:  {region: 0x9b, script: 0x3a, flags: 0x0},
-	766:  {region: 0x165, script: 0x57, flags: 0x0},
-	767:  {region: 0xc2, script: 0x1f, flags: 0x0},
-	768:  {region: 0x165, script: 0x5, flags: 0x0},
-	769:  {region: 0x165, script: 0x57, flags: 0x0},
-	770:  {region: 0x165, script: 0x57, flags: 0x0},
-	771:  {region: 0x165, script: 0x57, flags: 0x0},
-	772:  {region: 0x99, script: 0x6b, flags: 0x0},
-	773:  {region: 0x165, script: 0x57, flags: 0x0},
-	774:  {region: 0x165, script: 0x57, flags: 0x0},
-	775:  {region: 0x10b, script: 0x57, flags: 0x0},
-	776:  {region: 0x165, script: 0x57, flags: 0x0},
-	777:  {region: 0x165, script: 0x57, flags: 0x0},
-	778:  {region: 0x165, script: 0x57, flags: 0x0},
-	779:  {region: 0x26, script: 0x3, flags: 0x1},
-	780:  {region: 0x165, script: 0x57, flags: 0x0},
-	781:  {region: 0x165, script: 0x57, flags: 0x0},
-	782:  {region: 0x99, script: 0xe, flags: 0x0},
-	783:  {region: 0xc4, script: 0x72, flags: 0x0},
-	785:  {region: 0x165, script: 0x57, flags: 0x0},
-	786:  {region: 0x49, script: 0x57, flags: 0x0},
-	787:  {region: 0x49, script: 0x57, flags: 0x0},
-	788:  {region: 0x37, script: 0x57, flags: 0x0},
-	789:  {region: 0x165, script: 0x57, flags: 0x0},
-	790:  {region: 0x165, script: 0x57, flags: 0x0},
-	791:  {region: 0x165, script: 0x57, flags: 0x0},
-	792:  {region: 0x165, script: 0x57, flags: 0x0},
-	793:  {region: 0x165, script: 0x57, flags: 0x0},
-	794:  {region: 0x165, script: 0x57, flags: 0x0},
-	795:  {region: 0x99, script: 0x21, flags: 0x0},
-	796:  {region: 0xdb, script: 0x21, flags: 0x0},
-	797:  {region: 0x106, script: 0x1f, flags: 0x0},
-	798:  {region: 0x35, script: 0x6f, flags: 0x0},
-	799:  {region: 0x29, script: 0x3, flags: 0x1},
-	800:  {region: 0xcb, script: 0x57, flags: 0x0},
-	801:  {region: 0x165, script: 0x57, flags: 0x0},
-	802:  {region: 0x165, script: 0x57, flags: 0x0},
-	803:  {region: 0x165, script: 0x57, flags: 0x0},
-	804:  {region: 0x99, script: 0x21, flags: 0x0},
-	805:  {region: 0x52, script: 0x57, flags: 0x0},
-	807:  {region: 0x165, script: 0x57, flags: 0x0},
-	808:  {region: 0x135, script: 0x57, flags: 0x0},
-	809:  {region: 0x165, script: 0x57, flags: 0x0},
-	810:  {region: 0x165, script: 0x57, flags: 0x0},
-	811:  {region: 0xe8, script: 0x5, flags: 0x0},
-	812:  {region: 0xc3, script: 0x57, flags: 0x0},
-	813:  {region: 0x99, script: 0x21, flags: 0x0},
-	814:  {region: 0x95, script: 0x57, flags: 0x0},
-	815:  {region: 0x164, script: 0x57, flags: 0x0},
-	816:  {region: 0x165, script: 0x57, flags: 0x0},
-	817:  {region: 0xc4, script: 0x72, flags: 0x0},
-	818:  {region: 0x165, script: 0x57, flags: 0x0},
-	819:  {region: 0x165, script: 0x29, flags: 0x0},
-	820:  {region: 0x106, script: 0x1f, flags: 0x0},
-	821:  {region: 0x165, script: 0x57, flags: 0x0},
-	822:  {region: 0x131, script: 0x57, flags: 0x0},
-	823:  {region: 0x9c, script: 0x63, flags: 0x0},
-	824:  {region: 0x165, script: 0x57, flags: 0x0},
-	825:  {region: 0x165, script: 0x57, flags: 0x0},
-	826:  {region: 0x9c, script: 0x5, flags: 0x0},
-	827:  {region: 0x165, script: 0x57, flags: 0x0},
-	828:  {region: 0x165, script: 0x57, flags: 0x0},
-	829:  {region: 0x165, script: 0x57, flags: 0x0},
-	830:  {region: 0xdd, script: 0x57, flags: 0x0},
-	831:  {region: 0x165, script: 0x57, flags: 0x0},
-	832:  {region: 0x165, script: 0x57, flags: 0x0},
-	834:  {region: 0x165, script: 0x57, flags: 0x0},
-	835:  {region: 0x53, script: 0x38, flags: 0x0},
-	836:  {region: 0x9e, script: 0x57, flags: 0x0},
-	837:  {region: 0xd2, script: 0x57, flags: 0x0},
-	838:  {region: 0x165, script: 0x57, flags: 0x0},
-	839:  {region: 0xda, script: 0x57, flags: 0x0},
-	840:  {region: 0x165, script: 0x57, flags: 0x0},
-	841:  {region: 0x165, script: 0x57, flags: 0x0},
-	842:  {region: 0x165, script: 0x57, flags: 0x0},
-	843:  {region: 0xcf, script: 0x57, flags: 0x0},
-	844:  {region: 0x165, script: 0x57, flags: 0x0},
-	845:  {region: 0x165, script: 0x57, flags: 0x0},
-	846:  {region: 0x164, script: 0x57, flags: 0x0},
-	847:  {region: 0xd1, script: 0x57, flags: 0x0},
-	848:  {region: 0x60, script: 0x57, flags: 0x0},
-	849:  {region: 0xdb, script: 0x21, flags: 0x0},
-	850:  {region: 0x165, script: 0x57, flags: 0x0},
-	851:  {region: 0xdb, script: 0x21, flags: 0x0},
-	852:  {region: 0x165, script: 0x57, flags: 0x0},
-	853:  {region: 0x165, script: 0x57, flags: 0x0},
-	854:  {region: 0xd2, script: 0x57, flags: 0x0},
-	855:  {region: 0x165, script: 0x57, flags: 0x0},
-	856:  {region: 0x165, script: 0x57, flags: 0x0},
-	857:  {region: 0xd1, script: 0x57, flags: 0x0},
-	858:  {region: 0x165, script: 0x57, flags: 0x0},
-	859:  {region: 0xcf, script: 0x57, flags: 0x0},
-	860:  {region: 0xcf, script: 0x57, flags: 0x0},
-	861:  {region: 0x165, script: 0x57, flags: 0x0},
-	862:  {region: 0x165, script: 0x57, flags: 0x0},
-	863:  {region: 0x95, script: 0x57, flags: 0x0},
-	864:  {region: 0x165, script: 0x57, flags: 0x0},
-	865:  {region: 0xdf, script: 0x57, flags: 0x0},
-	866:  {region: 0x165, script: 0x57, flags: 0x0},
-	867:  {region: 0x165, script: 0x57, flags: 0x0},
-	868:  {region: 0x99, script: 0x57, flags: 0x0},
-	869:  {region: 0x165, script: 0x57, flags: 0x0},
-	870:  {region: 0x165, script: 0x57, flags: 0x0},
-	871:  {region: 0xd9, script: 0x57, flags: 0x0},
-	872:  {region: 0x52, script: 0x57, flags: 0x0},
-	873:  {region: 0x165, script: 0x57, flags: 0x0},
-	874:  {region: 0xda, script: 0x57, flags: 0x0},
-	875:  {region: 0x165, script: 0x57, flags: 0x0},
-	876:  {region: 0x52, script: 0x57, flags: 0x0},
-	877:  {region: 0x165, script: 0x57, flags: 0x0},
-	878:  {region: 0x165, script: 0x57, flags: 0x0},
-	879:  {region: 0xda, script: 0x57, flags: 0x0},
-	880:  {region: 0x123, script: 0x53, flags: 0x0},
-	881:  {region: 0x99, script: 0x21, flags: 0x0},
-	882:  {region: 0x10c, script: 0xbf, flags: 0x0},
-	883:  {region: 0x165, script: 0x57, flags: 0x0},
-	884:  {region: 0x165, script: 0x57, flags: 0x0},
-	885:  {region: 0x84, script: 0x78, flags: 0x0},
-	886:  {region: 0x161, script: 0x57, flags: 0x0},
-	887:  {region: 0x165, script: 0x57, flags: 0x0},
-	888:  {region: 0x49, script: 0x17, flags: 0x0},
-	889:  {region: 0x165, script: 0x57, flags: 0x0},
-	890:  {region: 0x161, script: 0x57, flags: 0x0},
-	891:  {region: 0x165, script: 0x57, flags: 0x0},
-	892:  {region: 0x165, script: 0x57, flags: 0x0},
-	893:  {region: 0x165, script: 0x57, flags: 0x0},
-	894:  {region: 0x165, script: 0x57, flags: 0x0},
-	895:  {region: 0x165, script: 0x57, flags: 0x0},
-	896:  {region: 0x117, script: 0x57, flags: 0x0},
-	897:  {region: 0x165, script: 0x57, flags: 0x0},
-	898:  {region: 0x165, script: 0x57, flags: 0x0},
-	899:  {region: 0x135, script: 0x57, flags: 0x0},
-	900:  {region: 0x165, script: 0x57, flags: 0x0},
-	901:  {region: 0x53, script: 0x57, flags: 0x0},
-	902:  {region: 0x165, script: 0x57, flags: 0x0},
-	903:  {region: 0xce, script: 0x57, flags: 0x0},
-	904:  {region: 0x12f, script: 0x57, flags: 0x0},
-	905:  {region: 0x131, script: 0x57, flags: 0x0},
-	906:  {region: 0x80, script: 0x57, flags: 0x0},
-	907:  {region: 0x78, script: 0x57, flags: 0x0},
-	908:  {region: 0x165, script: 0x57, flags: 0x0},
-	910:  {region: 0x165, script: 0x57, flags: 0x0},
-	911:  {region: 0x165, script: 0x57, flags: 0x0},
-	912:  {region: 0x6f, script: 0x57, flags: 0x0},
-	913:  {region: 0x165, script: 0x57, flags: 0x0},
-	914:  {region: 0x165, script: 0x57, flags: 0x0},
-	915:  {region: 0x165, script: 0x57, flags: 0x0},
-	916:  {region: 0x165, script: 0x57, flags: 0x0},
-	917:  {region: 0x99, script: 0x7d, flags: 0x0},
-	918:  {region: 0x165, script: 0x57, flags: 0x0},
-	919:  {region: 0x165, script: 0x5, flags: 0x0},
-	920:  {region: 0x7d, script: 0x1f, flags: 0x0},
-	921:  {region: 0x135, script: 0x7e, flags: 0x0},
-	922:  {region: 0x165, script: 0x5, flags: 0x0},
-	923:  {region: 0xc5, script: 0x7c, flags: 0x0},
-	924:  {region: 0x165, script: 0x57, flags: 0x0},
-	925:  {region: 0x2c, script: 0x3, flags: 0x1},
-	926:  {region: 0xe7, script: 0x57, flags: 0x0},
-	927:  {region: 0x2f, script: 0x2, flags: 0x1},
-	928:  {region: 0xe7, script: 0x57, flags: 0x0},
-	929:  {region: 0x30, script: 0x57, flags: 0x0},
-	930:  {region: 0xf0, script: 0x57, flags: 0x0},
-	931:  {region: 0x165, script: 0x57, flags: 0x0},
-	932:  {region: 0x78, script: 0x57, flags: 0x0},
-	933:  {region: 0xd6, script: 0x57, flags: 0x0},
-	934:  {region: 0x135, script: 0x57, flags: 0x0},
-	935:  {region: 0x49, script: 0x57, flags: 0x0},
-	936:  {region: 0x165, script: 0x57, flags: 0x0},
-	937:  {region: 0x9c, script: 0xe8, flags: 0x0},
-	938:  {region: 0x165, script: 0x57, flags: 0x0},
-	939:  {region: 0x60, script: 0x57, flags: 0x0},
-	940:  {region: 0x165, script: 0x5, flags: 0x0},
-	941:  {region: 0xb0, script: 0x87, flags: 0x0},
-	943:  {region: 0x165, script: 0x57, flags: 0x0},
-	944:  {region: 0x165, script: 0x57, flags: 0x0},
-	945:  {region: 0x99, script: 0x12, flags: 0x0},
-	946:  {region: 0xa4, script: 0x57, flags: 0x0},
-	947:  {region: 0xe9, script: 0x57, flags: 0x0},
-	948:  {region: 0x165, script: 0x57, flags: 0x0},
-	949:  {region: 0x9e, script: 0x57, flags: 0x0},
-	950:  {region: 0x165, script: 0x57, flags: 0x0},
-	951:  {region: 0x165, script: 0x57, flags: 0x0},
-	952:  {region: 0x87, script: 0x31, flags: 0x0},
-	953:  {region: 0x75, script: 0x57, flags: 0x0},
-	954:  {region: 0x165, script: 0x57, flags: 0x0},
-	955:  {region: 0xe8, script: 0x4a, flags: 0x0},
-	956:  {region: 0x9c, script: 0x5, flags: 0x0},
-	957:  {region: 0x1, script: 0x57, flags: 0x0},
-	958:  {region: 0x24, script: 0x5, flags: 0x0},
-	959:  {region: 0x165, script: 0x57, flags: 0x0},
-	960:  {region: 0x41, script: 0x57, flags: 0x0},
-	961:  {region: 0x165, script: 0x57, flags: 0x0},
-	962:  {region: 0x7a, script: 0x57, flags: 0x0},
-	963:  {region: 0x165, script: 0x57, flags: 0x0},
-	964:  {region: 0xe4, script: 0x57, flags: 0x0},
-	965:  {region: 0x89, script: 0x57, flags: 0x0},
-	966:  {region: 0x69, script: 0x57, flags: 0x0},
-	967:  {region: 0x165, script: 0x57, flags: 0x0},
-	968:  {region: 0x99, script: 0x21, flags: 0x0},
-	969:  {region: 0x165, script: 0x57, flags: 0x0},
-	970:  {region: 0x102, script: 0x57, flags: 0x0},
-	971:  {region: 0x95, script: 0x57, flags: 0x0},
-	972:  {region: 0x165, script: 0x57, flags: 0x0},
-	973:  {region: 0x165, script: 0x57, flags: 0x0},
-	974:  {region: 0x9e, script: 0x57, flags: 0x0},
-	975:  {region: 0x165, script: 0x5, flags: 0x0},
-	976:  {region: 0x99, script: 0x57, flags: 0x0},
-	977:  {region: 0x31, script: 0x2, flags: 0x1},
-	978:  {region: 0xdb, script: 0x21, flags: 0x0},
-	979:  {region: 0x35, script: 0xe, flags: 0x0},
-	980:  {region: 0x4e, script: 0x57, flags: 0x0},
-	981:  {region: 0x72, script: 0x57, flags: 0x0},
-	982:  {region: 0x4e, script: 0x57, flags: 0x0},
-	983:  {region: 0x9c, script: 0x5, flags: 0x0},
-	984:  {region: 0x10c, script: 0x57, flags: 0x0},
-	985:  {region: 0x3a, script: 0x57, flags: 0x0},
-	986:  {region: 0x165, script: 0x57, flags: 0x0},
-	987:  {region: 0xd1, script: 0x57, flags: 0x0},
-	988:  {region: 0x104, script: 0x57, flags: 0x0},
-	989:  {region: 0x95, script: 0x57, flags: 0x0},
-	990:  {region: 0x12f, script: 0x57, flags: 0x0},
-	991:  {region: 0x165, script: 0x57, flags: 0x0},
-	992:  {region: 0x165, script: 0x57, flags: 0x0},
-	993:  {region: 0x73, script: 0x57, flags: 0x0},
-	994:  {region: 0x106, script: 0x1f, flags: 0x0},
-	995:  {region: 0x130, script: 0x1f, flags: 0x0},
-	996:  {region: 0x109, script: 0x57, flags: 0x0},
-	997:  {region: 0x107, script: 0x57, flags: 0x0},
-	998:  {region: 0x12f, script: 0x57, flags: 0x0},
-	999:  {region: 0x165, script: 0x57, flags: 0x0},
-	1000: {region: 0xa2, script: 0x49, flags: 0x0},
-	1001: {region: 0x99, script: 0x21, flags: 0x0},
-	1002: {region: 0x80, script: 0x57, flags: 0x0},
-	1003: {region: 0x106, script: 0x1f, flags: 0x0},
-	1004: {region: 0xa4, script: 0x57, flags: 0x0},
-	1005: {region: 0x95, script: 0x57, flags: 0x0},
-	1006: {region: 0x99, script: 0x57, flags: 0x0},
-	1007: {region: 0x114, script: 0x57, flags: 0x0},
-	1008: {region: 0x99, script: 0xc3, flags: 0x0},
-	1009: {region: 0x165, script: 0x57, flags: 0x0},
-	1010: {region: 0x165, script: 0x57, flags: 0x0},
-	1011: {region: 0x12f, script: 0x57, flags: 0x0},
-	1012: {region: 0x9e, script: 0x57, flags: 0x0},
-	1013: {region: 0x99, script: 0x21, flags: 0x0},
-	1014: {region: 0x165, script: 0x5, flags: 0x0},
-	1015: {region: 0x9e, script: 0x57, flags: 0x0},
-	1016: {region: 0x7b, script: 0x57, flags: 0x0},
-	1017: {region: 0x49, script: 0x57, flags: 0x0},
-	1018: {region: 0x33, script: 0x4, flags: 0x1},
-	1019: {region: 0x9e, script: 0x57, flags: 0x0},
-	1020: {region: 0x9c, script: 0x5, flags: 0x0},
-	1021: {region: 0xda, script: 0x57, flags: 0x0},
-	1022: {region: 0x4f, script: 0x57, flags: 0x0},
-	1023: {region: 0xd1, script: 0x57, flags: 0x0},
-	1024: {region: 0xcf, script: 0x57, flags: 0x0},
-	1025: {region: 0xc3, script: 0x57, flags: 0x0},
-	1026: {region: 0x4c, script: 0x57, flags: 0x0},
-	1027: {region: 0x96, script: 0x7a, flags: 0x0},
-	1028: {region: 0xb6, script: 0x57, flags: 0x0},
-	1029: {region: 0x165, script: 0x29, flags: 0x0},
-	1030: {region: 0x165, script: 0x57, flags: 0x0},
-	1032: {region: 0xba, script: 0xdc, flags: 0x0},
-	1033: {region: 0x165, script: 0x57, flags: 0x0},
-	1034: {region: 0xc4, script: 0x72, flags: 0x0},
-	1035: {region: 0x165, script: 0x5, flags: 0x0},
-	1036: {region: 0xb3, script: 0xca, flags: 0x0},
-	1037: {region: 0x6f, script: 0x57, flags: 0x0},
-	1038: {region: 0x165, script: 0x57, flags: 0x0},
-	1039: {region: 0x165, script: 0x57, flags: 0x0},
-	1040: {region: 0x165, script: 0x57, flags: 0x0},
-	1041: {region: 0x165, script: 0x57, flags: 0x0},
-	1042: {region: 0x111, script: 0x57, flags: 0x0},
-	1043: {region: 0x165, script: 0x57, flags: 0x0},
-	1044: {region: 0xe8, script: 0x5, flags: 0x0},
-	1045: {region: 0x165, script: 0x57, flags: 0x0},
-	1046: {region: 0x10f, script: 0x57, flags: 0x0},
-	1047: {region: 0x165, script: 0x57, flags: 0x0},
-	1048: {region: 0xe9, script: 0x57, flags: 0x0},
-	1049: {region: 0x165, script: 0x57, flags: 0x0},
-	1050: {region: 0x95, script: 0x57, flags: 0x0},
-	1051: {region: 0x142, script: 0x57, flags: 0x0},
-	1052: {region: 0x10c, script: 0x57, flags: 0x0},
-	1054: {region: 0x10c, script: 0x57, flags: 0x0},
-	1055: {region: 0x72, script: 0x57, flags: 0x0},
-	1056: {region: 0x97, script: 0xc0, flags: 0x0},
-	1057: {region: 0x165, script: 0x57, flags: 0x0},
-	1058: {region: 0x72, script: 0x57, flags: 0x0},
-	1059: {region: 0x164, script: 0x57, flags: 0x0},
-	1060: {region: 0x165, script: 0x57, flags: 0x0},
-	1061: {region: 0xc3, script: 0x57, flags: 0x0},
-	1062: {region: 0x165, script: 0x57, flags: 0x0},
-	1063: {region: 0x165, script: 0x57, flags: 0x0},
-	1064: {region: 0x165, script: 0x57, flags: 0x0},
-	1065: {region: 0x115, script: 0x57, flags: 0x0},
-	1066: {region: 0x165, script: 0x57, flags: 0x0},
-	1067: {region: 0x165, script: 0x57, flags: 0x0},
-	1068: {region: 0x123, script: 0xdf, flags: 0x0},
-	1069: {region: 0x165, script: 0x57, flags: 0x0},
-	1070: {region: 0x165, script: 0x57, flags: 0x0},
-	1071: {region: 0x165, script: 0x57, flags: 0x0},
-	1072: {region: 0x165, script: 0x57, flags: 0x0},
-	1073: {region: 0x27, script: 0x57, flags: 0x0},
-	1074: {region: 0x37, script: 0x5, flags: 0x1},
-	1075: {region: 0x99, script: 0xcb, flags: 0x0},
-	1076: {region: 0x116, script: 0x57, flags: 0x0},
-	1077: {region: 0x114, script: 0x57, flags: 0x0},
-	1078: {region: 0x99, script: 0x21, flags: 0x0},
-	1079: {region: 0x161, script: 0x57, flags: 0x0},
-	1080: {region: 0x165, script: 0x57, flags: 0x0},
-	1081: {region: 0x165, script: 0x57, flags: 0x0},
-	1082: {region: 0x6d, script: 0x57, flags: 0x0},
-	1083: {region: 0x161, script: 0x57, flags: 0x0},
-	1084: {region: 0x165, script: 0x57, flags: 0x0},
-	1085: {region: 0x60, script: 0x57, flags: 0x0},
-	1086: {region: 0x95, script: 0x57, flags: 0x0},
-	1087: {region: 0x165, script: 0x57, flags: 0x0},
-	1088: {region: 0x165, script: 0x57, flags: 0x0},
-	1089: {region: 0x12f, script: 0x57, flags: 0x0},
-	1090: {region: 0x165, script: 0x57, flags: 0x0},
-	1091: {region: 0x84, script: 0x57, flags: 0x0},
-	1092: {region: 0x10c, script: 0x57, flags: 0x0},
-	1093: {region: 0x12f, script: 0x57, flags: 0x0},
-	1094: {region: 0x15f, script: 0x5, flags: 0x0},
-	1095: {region: 0x4b, script: 0x57, flags: 0x0},
-	1096: {region: 0x60, script: 0x57, flags: 0x0},
-	1097: {region: 0x165, script: 0x57, flags: 0x0},
-	1098: {region: 0x99, script: 0x21, flags: 0x0},
-	1099: {region: 0x95, script: 0x57, flags: 0x0},
-	1100: {region: 0x165, script: 0x57, flags: 0x0},
-	1101: {region: 0x35, script: 0xe, flags: 0x0},
-	1102: {region: 0x9b, script: 0xcf, flags: 0x0},
-	1103: {region: 0xe9, script: 0x57, flags: 0x0},
-	1104: {region: 0x99, script: 0xd7, flags: 0x0},
-	1105: {region: 0xdb, script: 0x21, flags: 0x0},
-	1106: {region: 0x165, script: 0x57, flags: 0x0},
-	1107: {region: 0x165, script: 0x57, flags: 0x0},
-	1108: {region: 0x165, script: 0x57, flags: 0x0},
-	1109: {region: 0x165, script: 0x57, flags: 0x0},
-	1110: {region: 0x165, script: 0x57, flags: 0x0},
-	1111: {region: 0x165, script: 0x57, flags: 0x0},
-	1112: {region: 0x165, script: 0x57, flags: 0x0},
-	1113: {region: 0x165, script: 0x57, flags: 0x0},
-	1114: {region: 0xe7, script: 0x57, flags: 0x0},
-	1115: {region: 0x165, script: 0x57, flags: 0x0},
-	1116: {region: 0x165, script: 0x57, flags: 0x0},
-	1117: {region: 0x99, script: 0x4f, flags: 0x0},
-	1118: {region: 0x53, script: 0xd5, flags: 0x0},
-	1119: {region: 0xdb, script: 0x21, flags: 0x0},
-	1120: {region: 0xdb, script: 0x21, flags: 0x0},
-	1121: {region: 0x99, script: 0xda, flags: 0x0},
-	1122: {region: 0x165, script: 0x57, flags: 0x0},
-	1123: {region: 0x112, script: 0x57, flags: 0x0},
-	1124: {region: 0x131, script: 0x57, flags: 0x0},
-	1125: {region: 0x126, script: 0x57, flags: 0x0},
-	1126: {region: 0x165, script: 0x57, flags: 0x0},
-	1127: {region: 0x3c, script: 0x3, flags: 0x1},
-	1128: {region: 0x165, script: 0x57, flags: 0x0},
-	1129: {region: 0x165, script: 0x57, flags: 0x0},
-	1130: {region: 0x165, script: 0x57, flags: 0x0},
-	1131: {region: 0x123, script: 0xdf, flags: 0x0},
-	1132: {region: 0xdb, script: 0x21, flags: 0x0},
-	1133: {region: 0xdb, script: 0x21, flags: 0x0},
-	1134: {region: 0xdb, script: 0x21, flags: 0x0},
-	1135: {region: 0x6f, script: 0x29, flags: 0x0},
-	1136: {region: 0x165, script: 0x57, flags: 0x0},
-	1137: {region: 0x6d, script: 0x29, flags: 0x0},
-	1138: {region: 0x165, script: 0x57, flags: 0x0},
-	1139: {region: 0x165, script: 0x57, flags: 0x0},
-	1140: {region: 0x165, script: 0x57, flags: 0x0},
-	1141: {region: 0xd6, script: 0x57, flags: 0x0},
-	1142: {region: 0x127, script: 0x57, flags: 0x0},
-	1143: {region: 0x125, script: 0x57, flags: 0x0},
-	1144: {region: 0x32, script: 0x57, flags: 0x0},
-	1145: {region: 0xdb, script: 0x21, flags: 0x0},
-	1146: {region: 0xe7, script: 0x57, flags: 0x0},
-	1147: {region: 0x165, script: 0x57, flags: 0x0},
-	1148: {region: 0x165, script: 0x57, flags: 0x0},
-	1149: {region: 0x32, script: 0x57, flags: 0x0},
-	1150: {region: 0xd4, script: 0x57, flags: 0x0},
-	1151: {region: 0x165, script: 0x57, flags: 0x0},
-	1152: {region: 0x161, script: 0x57, flags: 0x0},
-	1153: {region: 0x165, script: 0x57, flags: 0x0},
-	1154: {region: 0x129, script: 0x57, flags: 0x0},
-	1155: {region: 0x165, script: 0x57, flags: 0x0},
-	1156: {region: 0xce, script: 0x57, flags: 0x0},
-	1157: {region: 0x165, script: 0x57, flags: 0x0},
-	1158: {region: 0xe6, script: 0x57, flags: 0x0},
-	1159: {region: 0x165, script: 0x57, flags: 0x0},
-	1160: {region: 0x165, script: 0x57, flags: 0x0},
-	1161: {region: 0x165, script: 0x57, flags: 0x0},
-	1162: {region: 0x12b, script: 0x57, flags: 0x0},
-	1163: {region: 0x12b, script: 0x57, flags: 0x0},
-	1164: {region: 0x12e, script: 0x57, flags: 0x0},
-	1165: {region: 0x165, script: 0x5, flags: 0x0},
-	1166: {region: 0x161, script: 0x57, flags: 0x0},
-	1167: {region: 0x87, script: 0x31, flags: 0x0},
-	1168: {region: 0xdb, script: 0x21, flags: 0x0},
-	1169: {region: 0xe7, script: 0x57, flags: 0x0},
-	1170: {region: 0x43, script: 0xe0, flags: 0x0},
-	1171: {region: 0x165, script: 0x57, flags: 0x0},
-	1172: {region: 0x106, script: 0x1f, flags: 0x0},
-	1173: {region: 0x165, script: 0x57, flags: 0x0},
-	1174: {region: 0x165, script: 0x57, flags: 0x0},
-	1175: {region: 0x131, script: 0x57, flags: 0x0},
-	1176: {region: 0x165, script: 0x57, flags: 0x0},
-	1177: {region: 0x123, script: 0xdf, flags: 0x0},
-	1178: {region: 0x32, script: 0x57, flags: 0x0},
-	1179: {region: 0x165, script: 0x57, flags: 0x0},
-	1180: {region: 0x165, script: 0x57, flags: 0x0},
-	1181: {region: 0xce, script: 0x57, flags: 0x0},
-	1182: {region: 0x165, script: 0x57, flags: 0x0},
-	1183: {region: 0x165, script: 0x57, flags: 0x0},
-	1184: {region: 0x12d, script: 0x57, flags: 0x0},
-	1185: {region: 0x165, script: 0x57, flags: 0x0},
-	1187: {region: 0x165, script: 0x57, flags: 0x0},
-	1188: {region: 0xd4, script: 0x57, flags: 0x0},
-	1189: {region: 0x53, script: 0xd8, flags: 0x0},
-	1190: {region: 0xe5, script: 0x57, flags: 0x0},
-	1191: {region: 0x165, script: 0x57, flags: 0x0},
-	1192: {region: 0x106, script: 0x1f, flags: 0x0},
-	1193: {region: 0xba, script: 0x57, flags: 0x0},
-	1194: {region: 0x165, script: 0x57, flags: 0x0},
-	1195: {region: 0x106, script: 0x1f, flags: 0x0},
-	1196: {region: 0x3f, script: 0x4, flags: 0x1},
-	1197: {region: 0x11c, script: 0xe2, flags: 0x0},
-	1198: {region: 0x130, script: 0x1f, flags: 0x0},
-	1199: {region: 0x75, script: 0x57, flags: 0x0},
-	1200: {region: 0x2a, script: 0x57, flags: 0x0},
-	1202: {region: 0x43, script: 0x3, flags: 0x1},
-	1203: {region: 0x99, script: 0xe, flags: 0x0},
-	1204: {region: 0xe8, script: 0x5, flags: 0x0},
-	1205: {region: 0x165, script: 0x57, flags: 0x0},
-	1206: {region: 0x165, script: 0x57, flags: 0x0},
-	1207: {region: 0x165, script: 0x57, flags: 0x0},
-	1208: {region: 0x165, script: 0x57, flags: 0x0},
-	1209: {region: 0x165, script: 0x57, flags: 0x0},
-	1210: {region: 0x165, script: 0x57, flags: 0x0},
-	1211: {region: 0x165, script: 0x57, flags: 0x0},
-	1212: {region: 0x46, script: 0x4, flags: 0x1},
-	1213: {region: 0x165, script: 0x57, flags: 0x0},
-	1214: {region: 0xb4, script: 0xe3, flags: 0x0},
-	1215: {region: 0x165, script: 0x57, flags: 0x0},
-	1216: {region: 0x161, script: 0x57, flags: 0x0},
-	1217: {region: 0x9e, script: 0x57, flags: 0x0},
-	1218: {region: 0x106, script: 0x57, flags: 0x0},
-	1219: {region: 0x13e, script: 0x57, flags: 0x0},
-	1220: {region: 0x11b, script: 0x57, flags: 0x0},
-	1221: {region: 0x165, script: 0x57, flags: 0x0},
-	1222: {region: 0x36, script: 0x57, flags: 0x0},
-	1223: {region: 0x60, script: 0x57, flags: 0x0},
-	1224: {region: 0xd1, script: 0x57, flags: 0x0},
-	1225: {region: 0x1, script: 0x57, flags: 0x0},
-	1226: {region: 0x106, script: 0x57, flags: 0x0},
-	1227: {region: 0x6a, script: 0x57, flags: 0x0},
-	1228: {region: 0x12f, script: 0x57, flags: 0x0},
-	1229: {region: 0x165, script: 0x57, flags: 0x0},
-	1230: {region: 0x36, script: 0x57, flags: 0x0},
-	1231: {region: 0x4e, script: 0x57, flags: 0x0},
-	1232: {region: 0x165, script: 0x57, flags: 0x0},
-	1233: {region: 0x6f, script: 0x29, flags: 0x0},
-	1234: {region: 0x165, script: 0x57, flags: 0x0},
-	1235: {region: 0xe7, script: 0x57, flags: 0x0},
-	1236: {region: 0x2f, script: 0x57, flags: 0x0},
-	1237: {region: 0x99, script: 0xda, flags: 0x0},
-	1238: {region: 0x99, script: 0x21, flags: 0x0},
-	1239: {region: 0x165, script: 0x57, flags: 0x0},
-	1240: {region: 0x165, script: 0x57, flags: 0x0},
-	1241: {region: 0x165, script: 0x57, flags: 0x0},
-	1242: {region: 0x165, script: 0x57, flags: 0x0},
-	1243: {region: 0x165, script: 0x57, flags: 0x0},
-	1244: {region: 0x165, script: 0x57, flags: 0x0},
-	1245: {region: 0x165, script: 0x57, flags: 0x0},
-	1246: {region: 0x165, script: 0x57, flags: 0x0},
-	1247: {region: 0x165, script: 0x57, flags: 0x0},
-	1248: {region: 0x140, script: 0x57, flags: 0x0},
-	1249: {region: 0x165, script: 0x57, flags: 0x0},
-	1250: {region: 0x165, script: 0x57, flags: 0x0},
-	1251: {region: 0xa8, script: 0x5, flags: 0x0},
-	1252: {region: 0x165, script: 0x57, flags: 0x0},
-	1253: {region: 0x114, script: 0x57, flags: 0x0},
-	1254: {region: 0x165, script: 0x57, flags: 0x0},
-	1255: {region: 0x165, script: 0x57, flags: 0x0},
-	1256: {region: 0x165, script: 0x57, flags: 0x0},
-	1257: {region: 0x165, script: 0x57, flags: 0x0},
-	1258: {region: 0x99, script: 0x21, flags: 0x0},
-	1259: {region: 0x53, script: 0x38, flags: 0x0},
-	1260: {region: 0x165, script: 0x57, flags: 0x0},
-	1261: {region: 0x165, script: 0x57, flags: 0x0},
-	1262: {region: 0x41, script: 0x57, flags: 0x0},
-	1263: {region: 0x165, script: 0x57, flags: 0x0},
-	1264: {region: 0x12b, script: 0x18, flags: 0x0},
-	1265: {region: 0x165, script: 0x57, flags: 0x0},
-	1266: {region: 0x161, script: 0x57, flags: 0x0},
-	1267: {region: 0x165, script: 0x57, flags: 0x0},
-	1268: {region: 0x12b, script: 0x5f, flags: 0x0},
-	1269: {region: 0x12b, script: 0x60, flags: 0x0},
-	1270: {region: 0x7d, script: 0x2b, flags: 0x0},
-	1271: {region: 0x53, script: 0x64, flags: 0x0},
-	1272: {region: 0x10b, script: 0x69, flags: 0x0},
-	1273: {region: 0x108, script: 0x73, flags: 0x0},
-	1274: {region: 0x99, script: 0x21, flags: 0x0},
-	1275: {region: 0x131, script: 0x57, flags: 0x0},
-	1276: {region: 0x165, script: 0x57, flags: 0x0},
-	1277: {region: 0x9c, script: 0x8a, flags: 0x0},
-	1278: {region: 0x165, script: 0x57, flags: 0x0},
-	1279: {region: 0x15e, script: 0xc2, flags: 0x0},
-	1280: {region: 0x165, script: 0x57, flags: 0x0},
-	1281: {region: 0x165, script: 0x57, flags: 0x0},
-	1282: {region: 0xdb, script: 0x21, flags: 0x0},
-	1283: {region: 0x165, script: 0x57, flags: 0x0},
-	1284: {region: 0x165, script: 0x57, flags: 0x0},
-	1285: {region: 0xd1, script: 0x57, flags: 0x0},
-	1286: {region: 0x75, script: 0x57, flags: 0x0},
-	1287: {region: 0x165, script: 0x57, flags: 0x0},
-	1288: {region: 0x165, script: 0x57, flags: 0x0},
-	1289: {region: 0x52, script: 0x57, flags: 0x0},
-	1290: {region: 0x165, script: 0x57, flags: 0x0},
-	1291: {region: 0x165, script: 0x57, flags: 0x0},
-	1292: {region: 0x165, script: 0x57, flags: 0x0},
-	1293: {region: 0x52, script: 0x57, flags: 0x0},
-	1294: {region: 0x165, script: 0x57, flags: 0x0},
-	1295: {region: 0x165, script: 0x57, flags: 0x0},
-	1296: {region: 0x165, script: 0x57, flags: 0x0},
-	1297: {region: 0x165, script: 0x57, flags: 0x0},
-	1298: {region: 0x1, script: 0x3b, flags: 0x0},
-	1299: {region: 0x165, script: 0x57, flags: 0x0},
-	1300: {region: 0x165, script: 0x57, flags: 0x0},
-	1301: {region: 0x165, script: 0x57, flags: 0x0},
-	1302: {region: 0x165, script: 0x57, flags: 0x0},
-	1303: {region: 0x165, script: 0x57, flags: 0x0},
-	1304: {region: 0xd6, script: 0x57, flags: 0x0},
-	1305: {region: 0x165, script: 0x57, flags: 0x0},
-	1306: {region: 0x165, script: 0x57, flags: 0x0},
-	1307: {region: 0x165, script: 0x57, flags: 0x0},
-	1308: {region: 0x41, script: 0x57, flags: 0x0},
-	1309: {region: 0x165, script: 0x57, flags: 0x0},
-	1310: {region: 0xcf, script: 0x57, flags: 0x0},
-	1311: {region: 0x4a, script: 0x3, flags: 0x1},
-	1312: {region: 0x165, script: 0x57, flags: 0x0},
-	1313: {region: 0x165, script: 0x57, flags: 0x0},
-	1314: {region: 0x165, script: 0x57, flags: 0x0},
-	1315: {region: 0x53, script: 0x57, flags: 0x0},
-	1316: {region: 0x10b, script: 0x57, flags: 0x0},
-	1318: {region: 0xa8, script: 0x5, flags: 0x0},
-	1319: {region: 0xd9, script: 0x57, flags: 0x0},
-	1320: {region: 0xba, script: 0xdc, flags: 0x0},
-	1321: {region: 0x4d, script: 0x14, flags: 0x1},
-	1322: {region: 0x53, script: 0x79, flags: 0x0},
-	1323: {region: 0x165, script: 0x57, flags: 0x0},
-	1324: {region: 0x122, script: 0x57, flags: 0x0},
-	1325: {region: 0xd0, script: 0x57, flags: 0x0},
-	1326: {region: 0x165, script: 0x57, flags: 0x0},
-	1327: {region: 0x161, script: 0x57, flags: 0x0},
-	1329: {region: 0x12b, script: 0x57, flags: 0x0},
-}
-
-// likelyLangList holds lists info associated with likelyLang.
-// Size: 388 bytes, 97 elements
-var likelyLangList = [97]likelyScriptRegion{
-	0:  {region: 0x9c, script: 0x7, flags: 0x0},
-	1:  {region: 0xa1, script: 0x74, flags: 0x2},
-	2:  {region: 0x11c, script: 0x80, flags: 0x2},
-	3:  {region: 0x32, script: 0x57, flags: 0x0},
-	4:  {region: 0x9b, script: 0x5, flags: 0x4},
-	5:  {region: 0x9c, script: 0x5, flags: 0x4},
-	6:  {region: 0x106, script: 0x1f, flags: 0x4},
-	7:  {region: 0x9c, script: 0x5, flags: 0x2},
-	8:  {region: 0x106, script: 0x1f, flags: 0x0},
-	9:  {region: 0x38, script: 0x2c, flags: 0x2},
-	10: {region: 0x135, script: 0x57, flags: 0x0},
-	11: {region: 0x7b, script: 0xc5, flags: 0x2},
-	12: {region: 0x114, script: 0x57, flags: 0x0},
-	13: {region: 0x84, script: 0x1, flags: 0x2},
-	14: {region: 0x5d, script: 0x1e, flags: 0x0},
-	15: {region: 0x87, script: 0x5c, flags: 0x2},
-	16: {region: 0xd6, script: 0x57, flags: 0x0},
-	17: {region: 0x52, script: 0x5, flags: 0x4},
-	18: {region: 0x10b, script: 0x5, flags: 0x4},
-	19: {region: 0xae, script: 0x1f, flags: 0x0},
-	20: {region: 0x24, script: 0x5, flags: 0x4},
-	21: {region: 0x53, script: 0x5, flags: 0x4},
-	22: {region: 0x9c, script: 0x5, flags: 0x4},
-	23: {region: 0xc5, script: 0x5, flags: 0x4},
-	24: {region: 0x53, script: 0x5, flags: 0x2},
-	25: {region: 0x12b, script: 0x57, flags: 0x0},
-	26: {region: 0xb0, script: 0x5, flags: 0x4},
-	27: {region: 0x9b, script: 0x5, flags: 0x2},
-	28: {region: 0xa5, script: 0x1f, flags: 0x0},
-	29: {region: 0x53, script: 0x5, flags: 0x4},
-	30: {region: 0x12b, script: 0x57, flags: 0x4},
-	31: {region: 0x53, script: 0x5, flags: 0x2},
-	32: {region: 0x12b, script: 0x57, flags: 0x2},
-	33: {region: 0xdb, script: 0x21, flags: 0x0},
-	34: {region: 0x99, script: 0x5a, flags: 0x2},
-	35: {region: 0x83, script: 0x57, flags: 0x0},
-	36: {region: 0x84, script: 0x78, flags: 0x4},
-	37: {region: 0x84, script: 0x78, flags: 0x2},
-	38: {region: 0xc5, script: 0x1f, flags: 0x0},
-	39: {region: 0x53, script: 0x6d, flags: 0x4},
-	40: {region: 0x53, script: 0x6d, flags: 0x2},
-	41: {region: 0xd0, script: 0x57, flags: 0x0},
-	42: {region: 0x4a, script: 0x5, flags: 0x4},
-	43: {region: 0x95, script: 0x5, flags: 0x4},
-	44: {region: 0x99, script: 0x33, flags: 0x0},
-	45: {region: 0xe8, script: 0x5, flags: 0x4},
-	46: {region: 0xe8, script: 0x5, flags: 0x2},
-	47: {region: 0x9c, script: 0x84, flags: 0x0},
-	48: {region: 0x53, script: 0x85, flags: 0x2},
-	49: {region: 0xba, script: 0xdc, flags: 0x0},
-	50: {region: 0xd9, script: 0x57, flags: 0x4},
-	51: {region: 0xe8, script: 0x5, flags: 0x0},
-	52: {region: 0x99, script: 0x21, flags: 0x2},
-	53: {region: 0x99, script: 0x4c, flags: 0x2},
-	54: {region: 0x99, script: 0xc9, flags: 0x2},
-	55: {region: 0x105, script: 0x1f, flags: 0x0},
-	56: {region: 0xbd, script: 0x57, flags: 0x4},
-	57: {region: 0x104, script: 0x57, flags: 0x4},
-	58: {region: 0x106, script: 0x57, flags: 0x4},
-	59: {region: 0x12b, script: 0x57, flags: 0x4},
-	60: {region: 0x124, script: 0x1f, flags: 0x0},
-	61: {region: 0xe8, script: 0x5, flags: 0x4},
-	62: {region: 0xe8, script: 0x5, flags: 0x2},
-	63: {region: 0x53, script: 0x5, flags: 0x0},
-	64: {region: 0xae, script: 0x1f, flags: 0x4},
-	65: {region: 0xc5, script: 0x1f, flags: 0x4},
-	66: {region: 0xae, script: 0x1f, flags: 0x2},
-	67: {region: 0x99, script: 0xe, flags: 0x0},
-	68: {region: 0xdb, script: 0x21, flags: 0x4},
-	69: {region: 0xdb, script: 0x21, flags: 0x2},
-	70: {region: 0x137, script: 0x57, flags: 0x0},
-	71: {region: 0x24, script: 0x5, flags: 0x4},
-	72: {region: 0x53, script: 0x1f, flags: 0x4},
-	73: {region: 0x24, script: 0x5, flags: 0x2},
-	74: {region: 0x8d, script: 0x39, flags: 0x0},
-	75: {region: 0x53, script: 0x38, flags: 0x4},
-	76: {region: 0x53, script: 0x38, flags: 0x2},
-	77: {region: 0x53, script: 0x38, flags: 0x0},
-	78: {region: 0x2f, script: 0x39, flags: 0x4},
-	79: {region: 0x3e, script: 0x39, flags: 0x4},
-	80: {region: 0x7b, script: 0x39, flags: 0x4},
-	81: {region: 0x7e, script: 0x39, flags: 0x4},
-	82: {region: 0x8d, script: 0x39, flags: 0x4},
-	83: {region: 0x95, script: 0x39, flags: 0x4},
-	84: {region: 0xc6, script: 0x39, flags: 0x4},
-	85: {region: 0xd0, script: 0x39, flags: 0x4},
-	86: {region: 0xe2, script: 0x39, flags: 0x4},
-	87: {region: 0xe5, script: 0x39, flags: 0x4},
-	88: {region: 0xe7, script: 0x39, flags: 0x4},
-	89: {region: 0x116, script: 0x39, flags: 0x4},
-	90: {region: 0x123, script: 0x39, flags: 0x4},
-	91: {region: 0x12e, script: 0x39, flags: 0x4},
-	92: {region: 0x135, script: 0x39, flags: 0x4},
-	93: {region: 0x13e, script: 0x39, flags: 0x4},
-	94: {region: 0x12e, script: 0x11, flags: 0x2},
-	95: {region: 0x12e, script: 0x34, flags: 0x2},
-	96: {region: 0x12e, script: 0x39, flags: 0x2},
-}
-
-type likelyLangScript struct {
-	lang   uint16
-	script uint8
-	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: 1432 bytes, 358 elements
-var likelyRegion = [358]likelyLangScript{
-	34:  {lang: 0xd7, script: 0x57, 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: 0x57, flags: 0x0},
-	43:  {lang: 0x0, script: 0x57, flags: 0x0},
-	44:  {lang: 0x13e, script: 0x57, flags: 0x0},
-	45:  {lang: 0x41b, script: 0x57, flags: 0x0},
-	46:  {lang: 0x10d, script: 0x57, flags: 0x0},
-	48:  {lang: 0x367, script: 0x57, flags: 0x0},
-	49:  {lang: 0x444, script: 0x57, flags: 0x0},
-	50:  {lang: 0x58, script: 0x57, flags: 0x0},
-	51:  {lang: 0x6, script: 0x2, flags: 0x1},
-	53:  {lang: 0xa5, script: 0xe, flags: 0x0},
-	54:  {lang: 0x367, script: 0x57, flags: 0x0},
-	55:  {lang: 0x15e, script: 0x57, flags: 0x0},
-	56:  {lang: 0x7e, script: 0x1f, flags: 0x0},
-	57:  {lang: 0x3a, script: 0x5, flags: 0x0},
-	58:  {lang: 0x3d9, script: 0x57, flags: 0x0},
-	59:  {lang: 0x15e, script: 0x57, flags: 0x0},
-	60:  {lang: 0x15e, script: 0x57, flags: 0x0},
-	62:  {lang: 0x31f, script: 0x57, flags: 0x0},
-	63:  {lang: 0x13e, script: 0x57, flags: 0x0},
-	64:  {lang: 0x3a1, script: 0x57, flags: 0x0},
-	65:  {lang: 0x3c0, script: 0x57, flags: 0x0},
-	67:  {lang: 0x8, script: 0x2, flags: 0x1},
-	69:  {lang: 0x0, script: 0x57, flags: 0x0},
-	71:  {lang: 0x71, script: 0x1f, flags: 0x0},
-	73:  {lang: 0x512, script: 0x3b, flags: 0x2},
-	74:  {lang: 0x31f, script: 0x5, flags: 0x2},
-	75:  {lang: 0x445, script: 0x57, flags: 0x0},
-	76:  {lang: 0x15e, script: 0x57, flags: 0x0},
-	77:  {lang: 0x15e, script: 0x57, flags: 0x0},
-	78:  {lang: 0x10d, script: 0x57, flags: 0x0},
-	79:  {lang: 0x15e, script: 0x57, flags: 0x0},
-	81:  {lang: 0x13e, script: 0x57, flags: 0x0},
-	82:  {lang: 0x15e, script: 0x57, flags: 0x0},
-	83:  {lang: 0xa, script: 0x4, flags: 0x1},
-	84:  {lang: 0x13e, script: 0x57, flags: 0x0},
-	85:  {lang: 0x0, script: 0x57, flags: 0x0},
-	86:  {lang: 0x13e, script: 0x57, flags: 0x0},
-	89:  {lang: 0x13e, script: 0x57, flags: 0x0},
-	90:  {lang: 0x3c0, script: 0x57, flags: 0x0},
-	91:  {lang: 0x3a1, script: 0x57, flags: 0x0},
-	93:  {lang: 0xe, script: 0x2, flags: 0x1},
-	94:  {lang: 0xfa, script: 0x57, flags: 0x0},
-	96:  {lang: 0x10d, script: 0x57, flags: 0x0},
-	98:  {lang: 0x1, script: 0x57, flags: 0x0},
-	99:  {lang: 0x101, script: 0x57, flags: 0x0},
-	101: {lang: 0x13e, script: 0x57, flags: 0x0},
-	103: {lang: 0x10, script: 0x2, flags: 0x1},
-	104: {lang: 0x13e, script: 0x57, flags: 0x0},
-	105: {lang: 0x13e, script: 0x57, flags: 0x0},
-	106: {lang: 0x140, script: 0x57, flags: 0x0},
-	107: {lang: 0x3a, script: 0x5, flags: 0x0},
-	108: {lang: 0x3a, script: 0x5, flags: 0x0},
-	109: {lang: 0x46f, script: 0x29, flags: 0x0},
-	110: {lang: 0x13e, script: 0x57, flags: 0x0},
-	111: {lang: 0x12, script: 0x2, flags: 0x1},
-	113: {lang: 0x10d, script: 0x57, flags: 0x0},
-	114: {lang: 0x151, script: 0x57, flags: 0x0},
-	115: {lang: 0x1c0, script: 0x21, flags: 0x2},
-	118: {lang: 0x158, script: 0x57, flags: 0x0},
-	120: {lang: 0x15e, script: 0x57, flags: 0x0},
-	122: {lang: 0x15e, script: 0x57, flags: 0x0},
-	123: {lang: 0x14, script: 0x2, flags: 0x1},
-	125: {lang: 0x16, script: 0x3, flags: 0x1},
-	126: {lang: 0x15e, script: 0x57, flags: 0x0},
-	128: {lang: 0x21, script: 0x57, flags: 0x0},
-	130: {lang: 0x245, script: 0x57, flags: 0x0},
-	132: {lang: 0x15e, script: 0x57, flags: 0x0},
-	133: {lang: 0x15e, script: 0x57, flags: 0x0},
-	134: {lang: 0x13e, script: 0x57, flags: 0x0},
-	135: {lang: 0x19, script: 0x2, flags: 0x1},
-	136: {lang: 0x0, script: 0x57, flags: 0x0},
-	137: {lang: 0x13e, script: 0x57, flags: 0x0},
-	139: {lang: 0x3c0, script: 0x57, flags: 0x0},
-	141: {lang: 0x529, script: 0x39, flags: 0x0},
-	142: {lang: 0x0, script: 0x57, flags: 0x0},
-	143: {lang: 0x13e, script: 0x57, flags: 0x0},
-	144: {lang: 0x1d1, script: 0x57, flags: 0x0},
-	145: {lang: 0x1d4, script: 0x57, flags: 0x0},
-	146: {lang: 0x1d5, script: 0x57, flags: 0x0},
-	148: {lang: 0x13e, script: 0x57, flags: 0x0},
-	149: {lang: 0x1b, script: 0x2, flags: 0x1},
-	151: {lang: 0x1bc, script: 0x3b, flags: 0x0},
-	153: {lang: 0x1d, script: 0x3, flags: 0x1},
-	155: {lang: 0x3a, script: 0x5, flags: 0x0},
-	156: {lang: 0x20, script: 0x2, flags: 0x1},
-	157: {lang: 0x1f8, script: 0x57, flags: 0x0},
-	158: {lang: 0x1f9, script: 0x57, flags: 0x0},
-	161: {lang: 0x3a, script: 0x5, flags: 0x0},
-	162: {lang: 0x200, script: 0x46, flags: 0x0},
-	164: {lang: 0x445, script: 0x57, flags: 0x0},
-	165: {lang: 0x28a, script: 0x1f, flags: 0x0},
-	166: {lang: 0x22, script: 0x3, flags: 0x1},
-	168: {lang: 0x25, script: 0x2, flags: 0x1},
-	170: {lang: 0x254, script: 0x50, flags: 0x0},
-	171: {lang: 0x254, script: 0x50, flags: 0x0},
-	172: {lang: 0x3a, script: 0x5, flags: 0x0},
-	174: {lang: 0x3e2, script: 0x1f, flags: 0x0},
-	175: {lang: 0x27, script: 0x2, flags: 0x1},
-	176: {lang: 0x3a, script: 0x5, flags: 0x0},
-	178: {lang: 0x10d, script: 0x57, flags: 0x0},
-	179: {lang: 0x40c, script: 0xca, flags: 0x0},
-	181: {lang: 0x43b, script: 0x57, flags: 0x0},
-	182: {lang: 0x2c0, script: 0x57, flags: 0x0},
-	183: {lang: 0x15e, script: 0x57, flags: 0x0},
-	184: {lang: 0x2c7, script: 0x57, flags: 0x0},
-	185: {lang: 0x3a, script: 0x5, flags: 0x0},
-	186: {lang: 0x29, script: 0x2, flags: 0x1},
-	187: {lang: 0x15e, script: 0x57, flags: 0x0},
-	188: {lang: 0x2b, script: 0x2, flags: 0x1},
-	189: {lang: 0x432, script: 0x57, flags: 0x0},
-	190: {lang: 0x15e, script: 0x57, flags: 0x0},
-	191: {lang: 0x2f1, script: 0x57, flags: 0x0},
-	194: {lang: 0x2d, script: 0x2, flags: 0x1},
-	195: {lang: 0xa0, script: 0x57, flags: 0x0},
-	196: {lang: 0x2f, script: 0x2, flags: 0x1},
-	197: {lang: 0x31, script: 0x2, flags: 0x1},
-	198: {lang: 0x33, script: 0x2, flags: 0x1},
-	200: {lang: 0x15e, script: 0x57, flags: 0x0},
-	201: {lang: 0x35, script: 0x2, flags: 0x1},
-	203: {lang: 0x320, script: 0x57, flags: 0x0},
-	204: {lang: 0x37, script: 0x3, flags: 0x1},
-	205: {lang: 0x128, script: 0xde, flags: 0x0},
-	207: {lang: 0x13e, script: 0x57, flags: 0x0},
-	208: {lang: 0x31f, script: 0x57, flags: 0x0},
-	209: {lang: 0x3c0, script: 0x57, flags: 0x0},
-	210: {lang: 0x16, script: 0x57, flags: 0x0},
-	211: {lang: 0x15e, script: 0x57, flags: 0x0},
-	212: {lang: 0x1b4, script: 0x57, flags: 0x0},
-	214: {lang: 0x1b4, script: 0x5, flags: 0x2},
-	216: {lang: 0x13e, script: 0x57, flags: 0x0},
-	217: {lang: 0x367, script: 0x57, flags: 0x0},
-	218: {lang: 0x347, script: 0x57, flags: 0x0},
-	219: {lang: 0x351, script: 0x21, flags: 0x0},
-	225: {lang: 0x3a, script: 0x5, flags: 0x0},
-	226: {lang: 0x13e, script: 0x57, flags: 0x0},
-	228: {lang: 0x13e, script: 0x57, flags: 0x0},
-	229: {lang: 0x15e, script: 0x57, flags: 0x0},
-	230: {lang: 0x486, script: 0x57, flags: 0x0},
-	231: {lang: 0x153, script: 0x57, flags: 0x0},
-	232: {lang: 0x3a, script: 0x3, flags: 0x1},
-	233: {lang: 0x3b3, script: 0x57, flags: 0x0},
-	234: {lang: 0x15e, script: 0x57, flags: 0x0},
-	236: {lang: 0x13e, script: 0x57, flags: 0x0},
-	237: {lang: 0x3a, script: 0x5, flags: 0x0},
-	238: {lang: 0x3c0, script: 0x57, flags: 0x0},
-	240: {lang: 0x3a2, script: 0x57, flags: 0x0},
-	241: {lang: 0x194, script: 0x57, flags: 0x0},
-	243: {lang: 0x3a, script: 0x5, flags: 0x0},
-	258: {lang: 0x15e, script: 0x57, flags: 0x0},
-	260: {lang: 0x3d, script: 0x2, flags: 0x1},
-	261: {lang: 0x432, script: 0x1f, flags: 0x0},
-	262: {lang: 0x3f, script: 0x2, flags: 0x1},
-	263: {lang: 0x3e5, script: 0x57, flags: 0x0},
-	264: {lang: 0x3a, script: 0x5, flags: 0x0},
-	266: {lang: 0x15e, script: 0x57, flags: 0x0},
-	267: {lang: 0x3a, script: 0x5, flags: 0x0},
-	268: {lang: 0x41, script: 0x2, flags: 0x1},
-	271: {lang: 0x416, script: 0x57, flags: 0x0},
-	272: {lang: 0x347, script: 0x57, flags: 0x0},
-	273: {lang: 0x43, script: 0x2, flags: 0x1},
-	275: {lang: 0x1f9, script: 0x57, flags: 0x0},
-	276: {lang: 0x15e, script: 0x57, flags: 0x0},
-	277: {lang: 0x429, script: 0x57, flags: 0x0},
-	278: {lang: 0x367, script: 0x57, flags: 0x0},
-	280: {lang: 0x3c0, script: 0x57, flags: 0x0},
-	282: {lang: 0x13e, script: 0x57, flags: 0x0},
-	284: {lang: 0x45, script: 0x2, flags: 0x1},
-	288: {lang: 0x15e, script: 0x57, flags: 0x0},
-	289: {lang: 0x15e, script: 0x57, flags: 0x0},
-	290: {lang: 0x47, script: 0x2, flags: 0x1},
-	291: {lang: 0x49, script: 0x3, flags: 0x1},
-	292: {lang: 0x4c, script: 0x2, flags: 0x1},
-	293: {lang: 0x477, script: 0x57, flags: 0x0},
-	294: {lang: 0x3c0, script: 0x57, flags: 0x0},
-	295: {lang: 0x476, script: 0x57, flags: 0x0},
-	296: {lang: 0x4e, script: 0x2, flags: 0x1},
-	297: {lang: 0x482, script: 0x57, flags: 0x0},
-	299: {lang: 0x50, script: 0x4, flags: 0x1},
-	301: {lang: 0x4a0, script: 0x57, flags: 0x0},
-	302: {lang: 0x54, script: 0x2, flags: 0x1},
-	303: {lang: 0x445, script: 0x57, flags: 0x0},
-	304: {lang: 0x56, script: 0x3, flags: 0x1},
-	305: {lang: 0x445, script: 0x57, flags: 0x0},
-	309: {lang: 0x512, script: 0x3b, flags: 0x2},
-	310: {lang: 0x13e, script: 0x57, flags: 0x0},
-	311: {lang: 0x4bc, script: 0x57, flags: 0x0},
-	312: {lang: 0x1f9, script: 0x57, flags: 0x0},
-	315: {lang: 0x13e, script: 0x57, flags: 0x0},
-	318: {lang: 0x4c3, script: 0x57, flags: 0x0},
-	319: {lang: 0x8a, script: 0x57, flags: 0x0},
-	320: {lang: 0x15e, script: 0x57, flags: 0x0},
-	322: {lang: 0x41b, script: 0x57, flags: 0x0},
-	333: {lang: 0x59, script: 0x2, flags: 0x1},
-	350: {lang: 0x3a, script: 0x5, flags: 0x0},
-	351: {lang: 0x5b, script: 0x2, flags: 0x1},
-	356: {lang: 0x423, script: 0x57, flags: 0x0},
-}
-
-// likelyRegionList holds lists info associated with likelyRegion.
-// Size: 372 bytes, 93 elements
-var likelyRegionList = [93]likelyLangScript{
-	0:  {lang: 0x148, script: 0x5, flags: 0x0},
-	1:  {lang: 0x476, script: 0x57, flags: 0x0},
-	2:  {lang: 0x431, script: 0x57, flags: 0x0},
-	3:  {lang: 0x2ff, script: 0x1f, flags: 0x0},
-	4:  {lang: 0x1d7, script: 0x8, flags: 0x0},
-	5:  {lang: 0x274, script: 0x57, flags: 0x0},
-	6:  {lang: 0xb7, script: 0x57, flags: 0x0},
-	7:  {lang: 0x432, script: 0x1f, flags: 0x0},
-	8:  {lang: 0x12d, script: 0xe0, flags: 0x0},
-	9:  {lang: 0x351, script: 0x21, flags: 0x0},
-	10: {lang: 0x529, script: 0x38, flags: 0x0},
-	11: {lang: 0x4ac, script: 0x5, flags: 0x0},
-	12: {lang: 0x523, script: 0x57, flags: 0x0},
-	13: {lang: 0x29a, script: 0xdf, flags: 0x0},
-	14: {lang: 0x136, script: 0x31, flags: 0x0},
-	15: {lang: 0x48a, script: 0x57, flags: 0x0},
-	16: {lang: 0x3a, script: 0x5, flags: 0x0},
-	17: {lang: 0x15e, script: 0x57, flags: 0x0},
-	18: {lang: 0x27, script: 0x29, flags: 0x0},
-	19: {lang: 0x139, script: 0x57, flags: 0x0},
-	20: {lang: 0x26a, script: 0x5, flags: 0x2},
-	21: {lang: 0x512, script: 0x3b, flags: 0x2},
-	22: {lang: 0x210, script: 0x2b, flags: 0x0},
-	23: {lang: 0x5, script: 0x1f, flags: 0x0},
-	24: {lang: 0x274, script: 0x57, flags: 0x0},
-	25: {lang: 0x136, script: 0x31, flags: 0x0},
-	26: {lang: 0x2ff, script: 0x1f, flags: 0x0},
-	27: {lang: 0x1e1, script: 0x57, flags: 0x0},
-	28: {lang: 0x31f, script: 0x5, flags: 0x0},
-	29: {lang: 0x1be, script: 0x21, flags: 0x0},
-	30: {lang: 0x4b4, script: 0x5, flags: 0x0},
-	31: {lang: 0x236, script: 0x72, flags: 0x0},
-	32: {lang: 0x148, script: 0x5, flags: 0x0},
-	33: {lang: 0x476, script: 0x57, flags: 0x0},
-	34: {lang: 0x24a, script: 0x4b, flags: 0x0},
-	35: {lang: 0xe6, script: 0x5, flags: 0x0},
-	36: {lang: 0x226, script: 0xdf, flags: 0x0},
-	37: {lang: 0x3a, script: 0x5, flags: 0x0},
-	38: {lang: 0x15e, script: 0x57, flags: 0x0},
-	39: {lang: 0x2b8, script: 0x54, flags: 0x0},
-	40: {lang: 0x226, script: 0xdf, flags: 0x0},
-	41: {lang: 0x3a, script: 0x5, flags: 0x0},
-	42: {lang: 0x15e, script: 0x57, flags: 0x0},
-	43: {lang: 0x3dc, script: 0x57, flags: 0x0},
-	44: {lang: 0x4ae, script: 0x1f, flags: 0x0},
-	45: {lang: 0x2ff, script: 0x1f, flags: 0x0},
-	46: {lang: 0x431, script: 0x57, flags: 0x0},
-	47: {lang: 0x331, script: 0x72, flags: 0x0},
-	48: {lang: 0x213, script: 0x57, flags: 0x0},
-	49: {lang: 0x30b, script: 0x1f, flags: 0x0},
-	50: {lang: 0x242, script: 0x5, flags: 0x0},
-	51: {lang: 0x529, script: 0x39, flags: 0x0},
-	52: {lang: 0x3c0, script: 0x57, flags: 0x0},
-	53: {lang: 0x3a, script: 0x5, flags: 0x0},
-	54: {lang: 0x15e, script: 0x57, flags: 0x0},
-	55: {lang: 0x2ed, script: 0x57, flags: 0x0},
-	56: {lang: 0x4b4, script: 0x5, flags: 0x0},
-	57: {lang: 0x88, script: 0x21, flags: 0x0},
-	58: {lang: 0x4b4, script: 0x5, flags: 0x0},
-	59: {lang: 0x4b4, script: 0x5, flags: 0x0},
-	60: {lang: 0xbe, script: 0x21, flags: 0x0},
-	61: {lang: 0x3dc, script: 0x57, flags: 0x0},
-	62: {lang: 0x7e, script: 0x1f, flags: 0x0},
-	63: {lang: 0x3e2, script: 0x1f, flags: 0x0},
-	64: {lang: 0x267, script: 0x57, flags: 0x0},
-	65: {lang: 0x444, script: 0x57, flags: 0x0},
-	66: {lang: 0x512, script: 0x3b, flags: 0x0},
-	67: {lang: 0x412, script: 0x57, flags: 0x0},
-	68: {lang: 0x4ae, script: 0x1f, flags: 0x0},
-	69: {lang: 0x3a, script: 0x5, flags: 0x0},
-	70: {lang: 0x15e, script: 0x57, flags: 0x0},
-	71: {lang: 0x15e, script: 0x57, flags: 0x0},
-	72: {lang: 0x35, script: 0x5, flags: 0x0},
-	73: {lang: 0x46b, script: 0xdf, flags: 0x0},
-	74: {lang: 0x2ec, script: 0x5, flags: 0x0},
-	75: {lang: 0x30f, script: 0x72, flags: 0x0},
-	76: {lang: 0x467, script: 0x1f, flags: 0x0},
-	77: {lang: 0x148, script: 0x5, flags: 0x0},
-	78: {lang: 0x3a, script: 0x5, flags: 0x0},
-	79: {lang: 0x15e, script: 0x57, flags: 0x0},
-	80: {lang: 0x48a, script: 0x57, flags: 0x0},
-	81: {lang: 0x58, script: 0x5, flags: 0x0},
-	82: {lang: 0x219, script: 0x1f, flags: 0x0},
-	83: {lang: 0x81, script: 0x31, flags: 0x0},
-	84: {lang: 0x529, script: 0x39, flags: 0x0},
-	85: {lang: 0x48c, script: 0x57, flags: 0x0},
-	86: {lang: 0x4ae, script: 0x1f, flags: 0x0},
-	87: {lang: 0x512, script: 0x3b, flags: 0x0},
-	88: {lang: 0x3b3, script: 0x57, flags: 0x0},
-	89: {lang: 0x431, script: 0x57, flags: 0x0},
-	90: {lang: 0x432, script: 0x1f, flags: 0x0},
-	91: {lang: 0x15e, script: 0x57, flags: 0x0},
-	92: {lang: 0x446, script: 0x5, flags: 0x0},
-}
-
-type likelyTag struct {
-	lang   uint16
-	region uint16
-	script uint8
-}
-
-// Size: 198 bytes, 33 elements
-var likelyRegionGroup = [33]likelyTag{
-	1:  {lang: 0x139, region: 0xd6, script: 0x57},
-	2:  {lang: 0x139, region: 0x135, script: 0x57},
-	3:  {lang: 0x3c0, region: 0x41, script: 0x57},
-	4:  {lang: 0x139, region: 0x2f, script: 0x57},
-	5:  {lang: 0x139, region: 0xd6, script: 0x57},
-	6:  {lang: 0x13e, region: 0xcf, script: 0x57},
-	7:  {lang: 0x445, region: 0x12f, script: 0x57},
-	8:  {lang: 0x3a, region: 0x6b, script: 0x5},
-	9:  {lang: 0x445, region: 0x4b, script: 0x57},
-	10: {lang: 0x139, region: 0x161, script: 0x57},
-	11: {lang: 0x139, region: 0x135, script: 0x57},
-	12: {lang: 0x139, region: 0x135, script: 0x57},
-	13: {lang: 0x13e, region: 0x59, script: 0x57},
-	14: {lang: 0x529, region: 0x53, script: 0x38},
-	15: {lang: 0x1be, region: 0x99, script: 0x21},
-	16: {lang: 0x1e1, region: 0x95, script: 0x57},
-	17: {lang: 0x1f9, region: 0x9e, script: 0x57},
-	18: {lang: 0x139, region: 0x2f, script: 0x57},
-	19: {lang: 0x139, region: 0xe6, script: 0x57},
-	20: {lang: 0x139, region: 0x8a, script: 0x57},
-	21: {lang: 0x41b, region: 0x142, script: 0x57},
-	22: {lang: 0x529, region: 0x53, script: 0x38},
-	23: {lang: 0x4bc, region: 0x137, script: 0x57},
-	24: {lang: 0x3a, region: 0x108, script: 0x5},
-	25: {lang: 0x3e2, region: 0x106, script: 0x1f},
-	26: {lang: 0x3e2, region: 0x106, script: 0x1f},
-	27: {lang: 0x139, region: 0x7b, script: 0x57},
-	28: {lang: 0x10d, region: 0x60, script: 0x57},
-	29: {lang: 0x139, region: 0xd6, script: 0x57},
-	30: {lang: 0x13e, region: 0x1f, script: 0x57},
-	31: {lang: 0x139, region: 0x9a, script: 0x57},
-	32: {lang: 0x139, region: 0x7b, script: 0x57},
-}
-
-// Size: 358 bytes, 358 elements
-var regionToGroups = [358]uint8{
+// Size: 357 bytes, 357 elements
+var regionToGroups = [357]uint8{
 	// Entry 0 - 3F
 	0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x04,
 	0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00,
@@ -3343,7 +180,7 @@
 	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: 18 bytes, 3 elements
@@ -3546,141 +383,4 @@
 	14: {lang: 0x529, script: 0x39, group: 0x80, distance: 0x5},
 }
 
-// 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: 358 bytes, 358 elements
-var regionInclusion = [358]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, 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, 0x2c,
-	// Entry 80 - BF
-	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, 0x2f,
-	// Entry C0 - FF
-	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, 0x21,
-	// Entry 100 - 13F
-	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, 0x3b,
-	// Entry 140 - 17F
-	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     uint8
-	maxScript  uint8
-	toRegion   uint16
-	fromRegion []uint16
-}
-
-// Size: 414 bytes, 5 elements
-var parents = [5]parentRel{
-	0: {lang: 0x139, script: 0x0, maxScript: 0x57, toRegion: 0x1, fromRegion: []uint16{0x1a, 0x25, 0x26, 0x2f, 0x34, 0x36, 0x3d, 0x42, 0x46, 0x48, 0x49, 0x4a, 0x50, 0x52, 0x5c, 0x5d, 0x61, 0x64, 0x6d, 0x73, 0x74, 0x75, 0x7b, 0x7c, 0x7f, 0x80, 0x81, 0x83, 0x8c, 0x8d, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9f, 0xa0, 0xa4, 0xa7, 0xa9, 0xad, 0xb1, 0xb4, 0xb5, 0xbf, 0xc6, 0xca, 0xcb, 0xcc, 0xce, 0xd0, 0xd2, 0xd5, 0xd6, 0xdd, 0xdf, 0xe0, 0xe6, 0xe7, 0xe8, 0xeb, 0xf0, 0x107, 0x109, 0x10a, 0x10b, 0x10d, 0x10e, 0x112, 0x117, 0x11b, 0x11d, 0x11f, 0x125, 0x129, 0x12c, 0x12d, 0x12f, 0x131, 0x139, 0x13c, 0x13f, 0x142, 0x161, 0x162, 0x164}},
-	1: {lang: 0x139, script: 0x0, maxScript: 0x57, toRegion: 0x1a, fromRegion: []uint16{0x2e, 0x4e, 0x60, 0x63, 0x72, 0xd9, 0x10c, 0x10f}},
-	2: {lang: 0x13e, script: 0x0, maxScript: 0x57, toRegion: 0x1f, fromRegion: []uint16{0x2c, 0x3f, 0x41, 0x48, 0x51, 0x54, 0x56, 0x59, 0x65, 0x69, 0x89, 0x8f, 0xcf, 0xd8, 0xe2, 0xe4, 0xec, 0xf1, 0x11a, 0x135, 0x136, 0x13b}},
-	3: {lang: 0x3c0, script: 0x0, maxScript: 0x57, toRegion: 0xee, fromRegion: []uint16{0x2a, 0x4e, 0x5a, 0x86, 0x8b, 0xb7, 0xc6, 0xd1, 0x118, 0x126}},
-	4: {lang: 0x529, script: 0x39, maxScript: 0x39, toRegion: 0x8d, fromRegion: []uint16{0xc6}},
-}
-
-// Total table size 27238 bytes (26KiB); checksum: C9BBE4D5
+// Total table size 1351 bytes (1KiB); checksum: B5A6F1BC
diff --git a/language/tags.go b/language/tags.go
index de30155..1d1b7f8 100644
--- a/language/tags.go
+++ b/language/tags.go
@@ -61,83 +61,85 @@
 
 	Und Tag = Tag{}
 
-	Afrikaans            Tag = Tag{lang: _af}                //  af
-	Amharic              Tag = Tag{lang: _am}                //  am
-	Arabic               Tag = Tag{lang: _ar}                //  ar
-	ModernStandardArabic Tag = Tag{lang: _ar, region: _001}  //  ar-001
-	Azerbaijani          Tag = Tag{lang: _az}                //  az
-	Bulgarian            Tag = Tag{lang: _bg}                //  bg
-	Bengali              Tag = Tag{lang: _bn}                //  bn
-	Catalan              Tag = Tag{lang: _ca}                //  ca
-	Czech                Tag = Tag{lang: _cs}                //  cs
-	Danish               Tag = Tag{lang: _da}                //  da
-	German               Tag = Tag{lang: _de}                //  de
-	Greek                Tag = Tag{lang: _el}                //  el
-	English              Tag = Tag{lang: _en}                //  en
-	AmericanEnglish      Tag = Tag{lang: _en, region: _US}   //  en-US
-	BritishEnglish       Tag = Tag{lang: _en, region: _GB}   //  en-GB
-	Spanish              Tag = Tag{lang: _es}                //  es
-	EuropeanSpanish      Tag = Tag{lang: _es, region: _ES}   //  es-ES
-	LatinAmericanSpanish Tag = Tag{lang: _es, region: _419}  //  es-419
-	Estonian             Tag = Tag{lang: _et}                //  et
-	Persian              Tag = Tag{lang: _fa}                //  fa
-	Finnish              Tag = Tag{lang: _fi}                //  fi
-	Filipino             Tag = Tag{lang: _fil}               //  fil
-	French               Tag = Tag{lang: _fr}                //  fr
-	CanadianFrench       Tag = Tag{lang: _fr, region: _CA}   //  fr-CA
-	Gujarati             Tag = Tag{lang: _gu}                //  gu
-	Hebrew               Tag = Tag{lang: _he}                //  he
-	Hindi                Tag = Tag{lang: _hi}                //  hi
-	Croatian             Tag = Tag{lang: _hr}                //  hr
-	Hungarian            Tag = Tag{lang: _hu}                //  hu
-	Armenian             Tag = Tag{lang: _hy}                //  hy
-	Indonesian           Tag = Tag{lang: _id}                //  id
-	Icelandic            Tag = Tag{lang: _is}                //  is
-	Italian              Tag = Tag{lang: _it}                //  it
-	Japanese             Tag = Tag{lang: _ja}                //  ja
-	Georgian             Tag = Tag{lang: _ka}                //  ka
-	Kazakh               Tag = Tag{lang: _kk}                //  kk
-	Khmer                Tag = Tag{lang: _km}                //  km
-	Kannada              Tag = Tag{lang: _kn}                //  kn
-	Korean               Tag = Tag{lang: _ko}                //  ko
-	Kirghiz              Tag = Tag{lang: _ky}                //  ky
-	Lao                  Tag = Tag{lang: _lo}                //  lo
-	Lithuanian           Tag = Tag{lang: _lt}                //  lt
-	Latvian              Tag = Tag{lang: _lv}                //  lv
-	Macedonian           Tag = Tag{lang: _mk}                //  mk
-	Malayalam            Tag = Tag{lang: _ml}                //  ml
-	Mongolian            Tag = Tag{lang: _mn}                //  mn
-	Marathi              Tag = Tag{lang: _mr}                //  mr
-	Malay                Tag = Tag{lang: _ms}                //  ms
-	Burmese              Tag = Tag{lang: _my}                //  my
-	Nepali               Tag = Tag{lang: _ne}                //  ne
-	Dutch                Tag = Tag{lang: _nl}                //  nl
-	Norwegian            Tag = Tag{lang: _no}                //  no
-	Punjabi              Tag = Tag{lang: _pa}                //  pa
-	Polish               Tag = Tag{lang: _pl}                //  pl
-	Portuguese           Tag = Tag{lang: _pt}                //  pt
-	BrazilianPortuguese  Tag = Tag{lang: _pt, region: _BR}   //  pt-BR
-	EuropeanPortuguese   Tag = Tag{lang: _pt, region: _PT}   //  pt-PT
-	Romanian             Tag = Tag{lang: _ro}                //  ro
-	Russian              Tag = Tag{lang: _ru}                //  ru
-	Sinhala              Tag = Tag{lang: _si}                //  si
-	Slovak               Tag = Tag{lang: _sk}                //  sk
-	Slovenian            Tag = Tag{lang: _sl}                //  sl
-	Albanian             Tag = Tag{lang: _sq}                //  sq
-	Serbian              Tag = Tag{lang: _sr}                //  sr
-	SerbianLatin         Tag = Tag{lang: _sr, script: _Latn} //  sr-Latn
-	Swedish              Tag = Tag{lang: _sv}                //  sv
-	Swahili              Tag = Tag{lang: _sw}                //  sw
-	Tamil                Tag = Tag{lang: _ta}                //  ta
-	Telugu               Tag = Tag{lang: _te}                //  te
-	Thai                 Tag = Tag{lang: _th}                //  th
-	Turkish              Tag = Tag{lang: _tr}                //  tr
-	Ukrainian            Tag = Tag{lang: _uk}                //  uk
-	Urdu                 Tag = Tag{lang: _ur}                //  ur
-	Uzbek                Tag = Tag{lang: _uz}                //  uz
-	Vietnamese           Tag = Tag{lang: _vi}                //  vi
-	Chinese              Tag = Tag{lang: _zh}                //  zh
-	SimplifiedChinese    Tag = Tag{lang: _zh, script: _Hans} //  zh-Hans
-	TraditionalChinese   Tag = Tag{lang: _zh, script: _Hant} //  zh-Hant
-	Zulu                 Tag = Tag{lang: _zu}                //  zu
+	// TODO: use compact tags once the transition is completed.
+
+	Afrikaans            Tag = Raw.MustParse("af")      // Tag{lang: _af}                //  af
+	Amharic              Tag = Raw.MustParse("am")      // Tag{lang: _am}                //  am
+	Arabic               Tag = Raw.MustParse("ar")      // Tag{lang: _ar}                //  ar
+	ModernStandardArabic Tag = Raw.MustParse("ar-001")  // Tag{lang: _ar, region: _001}  //  ar-001
+	Azerbaijani          Tag = Raw.MustParse("az")      // Tag{lang: _az}                //  az
+	Bulgarian            Tag = Raw.MustParse("bg")      // Tag{lang: _bg}                //  bg
+	Bengali              Tag = Raw.MustParse("bn")      // Tag{lang: _bn}                //  bn
+	Catalan              Tag = Raw.MustParse("ca")      // Tag{lang: _ca}                //  ca
+	Czech                Tag = Raw.MustParse("cs")      // Tag{lang: _cs}                //  cs
+	Danish               Tag = Raw.MustParse("da")      // Tag{lang: _da}                //  da
+	German               Tag = Raw.MustParse("de")      // Tag{lang: _de}                //  de
+	Greek                Tag = Raw.MustParse("el")      // Tag{lang: _el}                //  el
+	English              Tag = Raw.MustParse("en")      // Tag{lang: _en}                //  en
+	AmericanEnglish      Tag = Raw.MustParse("en-US")   // Tag{lang: _en, region: _US}   //  en-US
+	BritishEnglish       Tag = Raw.MustParse("en-GB")   // Tag{lang: _en, region: _GB}   //  en-GB
+	Spanish              Tag = Raw.MustParse("es")      // Tag{lang: _es}                //  es
+	EuropeanSpanish      Tag = Raw.MustParse("es-ES")   // Tag{lang: _es, region: _ES}   //  es-ES
+	LatinAmericanSpanish Tag = Raw.MustParse("es-419")  // Tag{lang: _es, region: _419}  //  es-419
+	Estonian             Tag = Raw.MustParse("et")      // Tag{lang: _et}                //  et
+	Persian              Tag = Raw.MustParse("fa")      // Tag{lang: _fa}                //  fa
+	Finnish              Tag = Raw.MustParse("fi")      // Tag{lang: _fi}                //  fi
+	Filipino             Tag = Raw.MustParse("fil")     // Tag{lang: _fil}               //  fil
+	French               Tag = Raw.MustParse("fr")      // Tag{lang: _fr}                //  fr
+	CanadianFrench       Tag = Raw.MustParse("fr-CA")   // Tag{lang: _fr, region: _CA}   //  fr-CA
+	Gujarati             Tag = Raw.MustParse("gu")      // Tag{lang: _gu}                //  gu
+	Hebrew               Tag = Raw.MustParse("he")      // Tag{lang: _he}                //  he
+	Hindi                Tag = Raw.MustParse("hi")      // Tag{lang: _hi}                //  hi
+	Croatian             Tag = Raw.MustParse("hr")      // Tag{lang: _hr}                //  hr
+	Hungarian            Tag = Raw.MustParse("hu")      // Tag{lang: _hu}                //  hu
+	Armenian             Tag = Raw.MustParse("hy")      // Tag{lang: _hy}                //  hy
+	Indonesian           Tag = Raw.MustParse("id")      // Tag{lang: _id}                //  id
+	Icelandic            Tag = Raw.MustParse("is")      // Tag{lang: _is}                //  is
+	Italian              Tag = Raw.MustParse("it")      // Tag{lang: _it}                //  it
+	Japanese             Tag = Raw.MustParse("ja")      // Tag{lang: _ja}                //  ja
+	Georgian             Tag = Raw.MustParse("ka")      // Tag{lang: _ka}                //  ka
+	Kazakh               Tag = Raw.MustParse("kk")      // Tag{lang: _kk}                //  kk
+	Khmer                Tag = Raw.MustParse("km")      // Tag{lang: _km}                //  km
+	Kannada              Tag = Raw.MustParse("kn")      // Tag{lang: _kn}                //  kn
+	Korean               Tag = Raw.MustParse("ko")      // Tag{lang: _ko}                //  ko
+	Kirghiz              Tag = Raw.MustParse("ky")      // Tag{lang: _ky}                //  ky
+	Lao                  Tag = Raw.MustParse("lo")      // Tag{lang: _lo}                //  lo
+	Lithuanian           Tag = Raw.MustParse("lt")      // Tag{lang: _lt}                //  lt
+	Latvian              Tag = Raw.MustParse("lv")      // Tag{lang: _lv}                //  lv
+	Macedonian           Tag = Raw.MustParse("mk")      // Tag{lang: _mk}                //  mk
+	Malayalam            Tag = Raw.MustParse("ml")      // Tag{lang: _ml}                //  ml
+	Mongolian            Tag = Raw.MustParse("mn")      // Tag{lang: _mn}                //  mn
+	Marathi              Tag = Raw.MustParse("mr")      // Tag{lang: _mr}                //  mr
+	Malay                Tag = Raw.MustParse("ms")      // Tag{lang: _ms}                //  ms
+	Burmese              Tag = Raw.MustParse("my")      // Tag{lang: _my}                //  my
+	Nepali               Tag = Raw.MustParse("ne")      // Tag{lang: _ne}                //  ne
+	Dutch                Tag = Raw.MustParse("nl")      // Tag{lang: _nl}                //  nl
+	Norwegian            Tag = Raw.MustParse("no")      // Tag{lang: _no}                //  no
+	Punjabi              Tag = Raw.MustParse("pa")      // Tag{lang: _pa}                //  pa
+	Polish               Tag = Raw.MustParse("pl")      // Tag{lang: _pl}                //  pl
+	Portuguese           Tag = Raw.MustParse("pt")      // Tag{lang: _pt}                //  pt
+	BrazilianPortuguese  Tag = Raw.MustParse("pt-BR")   // Tag{lang: _pt, region: _BR}   //  pt-BR
+	EuropeanPortuguese   Tag = Raw.MustParse("pt-PT")   // Tag{lang: _pt, region: _PT}   //  pt-PT
+	Romanian             Tag = Raw.MustParse("ro")      // Tag{lang: _ro}                //  ro
+	Russian              Tag = Raw.MustParse("ru")      // Tag{lang: _ru}                //  ru
+	Sinhala              Tag = Raw.MustParse("si")      // Tag{lang: _si}                //  si
+	Slovak               Tag = Raw.MustParse("sk")      // Tag{lang: _sk}                //  sk
+	Slovenian            Tag = Raw.MustParse("sl")      // Tag{lang: _sl}                //  sl
+	Albanian             Tag = Raw.MustParse("sq")      // Tag{lang: _sq}                //  sq
+	Serbian              Tag = Raw.MustParse("sr")      // Tag{lang: _sr}                //  sr
+	SerbianLatin         Tag = Raw.MustParse("sr-Latn") // Tag{lang: _sr, script: _Latn} //  sr-Latn
+	Swedish              Tag = Raw.MustParse("sv")      // Tag{lang: _sv}                //  sv
+	Swahili              Tag = Raw.MustParse("sw")      // Tag{lang: _sw}                //  sw
+	Tamil                Tag = Raw.MustParse("ta")      // Tag{lang: _ta}                //  ta
+	Telugu               Tag = Raw.MustParse("te")      // Tag{lang: _te}                //  te
+	Thai                 Tag = Raw.MustParse("th")      // Tag{lang: _th}                //  th
+	Turkish              Tag = Raw.MustParse("tr")      // Tag{lang: _tr}                //  tr
+	Ukrainian            Tag = Raw.MustParse("uk")      // Tag{lang: _uk}                //  uk
+	Urdu                 Tag = Raw.MustParse("ur")      // Tag{lang: _ur}                //  ur
+	Uzbek                Tag = Raw.MustParse("uz")      // Tag{lang: _uz}                //  uz
+	Vietnamese           Tag = Raw.MustParse("vi")      // Tag{lang: _vi}                //  vi
+	Chinese              Tag = Raw.MustParse("zh")      // Tag{lang: _zh}                //  zh
+	SimplifiedChinese    Tag = Raw.MustParse("zh-Hans") // Tag{lang: _zh, script: _Hans} //  zh-Hans
+	TraditionalChinese   Tag = Raw.MustParse("zh-Hant") // Tag{lang: _zh, script: _Hant} //  zh-Hant
+	Zulu                 Tag = Raw.MustParse("zu")      // Tag{lang: _zu}                //  zu
 )