8387795: Remove hard coded set of locales in LocaleData

Reviewed-by: jlu
This commit is contained in:
Naoto Sato 2026-07-09 16:28:56 +00:00
parent 095cf06e73
commit a230a6099e
5 changed files with 66 additions and 17 deletions

View File

@ -29,6 +29,7 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Formatter;
import java.util.HashSet;
import java.util.HashMap;
@ -39,6 +40,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.stream.Collectors;
import static java.util.ResourceBundle.Control;
class ResourceBundleGenerator implements BundleGenerator {
// preferred timezones - keeping compatibility with JDK1.1 3 letter abbreviations
@ -69,6 +71,9 @@ class ResourceBundleGenerator implements BundleGenerator {
// For duplicated values
private static final String META_VALUE_PREFIX = "metaValue_";
// locales in the base module
private final Set<Locale> baseModuleLocales = new HashSet<>();
@Override
public void generateBundle(String packageName, String baseName, String localeID,
Map<String, ?> map, BundleType type) throws IOException {
@ -80,8 +85,15 @@ class ResourceBundleGenerator implements BundleGenerator {
return;
}
// Assume that non-base resources go into jdk.localedata
if (!CLDRConverter.isBaseModule) {
if (CLDRConverter.isBaseModule) {
if (!localeID.equals("root")) {
baseModuleLocales.addAll(
Control.getControl(Control.FORMAT_DEFAULT)
.getCandidateLocales("",
Locale.forLanguageTag(CLDRConverter.toLanguageTag(localeID))));
}
} else {
// Assume that non-base resources go into jdk.localedata
dirName = dirName + File.separator + "ext";
packageName = packageName + ".ext";
}
@ -284,6 +296,7 @@ class ResourceBundleGenerator implements BundleGenerator {
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import sun.util.locale.provider.LocaleDataMetaInfo;
import sun.util.locale.provider.LocaleProviderAdapter;
@ -296,6 +309,7 @@ class ResourceBundleGenerator implements BundleGenerator {
out.printf("""
private static final Map<Locale, String[]> parentLocalesMap = HashMap.newHashMap(%d);
private static final Map<String, String> languageAliasMap = HashMap.newHashMap(%d);
private static final Set<Locale> baseModuleLocales;
static final boolean nonlikelyScript = %s; // package access from CLDRLocaleProviderAdapter
static {
@ -322,7 +336,23 @@ class ResourceBundleGenerator implements BundleGenerator {
CLDRConverter.handlerSupplMeta.getLanguageAliasData().forEach((key, value) -> {
out.printf(" languageAliasMap.put(\"%s\", \"%s\");\n", CLDRConverter.escape(key), CLDRConverter.escape(value));
});
out.printf(" }\n\n");
out.println();
// for baseModuleLocales
out.printf(" baseModuleLocales = Set.of(\n");
out.printf(" %s",
baseModuleLocales.stream()
.map(Locale::toLanguageTag)
.sorted(Comparator.comparing(l -> l.equals("und") ? "" : l))
.map(l -> switch(l) {
case "und" -> "Locale.ROOT";
case "en" -> "Locale.ENGLISH";
case "en-US" -> "Locale.US";
default -> "Locale.forLanguageTag(\"" + l + "\")";
})
.collect(Collectors.joining(",\n ")));
out.printf("\n );");
out.println("\n }\n");
// end of static initializer block.
@ -391,6 +421,10 @@ class ResourceBundleGenerator implements BundleGenerator {
return parentLocalesMap;
}
public Set<Locale> baseModuleLocales() {
return baseModuleLocales;
}
// package access from CLDRLocaleProviderAdapter
Map<String, String> likelyScriptMap() {
return CLDRMapHolder.likelyScriptMap;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, 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
@ -288,6 +288,10 @@ public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
|| langtags.contains(getEquivalentLoc(locale).toLanguageTag());
}
public Set<Locale> baseModuleLocales() {
return baseMetaInfo.baseModuleLocales();
}
/**
* Returns the canonical ID for the given ID
*/

View File

@ -488,4 +488,8 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R
"th-TH-TH".equals(oldname) ||
"no-NO-NY".equals(oldname);
}
public Set<Locale> baseModuleLocales() {
return Set.of(Locale.ROOT);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, 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
@ -27,6 +27,8 @@ package sun.util.locale.provider;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import sun.util.resources.LocaleData;
/**
@ -40,5 +42,11 @@ public interface ResourceBundleBasedAdapter {
/**
* candidate locales customization
*/
public List<Locale> getCandidateLocales(String baseName, Locale locale);
List<Locale> getCandidateLocales(String baseName, Locale locale);
/**
* Returns the locales whose resource bundles are resolved from
* the java.base module for this adapter.
*/
Set<Locale> baseModuleLocales();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2026, 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
@ -45,7 +45,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.spi.ResourceBundleProvider;
import sun.util.locale.provider.JRELocaleProviderAdapter;
@ -180,9 +179,6 @@ public class LocaleData {
private static class LocaleDataStrategy implements Bundles.Strategy {
private static final LocaleDataStrategy INSTANCE = new LocaleDataStrategy();
// TODO: avoid hard-coded Locales
private static final Set<Locale> JAVA_BASE_LOCALES
= Set.of(Locale.ROOT, Locale.ENGLISH, Locale.US, Locale.of("en", "US", "POSIX"));
private LocaleDataStrategy() {
}
@ -202,11 +198,8 @@ public class LocaleData {
String key = baseName + '-' + locale.toLanguageTag();
List<Locale> candidates = CANDIDATES_MAP.get(key);
if (candidates == null) {
LocaleProviderAdapter.Type type = baseName.contains(DOTCLDR) ? CLDR : JRE;
LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type);
candidates = adapter instanceof ResourceBundleBasedAdapter rbba ?
rbba.getCandidateLocales(baseName, locale) :
defaultControl.getCandidateLocales(baseName, locale);
var adapter = getAdapter(baseName);
candidates = adapter.getCandidateLocales(baseName, locale);
// Weed out Locales which are known to have no resource bundles
int lastDot = baseName.lastIndexOf('.');
@ -227,7 +220,13 @@ public class LocaleData {
}
boolean inJavaBaseModule(String baseName, Locale locale) {
return JAVA_BASE_LOCALES.contains(locale);
return getAdapter(baseName).baseModuleLocales().contains(locale);
}
private static ResourceBundleBasedAdapter getAdapter(String baseName) {
return (ResourceBundleBasedAdapter)(baseName.contains(DOTCLDR) ?
LocaleProviderAdapter.forType(CLDR) :
LocaleProviderAdapter.forType(JRE));
}
@Override