Culture names are now limited to a known list:
- Added tool to generate a set of known culture names from the OS/Fx - CultureInfoCache is now limited to only caching/returning cultures from the known list - #6
This commit is contained in:
parent
ca4b85e19f
commit
9834a27728
|
|
@ -20,6 +20,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
global.json = global.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "CultureInfoGenerator", "src\CultureInfoGenerator\CultureInfoGenerator.xproj", "{BD22AE1C-6631-4DA6-874D-0DC0F803CEAB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -42,6 +44,10 @@ Global
|
|||
{55D9501F-15B9-4339-A0AB-6082850E5FCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{55D9501F-15B9-4339-A0AB-6082850E5FCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{55D9501F-15B9-4339-A0AB-6082850E5FCE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD22AE1C-6631-4DA6-874D-0DC0F803CEAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD22AE1C-6631-4DA6-874D-0DC0F803CEAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD22AE1C-6631-4DA6-874D-0DC0F803CEAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD22AE1C-6631-4DA6-874D-0DC0F803CEAB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -51,5 +57,6 @@ Global
|
|||
{23E3BC23-3464-4D9B-BF78-02CB2182BEF0} = {FB313677-BAB3-4E49-8CDB-4FA4A9564767}
|
||||
{A1FCF259-70F6-4605-AA2D-E4B356BE771A} = {FB313677-BAB3-4E49-8CDB-4FA4A9564767}
|
||||
{55D9501F-15B9-4339-A0AB-6082850E5FCE} = {79878809-8D1C-4BD4-BA99-F1F13FF96FD8}
|
||||
{BD22AE1C-6631-4DA6-874D-0DC0F803CEAB} = {FB313677-BAB3-4E49-8CDB-4FA4A9564767}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ $@"<!doctype html>
|
|||
#if DNX451
|
||||
await context.Response.WriteAsync($" <option value=\"{new CultureInfo("zh-CHT").Name}\">{new CultureInfo("zh-CHT").DisplayName}</option>");
|
||||
#endif
|
||||
await context.Response.WriteAsync($" <option value=\"en-NOTREAL\">English (Not a real culture)</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"en-NOTREAL\">English (Not a real locale)</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"pp-NOTREAL\">Made-up (Not a real anything)</option>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>bd22ae1c-6631-4da6-874d-0dc0f803ceab</ProjectGuid>
|
||||
<RootNamespace>CultureInfoGenerator</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace CultureInfoGenerator
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
private readonly string _appName;
|
||||
private readonly string _appPath;
|
||||
|
||||
public Program(IApplicationEnvironment appEnvironment)
|
||||
{
|
||||
_appName = appEnvironment.ApplicationName;
|
||||
_appPath = appEnvironment.ApplicationBasePath;
|
||||
}
|
||||
|
||||
public void Main(string[] args)
|
||||
{
|
||||
var outputFilePath = args.Length > 0 ? args[0] : Path.Combine(_appPath, "../Microsoft.AspNet.Localization/Internal/CultureInfoList.cs");
|
||||
var netFxVersion = Get45or451FromRegistry();
|
||||
var windowsVersion = Environment.OSVersion;
|
||||
|
||||
using (var writer = new StreamWriter(outputFilePath, false))
|
||||
{
|
||||
writer.WriteLine($@"// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Localization.Internal
|
||||
{{
|
||||
public static class CultureInfoList
|
||||
{{
|
||||
// This list of known cultures was generated by {_appName} using .NET Framework {netFxVersion} on
|
||||
// {windowsVersion}.
|
||||
// As new versions of .NET Framework and Windows are released, this list should be regenerated to ensure it
|
||||
// contains the latest culture names.
|
||||
public static readonly HashSet<string> KnownCultureNames = new HashSet<string>
|
||||
{{"
|
||||
);
|
||||
|
||||
var cultures = CultureInfo.GetCultures(
|
||||
CultureTypes.NeutralCultures
|
||||
| CultureTypes.InstalledWin32Cultures
|
||||
| CultureTypes.SpecificCultures);
|
||||
|
||||
var format = " \"{0}\"";
|
||||
|
||||
for (int i = 0; i < cultures.Length; i++)
|
||||
{
|
||||
var culture = cultures[i];
|
||||
|
||||
writer.Write(format, culture.Name);
|
||||
|
||||
if (i < cultures.Length - 1)
|
||||
{
|
||||
writer.WriteLine(",");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Last entry
|
||||
writer.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteLine(
|
||||
@" };
|
||||
}
|
||||
}");
|
||||
}
|
||||
}
|
||||
|
||||
// .NET Framework detection code copied from https://msdn.microsoft.com/en-us/library/hh925568%28v=vs.110%29.aspx#net_d
|
||||
private static string Get45or451FromRegistry()
|
||||
{
|
||||
using (var ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)
|
||||
.OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\"))
|
||||
{
|
||||
var releaseKey = Convert.ToInt32(ndpKey.GetValue("Release"));
|
||||
return CheckFor45DotVersion(releaseKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Checking the version using >= will enable forward compatibility,
|
||||
// however you should always compile your code on newer versions of
|
||||
// the framework to ensure your app works the same.
|
||||
private static string CheckFor45DotVersion(int releaseKey)
|
||||
{
|
||||
if (releaseKey >= 393273)
|
||||
{
|
||||
return "4.6 RC or later";
|
||||
}
|
||||
if ((releaseKey >= 379893))
|
||||
{
|
||||
return "4.5.2 or later";
|
||||
}
|
||||
if ((releaseKey >= 378675))
|
||||
{
|
||||
return "4.5.1 or later";
|
||||
}
|
||||
if ((releaseKey >= 378389))
|
||||
{
|
||||
return "4.5 or later";
|
||||
}
|
||||
// This line should never execute. A non-null release key should mean
|
||||
// that 4.5 or later is installed.
|
||||
return "No 4.5 or later version detected";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"description": "Generates a list of known culture names from the OS using CultureInfo.GetCultures. This tool is intended to be run on Windows using full .NET Framework.",
|
||||
|
||||
"dependencies": {
|
||||
"Microsoft.Framework.Runtime.Abstractions": "1.0.0-beta5-11739"
|
||||
},
|
||||
|
||||
"commands": {
|
||||
"CultureInfoGenerator": "CultureInfoGenerator"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"dnx451": { }
|
||||
}
|
||||
}
|
||||
|
|
@ -11,11 +11,11 @@ namespace Microsoft.AspNet.Localization.Internal
|
|||
{
|
||||
private static readonly ConcurrentDictionary<string, CacheEntry> _cache = new ConcurrentDictionary<string, CacheEntry>();
|
||||
|
||||
public static CultureInfo GetCultureInfo(string name, bool throwIfNotFound = false)
|
||||
public static CultureInfo GetCultureInfo(string name)
|
||||
{
|
||||
// Allow empty string values as they map to InvariantCulture, whereas null culture values will throw in
|
||||
// the CultureInfo ctor
|
||||
if (name == null)
|
||||
// Allow only known culture names as this API is called with input from users (HTTP requests) and
|
||||
// creating CultureInfo objects is expensive and we don't want it to throw either.
|
||||
if (name == null || !CultureInfoList.KnownCultureNames.Contains(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
@ -26,17 +26,15 @@ namespace Microsoft.AspNet.Localization.Internal
|
|||
{
|
||||
return new CacheEntry(CultureInfo.ReadOnly(new CultureInfo(n)));
|
||||
}
|
||||
catch (CultureNotFoundException ex)
|
||||
catch (CultureNotFoundException)
|
||||
{
|
||||
return new CacheEntry(ex);
|
||||
// This can still throw as the list of culture names we have is generated from latest .NET Framework
|
||||
// on latest Windows and thus contains names that won't be supported on lower framework or OS versions.
|
||||
// We can just cache the null result in these cases as it's ultimately bound by the list anyway.
|
||||
return new CacheEntry(cultureInfo: null);
|
||||
}
|
||||
});
|
||||
|
||||
if (entry.Exception != null && throwIfNotFound)
|
||||
{
|
||||
throw entry.Exception;
|
||||
}
|
||||
|
||||
return entry.CultureInfo;
|
||||
}
|
||||
|
||||
|
|
@ -47,14 +45,7 @@ namespace Microsoft.AspNet.Localization.Internal
|
|||
CultureInfo = cultureInfo;
|
||||
}
|
||||
|
||||
public CacheEntry(Exception exception)
|
||||
{
|
||||
Exception = exception;
|
||||
}
|
||||
|
||||
public CultureInfo CultureInfo { get; }
|
||||
|
||||
public Exception Exception { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,436 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Localization.Internal
|
||||
{
|
||||
public static class CultureInfoList
|
||||
{
|
||||
// This list of known cultures was generated by CultureInfoGenerator using .NET Framework 4.6 RC or later on
|
||||
// Microsoft Windows NT 6.2.9200.0.
|
||||
// As new versions of .NET Framework and Windows are released, this list should be regenerated to ensure it
|
||||
// contains the latest culture names.
|
||||
public static readonly HashSet<string> KnownCultureNames = new HashSet<string>
|
||||
{
|
||||
"",
|
||||
"af",
|
||||
"af-ZA",
|
||||
"am",
|
||||
"am-ET",
|
||||
"ar",
|
||||
"ar-AE",
|
||||
"ar-BH",
|
||||
"ar-DZ",
|
||||
"ar-EG",
|
||||
"ar-IQ",
|
||||
"ar-JO",
|
||||
"ar-KW",
|
||||
"ar-LB",
|
||||
"ar-LY",
|
||||
"ar-MA",
|
||||
"ar-OM",
|
||||
"ar-QA",
|
||||
"ar-SA",
|
||||
"ar-SY",
|
||||
"ar-TN",
|
||||
"ar-YE",
|
||||
"arn",
|
||||
"arn-CL",
|
||||
"as",
|
||||
"as-IN",
|
||||
"az",
|
||||
"az-Cyrl",
|
||||
"az-Cyrl-AZ",
|
||||
"az-Latn",
|
||||
"az-Latn-AZ",
|
||||
"ba",
|
||||
"ba-RU",
|
||||
"be",
|
||||
"be-BY",
|
||||
"bg",
|
||||
"bg-BG",
|
||||
"bn",
|
||||
"bn-BD",
|
||||
"bn-IN",
|
||||
"bo",
|
||||
"bo-CN",
|
||||
"br",
|
||||
"br-FR",
|
||||
"bs",
|
||||
"bs-Cyrl",
|
||||
"bs-Cyrl-BA",
|
||||
"bs-Latn",
|
||||
"bs-Latn-BA",
|
||||
"ca",
|
||||
"ca-ES",
|
||||
"ca-ES-valencia",
|
||||
"chr",
|
||||
"chr-Cher",
|
||||
"chr-Cher-US",
|
||||
"co",
|
||||
"co-FR",
|
||||
"cs",
|
||||
"cs-CZ",
|
||||
"cy",
|
||||
"cy-GB",
|
||||
"da",
|
||||
"da-DK",
|
||||
"de",
|
||||
"de-AT",
|
||||
"de-CH",
|
||||
"de-DE",
|
||||
"de-LI",
|
||||
"de-LU",
|
||||
"dsb",
|
||||
"dsb-DE",
|
||||
"dv",
|
||||
"dv-MV",
|
||||
"el",
|
||||
"el-GR",
|
||||
"en",
|
||||
"en-029",
|
||||
"en-AU",
|
||||
"en-BZ",
|
||||
"en-CA",
|
||||
"en-GB",
|
||||
"en-HK",
|
||||
"en-IE",
|
||||
"en-IN",
|
||||
"en-JM",
|
||||
"en-MY",
|
||||
"en-NZ",
|
||||
"en-PH",
|
||||
"en-SG",
|
||||
"en-TT",
|
||||
"en-US",
|
||||
"en-ZA",
|
||||
"en-ZW",
|
||||
"es",
|
||||
"es-419",
|
||||
"es-AR",
|
||||
"es-BO",
|
||||
"es-CL",
|
||||
"es-CO",
|
||||
"es-CR",
|
||||
"es-DO",
|
||||
"es-EC",
|
||||
"es-ES",
|
||||
"es-GT",
|
||||
"es-HN",
|
||||
"es-MX",
|
||||
"es-NI",
|
||||
"es-PA",
|
||||
"es-PE",
|
||||
"es-PR",
|
||||
"es-PY",
|
||||
"es-SV",
|
||||
"es-US",
|
||||
"es-UY",
|
||||
"es-VE",
|
||||
"et",
|
||||
"et-EE",
|
||||
"eu",
|
||||
"eu-ES",
|
||||
"fa",
|
||||
"fa-IR",
|
||||
"ff",
|
||||
"ff-Latn",
|
||||
"ff-Latn-SN",
|
||||
"fi",
|
||||
"fi-FI",
|
||||
"fil",
|
||||
"fil-PH",
|
||||
"fo",
|
||||
"fo-FO",
|
||||
"fr",
|
||||
"fr-BE",
|
||||
"fr-CA",
|
||||
"fr-CD",
|
||||
"fr-CH",
|
||||
"fr-CI",
|
||||
"fr-CM",
|
||||
"fr-FR",
|
||||
"fr-HT",
|
||||
"fr-LU",
|
||||
"fr-MA",
|
||||
"fr-MC",
|
||||
"fr-ML",
|
||||
"fr-RE",
|
||||
"fr-SN",
|
||||
"fy",
|
||||
"fy-NL",
|
||||
"ga",
|
||||
"ga-IE",
|
||||
"gd",
|
||||
"gd-GB",
|
||||
"gl",
|
||||
"gl-ES",
|
||||
"gn",
|
||||
"gn-PY",
|
||||
"gsw",
|
||||
"gsw-FR",
|
||||
"gu",
|
||||
"gu-IN",
|
||||
"ha",
|
||||
"ha-Latn",
|
||||
"ha-Latn-NG",
|
||||
"haw",
|
||||
"haw-US",
|
||||
"he",
|
||||
"he-IL",
|
||||
"hi",
|
||||
"hi-IN",
|
||||
"hr",
|
||||
"hr-BA",
|
||||
"hr-HR",
|
||||
"hsb",
|
||||
"hsb-DE",
|
||||
"hu",
|
||||
"hu-HU",
|
||||
"hy",
|
||||
"hy-AM",
|
||||
"id",
|
||||
"id-ID",
|
||||
"ig",
|
||||
"ig-NG",
|
||||
"ii",
|
||||
"ii-CN",
|
||||
"is",
|
||||
"is-IS",
|
||||
"it",
|
||||
"it-CH",
|
||||
"it-IT",
|
||||
"iu",
|
||||
"iu-Cans",
|
||||
"iu-Cans-CA",
|
||||
"iu-Latn",
|
||||
"iu-Latn-CA",
|
||||
"ja",
|
||||
"ja-JP",
|
||||
"jv",
|
||||
"jv-Latn",
|
||||
"jv-Latn-ID",
|
||||
"ka",
|
||||
"ka-GE",
|
||||
"kk",
|
||||
"kk-KZ",
|
||||
"kl",
|
||||
"kl-GL",
|
||||
"km",
|
||||
"km-KH",
|
||||
"kn",
|
||||
"kn-IN",
|
||||
"ko",
|
||||
"ko-KR",
|
||||
"kok",
|
||||
"kok-IN",
|
||||
"ku",
|
||||
"ku-Arab",
|
||||
"ku-Arab-IQ",
|
||||
"ky",
|
||||
"ky-KG",
|
||||
"lb",
|
||||
"lb-LU",
|
||||
"lo",
|
||||
"lo-LA",
|
||||
"lt",
|
||||
"lt-LT",
|
||||
"lv",
|
||||
"lv-LV",
|
||||
"mg",
|
||||
"mg-MG",
|
||||
"mi",
|
||||
"mi-NZ",
|
||||
"mk",
|
||||
"mk-MK",
|
||||
"ml",
|
||||
"ml-IN",
|
||||
"mn",
|
||||
"mn-Cyrl",
|
||||
"mn-MN",
|
||||
"mn-Mong",
|
||||
"mn-Mong-CN",
|
||||
"mn-Mong-MN",
|
||||
"moh",
|
||||
"moh-CA",
|
||||
"mr",
|
||||
"mr-IN",
|
||||
"ms",
|
||||
"ms-BN",
|
||||
"ms-MY",
|
||||
"mt",
|
||||
"mt-MT",
|
||||
"my",
|
||||
"my-MM",
|
||||
"nb",
|
||||
"nb-NO",
|
||||
"ne",
|
||||
"ne-IN",
|
||||
"ne-NP",
|
||||
"nl",
|
||||
"nl-BE",
|
||||
"nl-NL",
|
||||
"nn",
|
||||
"nn-NO",
|
||||
"no",
|
||||
"nqo",
|
||||
"nqo-GN",
|
||||
"nso",
|
||||
"nso-ZA",
|
||||
"oc",
|
||||
"oc-FR",
|
||||
"om",
|
||||
"om-ET",
|
||||
"or",
|
||||
"or-IN",
|
||||
"pa",
|
||||
"pa-Arab",
|
||||
"pa-Arab-PK",
|
||||
"pa-IN",
|
||||
"pl",
|
||||
"pl-PL",
|
||||
"prs",
|
||||
"prs-AF",
|
||||
"ps",
|
||||
"ps-AF",
|
||||
"pt",
|
||||
"pt-AO",
|
||||
"pt-BR",
|
||||
"pt-PT",
|
||||
"qut",
|
||||
"qut-GT",
|
||||
"quz",
|
||||
"quz-BO",
|
||||
"quz-EC",
|
||||
"quz-PE",
|
||||
"rm",
|
||||
"rm-CH",
|
||||
"ro",
|
||||
"ro-MD",
|
||||
"ro-RO",
|
||||
"ru",
|
||||
"ru-RU",
|
||||
"rw",
|
||||
"rw-RW",
|
||||
"sa",
|
||||
"sa-IN",
|
||||
"sah",
|
||||
"sah-RU",
|
||||
"sd",
|
||||
"sd-Arab",
|
||||
"sd-Arab-PK",
|
||||
"se",
|
||||
"se-FI",
|
||||
"se-NO",
|
||||
"se-SE",
|
||||
"si",
|
||||
"si-LK",
|
||||
"sk",
|
||||
"sk-SK",
|
||||
"sl",
|
||||
"sl-SI",
|
||||
"sma",
|
||||
"sma-NO",
|
||||
"sma-SE",
|
||||
"smj",
|
||||
"smj-NO",
|
||||
"smj-SE",
|
||||
"smn",
|
||||
"smn-FI",
|
||||
"sms",
|
||||
"sms-FI",
|
||||
"sn",
|
||||
"sn-Latn",
|
||||
"sn-Latn-ZW",
|
||||
"so",
|
||||
"so-SO",
|
||||
"sq",
|
||||
"sq-AL",
|
||||
"sr",
|
||||
"sr-Cyrl",
|
||||
"sr-Cyrl-BA",
|
||||
"sr-Cyrl-CS",
|
||||
"sr-Cyrl-ME",
|
||||
"sr-Cyrl-RS",
|
||||
"sr-Latn",
|
||||
"sr-Latn-BA",
|
||||
"sr-Latn-CS",
|
||||
"sr-Latn-ME",
|
||||
"sr-Latn-RS",
|
||||
"st",
|
||||
"st-ZA",
|
||||
"sv",
|
||||
"sv-FI",
|
||||
"sv-SE",
|
||||
"sw",
|
||||
"sw-KE",
|
||||
"syr",
|
||||
"syr-SY",
|
||||
"ta",
|
||||
"ta-IN",
|
||||
"ta-LK",
|
||||
"te",
|
||||
"te-IN",
|
||||
"tg",
|
||||
"tg-Cyrl",
|
||||
"tg-Cyrl-TJ",
|
||||
"th",
|
||||
"th-TH",
|
||||
"ti",
|
||||
"ti-ER",
|
||||
"ti-ET",
|
||||
"tk",
|
||||
"tk-TM",
|
||||
"tn",
|
||||
"tn-BW",
|
||||
"tn-ZA",
|
||||
"tr",
|
||||
"tr-TR",
|
||||
"ts",
|
||||
"ts-ZA",
|
||||
"tt",
|
||||
"tt-RU",
|
||||
"tzm",
|
||||
"tzm-Latn",
|
||||
"tzm-Latn-DZ",
|
||||
"tzm-Tfng",
|
||||
"tzm-Tfng-MA",
|
||||
"ug",
|
||||
"ug-CN",
|
||||
"uk",
|
||||
"uk-UA",
|
||||
"ur",
|
||||
"ur-IN",
|
||||
"ur-PK",
|
||||
"uz",
|
||||
"uz-Cyrl",
|
||||
"uz-Cyrl-UZ",
|
||||
"uz-Latn",
|
||||
"uz-Latn-UZ",
|
||||
"vi",
|
||||
"vi-VN",
|
||||
"wo",
|
||||
"wo-SN",
|
||||
"xh",
|
||||
"xh-ZA",
|
||||
"yo",
|
||||
"yo-NG",
|
||||
"zgh",
|
||||
"zgh-Tfng",
|
||||
"zgh-Tfng-MA",
|
||||
"zh",
|
||||
"zh-CN",
|
||||
"zh-Hans",
|
||||
"zh-Hant",
|
||||
"zh-HK",
|
||||
"zh-MO",
|
||||
"zh-SG",
|
||||
"zh-TW",
|
||||
"zu",
|
||||
"zu-ZA",
|
||||
"zh-CHS",
|
||||
"zh-CHT"
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue