...

Source file src/golang.org/x/text/language/display/display_test.go

Documentation: golang.org/x/text/language/display

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package display
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"strings"
    11  	"testing"
    12  	"unicode"
    13  
    14  	"golang.org/x/text/language"
    15  	"golang.org/x/text/message"
    16  )
    17  
    18  // TODO: test that tables are properly dropped by the linker for various use
    19  // cases.
    20  
    21  var (
    22  	firstLang2aa  = language.MustParseBase("aa")
    23  	lastLang2zu   = language.MustParseBase("zu")
    24  	firstLang3ace = language.MustParseBase("ace")
    25  	lastLang3zza  = language.MustParseBase("zza")
    26  	firstTagAr001 = language.MustParse("ar-001")
    27  	lastTagZhHant = language.MustParse("zh-Hant")
    28  )
    29  
    30  // TestValues tests that for all languages, regions, and scripts in Values, at
    31  // least one language has a name defined for it by checking it exists in
    32  // English, which is assumed to be the most comprehensive. It is also tested
    33  // that a Namer returns "" for unsupported values.
    34  func TestValues(t *testing.T) {
    35  	type testcase struct {
    36  		kind string
    37  		n    Namer
    38  	}
    39  	// checkDefined checks that a value exists in a Namer.
    40  	checkDefined := func(x interface{}, namers []testcase) {
    41  		for _, n := range namers {
    42  			t.Run(fmt.Sprintf("%s.Name(%s)", n.kind, x), func(t *testing.T) {
    43  				if n.n.Name(x) == "" {
    44  					// As of version 28 there is no data for az-Arab in English,
    45  					// although there is useful data in other languages.
    46  					if x.(fmt.Stringer).String() == "az-Arab" {
    47  						return
    48  					}
    49  					t.Errorf("supported but no result")
    50  				}
    51  			})
    52  		}
    53  	}
    54  	// checkUnsupported checks that a value does not exist in a Namer.
    55  	checkUnsupported := func(x interface{}, namers []testcase) {
    56  		for _, n := range namers {
    57  			if got := n.n.Name(x); got != "" {
    58  				t.Fatalf("%s.Name(%s): unsupported tag gave non-empty result: %q", n.kind, x, got)
    59  			}
    60  		}
    61  	}
    62  
    63  	tags := map[language.Tag]bool{}
    64  	namers := []testcase{
    65  		{"Languages(en)", Languages(language.English)},
    66  		{"Tags(en)", Tags(language.English)},
    67  		{"English.Languages()", English.Languages()},
    68  		{"English.Tags()", English.Tags()},
    69  	}
    70  	for _, tag := range Values.Tags() {
    71  		checkDefined(tag, namers)
    72  		tags[tag] = true
    73  	}
    74  	for _, base := range language.Supported.BaseLanguages() {
    75  		tag, _ := language.All.Compose(base)
    76  		if !tags[tag] {
    77  			checkUnsupported(tag, namers)
    78  		}
    79  	}
    80  
    81  	regions := map[language.Region]bool{}
    82  	namers = []testcase{
    83  		{"Regions(en)", Regions(language.English)},
    84  		{"English.Regions()", English.Regions()},
    85  	}
    86  	for _, r := range Values.Regions() {
    87  		checkDefined(r, namers)
    88  		regions[r] = true
    89  	}
    90  	for _, r := range language.Supported.Regions() {
    91  		if r = r.Canonicalize(); !regions[r] {
    92  			checkUnsupported(r, namers)
    93  		}
    94  	}
    95  
    96  	scripts := map[language.Script]bool{}
    97  	namers = []testcase{
    98  		{"Scripts(en)", Scripts(language.English)},
    99  		{"English.Scripts()", English.Scripts()},
   100  	}
   101  	for _, s := range Values.Scripts() {
   102  		checkDefined(s, namers)
   103  		scripts[s] = true
   104  	}
   105  	for _, s := range language.Supported.Scripts() {
   106  		// Canonicalize the script.
   107  		tag, _ := language.DeprecatedScript.Compose(s)
   108  		if _, s, _ = tag.Raw(); !scripts[s] {
   109  			checkUnsupported(s, namers)
   110  		}
   111  	}
   112  }
   113  
   114  // TestSupported tests that we have at least some Namers for languages that we
   115  // claim to support. To test the claims in the documentation, it also verifies
   116  // that if a Namer is returned, it will have at least some data.
   117  func TestSupported(t *testing.T) {
   118  	supportedTags := Supported.Tags()
   119  	if len(supportedTags) != numSupported {
   120  		t.Errorf("number of supported was %d; want %d", len(supportedTags), numSupported)
   121  	}
   122  
   123  	namerFuncs := []struct {
   124  		kind string
   125  		fn   func(language.Tag) Namer
   126  	}{
   127  		{"Tags", Tags},
   128  		{"Languages", Languages},
   129  		{"Regions", Regions},
   130  		{"Scripts", Scripts},
   131  	}
   132  
   133  	// Verify that we have at least one Namer for all tags we claim to support.
   134  	tags := make(map[language.Tag]bool)
   135  	for _, tag := range supportedTags {
   136  		// Test we have at least one Namer for this supported Tag.
   137  		found := false
   138  		for _, kind := range namerFuncs {
   139  			if defined(t, kind.kind, kind.fn(tag), tag) {
   140  				found = true
   141  			}
   142  		}
   143  		if !found {
   144  			t.Errorf("%s: supported, but no data available", tag)
   145  		}
   146  		if tags[tag] {
   147  			t.Errorf("%s: included in Supported.Tags more than once", tag)
   148  		}
   149  		tags[tag] = true
   150  	}
   151  
   152  	// Verify that we have no Namers for tags we don't claim to support.
   153  	for _, base := range language.Supported.BaseLanguages() {
   154  		tag, _ := language.All.Compose(base)
   155  		// Skip tags that are supported after matching.
   156  		if _, _, conf := matcher.Match(tag); conf != language.No {
   157  			continue
   158  		}
   159  		// Test there are no Namers for this tag.
   160  		for _, kind := range namerFuncs {
   161  			if defined(t, kind.kind, kind.fn(tag), tag) {
   162  				t.Errorf("%[1]s(%[2]s) returns a Namer, but %[2]s is not in the set of supported Tags.", kind.kind, tag)
   163  			}
   164  		}
   165  	}
   166  }
   167  
   168  // defined reports whether n is a proper Namer, which means it is non-nil and
   169  // must have at least one non-empty value.
   170  func defined(t *testing.T, kind string, n Namer, tag language.Tag) bool {
   171  	if n == nil {
   172  		return false
   173  	}
   174  	switch kind {
   175  	case "Tags":
   176  		for _, t := range Values.Tags() {
   177  			if n.Name(t) != "" {
   178  				return true
   179  			}
   180  		}
   181  	case "Languages":
   182  		for _, t := range Values.BaseLanguages() {
   183  			if n.Name(t) != "" {
   184  				return true
   185  			}
   186  		}
   187  	case "Regions":
   188  		for _, t := range Values.Regions() {
   189  			if n.Name(t) != "" {
   190  				return true
   191  			}
   192  		}
   193  	case "Scripts":
   194  		for _, t := range Values.Scripts() {
   195  			if n.Name(t) != "" {
   196  				return true
   197  			}
   198  		}
   199  	}
   200  	t.Errorf("%s(%s) returns non-nil Namer without content", kind, tag)
   201  	return false
   202  }
   203  
   204  func TestCoverage(t *testing.T) {
   205  	en := language.English
   206  	tests := []struct {
   207  		n Namer
   208  		x interface{}
   209  	}{
   210  		{Languages(en), Values.Tags()},
   211  		{Scripts(en), Values.Scripts()},
   212  		{Regions(en), Values.Regions()},
   213  	}
   214  	for i, tt := range tests {
   215  		uniq := make(map[string]interface{})
   216  
   217  		v := reflect.ValueOf(tt.x)
   218  		for j := 0; j < v.Len(); j++ {
   219  			x := v.Index(j).Interface()
   220  			// As of version 28 there is no data for az-Arab in English,
   221  			// although there is useful data in other languages.
   222  			if x.(fmt.Stringer).String() == "az-Arab" {
   223  				continue
   224  			}
   225  			s := tt.n.Name(x)
   226  			if s == "" {
   227  				t.Errorf("%d:%d:%s: missing content", i, j, x)
   228  			} else if uniq[s] != nil {
   229  				t.Errorf("%d:%d:%s: identical return value %q for %v and %v", i, j, x, s, x, uniq[s])
   230  			}
   231  			uniq[s] = x
   232  		}
   233  	}
   234  }
   235  
   236  // TestUpdate tests whether dictionary entries for certain languages need to be
   237  // updated. For some languages, some of the headers may be empty or they may be
   238  // identical to the parent. This code detects if such entries need to be updated
   239  // after a table update.
   240  func TestUpdate(t *testing.T) {
   241  	tests := []struct {
   242  		d   *Dictionary
   243  		tag string
   244  	}{
   245  		{ModernStandardArabic, "ar-001"},
   246  		{AmericanEnglish, "en-US"},
   247  		{EuropeanSpanish, "es-ES"},
   248  		{BrazilianPortuguese, "pt-BR"},
   249  		{SimplifiedChinese, "zh-Hans"},
   250  	}
   251  
   252  	for _, tt := range tests {
   253  		_, i, _ := matcher.Match(language.MustParse(tt.tag))
   254  		if !reflect.DeepEqual(tt.d.lang, langHeaders[i]) {
   255  			t.Errorf("%s: lang table update needed", tt.tag)
   256  		}
   257  		if !reflect.DeepEqual(tt.d.script, scriptHeaders[i]) {
   258  			t.Errorf("%s: script table update needed", tt.tag)
   259  		}
   260  		if !reflect.DeepEqual(tt.d.region, regionHeaders[i]) {
   261  			t.Errorf("%s: region table update needed", tt.tag)
   262  		}
   263  	}
   264  }
   265  
   266  func TestIndex(t *testing.T) {
   267  	notIn := []string{"aa", "xx", "zz", "aaa", "xxx", "zzz", "Aaaa", "Xxxx", "Zzzz"}
   268  	tests := []tagIndex{
   269  		{
   270  			"",
   271  			"",
   272  			"",
   273  		},
   274  		{
   275  			"bb",
   276  			"",
   277  			"",
   278  		},
   279  		{
   280  			"",
   281  			"bbb",
   282  			"",
   283  		},
   284  		{
   285  			"",
   286  			"",
   287  			"Bbbb",
   288  		},
   289  		{
   290  			"bb",
   291  			"bbb",
   292  			"Bbbb",
   293  		},
   294  		{
   295  			"bbccddyy",
   296  			"bbbcccdddyyy",
   297  			"BbbbCcccDdddYyyy",
   298  		},
   299  	}
   300  	for i, tt := range tests {
   301  		// Create the test set from the tagIndex.
   302  		cnt := 0
   303  		for sz := 2; sz <= 4; sz++ {
   304  			a := tt[sz-2]
   305  			for j := 0; j < len(a); j += sz {
   306  				s := a[j : j+sz]
   307  				if idx := tt.index(s); idx != cnt {
   308  					t.Errorf("%d:%s: index was %d; want %d", i, s, idx, cnt)
   309  				}
   310  				cnt++
   311  			}
   312  		}
   313  		if n := tt.len(); n != cnt {
   314  			t.Errorf("%d: len was %d; want %d", i, n, cnt)
   315  		}
   316  		for _, x := range notIn {
   317  			if idx := tt.index(x); idx != -1 {
   318  				t.Errorf("%d:%s: index was %d; want -1", i, x, idx)
   319  			}
   320  		}
   321  	}
   322  }
   323  
   324  func TestTag(t *testing.T) {
   325  	tests := []struct {
   326  		dict string
   327  		tag  string
   328  		name string
   329  	}{
   330  		// sr is in Value.Languages(), but is not supported by agq.
   331  		{"agq", "sr", "|[language: sr]"},
   332  		{"nl", "nl", "Nederlands"},
   333  		// CLDR 30 dropped Vlaams as the word for nl-BE. It is still called
   334  		// Flemish in English, though. TODO: check if this is a CLDR bug.
   335  		// {"nl", "nl-BE", "Vlaams"},
   336  		{"nl", "nl-BE", "Nederlands (België)"},
   337  		{"nl", "vls", "West-Vlaams"},
   338  		{"en", "nl-BE", "Flemish"},
   339  		{"en", "en", "English"},
   340  		{"en", "en-GB", "British English"},
   341  		{"en", "en-US", "American English"}, // American English in CLDR 24+
   342  		{"ru", "ru", "русский"},
   343  		{"ru", "ru-RU", "русский (Россия)"},
   344  		{"ru", "ru-Cyrl", "русский (кириллица)"},
   345  		{"en", lastLang2zu.String(), "Zulu"},
   346  		{"en", firstLang2aa.String(), "Afar"},
   347  		{"en", lastLang3zza.String(), "Zaza"},
   348  		{"en", firstLang3ace.String(), "Achinese"},
   349  		{"en", firstTagAr001.String(), "Modern Standard Arabic"},
   350  		{"en", lastTagZhHant.String(), "Traditional Chinese"},
   351  		{"en", "aaa", "|Unknown language (aaa)"},
   352  		{"en", "zzj", "|Unknown language (zzj)"},
   353  		// If full tag doesn't match, try without script or region.
   354  		{"en", "aa-Hans", "Afar (Simplified Han)"},
   355  		{"en", "af-Arab", "Afrikaans (Arabic)"},
   356  		{"en", "zu-Cyrl", "Zulu (Cyrillic)"},
   357  		{"en", "aa-GB", "Afar (United Kingdom)"},
   358  		{"en", "af-NA", "Afrikaans (Namibia)"},
   359  		{"en", "zu-BR", "Zulu (Brazil)"},
   360  		// Correct inheritance and language selection.
   361  		{"zh", "zh-TW", "中文 (台湾)"},
   362  		{"zh", "zh-Hant-TW", "繁体中文 (台湾)"},
   363  		{"zh-Hant", "zh-TW", "中文 (台灣)"},
   364  		{"zh-Hant", "zh-Hant-TW", "繁體中文 (台灣)"},
   365  		// Some rather arbitrary interpretations for Serbian. This is arguably
   366  		// correct and consistent with the way zh-[Hant-]TW is handled. It will
   367  		// also give results more in line with the expectations if users
   368  		// explicitly use "sh".
   369  		{"sr-Latn", "sr-ME", "srpski (Crna Gora)"},
   370  		{"sr-Latn", "sr-Latn-ME", "srpskohrvatski (Crna Gora)"},
   371  		// Double script and region
   372  		{"nl", "en-Cyrl-BE", "Engels (Cyrillisch, België)"},
   373  	}
   374  	for _, tt := range tests {
   375  		t.Run(tt.dict+"/"+tt.tag, func(t *testing.T) {
   376  			name, fmtName := splitName(tt.name)
   377  			dict := language.MustParse(tt.dict)
   378  			tag := language.Raw.MustParse(tt.tag)
   379  			d := Tags(dict)
   380  			if n := d.Name(tag); n != name {
   381  				// There are inconsistencies w.r.t. capitalization in the tests
   382  				// due to CLDR's update procedure which treats modern and other
   383  				// languages differently.
   384  				// See https://unicode.org/cldr/trac/ticket/8051.
   385  				// TODO: use language capitalization to sanitize the strings.
   386  				t.Errorf("Name(%s) = %q; want %q", tag, n, name)
   387  			}
   388  
   389  			p := message.NewPrinter(dict)
   390  			if n := p.Sprint(Tag(tag)); n != fmtName {
   391  				t.Errorf("Tag(%s) = %q; want %q", tag, n, fmtName)
   392  			}
   393  		})
   394  	}
   395  }
   396  
   397  func splitName(names string) (name, formatName string) {
   398  	split := strings.Split(names, "|")
   399  	name, formatName = split[0], split[0]
   400  	if len(split) > 1 {
   401  		formatName = split[1]
   402  	}
   403  	return name, formatName
   404  }
   405  
   406  func TestLanguage(t *testing.T) {
   407  	tests := []struct {
   408  		dict string
   409  		tag  string
   410  		name string
   411  	}{
   412  		// sr is in Value.Languages(), but is not supported by agq.
   413  		{"agq", "sr", "|[language: sr]"},
   414  		// CLDR 30 dropped Vlaams as the word for nl-BE. It is still called
   415  		// Flemish in English, though. TODO: this is probably incorrect.
   416  		// West-Vlaams (vls) is not Vlaams. West-Vlaams could be considered its
   417  		// own language, whereas Vlaams is generally Dutch. So expect to have
   418  		// to change these tests back.
   419  		{"nl", "nl", "Nederlands"},
   420  		{"nl", "vls", "West-Vlaams"},
   421  		{"nl", "nl-BE", "Nederlands"},
   422  		{"en", "pt", "Portuguese"},
   423  		{"en", "pt-PT", "European Portuguese"},
   424  		{"en", "pt-BR", "Brazilian Portuguese"},
   425  		{"en", "en", "English"},
   426  		{"en", "en-GB", "British English"},
   427  		{"en", "en-US", "American English"}, // American English in CLDR 24+
   428  		{"en", lastLang2zu.String(), "Zulu"},
   429  		{"en", firstLang2aa.String(), "Afar"},
   430  		{"en", lastLang3zza.String(), "Zaza"},
   431  		{"en", firstLang3ace.String(), "Achinese"},
   432  		{"en", firstTagAr001.String(), "Modern Standard Arabic"},
   433  		{"en", lastTagZhHant.String(), "Traditional Chinese"},
   434  		{"en", "aaa", "|Unknown language (aaa)"},
   435  		{"en", "zzj", "|Unknown language (zzj)"},
   436  		// If full tag doesn't match, try without script or region.
   437  		{"en", "aa-Hans", "Afar"},
   438  		{"en", "af-Arab", "Afrikaans"},
   439  		{"en", "zu-Cyrl", "Zulu"},
   440  		{"en", "aa-GB", "Afar"},
   441  		{"en", "af-NA", "Afrikaans"},
   442  		{"en", "zu-BR", "Zulu"},
   443  		{"agq", "zh-Hant", "|[language: zh-Hant]"},
   444  		{"en", "sh", "Serbo-Croatian"},
   445  		{"en", "sr-Latn", "Serbo-Croatian"},
   446  		{"en", "sr", "Serbian"},
   447  		{"en", "sr-ME", "Serbian"},
   448  		{"en", "sr-Latn-ME", "Serbo-Croatian"}, // See comments in TestTag.
   449  	}
   450  	for _, tt := range tests {
   451  		t.Run(tt.dict+"/"+tt.tag, func(t *testing.T) {
   452  			name, fmtName := splitName(tt.name)
   453  			dict := language.MustParse(tt.dict)
   454  			tag := language.Raw.MustParse(tt.tag)
   455  			p := message.NewPrinter(dict)
   456  			d := Languages(dict)
   457  			if n := d.Name(tag); n != name {
   458  				t.Errorf("Name(%v) = %q; want %q", tag, n, name)
   459  			}
   460  			if n := p.Sprint(Language(tag)); n != fmtName {
   461  				t.Errorf("Language(%v) = %q; want %q", tag, n, fmtName)
   462  			}
   463  			if len(tt.tag) <= 3 {
   464  				base := language.MustParseBase(tt.tag)
   465  				if n := d.Name(base); n != name {
   466  					t.Errorf("Name(%v) = %q; want %q", base, n, name)
   467  				}
   468  				if n := p.Sprint(Language(base)); n != fmtName {
   469  					t.Errorf("Language(%v) = %q; want %q", base, n, fmtName)
   470  				}
   471  			}
   472  		})
   473  	}
   474  }
   475  
   476  func TestScript(t *testing.T) {
   477  	tests := []struct {
   478  		dict string
   479  		scr  string
   480  		name string
   481  	}{
   482  		{"nl", "Arab", "Arabisch"},
   483  		{"en", "Arab", "Arabic"},
   484  		{"en", "Zzzz", "Unknown Script"},
   485  		{"zh-Hant", "Hang", "韓文字"},
   486  		{"zh-Hant-HK", "Hang", "韓文字"},
   487  		{"zh", "Arab", "阿拉伯文"},
   488  		{"zh-Hans-HK", "Arab", "阿拉伯文"}, // same as zh
   489  		{"zh-Hant", "Arab", "阿拉伯文"},
   490  		{"zh-Hant-HK", "Arab", "阿拉伯文"}, // same as zh
   491  		// Canonicalized form
   492  		{"en", "Qaai", "Inherited"},    // deprecated script, now is Zinh
   493  		{"en", "sh", "Unknown Script"}, // sh canonicalizes to sr-Latn
   494  		{"en", "en", "Unknown Script"},
   495  		// Don't introduce scripts with canonicalization.
   496  		{"en", "sh", "Unknown Script"}, // sh canonicalizes to sr-Latn
   497  	}
   498  	for _, tt := range tests {
   499  		t.Run(tt.dict+"/"+tt.scr, func(t *testing.T) {
   500  			name, fmtName := splitName(tt.name)
   501  			dict := language.MustParse(tt.dict)
   502  			p := message.NewPrinter(dict)
   503  			d := Scripts(dict)
   504  			var tag language.Tag
   505  			if unicode.IsUpper(rune(tt.scr[0])) {
   506  				x := language.MustParseScript(tt.scr)
   507  				if n := d.Name(x); n != name {
   508  					t.Errorf("Name(%v) = %q; want %q", x, n, name)
   509  				}
   510  				if n := p.Sprint(Script(x)); n != fmtName {
   511  					t.Errorf("Script(%v) = %q; want %q", x, n, fmtName)
   512  				}
   513  				tag, _ = language.Raw.Compose(x)
   514  			} else {
   515  				tag = language.Raw.MustParse(tt.scr)
   516  			}
   517  			if n := d.Name(tag); n != name {
   518  				t.Errorf("Name(%v) = %q; want %q", tag, n, name)
   519  			}
   520  			if n := p.Sprint(Script(tag)); n != fmtName {
   521  				t.Errorf("Script(%v) = %q; want %q", tag, n, fmtName)
   522  			}
   523  		})
   524  	}
   525  }
   526  
   527  func TestRegion(t *testing.T) {
   528  	tests := []struct {
   529  		dict string
   530  		reg  string
   531  		name string
   532  	}{
   533  		{"nl", "NL", "Nederland"},
   534  		{"en", "US", "United States"},
   535  		{"en", "ZZ", "Unknown Region"},
   536  		{"en-GB", "NL", "Netherlands"},
   537  		// Canonical equivalents
   538  		{"en", "UK", "United Kingdom"},
   539  		// No region
   540  		{"en", "pt", "Unknown Region"},
   541  		{"en", "und", "Unknown Region"},
   542  		// Don't introduce regions with canonicalization.
   543  		{"en", "mo", "Unknown Region"},
   544  	}
   545  	for _, tt := range tests {
   546  		t.Run(tt.dict+"/"+tt.reg, func(t *testing.T) {
   547  			dict := language.MustParse(tt.dict)
   548  			p := message.NewPrinter(dict)
   549  			d := Regions(dict)
   550  			var tag language.Tag
   551  			if unicode.IsUpper(rune(tt.reg[0])) {
   552  				// Region
   553  				x := language.MustParseRegion(tt.reg)
   554  				if n := d.Name(x); n != tt.name {
   555  					t.Errorf("Name(%v) = %q; want %q", x, n, tt.name)
   556  				}
   557  				if n := p.Sprint(Region(x)); n != tt.name {
   558  					t.Errorf("Region(%v) = %q; want %q", x, n, tt.name)
   559  				}
   560  				tag, _ = language.Raw.Compose(x)
   561  			} else {
   562  				tag = language.Raw.MustParse(tt.reg)
   563  			}
   564  			if n := d.Name(tag); n != tt.name {
   565  				t.Errorf("Name(%v) = %q; want %q", tag, n, tt.name)
   566  			}
   567  			if n := p.Sprint(Region(tag)); n != tt.name {
   568  				t.Errorf("Region(%v) = %q; want %q", tag, n, tt.name)
   569  			}
   570  		})
   571  	}
   572  }
   573  
   574  func TestSelf(t *testing.T) {
   575  	tests := []struct {
   576  		tag  string
   577  		name string
   578  	}{
   579  		{"nl", "Nederlands"},
   580  		// CLDR 30 dropped Vlaams as the word for nl-BE. It is still called
   581  		// Flemish in English, though. TODO: check if this is a CLDR bug.
   582  		// {"nl-BE", "Vlaams"},
   583  		{"nl-BE", "Nederlands"},
   584  		{"en-GB", "British English"},
   585  		{lastLang2zu.String(), "isiZulu"},
   586  		{firstLang2aa.String(), ""},  // not defined
   587  		{lastLang3zza.String(), ""},  // not defined
   588  		{firstLang3ace.String(), ""}, // not defined
   589  		{firstTagAr001.String(), "العربية الرسمية الحديثة"},
   590  		{"ar", "العربية"},
   591  		{lastTagZhHant.String(), "繁體中文"},
   592  		{"aaa", ""},
   593  		{"zzj", ""},
   594  		// Drop entries that are not in the requested script, even if there is
   595  		// an entry for the language.
   596  		{"aa-Hans", ""},
   597  		{"af-Arab", ""},
   598  		{"zu-Cyrl", ""},
   599  		// Append the country name in the language of the matching language.
   600  		{"af-NA", "Afrikaans"},
   601  		{"zh", "中文"},
   602  		// zh-TW should match zh-Hant instead of zh!
   603  		{"zh-TW", "繁體中文"},
   604  		{"zh-Hant", "繁體中文"},
   605  		{"zh-Hans", "简体中文"},
   606  		{"zh-Hant-TW", "繁體中文"},
   607  		{"zh-Hans-TW", "简体中文"},
   608  		// Take the entry for sr which has the matching script.
   609  		// TODO: Capitalization changed as of CLDR 26, but change seems
   610  		// arbitrary. Revisit capitalization with revision 27. See
   611  		// https://unicode.org/cldr/trac/ticket/8051.
   612  		{"sr", "српски"},
   613  		// TODO: sr-ME should show up as Serbian or Montenegrin, not Serbo-
   614  		// Croatian. This is an artifact of the current algorithm, which is the
   615  		// way it is to have the preferred behavior for other languages such as
   616  		// Chinese. We can hardwire this case in the table generator or package
   617  		// code, but we first check if CLDR can be updated.
   618  		// {"sr-ME", "Srpski"}, // Is Srpskohrvatski
   619  		{"sr-Latn-ME", "srpskohrvatski"},
   620  		{"sr-Cyrl-ME", "српски"},
   621  		{"sr-NL", "српски"},
   622  		// NOTE: kk is defined, but in Cyrillic script. For China, Arab is the
   623  		// dominant script. We do not have data for kk-Arab and we chose to not
   624  		// fall back in such cases.
   625  		{"kk-CN", ""},
   626  	}
   627  	for i, tt := range tests {
   628  		d := Self
   629  		if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name {
   630  			t.Errorf("%d:%s: was %q; want %q", i, tt.tag, n, tt.name)
   631  		}
   632  	}
   633  }
   634  
   635  func TestEquivalence(t *testing.T) {
   636  	testCases := []struct {
   637  		desc  string
   638  		namer Namer
   639  	}{
   640  		{"Self", Self},
   641  		{"Tags", Tags(language.Romanian)},
   642  		{"Languages", Languages(language.Romanian)},
   643  		{"Scripts", Scripts(language.Romanian)},
   644  	}
   645  	for _, tc := range testCases {
   646  		t.Run(tc.desc, func(t *testing.T) {
   647  			ro := tc.namer.Name(language.Raw.MustParse("ro-MD"))
   648  			mo := tc.namer.Name(language.Raw.MustParse("mo"))
   649  			if ro != mo {
   650  				t.Errorf("%q != %q", ro, mo)
   651  			}
   652  		})
   653  	}
   654  }
   655  
   656  func TestDictionaryLang(t *testing.T) {
   657  	tests := []struct {
   658  		d    *Dictionary
   659  		tag  string
   660  		name string
   661  	}{
   662  		{English, "en", "English"},
   663  		{Portuguese, "af", "africâner"},
   664  		{EuropeanPortuguese, "af", "africanês"},
   665  		{English, "nl-BE", "Flemish"},
   666  	}
   667  	for i, test := range tests {
   668  		tag := language.MustParse(test.tag)
   669  		if got := test.d.Tags().Name(tag); got != test.name {
   670  			t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
   671  		}
   672  		if base, _ := language.Compose(tag.Base()); base == tag {
   673  			if got := test.d.Languages().Name(base); got != test.name {
   674  				t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
   675  			}
   676  		}
   677  	}
   678  }
   679  
   680  func TestDictionaryRegion(t *testing.T) {
   681  	tests := []struct {
   682  		d      *Dictionary
   683  		region string
   684  		name   string
   685  	}{
   686  		{English, "FR", "France"},
   687  		{Portuguese, "009", "Oceania"},
   688  		{EuropeanPortuguese, "009", "Oceânia"},
   689  	}
   690  	for i, test := range tests {
   691  		tag := language.MustParseRegion(test.region)
   692  		if got := test.d.Regions().Name(tag); got != test.name {
   693  			t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
   694  		}
   695  	}
   696  }
   697  
   698  func TestDictionaryScript(t *testing.T) {
   699  	tests := []struct {
   700  		d      *Dictionary
   701  		script string
   702  		name   string
   703  	}{
   704  		{English, "Cyrl", "Cyrillic"},
   705  		{EuropeanPortuguese, "Gujr", "guzerate"},
   706  	}
   707  	for i, test := range tests {
   708  		tag := language.MustParseScript(test.script)
   709  		if got := test.d.Scripts().Name(tag); got != test.name {
   710  			t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
   711  		}
   712  	}
   713  }
   714  

View as plain text