8329691: Support nonlikelyScript
parent locale inheritance
Reviewed-by: joehw
This commit is contained in:
parent
aa4cddd4b8
commit
c7d98df2ac
@ -87,6 +87,7 @@ public class CLDRConverter {
|
|||||||
static final String ZONE_NAME_PREFIX = "timezone.displayname.";
|
static final String ZONE_NAME_PREFIX = "timezone.displayname.";
|
||||||
static final String METAZONE_ID_PREFIX = "metazone.id.";
|
static final String METAZONE_ID_PREFIX = "metazone.id.";
|
||||||
static final String PARENT_LOCALE_PREFIX = "parentLocale.";
|
static final String PARENT_LOCALE_PREFIX = "parentLocale.";
|
||||||
|
static final String LIKELY_SCRIPT_PREFIX = "likelyScript.";
|
||||||
static final String META_EMPTY_ZONE_NAME = "EMPTY_ZONE";
|
static final String META_EMPTY_ZONE_NAME = "EMPTY_ZONE";
|
||||||
static final String[] EMPTY_ZONE = {"", "", "", "", "", ""};
|
static final String[] EMPTY_ZONE = {"", "", "", "", "", ""};
|
||||||
static final String META_ETCUTC_ZONE_NAME = "ETC_UTC";
|
static final String META_ETCUTC_ZONE_NAME = "ETC_UTC";
|
||||||
@ -114,9 +115,13 @@ public class CLDRConverter {
|
|||||||
|
|
||||||
// "parentLocales" map
|
// "parentLocales" map
|
||||||
private static final Map<String, SortedSet<String>> parentLocalesMap = new HashMap<>();
|
private static final Map<String, SortedSet<String>> parentLocalesMap = new HashMap<>();
|
||||||
|
static boolean nonlikelyScript;
|
||||||
private static final ResourceBundle.Control defCon =
|
private static final ResourceBundle.Control defCon =
|
||||||
ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
|
ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
|
||||||
|
|
||||||
|
// "likelyScript" map
|
||||||
|
private static final Map<String, SortedSet<String>> likelyScriptMap = new HashMap<>();
|
||||||
|
|
||||||
private static Set<String> AVAILABLE_TZIDS;
|
private static Set<String> AVAILABLE_TZIDS;
|
||||||
static int copyrightYear;
|
static int copyrightYear;
|
||||||
static String jdkHeaderTemplate;
|
static String jdkHeaderTemplate;
|
||||||
@ -175,7 +180,7 @@ public class CLDRConverter {
|
|||||||
private static boolean verbose;
|
private static boolean verbose;
|
||||||
|
|
||||||
private CLDRConverter() {
|
private CLDRConverter() {
|
||||||
// no instantiation
|
// no instantiation
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("AssignmentToForLoopParameter")
|
@SuppressWarnings("AssignmentToForLoopParameter")
|
||||||
@ -475,8 +480,8 @@ public class CLDRConverter {
|
|||||||
parseLDMLFile(new File(SPPL_SOURCE_FILE), handlerSuppl);
|
parseLDMLFile(new File(SPPL_SOURCE_FILE), handlerSuppl);
|
||||||
Map<String, Object> parentData = handlerSuppl.getData("root");
|
Map<String, Object> parentData = handlerSuppl.getData("root");
|
||||||
parentData.keySet().stream()
|
parentData.keySet().stream()
|
||||||
.filter(key -> key.startsWith(PARENT_LOCALE_PREFIX))
|
.filter(key -> key.startsWith(PARENT_LOCALE_PREFIX))
|
||||||
.forEach(key -> {
|
.forEach(key -> {
|
||||||
parentLocalesMap.put(key, new TreeSet<String>(
|
parentLocalesMap.put(key, new TreeSet<String>(
|
||||||
Arrays.asList(((String)parentData.get(key)).split(" "))));
|
Arrays.asList(((String)parentData.get(key)).split(" "))));
|
||||||
});
|
});
|
||||||
@ -492,6 +497,16 @@ public class CLDRConverter {
|
|||||||
// Parse likelySubtags
|
// Parse likelySubtags
|
||||||
handlerLikelySubtags = new LikelySubtagsParseHandler();
|
handlerLikelySubtags = new LikelySubtagsParseHandler();
|
||||||
parseLDMLFile(new File(LIKELYSUBTAGS_SOURCE_FILE), handlerLikelySubtags);
|
parseLDMLFile(new File(LIKELYSUBTAGS_SOURCE_FILE), handlerLikelySubtags);
|
||||||
|
handlerLikelySubtags.getData().forEach((from, to) -> {
|
||||||
|
if (!from.contains("-")) { // look for language-only tag
|
||||||
|
var script = to.split("-")[1];
|
||||||
|
var key = LIKELY_SCRIPT_PREFIX + script;
|
||||||
|
var prev = likelyScriptMap.putIfAbsent(key, new TreeSet<String>(Set.of(from)));
|
||||||
|
if (prev != null) {
|
||||||
|
prev.add(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Parse supplementalMetadata
|
// Parse supplementalMetadata
|
||||||
// Currently interested in deprecated time zone ids and language aliases.
|
// Currently interested in deprecated time zone ids and language aliases.
|
||||||
@ -561,6 +576,7 @@ public class CLDRConverter {
|
|||||||
// for now.
|
// for now.
|
||||||
if (isBaseModule) {
|
if (isBaseModule) {
|
||||||
metaInfo.putAll(parentLocalesMap);
|
metaInfo.putAll(parentLocalesMap);
|
||||||
|
metaInfo.putAll(likelyScriptMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Bundle bundle : bundles) {
|
for (Bundle bundle : bundles) {
|
||||||
@ -1135,7 +1151,7 @@ public class CLDRConverter {
|
|||||||
// check irregular parents
|
// check irregular parents
|
||||||
for (int i = 0; i < candidates.size(); i++) {
|
for (int i = 0; i < candidates.size(); i++) {
|
||||||
Locale l = candidates.get(i);
|
Locale l = candidates.get(i);
|
||||||
Locale p = childToParentLocaleMap.get(l);
|
Locale p = getParentLocale(l);
|
||||||
if (!l.equals(Locale.ROOT) &&
|
if (!l.equals(Locale.ROOT) &&
|
||||||
Objects.nonNull(p) &&
|
Objects.nonNull(p) &&
|
||||||
!candidates.get(i+1).equals(p)) {
|
!candidates.get(i+1).equals(p)) {
|
||||||
@ -1152,6 +1168,27 @@ public class CLDRConverter {
|
|||||||
return candidates;
|
return candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Locale getParentLocale(Locale child) {
|
||||||
|
Locale parent = childToParentLocaleMap.get(child);
|
||||||
|
|
||||||
|
// check non-likely script for root
|
||||||
|
if (nonlikelyScript && parent == null && child.getCountry().isEmpty()) {
|
||||||
|
var lang = " " + child.getLanguage() + " ";
|
||||||
|
var script = child.getScript();
|
||||||
|
|
||||||
|
if (!script.isEmpty()) {
|
||||||
|
parent = likelyScriptMap.entrySet().stream()
|
||||||
|
.filter(e -> e.getValue().contains(lang))
|
||||||
|
.findAny()
|
||||||
|
.map(Map.Entry::getKey)
|
||||||
|
.map(likely -> likely.equals(script) ? null : Locale.ROOT)
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
private static void generateZoneName() throws Exception {
|
private static void generateZoneName() throws Exception {
|
||||||
Files.createDirectories(Paths.get(DESTINATION_DIR, "java", "time", "format"));
|
Files.createDirectories(Paths.get(DESTINATION_DIR, "java", "time", "format"));
|
||||||
Files.write(Paths.get(DESTINATION_DIR, "java", "time", "format", "ZoneName.java"),
|
Files.write(Paths.get(DESTINATION_DIR, "java", "time", "format", "ZoneName.java"),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -38,6 +38,7 @@ import java.util.Locale;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
class ResourceBundleGenerator implements BundleGenerator {
|
class ResourceBundleGenerator implements BundleGenerator {
|
||||||
// preferred timezones - keeping compatibility with JDK1.1 3 letter abbreviations
|
// preferred timezones - keeping compatibility with JDK1.1 3 letter abbreviations
|
||||||
@ -306,81 +307,77 @@ class ResourceBundleGenerator implements BundleGenerator {
|
|||||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||||
|
|
||||||
public class %s implements LocaleDataMetaInfo {
|
public class %s implements LocaleDataMetaInfo {
|
||||||
private static final Map<String, String> resourceNameToLocales = HashMap.newHashMap(%d);
|
""",
|
||||||
%s
|
CLDRConverter.isBaseModule ? "cldr" : "resources.cldr.provider",
|
||||||
static {
|
className);
|
||||||
""", CLDRConverter.isBaseModule ? "cldr" : "resources.cldr.provider",
|
|
||||||
className, metaInfo.keySet().stream().filter(k -> k.equals("AvailableLocales")).count(),
|
if (CLDRConverter.isBaseModule) {
|
||||||
CLDRConverter.isBaseModule ?
|
out.printf("""
|
||||||
"""
|
|
||||||
private static final Map<Locale, String[]> parentLocalesMap = HashMap.newHashMap(%d);
|
private static final Map<Locale, String[]> parentLocalesMap = HashMap.newHashMap(%d);
|
||||||
private static final Map<String, String> languageAliasMap = HashMap.newHashMap(%d);
|
private static final Map<String, String> languageAliasMap = HashMap.newHashMap(%d);
|
||||||
|
static final boolean nonlikelyScript = %s; // package access from CLDRLocaleProviderAdapter
|
||||||
|
|
||||||
|
static {
|
||||||
""".formatted(
|
""".formatted(
|
||||||
metaInfo.keySet().stream().filter(k -> k.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)).count(),
|
metaInfo.keySet().stream().filter(k -> k.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)).count(),
|
||||||
CLDRConverter.handlerSupplMeta.getLanguageAliasData().size()) :
|
CLDRConverter.handlerSupplMeta.getLanguageAliasData().size(),
|
||||||
"");
|
Boolean.valueOf(CLDRConverter.nonlikelyScript)));
|
||||||
|
|
||||||
for (String key : metaInfo.keySet()) {
|
for (String key : metaInfo.keySet()) {
|
||||||
if (key.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)) {
|
if (key.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)) {
|
||||||
String parentTag = key.substring(CLDRConverter.PARENT_LOCALE_PREFIX.length());
|
String parentTag = key.substring(CLDRConverter.PARENT_LOCALE_PREFIX.length());
|
||||||
if ("root".equals(parentTag)) {
|
if ("root".equals(parentTag)) {
|
||||||
out.printf(" parentLocalesMap.put(Locale.ROOT,\n");
|
out.printf(" parentLocalesMap.put(Locale.ROOT,\n");
|
||||||
} else {
|
} else {
|
||||||
out.printf(" parentLocalesMap.put(Locale.forLanguageTag(\"%s\"),\n",
|
out.printf(" parentLocalesMap.put(Locale.forLanguageTag(\"%s\"),\n",
|
||||||
parentTag);
|
parentTag);
|
||||||
}
|
|
||||||
String[] children = toLocaleList(metaInfo.get(key), true).split(" ");
|
|
||||||
Arrays.sort(children);
|
|
||||||
out.printf(" new String[] {\n" +
|
|
||||||
" ");
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; i < children.length; i++) {
|
|
||||||
String child = children[i];
|
|
||||||
out.printf("\"%s\", ", child);
|
|
||||||
count += child.length() + 4;
|
|
||||||
if (i != children.length - 1 && count > 64) {
|
|
||||||
out.printf("\n ");
|
|
||||||
count = 0;
|
|
||||||
}
|
}
|
||||||
}
|
generateStringArray(metaInfo.get(key), out);
|
||||||
out.printf("\n });\n");
|
|
||||||
} else {
|
|
||||||
if ("AvailableLocales".equals(key)) {
|
|
||||||
out.printf(" resourceNameToLocales.put(\"%s\",\n", key);
|
|
||||||
out.printf(" \"%s\");\n", toLocaleList(applyLanguageAliases(metaInfo.get(key)), false));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
out.println();
|
||||||
// for languageAliasMap
|
|
||||||
if (CLDRConverter.isBaseModule) {
|
// for languageAliasMap
|
||||||
CLDRConverter.handlerSupplMeta.getLanguageAliasData().forEach((key, value) -> {
|
CLDRConverter.handlerSupplMeta.getLanguageAliasData().forEach((key, value) -> {
|
||||||
out.printf(" languageAliasMap.put(\"%s\", \"%s\");\n", key, value);
|
out.printf(" languageAliasMap.put(\"%s\", \"%s\");\n", key, value);
|
||||||
});
|
});
|
||||||
}
|
out.printf(" }\n\n");
|
||||||
|
|
||||||
out.printf(" }\n\n");
|
// end of static initializer block.
|
||||||
|
|
||||||
// end of static initializer block.
|
// Delayed initialization section
|
||||||
|
|
||||||
// Canonical TZ names for delayed initialization
|
|
||||||
if (CLDRConverter.isBaseModule) {
|
|
||||||
out.printf("""
|
out.printf("""
|
||||||
private static class TZCanonicalIDMapHolder {
|
private static class CLDRMapHolder {
|
||||||
static final Map<String, String> tzCanonicalIDMap = HashMap.newHashMap(%d);
|
private static final Map<String, String> tzCanonicalIDMap = HashMap.newHashMap(%d);
|
||||||
|
private static final Map<String, String> likelyScriptMap = HashMap.newHashMap(%d);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
""", CLDRConverter.handlerTimeZone.getData().size());
|
""", CLDRConverter.handlerTimeZone.getData().size(),
|
||||||
|
metaInfo.keySet().stream().filter(k -> k.startsWith(CLDRConverter.LIKELY_SCRIPT_PREFIX)).count());
|
||||||
CLDRConverter.handlerTimeZone.getData().entrySet().stream()
|
CLDRConverter.handlerTimeZone.getData().entrySet().stream()
|
||||||
.forEach(e -> {
|
.forEach(e -> {
|
||||||
String[] ids = ((String)e.getValue()).split("\\s");
|
String[] ids = ((String)e.getValue()).split("\\s");
|
||||||
out.printf(" tzCanonicalIDMap.put(\"%s\", \"%s\");\n", e.getKey(),
|
out.printf(" tzCanonicalIDMap.put(\"%s\", \"%s\");\n", e.getKey(),
|
||||||
ids[0]);
|
ids[0]);
|
||||||
for (int i = 1; i < ids.length; i++) {
|
for (int i = 1; i < ids.length; i++) {
|
||||||
out.printf(" tzCanonicalIDMap.put(\"%s\", \"%s\");\n", ids[i],
|
out.printf(" tzCanonicalIDMap.put(\"%s\", \"%s\");\n", ids[i],
|
||||||
ids[0]);
|
ids[0]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
out.printf(" }\n }\n\n");
|
out.println();
|
||||||
|
|
||||||
|
// for likelyScript map
|
||||||
|
for (String key : metaInfo.keySet()) {
|
||||||
|
if (key.startsWith(CLDRConverter.LIKELY_SCRIPT_PREFIX)) {
|
||||||
|
// ensure spaces at the begin/end for delimiting purposes
|
||||||
|
out.printf(" likelyScriptMap.put(\"%s\", \"%s\");\n",
|
||||||
|
key.substring(CLDRConverter.LIKELY_SCRIPT_PREFIX.length()),
|
||||||
|
" " + metaInfo.get(key).stream().collect(Collectors.joining(" ")) + " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.printf(" }\n }\n");
|
||||||
}
|
}
|
||||||
|
out.println();
|
||||||
|
|
||||||
out.printf("""
|
out.printf("""
|
||||||
@Override
|
@Override
|
||||||
@ -390,12 +387,13 @@ class ResourceBundleGenerator implements BundleGenerator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String availableLanguageTags(String category) {
|
public String availableLanguageTags(String category) {
|
||||||
return resourceNameToLocales.getOrDefault(category, "");
|
return " %s";
|
||||||
}
|
}
|
||||||
%s
|
|
||||||
}
|
|
||||||
""",
|
""",
|
||||||
CLDRConverter.isBaseModule ? """
|
toLocaleList(applyLanguageAliases(metaInfo.get("AvailableLocales")), false));
|
||||||
|
|
||||||
|
if(CLDRConverter.isBaseModule) {
|
||||||
|
out.printf("""
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getLanguageAliasMap() {
|
public Map<String, String> getLanguageAliasMap() {
|
||||||
@ -404,16 +402,41 @@ class ResourceBundleGenerator implements BundleGenerator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> tzCanonicalIDs() {
|
public Map<String, String> tzCanonicalIDs() {
|
||||||
return TZCanonicalIDMapHolder.tzCanonicalIDMap;
|
return CLDRMapHolder.tzCanonicalIDMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Locale, String[]> parentLocales() {
|
public Map<Locale, String[]> parentLocales() {
|
||||||
return parentLocalesMap;
|
return parentLocalesMap;
|
||||||
}
|
}
|
||||||
""" : "");
|
|
||||||
|
// package access from CLDRLocaleProviderAdapter
|
||||||
|
Map<String, String> likelyScriptMap() {
|
||||||
|
return CLDRMapHolder.likelyScriptMap;
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
out.printf("}\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void generateStringArray(SortedSet<String> set, PrintWriter out) throws IOException {
|
||||||
|
String[] children = toLocaleList(set, true).split(" ");
|
||||||
|
Arrays.sort(children);
|
||||||
|
out.printf(" new String[] {\n" +
|
||||||
|
" ");
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < children.length; i++) {
|
||||||
|
String child = children[i];
|
||||||
|
out.printf("\"%s\", ", child);
|
||||||
|
count += child.length() + 4;
|
||||||
|
if (i != children.length - 1 && count > 64) {
|
||||||
|
out.printf("\n ");
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.printf("\n });\n");
|
||||||
|
}
|
||||||
|
|
||||||
private static final Locale.Builder LOCALE_BUILDER = new Locale.Builder();
|
private static final Locale.Builder LOCALE_BUILDER = new Locale.Builder();
|
||||||
private static boolean isBaseLocale(String localeID) {
|
private static boolean isBaseLocale(String localeID) {
|
||||||
localeID = localeID.replaceAll("-", "_");
|
localeID = localeID.replaceAll("-", "_");
|
||||||
@ -433,7 +456,9 @@ class ResourceBundleGenerator implements BundleGenerator {
|
|||||||
if (!all && CLDRConverter.isBaseModule ^ isBaseLocale(id)) {
|
if (!all && CLDRConverter.isBaseModule ^ isBaseLocale(id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sb.append(' ');
|
if (sb.length() > 0) {
|
||||||
|
sb.append(' ');
|
||||||
|
}
|
||||||
sb.append(id);
|
sb.append(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,29 +57,22 @@ class SupplementalDataParseHandler extends AbstractLDMLHandler<Object> {
|
|||||||
// the weekData is listed using country code.
|
// the weekData is listed using country code.
|
||||||
//
|
//
|
||||||
// weekData are generated per each country
|
// weekData are generated per each country
|
||||||
private final Map<String, Object> firstDayMap;
|
private static final Map<String, Object> firstDayMap = new HashMap<>();
|
||||||
private final Map<String, Object> minDaysMap;
|
private static final Map<String, Object> minDaysMap = new HashMap<>();
|
||||||
|
|
||||||
// Parent locales. These information will only be
|
// Parent locales. These information will only be
|
||||||
// generated towards the base meta info, with the format of
|
// generated towards the base meta info, with the format of
|
||||||
//
|
//
|
||||||
// parentLocale.<parent_locale_id>=<child_locale_id>(" "<child_locale_id>)+
|
// parentLocale.<parent_locale_id>=<child_locale_id>(" "<child_locale_id>)+
|
||||||
private final Map<String, String> parentLocalesMap;
|
private static final Map<String, String> parentLocalesMap = new HashMap<>();
|
||||||
|
|
||||||
// Input Skeleton map for "preferred" and "allowed"
|
// Input Skeleton map for "preferred" and "allowed"
|
||||||
// Map<"preferred"/"allowed", Map<"skeleton", SortedSet<"regions">>>
|
// Map<"preferred"/"allowed", Map<"skeleton", SortedSet<"regions">>>
|
||||||
private final Map<String, Map<String, SortedSet<String>>> inputSkeletonMap;
|
private static final Map<String, Map<String, SortedSet<String>>> inputSkeletonMap = new HashMap<>();
|
||||||
|
|
||||||
// "component" specific to this parent locale chain
|
// "component" specific to this parent locale chain
|
||||||
private String currentParentLocaleComponent;
|
private String currentParentLocaleComponent;
|
||||||
|
|
||||||
SupplementalDataParseHandler() {
|
|
||||||
firstDayMap = new HashMap<>();
|
|
||||||
minDaysMap = new HashMap<>();
|
|
||||||
parentLocalesMap = new HashMap<>();
|
|
||||||
inputSkeletonMap = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It returns Map that contains the firstDay and minDays information for
|
* It returns Map that contains the firstDay and minDays information for
|
||||||
* the country. The Map is created in JRE format after obtaining the data
|
* the country. The Map is created in JRE format after obtaining the data
|
||||||
@ -158,9 +151,15 @@ class SupplementalDataParseHandler extends AbstractLDMLHandler<Object> {
|
|||||||
// Ignore component for now, otherwise "zh-Hant" falling back to "zh" would happen
|
// Ignore component for now, otherwise "zh-Hant" falling back to "zh" would happen
|
||||||
// https://github.com/unicode-org/cldr/pull/2664
|
// https://github.com/unicode-org/cldr/pull/2664
|
||||||
if (currentParentLocaleComponent == null) {
|
if (currentParentLocaleComponent == null) {
|
||||||
|
var parent = attributes.getValue("parent").replaceAll("_", "-");
|
||||||
|
|
||||||
parentLocalesMap.put(
|
parentLocalesMap.put(
|
||||||
attributes.getValue("parent").replaceAll("_", "-"),
|
parent,
|
||||||
attributes.getValue("locales").replaceAll("_", "-"));
|
attributes.getValue("locales").replaceAll("_", "-"));
|
||||||
|
|
||||||
|
if ("root".equals(parent)) {
|
||||||
|
CLDRConverter.nonlikelyScript = "nonlikelyScript".equals(attributes.getValue("localeRules"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -259,6 +259,24 @@ public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parent == null) {
|
||||||
|
// check nonlikelyScript locales
|
||||||
|
if (CLDRBaseLocaleDataMetaInfo.nonlikelyScript && locale.getCountry().isEmpty()) {
|
||||||
|
var lang = " " + locale.getLanguage() + " ";
|
||||||
|
var script= locale.getScript();
|
||||||
|
if (!script.isEmpty()) {
|
||||||
|
parent = baseMetaInfo.likelyScriptMap().entrySet().stream()
|
||||||
|
.filter(e -> e.getValue().contains(lang))
|
||||||
|
.findAny()
|
||||||
|
.map(Map.Entry::getKey)
|
||||||
|
.map(likely -> likely.equals(script) ? null : Locale.ROOT)
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no parent found
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
parent = locale; // non existent marker
|
parent = locale; // non existent marker
|
||||||
}
|
}
|
||||||
|
101
test/jdk/sun/util/locale/provider/NonLikelyScriptTest.java
Normal file
101
test/jdk/sun/util/locale/provider/NonLikelyScriptTest.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8329691
|
||||||
|
* @modules java.base/sun.util.locale.provider
|
||||||
|
* java.base/sun.util.cldr
|
||||||
|
* @summary Tests CLDR's `nonlikelyScript` attribute is correctly implemented
|
||||||
|
* with the CLDRLocaleProviderAdapter
|
||||||
|
* @run junit NonLikelyScriptTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import sun.util.cldr.CLDRLocaleProviderAdapter;
|
||||||
|
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
public class NonLikelyScriptTest {
|
||||||
|
private static final CLDRLocaleProviderAdapter CLDR_LOCALE_PROVIDER_ADAPTER
|
||||||
|
= (CLDRLocaleProviderAdapter) LocaleProviderAdapter.forType(LocaleProviderAdapter.Type.CLDR);
|
||||||
|
private static final Locale AZ_ARAB = Locale.forLanguageTag("az-Arab");
|
||||||
|
private static final Locale AZ_CYRL = Locale.forLanguageTag("az-Cyrl");
|
||||||
|
private static final Locale AZ_LATN = Locale.forLanguageTag("az-Latn");
|
||||||
|
private static final Locale AZ_XXXX = Locale.forLanguageTag("az-Xxxx");
|
||||||
|
private static final Locale RU_LATN = Locale.forLanguageTag("ru-Latn");
|
||||||
|
private static final Locale RU_CYRL = Locale.forLanguageTag("ru-Cyrl");
|
||||||
|
private static final Locale RU_XXXX = Locale.forLanguageTag("ru-Xxxx");
|
||||||
|
private static final Locale EN_LATN = Locale.forLanguageTag("en-Latn");
|
||||||
|
private static final Locale EN_DSRT = Locale.forLanguageTag("en-Dsrt");
|
||||||
|
private static final Locale EN_XXXX = Locale.forLanguageTag("en-Xxxx");
|
||||||
|
private static final Locale ZH_HANT_MO = Locale.forLanguageTag("zh-Hant-MO");
|
||||||
|
private static final Locale ZH_HANS_SG = Locale.forLanguageTag("zh-Hans-SG");
|
||||||
|
private static final Locale ZH_HANS = Locale.forLanguageTag("zh-Hans");
|
||||||
|
private static final Locale ZH_HANT = Locale.forLanguageTag("zh-Hant");
|
||||||
|
private static final Locale ZH_XXXX = Locale.forLanguageTag("zh-Xxxx");
|
||||||
|
|
||||||
|
private static Stream<Arguments> parentLocales() {
|
||||||
|
|
||||||
|
return Stream.of(
|
||||||
|
// likely script
|
||||||
|
Arguments.of(AZ_LATN, List.of(AZ_LATN, Locale.of("az"), Locale.ROOT)),
|
||||||
|
Arguments.of(RU_CYRL, List.of(RU_CYRL, Locale.of("ru"), Locale.ROOT)),
|
||||||
|
Arguments.of(EN_LATN, List.of(EN_LATN, Locale.ENGLISH, Locale.ROOT)),
|
||||||
|
Arguments.of(ZH_HANS, List.of(ZH_HANS, Locale.CHINA, Locale.CHINESE, Locale.ROOT)),
|
||||||
|
Arguments.of(Locale.CHINA, List.of(Locale.forLanguageTag("zh-Hans-CN"), ZH_HANS, Locale.CHINA, Locale.CHINESE, Locale.ROOT)),
|
||||||
|
Arguments.of(ZH_HANS_SG, List.of(ZH_HANS_SG, ZH_HANS, Locale.forLanguageTag("zh-SG"), Locale.CHINESE, Locale.ROOT)),
|
||||||
|
|
||||||
|
// non-likely script, explicit (as of CLDR 45)
|
||||||
|
Arguments.of(AZ_ARAB, List.of(AZ_ARAB, Locale.ROOT)),
|
||||||
|
Arguments.of(AZ_CYRL, List.of(AZ_CYRL, Locale.ROOT)),
|
||||||
|
Arguments.of(EN_DSRT, List.of(EN_DSRT, Locale.ROOT)),
|
||||||
|
Arguments.of(ZH_HANT, List.of(ZH_HANT, Locale.ROOT)),
|
||||||
|
Arguments.of(Locale.TAIWAN, List.of(Locale.forLanguageTag("zh-Hant-TW"), ZH_HANT, Locale.ROOT)),
|
||||||
|
Arguments.of(ZH_HANT_MO, List.of(ZH_HANT_MO, Locale.forLanguageTag("zh-Hant-HK"), ZH_HANT, Locale.ROOT)),
|
||||||
|
|
||||||
|
// non-likely script, implicit
|
||||||
|
Arguments.of(AZ_XXXX, List.of(AZ_XXXX, Locale.ROOT)),
|
||||||
|
Arguments.of(RU_LATN, List.of(RU_LATN, Locale.ROOT)),
|
||||||
|
Arguments.of(RU_XXXX, List.of(RU_XXXX, Locale.ROOT)),
|
||||||
|
Arguments.of(EN_XXXX, List.of(EN_XXXX, Locale.ROOT)),
|
||||||
|
Arguments.of(ZH_XXXX, List.of(ZH_XXXX, Locale.ROOT))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("parentLocales")
|
||||||
|
public void checkParentLocales(Locale locale, List<Locale> expected) {
|
||||||
|
var actual = CLDR_LOCALE_PROVIDER_ADAPTER.getCandidateLocales("", locale);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user