feature #32988 [Intl] Support ISO 3166-1 Alpha-3 country codes (terjebraten-certua)

This PR was merged into the 4.4 branch.

Discussion
----------

[Intl] Support ISO 3166-1 Alpha-3 country codes

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #20313
| Doc PR | symfony/symfony-docs#12105
| License       | MIT

This is a pre-requiste for fixing #20313 and only handles the changes to the INTL component.

Commits
-------

848f60e905 Support ISO 3166-1 Alpha-3 country codes
This commit is contained in:
Fabien Potencier 2019-08-09 11:14:26 +02:00
commit 32b2a5251d
9 changed files with 1262 additions and 9 deletions

View File

@ -5,6 +5,7 @@ CHANGELOG
-----
* excluded language code `root`
* added to both `Countries` and `Languages` the methods `getAlpha3Codes`, `getAlpha3Code`, `getAlpha2Code`, `alpha3CodeExists`, `getAlpha3Name` and `getAlpha3Names`
4.3.0
-----

View File

@ -39,12 +39,44 @@ final class Countries extends ResourceBundle
}
/**
* @param string $country Alpha2 country code
* Returns all available countries (3 letters).
*
* Countries are returned as uppercase ISO 3166 three-letter country codes.
*
* This list only contains "officially assigned ISO 3166-1 alpha-3" country codes.
*
* @return string[] an array of canonical ISO 3166 alpha-3 country codes
*/
public static function exists(string $country): bool
public static function getAlpha3Codes(): array
{
return self::readEntry(['Alpha2ToAlpha3'], 'meta');
}
public static function getAlpha3Code(string $alpha2Code): string
{
return self::readEntry(['Alpha2ToAlpha3', $alpha2Code], 'meta');
}
public static function getAlpha2Code(string $alpha3Code): string
{
return self::readEntry(['Alpha3ToAlpha2', $alpha3Code], 'meta');
}
public static function exists(string $alpha2Code): bool
{
try {
self::readEntry(['Names', $country]);
self::readEntry(['Names', $alpha2Code]);
return true;
} catch (MissingResourceException $e) {
return false;
}
}
public static function alpha3CodeExists(string $alpha3Code): bool
{
try {
self::getAlpha2Code($alpha3Code);
return true;
} catch (MissingResourceException $e) {
@ -53,15 +85,25 @@ final class Countries extends ResourceBundle
}
/**
* Gets the country name from alpha2 code.
* Gets the country name from its alpha2 code.
*
* @throws MissingResourceException if the country code does not exists
* @throws MissingResourceException if the country code does not exist
*/
public static function getName(string $country, string $displayLocale = null): string
{
return self::readEntry(['Names', $country], $displayLocale);
}
/**
* Gets the country name from its alpha3 code.
*
* @throws MissingResourceException if the country code does not exist
*/
public static function getAlpha3Name(string $alpha3Code, string $displayLocale = null): string
{
return self::getName(self::getAlpha2Code($alpha3Code), $displayLocale);
}
/**
* Gets the list of country names indexed with alpha2 codes as keys.
*
@ -72,6 +114,24 @@ final class Countries extends ResourceBundle
return self::asort(self::readEntry(['Names'], $displayLocale), $displayLocale);
}
/**
* Gets the list of country names indexed with alpha3 codes as keys.
*
* Same as method getNames, but with alpha3 codes instead of alpha2 codes as keys.
*
* @return string[]
*/
public static function getAlpha3Names($displayLocale = null): array
{
$alpha2Names = self::getNames($displayLocale);
$alpha3Names = [];
foreach ($alpha2Names as $alpha2Code => $name) {
$alpha3Names[self::getAlpha3Code($alpha2Code)] = $name;
}
return $alpha3Names;
}
protected static function getPath(): string
{
return Intl::getDataDirectory().'/'.Intl::REGION_DIR;

View File

@ -162,11 +162,16 @@ class LanguageDataGenerator extends AbstractDataGenerator
sort($this->languageCodes);
$alpha2ToAlpha3 = $this->generateAlpha2ToAlpha3Mapping($metadataBundle);
$alpha3ToAlpha2 = array_flip($alpha2ToAlpha3);
asort($alpha3ToAlpha2);
return [
'Version' => $rootBundle['Version'],
'Languages' => $this->languageCodes,
'Aliases' => array_column(iterator_to_array($metadataBundle['alias']['language']), 'replacement'),
'Alpha2ToAlpha3' => $this->generateAlpha2ToAlpha3Mapping($metadataBundle),
'Alpha2ToAlpha3' => $alpha2ToAlpha3,
'Alpha3ToAlpha2' => $alpha3ToAlpha2,
];
}

View File

@ -27,6 +27,17 @@ use Symfony\Component\Intl\Data\Util\LocaleScanner;
*/
class RegionDataGenerator extends AbstractDataGenerator
{
/**
* Source https://www.iso.org/obp/ui/#iso:pub:PUB500001:en
*/
private static $preferredAlpha2ToAlpha3Mapping = [
'DE' => 'DEU',
'FR' => 'FRA',
'MM' => 'MMR',
'TL' => 'TLS',
'YE' => 'YEM',
];
private static $blacklist = [
// Exceptional reservations
'AC' => true, // Ascension Island
@ -82,6 +93,7 @@ class RegionDataGenerator extends AbstractDataGenerator
protected function compileTemporaryBundles(BundleCompilerInterface $compiler, $sourceDir, $tempDir)
{
$compiler->compile($sourceDir.'/region', $tempDir);
$compiler->compile($sourceDir.'/misc/metadata.txt', $tempDir);
}
/**
@ -125,14 +137,25 @@ class RegionDataGenerator extends AbstractDataGenerator
protected function generateDataForMeta(BundleEntryReaderInterface $reader, $tempDir)
{
$rootBundle = $reader->read($tempDir, 'root');
$metadataBundle = $reader->read($tempDir, 'metadata');
$this->regionCodes = array_unique($this->regionCodes);
$alpha2ToAlpha3 = $this->generateAlpha3($metadataBundle);
sort($this->regionCodes);
$alpha3ToAlpha2 = [];
foreach ($this->regionCodes as $alpha2Code) {
$alpha3code = $alpha2ToAlpha3[$alpha2Code];
$alpha3ToAlpha2[$alpha3code] = $alpha2Code;
}
return [
'Version' => $rootBundle['Version'],
'Regions' => $this->regionCodes,
'Alpha2ToAlpha3' => $alpha2ToAlpha3,
'Alpha3ToAlpha2' => $alpha3ToAlpha2,
];
}
@ -154,4 +177,38 @@ class RegionDataGenerator extends AbstractDataGenerator
return $regionNames;
}
protected function generateAlpha3(ArrayAccessibleResourceBundle $metadataBundle)
{
$alpha2Codes = array_flip($this->regionCodes);
$alpha2ToAlpha3 = [];
foreach ($metadataBundle['alias']['territory'] as $alias => $data) {
if (3 !== \strlen($alias) || 'overlong' !== $data['reason'] || ctype_digit($alias)) {
continue;
}
$alpha2Code = $data['replacement'];
if (!isset($alpha2Codes[$alpha2Code])) {
continue;
}
if (!isset($alpha2ToAlpha3[$alpha2Code])) {
$alpha2ToAlpha3[$alpha2Code] = $alias;
continue;
}
// Found a second alias for the same country
if (isset(self::$preferredAlpha2ToAlpha3Mapping[$alpha2Code])) {
$preferred = self::$preferredAlpha2ToAlpha3Mapping[$alpha2Code];
// Only use the preferred mapping if it actually is in the mapping
if ($alias === $preferred) {
$alpha2ToAlpha3[$alpha2Code] = $preferred;
}
}
}
asort($alpha2ToAlpha3);
return $alpha2ToAlpha3;
}
}

View File

@ -50,9 +50,9 @@ final class Languages extends ResourceBundle
}
/**
* Gets the language name from alpha2 code.
* Gets the language name from its alpha2 code.
*
* @throws MissingResourceException if the language code does not exists
* @throws MissingResourceException if the language code does not exist
*/
public static function getName(string $language, string $displayLocale = null): string
{
@ -79,6 +79,73 @@ final class Languages extends ResourceBundle
return self::readEntry(['Alpha2ToAlpha3', $language], 'meta');
}
/**
* Returns the ISO 639-1 two-letter code of a language, given a three letter code.
*
* @throws MissingResourceException if the language has no corresponding three-letter code
*/
public static function getAlpha2Code(string $language): string
{
return self::readEntry(['Alpha3ToAlpha2', $language], 'meta');
}
/**
* Returns all available languages as three-letter codes.
*
* Languages are returned as lowercase ISO 639-2 three-letter language codes.
*
* @return string[] an array of canonical ISO 639-2 language codes
*/
public static function getAlpha3Codes(): array
{
return self::readEntry(['Alpha2ToAlpha3'], 'meta');
}
/**
* @param string $language ISO 639-2 three-letter language code
*/
public static function alpha3CodeExists(string $language): bool
{
try {
self::getAlpha2Code($language);
return true;
} catch (MissingResourceException $e) {
return false;
}
}
/**
* Gets the language name from its ISO 639-2 three-letter code.
*
* @throws MissingResourceException if the country code does not exists
*/
public static function getAlpha3Name(string $language, string $displayLocale = null): string
{
return self::getName(self::getAlpha2Code($language), $displayLocale);
}
/**
* Gets the list of language names indexed with ISO 639-2 three-letter codes as keys.
*
* Same as method getNames, but with ISO 639-2 three-letter codes instead of ISO 639-1 codes as keys.
*
* @return string[]
*/
public static function getAlpha3Names($displayLocale = null): array
{
$alpha2Names = self::getNames($displayLocale);
$alpha3Names = [];
foreach ($alpha2Names as $alpha2Code => $name) {
try {
$alpha3Names[self::getAlpha3Code($alpha2Code)] = $name;
} catch (MissingResourceException $e) {
}
}
return $alpha3Names;
}
protected static function getPath(): string
{
return Intl::getDataDirectory().'/'.Intl::LANGUAGE_DIR;

View File

@ -800,5 +800,187 @@
"za": "zha",
"zh": "zho",
"zu": "zul"
},
"Alpha3ToAlpha2": {
"aar": "aa",
"abk": "ab",
"ave": "ae",
"afr": "af",
"aka": "ak",
"amh": "am",
"arg": "an",
"ara": "ar",
"asm": "as",
"ava": "av",
"aym": "ay",
"aze": "az",
"bak": "ba",
"bel": "be",
"bul": "bg",
"bis": "bi",
"bam": "bm",
"ben": "bn",
"bod": "bo",
"bre": "br",
"bos": "bs",
"cat": "ca",
"che": "ce",
"cha": "ch",
"cos": "co",
"cre": "cr",
"ces": "cs",
"chu": "cu",
"chv": "cv",
"cym": "cy",
"dan": "da",
"deu": "de",
"div": "dv",
"dzo": "dz",
"ewe": "ee",
"ell": "el",
"eng": "en",
"epo": "eo",
"spa": "es",
"est": "et",
"eus": "eu",
"fas": "fa",
"ful": "ff",
"fin": "fi",
"fij": "fj",
"fao": "fo",
"fra": "fr",
"fry": "fy",
"gle": "ga",
"gla": "gd",
"glg": "gl",
"grn": "gn",
"guj": "gu",
"glv": "gv",
"hau": "ha",
"heb": "he",
"hin": "hi",
"hmo": "ho",
"hrv": "hr",
"hat": "ht",
"hun": "hu",
"hye": "hy",
"her": "hz",
"ina": "ia",
"ind": "id",
"ile": "ie",
"ibo": "ig",
"iii": "ii",
"ipk": "ik",
"ido": "io",
"isl": "is",
"ita": "it",
"iku": "iu",
"jpn": "ja",
"jav": "jv",
"kat": "ka",
"kon": "kg",
"kik": "ki",
"kua": "kj",
"kaz": "kk",
"kal": "kl",
"khm": "km",
"kan": "kn",
"kor": "ko",
"kau": "kr",
"kas": "ks",
"kur": "ku",
"kom": "kv",
"cor": "kw",
"kir": "ky",
"lat": "la",
"ltz": "lb",
"lug": "lg",
"lim": "li",
"lin": "ln",
"lao": "lo",
"lit": "lt",
"lub": "lu",
"lav": "lv",
"mlg": "mg",
"mah": "mh",
"mri": "mi",
"mkd": "mk",
"mal": "ml",
"mon": "mn",
"mar": "mr",
"msa": "ms",
"mlt": "mt",
"mya": "my",
"nau": "na",
"nob": "nb",
"nde": "nd",
"nep": "ne",
"ndo": "ng",
"nld": "nl",
"nno": "nn",
"nbl": "nr",
"nav": "nv",
"nya": "ny",
"oci": "oc",
"oji": "oj",
"orm": "om",
"ori": "or",
"oss": "os",
"pan": "pa",
"pli": "pi",
"pol": "pl",
"pus": "ps",
"por": "pt",
"que": "qu",
"roh": "rm",
"run": "rn",
"ron": "ro",
"rus": "ru",
"kin": "rw",
"san": "sa",
"srd": "sc",
"snd": "sd",
"sme": "se",
"sag": "sg",
"sin": "si",
"slk": "sk",
"slv": "sl",
"smo": "sm",
"sna": "sn",
"som": "so",
"sqi": "sq",
"srp": "sr",
"ssw": "ss",
"sot": "st",
"sun": "su",
"swe": "sv",
"swa": "sw",
"tam": "ta",
"tel": "te",
"tgk": "tg",
"tha": "th",
"tir": "ti",
"tuk": "tk",
"tsn": "tn",
"ton": "to",
"tur": "tr",
"tso": "ts",
"tat": "tt",
"tah": "ty",
"uig": "ug",
"ukr": "uk",
"urd": "ur",
"uzb": "uz",
"ven": "ve",
"vie": "vi",
"vol": "vo",
"wln": "wa",
"wol": "wo",
"xho": "xh",
"yid": "yi",
"yor": "yo",
"zha": "za",
"zho": "zh",
"zul": "zu"
}
}

View File

@ -250,5 +250,507 @@
"ZA",
"ZM",
"ZW"
]
],
"Alpha2ToAlpha3": {
"AW": "ABW",
"AF": "AFG",
"AO": "AGO",
"AI": "AIA",
"AX": "ALA",
"AL": "ALB",
"AD": "AND",
"AE": "ARE",
"AR": "ARG",
"AM": "ARM",
"AS": "ASM",
"AQ": "ATA",
"TF": "ATF",
"AG": "ATG",
"AU": "AUS",
"AT": "AUT",
"AZ": "AZE",
"BI": "BDI",
"BE": "BEL",
"BJ": "BEN",
"BQ": "BES",
"BF": "BFA",
"BD": "BGD",
"BG": "BGR",
"BH": "BHR",
"BS": "BHS",
"BA": "BIH",
"BL": "BLM",
"BY": "BLR",
"BZ": "BLZ",
"BM": "BMU",
"BO": "BOL",
"BR": "BRA",
"BB": "BRB",
"BN": "BRN",
"BT": "BTN",
"BV": "BVT",
"BW": "BWA",
"CF": "CAF",
"CA": "CAN",
"CC": "CCK",
"CH": "CHE",
"CL": "CHL",
"CN": "CHN",
"CI": "CIV",
"CM": "CMR",
"CD": "COD",
"CG": "COG",
"CK": "COK",
"CO": "COL",
"KM": "COM",
"CV": "CPV",
"CR": "CRI",
"CU": "CUB",
"CW": "CUW",
"CX": "CXR",
"KY": "CYM",
"CY": "CYP",
"CZ": "CZE",
"DE": "DEU",
"DJ": "DJI",
"DM": "DMA",
"DK": "DNK",
"DO": "DOM",
"DZ": "DZA",
"EC": "ECU",
"EG": "EGY",
"ER": "ERI",
"EH": "ESH",
"ES": "ESP",
"EE": "EST",
"ET": "ETH",
"FI": "FIN",
"FJ": "FJI",
"FK": "FLK",
"FR": "FRA",
"FO": "FRO",
"FM": "FSM",
"GA": "GAB",
"GB": "GBR",
"GE": "GEO",
"GG": "GGY",
"GH": "GHA",
"GI": "GIB",
"GN": "GIN",
"GP": "GLP",
"GM": "GMB",
"GW": "GNB",
"GQ": "GNQ",
"GR": "GRC",
"GD": "GRD",
"GL": "GRL",
"GT": "GTM",
"GF": "GUF",
"GU": "GUM",
"GY": "GUY",
"HK": "HKG",
"HM": "HMD",
"HN": "HND",
"HR": "HRV",
"HT": "HTI",
"HU": "HUN",
"ID": "IDN",
"IM": "IMN",
"IN": "IND",
"IO": "IOT",
"IE": "IRL",
"IR": "IRN",
"IQ": "IRQ",
"IS": "ISL",
"IL": "ISR",
"IT": "ITA",
"JM": "JAM",
"JE": "JEY",
"JO": "JOR",
"JP": "JPN",
"KZ": "KAZ",
"KE": "KEN",
"KG": "KGZ",
"KH": "KHM",
"KI": "KIR",
"KN": "KNA",
"KR": "KOR",
"KW": "KWT",
"LA": "LAO",
"LB": "LBN",
"LR": "LBR",
"LY": "LBY",
"LC": "LCA",
"LI": "LIE",
"LK": "LKA",
"LS": "LSO",
"LT": "LTU",
"LU": "LUX",
"LV": "LVA",
"MO": "MAC",
"MF": "MAF",
"MA": "MAR",
"MC": "MCO",
"MD": "MDA",
"MG": "MDG",
"MV": "MDV",
"MX": "MEX",
"MH": "MHL",
"MK": "MKD",
"ML": "MLI",
"MT": "MLT",
"MM": "MMR",
"ME": "MNE",
"MN": "MNG",
"MP": "MNP",
"MZ": "MOZ",
"MR": "MRT",
"MS": "MSR",
"MQ": "MTQ",
"MU": "MUS",
"MW": "MWI",
"MY": "MYS",
"YT": "MYT",
"NA": "NAM",
"NC": "NCL",
"NE": "NER",
"NF": "NFK",
"NG": "NGA",
"NI": "NIC",
"NU": "NIU",
"NL": "NLD",
"NO": "NOR",
"NP": "NPL",
"NR": "NRU",
"NZ": "NZL",
"OM": "OMN",
"PK": "PAK",
"PA": "PAN",
"PN": "PCN",
"PE": "PER",
"PH": "PHL",
"PW": "PLW",
"PG": "PNG",
"PL": "POL",
"PR": "PRI",
"KP": "PRK",
"PT": "PRT",
"PY": "PRY",
"PS": "PSE",
"PF": "PYF",
"QA": "QAT",
"RE": "REU",
"RO": "ROU",
"RU": "RUS",
"RW": "RWA",
"SA": "SAU",
"SD": "SDN",
"SN": "SEN",
"SG": "SGP",
"GS": "SGS",
"SH": "SHN",
"SJ": "SJM",
"SB": "SLB",
"SL": "SLE",
"SV": "SLV",
"SM": "SMR",
"SO": "SOM",
"PM": "SPM",
"RS": "SRB",
"SS": "SSD",
"ST": "STP",
"SR": "SUR",
"SK": "SVK",
"SI": "SVN",
"SE": "SWE",
"SZ": "SWZ",
"SX": "SXM",
"SC": "SYC",
"SY": "SYR",
"TC": "TCA",
"TD": "TCD",
"TG": "TGO",
"TH": "THA",
"TJ": "TJK",
"TK": "TKL",
"TM": "TKM",
"TL": "TLS",
"TO": "TON",
"TT": "TTO",
"TN": "TUN",
"TR": "TUR",
"TV": "TUV",
"TW": "TWN",
"TZ": "TZA",
"UG": "UGA",
"UA": "UKR",
"UM": "UMI",
"UY": "URY",
"US": "USA",
"UZ": "UZB",
"VA": "VAT",
"VC": "VCT",
"VE": "VEN",
"VG": "VGB",
"VI": "VIR",
"VN": "VNM",
"VU": "VUT",
"WF": "WLF",
"WS": "WSM",
"YE": "YEM",
"ZA": "ZAF",
"ZM": "ZMB",
"ZW": "ZWE"
},
"Alpha3ToAlpha2": {
"AND": "AD",
"ARE": "AE",
"AFG": "AF",
"ATG": "AG",
"AIA": "AI",
"ALB": "AL",
"ARM": "AM",
"AGO": "AO",
"ATA": "AQ",
"ARG": "AR",
"ASM": "AS",
"AUT": "AT",
"AUS": "AU",
"ABW": "AW",
"ALA": "AX",
"AZE": "AZ",
"BIH": "BA",
"BRB": "BB",
"BGD": "BD",
"BEL": "BE",
"BFA": "BF",
"BGR": "BG",
"BHR": "BH",
"BDI": "BI",
"BEN": "BJ",
"BLM": "BL",
"BMU": "BM",
"BRN": "BN",
"BOL": "BO",
"BES": "BQ",
"BRA": "BR",
"BHS": "BS",
"BTN": "BT",
"BVT": "BV",
"BWA": "BW",
"BLR": "BY",
"BLZ": "BZ",
"CAN": "CA",
"CCK": "CC",
"COD": "CD",
"CAF": "CF",
"COG": "CG",
"CHE": "CH",
"CIV": "CI",
"COK": "CK",
"CHL": "CL",
"CMR": "CM",
"CHN": "CN",
"COL": "CO",
"CRI": "CR",
"CUB": "CU",
"CPV": "CV",
"CUW": "CW",
"CXR": "CX",
"CYP": "CY",
"CZE": "CZ",
"DEU": "DE",
"DJI": "DJ",
"DNK": "DK",
"DMA": "DM",
"DOM": "DO",
"DZA": "DZ",
"ECU": "EC",
"EST": "EE",
"EGY": "EG",
"ESH": "EH",
"ERI": "ER",
"ESP": "ES",
"ETH": "ET",
"FIN": "FI",
"FJI": "FJ",
"FLK": "FK",
"FSM": "FM",
"FRO": "FO",
"FRA": "FR",
"GAB": "GA",
"GBR": "GB",
"GRD": "GD",
"GEO": "GE",
"GUF": "GF",
"GGY": "GG",
"GHA": "GH",
"GIB": "GI",
"GRL": "GL",
"GMB": "GM",
"GIN": "GN",
"GLP": "GP",
"GNQ": "GQ",
"GRC": "GR",
"SGS": "GS",
"GTM": "GT",
"GUM": "GU",
"GNB": "GW",
"GUY": "GY",
"HKG": "HK",
"HMD": "HM",
"HND": "HN",
"HRV": "HR",
"HTI": "HT",
"HUN": "HU",
"IDN": "ID",
"IRL": "IE",
"ISR": "IL",
"IMN": "IM",
"IND": "IN",
"IOT": "IO",
"IRQ": "IQ",
"IRN": "IR",
"ISL": "IS",
"ITA": "IT",
"JEY": "JE",
"JAM": "JM",
"JOR": "JO",
"JPN": "JP",
"KEN": "KE",
"KGZ": "KG",
"KHM": "KH",
"KIR": "KI",
"COM": "KM",
"KNA": "KN",
"PRK": "KP",
"KOR": "KR",
"KWT": "KW",
"CYM": "KY",
"KAZ": "KZ",
"LAO": "LA",
"LBN": "LB",
"LCA": "LC",
"LIE": "LI",
"LKA": "LK",
"LBR": "LR",
"LSO": "LS",
"LTU": "LT",
"LUX": "LU",
"LVA": "LV",
"LBY": "LY",
"MAR": "MA",
"MCO": "MC",
"MDA": "MD",
"MNE": "ME",
"MAF": "MF",
"MDG": "MG",
"MHL": "MH",
"MKD": "MK",
"MLI": "ML",
"MMR": "MM",
"MNG": "MN",
"MAC": "MO",
"MNP": "MP",
"MTQ": "MQ",
"MRT": "MR",
"MSR": "MS",
"MLT": "MT",
"MUS": "MU",
"MDV": "MV",
"MWI": "MW",
"MEX": "MX",
"MYS": "MY",
"MOZ": "MZ",
"NAM": "NA",
"NCL": "NC",
"NER": "NE",
"NFK": "NF",
"NGA": "NG",
"NIC": "NI",
"NLD": "NL",
"NOR": "NO",
"NPL": "NP",
"NRU": "NR",
"NIU": "NU",
"NZL": "NZ",
"OMN": "OM",
"PAN": "PA",
"PER": "PE",
"PYF": "PF",
"PNG": "PG",
"PHL": "PH",
"PAK": "PK",
"POL": "PL",
"SPM": "PM",
"PCN": "PN",
"PRI": "PR",
"PSE": "PS",
"PRT": "PT",
"PLW": "PW",
"PRY": "PY",
"QAT": "QA",
"REU": "RE",
"ROU": "RO",
"SRB": "RS",
"RUS": "RU",
"RWA": "RW",
"SAU": "SA",
"SLB": "SB",
"SYC": "SC",
"SDN": "SD",
"SWE": "SE",
"SGP": "SG",
"SHN": "SH",
"SVN": "SI",
"SJM": "SJ",
"SVK": "SK",
"SLE": "SL",
"SMR": "SM",
"SEN": "SN",
"SOM": "SO",
"SUR": "SR",
"SSD": "SS",
"STP": "ST",
"SLV": "SV",
"SXM": "SX",
"SYR": "SY",
"SWZ": "SZ",
"TCA": "TC",
"TCD": "TD",
"ATF": "TF",
"TGO": "TG",
"THA": "TH",
"TJK": "TJ",
"TKL": "TK",
"TLS": "TL",
"TKM": "TM",
"TUN": "TN",
"TON": "TO",
"TUR": "TR",
"TTO": "TT",
"TUV": "TV",
"TWN": "TW",
"TZA": "TZ",
"UKR": "UA",
"UGA": "UG",
"UMI": "UM",
"USA": "US",
"URY": "UY",
"UZB": "UZ",
"VAT": "VA",
"VCT": "VC",
"VEN": "VE",
"VGB": "VG",
"VIR": "VI",
"VNM": "VN",
"VUT": "VU",
"WLF": "WF",
"WSM": "WS",
"YEM": "YE",
"MYT": "YT",
"ZAF": "ZA",
"ZMB": "ZM",
"ZWE": "ZW"
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Intl\Tests;
use Symfony\Component\Intl\Countries;
use Symfony\Component\Intl\Exception\MissingResourceException;
/**
* @group intl-data
@ -272,6 +273,258 @@ class CountriesTest extends ResourceBundleTestCase
'ZW',
];
private static $alpha2ToAlpha3 = [
'AW' => 'ABW',
'AF' => 'AFG',
'AO' => 'AGO',
'AI' => 'AIA',
'AX' => 'ALA',
'AL' => 'ALB',
'AD' => 'AND',
'AE' => 'ARE',
'AR' => 'ARG',
'AM' => 'ARM',
'AS' => 'ASM',
'AQ' => 'ATA',
'TF' => 'ATF',
'AG' => 'ATG',
'AU' => 'AUS',
'AT' => 'AUT',
'AZ' => 'AZE',
'BI' => 'BDI',
'BE' => 'BEL',
'BJ' => 'BEN',
'BQ' => 'BES',
'BF' => 'BFA',
'BD' => 'BGD',
'BG' => 'BGR',
'BH' => 'BHR',
'BS' => 'BHS',
'BA' => 'BIH',
'BL' => 'BLM',
'BY' => 'BLR',
'BZ' => 'BLZ',
'BM' => 'BMU',
'BO' => 'BOL',
'BR' => 'BRA',
'BB' => 'BRB',
'BN' => 'BRN',
'BT' => 'BTN',
'BV' => 'BVT',
'BW' => 'BWA',
'CF' => 'CAF',
'CA' => 'CAN',
'CC' => 'CCK',
'CH' => 'CHE',
'CL' => 'CHL',
'CN' => 'CHN',
'CI' => 'CIV',
'CM' => 'CMR',
'CD' => 'COD',
'CG' => 'COG',
'CK' => 'COK',
'CO' => 'COL',
'KM' => 'COM',
'CV' => 'CPV',
'CR' => 'CRI',
'CU' => 'CUB',
'CW' => 'CUW',
'CX' => 'CXR',
'KY' => 'CYM',
'CY' => 'CYP',
'CZ' => 'CZE',
'DE' => 'DEU',
'DJ' => 'DJI',
'DM' => 'DMA',
'DK' => 'DNK',
'DO' => 'DOM',
'DZ' => 'DZA',
'EC' => 'ECU',
'EG' => 'EGY',
'ER' => 'ERI',
'EH' => 'ESH',
'ES' => 'ESP',
'EE' => 'EST',
'ET' => 'ETH',
'FI' => 'FIN',
'FJ' => 'FJI',
'FK' => 'FLK',
'FR' => 'FRA',
'FO' => 'FRO',
'FM' => 'FSM',
'GA' => 'GAB',
'GB' => 'GBR',
'GE' => 'GEO',
'GG' => 'GGY',
'GH' => 'GHA',
'GI' => 'GIB',
'GN' => 'GIN',
'GP' => 'GLP',
'GM' => 'GMB',
'GW' => 'GNB',
'GQ' => 'GNQ',
'GR' => 'GRC',
'GD' => 'GRD',
'GL' => 'GRL',
'GT' => 'GTM',
'GF' => 'GUF',
'GU' => 'GUM',
'GY' => 'GUY',
'HK' => 'HKG',
'HM' => 'HMD',
'HN' => 'HND',
'HR' => 'HRV',
'HT' => 'HTI',
'HU' => 'HUN',
'ID' => 'IDN',
'IM' => 'IMN',
'IN' => 'IND',
'IO' => 'IOT',
'IE' => 'IRL',
'IR' => 'IRN',
'IQ' => 'IRQ',
'IS' => 'ISL',
'IL' => 'ISR',
'IT' => 'ITA',
'JM' => 'JAM',
'JE' => 'JEY',
'JO' => 'JOR',
'JP' => 'JPN',
'KZ' => 'KAZ',
'KE' => 'KEN',
'KG' => 'KGZ',
'KH' => 'KHM',
'KI' => 'KIR',
'KN' => 'KNA',
'KR' => 'KOR',
'KW' => 'KWT',
'LA' => 'LAO',
'LB' => 'LBN',
'LR' => 'LBR',
'LY' => 'LBY',
'LC' => 'LCA',
'LI' => 'LIE',
'LK' => 'LKA',
'LS' => 'LSO',
'LT' => 'LTU',
'LU' => 'LUX',
'LV' => 'LVA',
'MO' => 'MAC',
'MF' => 'MAF',
'MA' => 'MAR',
'MC' => 'MCO',
'MD' => 'MDA',
'MG' => 'MDG',
'MV' => 'MDV',
'MX' => 'MEX',
'MH' => 'MHL',
'MK' => 'MKD',
'ML' => 'MLI',
'MT' => 'MLT',
'MM' => 'MMR',
'ME' => 'MNE',
'MN' => 'MNG',
'MP' => 'MNP',
'MZ' => 'MOZ',
'MR' => 'MRT',
'MS' => 'MSR',
'MQ' => 'MTQ',
'MU' => 'MUS',
'MW' => 'MWI',
'MY' => 'MYS',
'YT' => 'MYT',
'NA' => 'NAM',
'NC' => 'NCL',
'NE' => 'NER',
'NF' => 'NFK',
'NG' => 'NGA',
'NI' => 'NIC',
'NU' => 'NIU',
'NL' => 'NLD',
'NO' => 'NOR',
'NP' => 'NPL',
'NR' => 'NRU',
'NZ' => 'NZL',
'OM' => 'OMN',
'PK' => 'PAK',
'PA' => 'PAN',
'PN' => 'PCN',
'PE' => 'PER',
'PH' => 'PHL',
'PW' => 'PLW',
'PG' => 'PNG',
'PL' => 'POL',
'PR' => 'PRI',
'KP' => 'PRK',
'PT' => 'PRT',
'PY' => 'PRY',
'PS' => 'PSE',
'PF' => 'PYF',
'QA' => 'QAT',
'RE' => 'REU',
'RO' => 'ROU',
'RU' => 'RUS',
'RW' => 'RWA',
'SA' => 'SAU',
'SD' => 'SDN',
'SN' => 'SEN',
'SG' => 'SGP',
'GS' => 'SGS',
'SH' => 'SHN',
'SJ' => 'SJM',
'SB' => 'SLB',
'SL' => 'SLE',
'SV' => 'SLV',
'SM' => 'SMR',
'SO' => 'SOM',
'PM' => 'SPM',
'RS' => 'SRB',
'SS' => 'SSD',
'ST' => 'STP',
'SR' => 'SUR',
'SK' => 'SVK',
'SI' => 'SVN',
'SE' => 'SWE',
'SZ' => 'SWZ',
'SX' => 'SXM',
'SC' => 'SYC',
'SY' => 'SYR',
'TC' => 'TCA',
'TD' => 'TCD',
'TG' => 'TGO',
'TH' => 'THA',
'TJ' => 'TJK',
'TK' => 'TKL',
'TM' => 'TKM',
'TL' => 'TLS',
'TO' => 'TON',
'TT' => 'TTO',
'TN' => 'TUN',
'TR' => 'TUR',
'TV' => 'TUV',
'TW' => 'TWN',
'TZ' => 'TZA',
'UG' => 'UGA',
'UA' => 'UKR',
'UM' => 'UMI',
'UY' => 'URY',
'US' => 'USA',
'UZ' => 'UZB',
'VA' => 'VAT',
'VC' => 'VCT',
'VE' => 'VEN',
'VG' => 'VGB',
'VI' => 'VIR',
'VN' => 'VNM',
'VU' => 'VUT',
'WF' => 'WLF',
'WS' => 'WSM',
'YE' => 'YEM',
'ZA' => 'ZAF',
'ZM' => 'ZMB',
'ZW' => 'ZWE',
];
public function testGetCountryCodes()
{
$this->assertSame(self::$countries, Countries::getCountryCodes());
@ -348,4 +601,67 @@ class CountriesTest extends ResourceBundleTestCase
$this->assertTrue(Countries::exists('NL'));
$this->assertFalse(Countries::exists('ZZ'));
}
public function testGetAlpha3Codes()
{
$this->assertSame(self::$alpha2ToAlpha3, Countries::getAlpha3Codes());
}
public function testGetAlpha3Code()
{
foreach (self::$countries as $country) {
$this->assertSame(self::$alpha2ToAlpha3[$country], Countries::getAlpha3Code($country));
}
}
public function testGetAlpha2Code()
{
foreach (self::$countries as $alpha2Code) {
$alpha3Code = self::$alpha2ToAlpha3[$alpha2Code];
$this->assertSame($alpha2Code, Countries::getAlpha2Code($alpha3Code));
}
}
public function testAlpha3CodeExists()
{
$this->assertTrue(Countries::alpha3CodeExists('NOR'));
$this->assertTrue(Countries::alpha3CodeExists('NLD'));
$this->assertFalse(Countries::alpha3CodeExists('NIO'));
$this->assertFalse(Countries::alpha3CodeExists('ZZZ'));
}
/**
* @dataProvider provideLocales
*/
public function testGetAlpha3Name($displayLocale)
{
$names = Countries::getNames($displayLocale);
foreach ($names as $alpha2 => $name) {
$alpha3 = self::$alpha2ToAlpha3[$alpha2];
$this->assertSame($name, Countries::getAlpha3Name($alpha3, $displayLocale));
}
}
public function testGetAlpha3NameWithInvalidCountryCode()
{
$this->expectException(MissingResourceException::class);
Countries::getAlpha3Name('ZZZ');
}
/**
* @dataProvider provideLocales
*/
public function testGetAlpha3Names($displayLocale)
{
$names = Countries::getAlpha3Names($displayLocale);
$alpha3Codes = array_keys($names);
sort($alpha3Codes);
$this->assertSame(array_values(self::$alpha2ToAlpha3), $alpha3Codes);
$alpha2Names = Countries::getNames($displayLocale);
$this->assertSame(array_values($alpha2Names), array_values($names));
}
}

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Intl\Tests;
use Symfony\Component\Intl\Exception\MissingResourceException;
use Symfony\Component\Intl\Languages;
/**
@ -925,4 +926,66 @@ class LanguagesTest extends ResourceBundleTestCase
$this->assertTrue(Languages::exists('nl'));
$this->assertFalse(Languages::exists('zxx'));
}
public function testGetAlpha3Codes()
{
$this->assertSame(self::$alpha2ToAlpha3, Languages::getAlpha3Codes());
}
public function testGetAlpha2Code()
{
foreach (self::$alpha2ToAlpha3 as $alpha2Code => $alpha3Code) {
$this->assertSame($alpha2Code, Languages::getAlpha2Code($alpha3Code));
}
}
public function testAlpha3CodeExists()
{
$this->assertTrue(Languages::alpha3CodeExists('nob'));
$this->assertTrue(Languages::alpha3CodeExists('nld'));
$this->assertFalse(Languages::alpha3CodeExists('foo'));
$this->assertFalse(Languages::alpha3CodeExists('zzz'));
}
/**
* @dataProvider provideLocales
*/
public function testGetAlpha3Name($displayLocale)
{
$names = Languages::getNames($displayLocale);
foreach ($names as $alpha2 => $name) {
$alpha3 = self::$alpha2ToAlpha3[$alpha2] ?? false;
if ($alpha3) {
$this->assertSame($name, Languages::getAlpha3Name($alpha3, $displayLocale));
}
}
}
public function testGetAlpha3NameWithInvalidCountryCode()
{
$this->expectException(MissingResourceException::class);
Languages::getAlpha3Name('ZZZ');
}
/**
* @dataProvider provideLocales
*/
public function testGetAlpha3Names($displayLocale)
{
$names = Languages::getAlpha3Names($displayLocale);
$alpha3Codes = array_keys($names);
sort($alpha3Codes);
$this->assertSame(array_values(self::$alpha2ToAlpha3), $alpha3Codes);
$alpha2Names = Languages::getNames($displayLocale);
foreach ($alpha2Names as $alpha2Code => $name) {
if (!isset(self::$alpha2ToAlpha3[$alpha2Code])) {
unset($alpha2Names[$alpha2Code]);
}
}
$this->assertSame(array_values($alpha2Names), array_values($names));
}
}