@@ -116,24 +116,26 @@ public final class LocaleUtils {
|
||||
: locale.stripExtensions().toLanguageTag();
|
||||
}
|
||||
|
||||
public static @NotNull String getISO2Language(Locale locale) {
|
||||
String language = locale.getLanguage();
|
||||
public static @NotNull String getRootLanguage(Locale locale) {
|
||||
return getRootLanguage(locale.getLanguage());
|
||||
}
|
||||
|
||||
/// - If `language` is a sublanguage of a [macrolanguage](https://en.wikipedia.org/wiki/ISO_639_macrolanguage),
|
||||
/// return the macrolanguage;
|
||||
/// - If `language` is an ISO 639 alpha-3 language code and there is a corresponding ISO 639 alpha-2 language code, return the ISO 639 alpha-2 code;
|
||||
/// - If `language` is empty, return `en`;
|
||||
/// - Otherwise, return the `language`.
|
||||
public static @NotNull String getRootLanguage(String language) {
|
||||
if (language.isEmpty()) return "en";
|
||||
if (language.length() <= 2)
|
||||
return language;
|
||||
|
||||
String lang = language;
|
||||
while (lang != null) {
|
||||
if (lang.length() <= 2)
|
||||
return lang;
|
||||
else {
|
||||
String iso1 = mapToISO2Language(lang);
|
||||
if (iso1 != null)
|
||||
return iso1;
|
||||
}
|
||||
lang = getParentLanguage(lang);
|
||||
}
|
||||
return language;
|
||||
String iso2 = mapToISO2Language(language);
|
||||
if (iso2 != null)
|
||||
return iso2;
|
||||
|
||||
String parent = getParentLanguage(language);
|
||||
return parent != null ? parent : language;
|
||||
}
|
||||
|
||||
/// Get the script of the locale. If the script is empty and the language is Chinese,
|
||||
@@ -180,66 +182,52 @@ public final class LocaleUtils {
|
||||
|
||||
ArrayList<Locale> result = new ArrayList<>();
|
||||
do {
|
||||
List<String> languages;
|
||||
String currentLanguage;
|
||||
|
||||
if (language.isEmpty()) {
|
||||
result.add(Locale.ROOT);
|
||||
break;
|
||||
} else if (language.length() <= 2) {
|
||||
languages = List.of(language);
|
||||
if (language.length() <= 2) {
|
||||
currentLanguage = language;
|
||||
} else {
|
||||
String iso1Language = mapToISO2Language(language);
|
||||
languages = iso1Language != null
|
||||
? List.of(language, iso1Language)
|
||||
: List.of(language);
|
||||
String iso2 = mapToISO2Language(language);
|
||||
currentLanguage = iso2 != null
|
||||
? iso2
|
||||
: language;
|
||||
}
|
||||
|
||||
addCandidateLocales(result, languages, script, region, variants);
|
||||
addCandidateLocales(result, currentLanguage, script, region, variants);
|
||||
} while ((language = getParentLanguage(language)) != null);
|
||||
|
||||
result.add(Locale.ROOT);
|
||||
return List.copyOf(result);
|
||||
}
|
||||
|
||||
private static void addCandidateLocales(ArrayList<Locale> list,
|
||||
List<String> languages,
|
||||
String language,
|
||||
String script,
|
||||
String region,
|
||||
List<String> variants) {
|
||||
if (!variants.isEmpty()) {
|
||||
for (String v : variants) {
|
||||
for (String language : languages) {
|
||||
list.add(getInstance(language, script, region, v));
|
||||
}
|
||||
list.add(getInstance(language, script, region, v));
|
||||
}
|
||||
}
|
||||
if (!region.isEmpty()) {
|
||||
for (String language : languages) {
|
||||
list.add(getInstance(language, script, region, ""));
|
||||
}
|
||||
list.add(getInstance(language, script, region, ""));
|
||||
}
|
||||
if (!script.isEmpty()) {
|
||||
for (String language : languages) {
|
||||
list.add(getInstance(language, script, "", ""));
|
||||
}
|
||||
list.add(getInstance(language, script, "", ""));
|
||||
if (!variants.isEmpty()) {
|
||||
for (String v : variants) {
|
||||
for (String language : languages) {
|
||||
list.add(getInstance(language, "", region, v));
|
||||
}
|
||||
list.add(getInstance(language, "", region, v));
|
||||
}
|
||||
}
|
||||
if (!region.isEmpty()) {
|
||||
for (String language : languages) {
|
||||
list.add(getInstance(language, "", region, ""));
|
||||
}
|
||||
list.add(getInstance(language, "", region, ""));
|
||||
}
|
||||
}
|
||||
|
||||
for (String language : languages) {
|
||||
list.add(getInstance(language, "", "", ""));
|
||||
}
|
||||
list.add(getInstance(language, "", "", ""));
|
||||
|
||||
if (languages.contains("zh")) {
|
||||
if (language.equals("zh")) {
|
||||
if (list.contains(LocaleUtils.LOCALE_ZH_HANT) && !list.contains(Locale.TRADITIONAL_CHINESE)) {
|
||||
int chineseIdx = list.indexOf(Locale.CHINESE);
|
||||
if (chineseIdx >= 0)
|
||||
@@ -353,25 +341,26 @@ public final class LocaleUtils {
|
||||
// ---
|
||||
|
||||
/// Map ISO 639 alpha-3 language codes to ISO 639 alpha-2 language codes.
|
||||
/// Returns `null` if there is no corresponding ISO 639 alpha-2 language code.
|
||||
public static @Nullable String mapToISO2Language(String iso3Language) {
|
||||
return iso3To2.get(iso3Language);
|
||||
}
|
||||
|
||||
/// If `language` is a sublanguage of a [macrolanguage](https://en.wikipedia.org/wiki/ISO_639_macrolanguage),
|
||||
/// return the macrolanguage; otherwise, return `null`.
|
||||
public static @Nullable String getParentLanguage(String language) {
|
||||
return !language.isEmpty()
|
||||
? subLanguageToParent.getOrDefault(language, "")
|
||||
: null;
|
||||
return subLanguageToParent.get(language);
|
||||
}
|
||||
|
||||
public static boolean isEnglish(Locale locale) {
|
||||
return "en".equals(getISO2Language(locale));
|
||||
return "en".equals(getRootLanguage(locale));
|
||||
}
|
||||
|
||||
public static final Set<String> CHINESE_TRADITIONAL_REGIONS = Set.of("TW", "HK", "MO");
|
||||
public static final Set<String> CHINESE_LATN_VARIANTS = Set.of("pinyin", "wadegile", "tongyong");
|
||||
|
||||
public static boolean isChinese(Locale locale) {
|
||||
return "zh".equals(getISO2Language(locale));
|
||||
return "zh".equals(getRootLanguage(locale));
|
||||
}
|
||||
|
||||
private LocaleUtils() {
|
||||
|
||||
@@ -1 +1 @@
|
||||
zh,cmn,lzh,cdo,cjy,cpx,czh,gan,hak,hsn,mnp,nan,wuu,yue
|
||||
zh,cdo,cjy,cmn,cnp,cpx,csp,czh,czo,gan,hak,hnm,hsn,luh,lzh,mnp,nan,sjc,wuu,yue
|
||||
|
@@ -62,7 +62,7 @@ public final class LocaleUtilsTest {
|
||||
assertCandidateLocales("zh-Latn", List.of("zh-Latn", "zh", "zh-CN", "und"));
|
||||
assertCandidateLocales("zh-Latn-CN", List.of("zh-Latn-CN", "zh-Latn", "zh-CN", "zh", "und"));
|
||||
assertCandidateLocales("zh-pinyin", List.of("zh-Latn-pinyin", "zh-Latn", "zh-pinyin", "zh", "zh-CN", "und"));
|
||||
assertCandidateLocales("zho", List.of("zho-Hans", "zh-Hans", "zho", "zh-CN", "zh", "und"));
|
||||
assertCandidateLocales("zho", List.of("zh-Hans", "zh-CN", "zh", "und"));
|
||||
assertCandidateLocales("lzh", List.of("lzh-Hant", "lzh", "zh-Hant", "zh-TW", "zh", "zh-CN", "und"));
|
||||
assertCandidateLocales("lzh-Hant", List.of("lzh-Hant", "lzh", "zh-Hant", "zh-TW", "zh", "zh-CN", "und"));
|
||||
assertCandidateLocales("lzh-Hans", List.of("lzh-Hans", "lzh", "zh-Hans", "zh-CN", "zh", "und"));
|
||||
@@ -71,23 +71,23 @@ public final class LocaleUtilsTest {
|
||||
assertCandidateLocales("yue", List.of("yue-Hans", "yue", "zh-Hans", "zh-CN", "zh", "und"));
|
||||
|
||||
assertCandidateLocales("ja", List.of("ja", "und"));
|
||||
assertCandidateLocales("jpn", List.of("ja", "und"));
|
||||
assertCandidateLocales("ja-JP", List.of("ja-JP", "ja", "und"));
|
||||
assertCandidateLocales("jpn", List.of("jpn", "ja", "und"));
|
||||
assertCandidateLocales("jpn-JP", List.of("jpn-JP", "ja-JP", "jpn", "ja", "und"));
|
||||
assertCandidateLocales("jpn-JP", List.of("ja-JP", "ja", "und"));
|
||||
|
||||
assertCandidateLocales("en", List.of("en", "und"));
|
||||
assertCandidateLocales("eng", List.of("en", "und"));
|
||||
assertCandidateLocales("en-US", List.of("en-US", "en", "und"));
|
||||
assertCandidateLocales("eng", List.of("eng", "en", "und"));
|
||||
assertCandidateLocales("eng-US", List.of("eng-US", "en-US", "eng", "en", "und"));
|
||||
assertCandidateLocales("eng-US", List.of("en-US", "en", "und"));
|
||||
|
||||
assertCandidateLocales("es", List.of("es", "und"));
|
||||
assertCandidateLocales("spa", List.of("spa", "es", "und"));
|
||||
assertCandidateLocales("spa", List.of("es", "und"));
|
||||
|
||||
assertCandidateLocales("ru", List.of("ru", "und"));
|
||||
assertCandidateLocales("rus", List.of("rus", "ru", "und"));
|
||||
assertCandidateLocales("rus", List.of("ru", "und"));
|
||||
|
||||
assertCandidateLocales("uk", List.of("uk", "und"));
|
||||
assertCandidateLocales("ukr", List.of("ukr", "uk", "und"));
|
||||
assertCandidateLocales("ukr", List.of("uk", "und"));
|
||||
|
||||
assertCandidateLocales("und", List.of("en", "und"));
|
||||
}
|
||||
@@ -192,7 +192,7 @@ public final class LocaleUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapToISO2Language() throws IOException {
|
||||
public void testMapToISO2Language() {
|
||||
assertEquals("en", LocaleUtils.mapToISO2Language("eng"));
|
||||
assertEquals("es", LocaleUtils.mapToISO2Language("spa"));
|
||||
assertEquals("ja", LocaleUtils.mapToISO2Language("jpn"));
|
||||
@@ -207,4 +207,17 @@ public final class LocaleUtilsTest {
|
||||
assertNull(LocaleUtils.mapToISO2Language("lzh"));
|
||||
assertNull(LocaleUtils.mapToISO2Language("tlh"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetParentLanguage() {
|
||||
assertEquals("zh", LocaleUtils.getParentLanguage("cmn"));
|
||||
assertEquals("zh", LocaleUtils.getParentLanguage("yue"));
|
||||
assertEquals("zh", LocaleUtils.getParentLanguage("lzh"));
|
||||
|
||||
assertNull(LocaleUtils.getParentLanguage(""));
|
||||
assertNull(LocaleUtils.getParentLanguage("en"));
|
||||
assertNull(LocaleUtils.getParentLanguage("eng"));
|
||||
assertNull(LocaleUtils.getParentLanguage("zh"));
|
||||
assertNull(LocaleUtils.getParentLanguage("zho"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user