Skip to content

Commit 54b79e8

Browse files
authored
Merge pull request #63 from salesforce/jdk-17
fixed locale changes by JDK 17
2 parents 840b447 + 84943ac commit 54b79e8

27 files changed

+511
-465
lines changed

src/main/java/com/force/i18n/LabelUtils.java

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public static String getSampleGrammarFile(@Nullable String grammar) {
130130
} else {
131131
// If they pasted in a whole file, it's fine.
132132
if (!grammar.contains("<sfdcnames>") && !grammar.contains("<sfdcadjectives>")
133-
&& !grammar.contains("<names>") && !grammar.contains("<adjectives>")) {
133+
&& !grammar.contains("<names>") && !grammar.contains("<adjectives>")) {
134134
StringBuilder sb = new StringBuilder(grammar.length() + 100);
135135
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
136136
sb.append("<names>");
@@ -139,7 +139,7 @@ public static String getSampleGrammarFile(@Nullable String grammar) {
139139
return sb.toString();
140140
} else {
141141
// Remove the dtd which confuses the parser
142-
String fixedGrammar = grammar.replace("<!DOCTYPE sfdcnames SYSTEM \"sfdcnames.dtd\">", "");
142+
String fixedGrammar = grammar.replace("<!DOCTYPE sfdcnames SYSTEM \"sfdcnames.dtd\">", "");
143143
fixedGrammar = fixedGrammar.replace("<!DOCTYPE sfdcadjectives SYSTEM \"sfdcadjectives.dtd\">", "");
144144
fixedGrammar = fixedGrammar.replace("<!DOCTYPE names SYSTEM \"names.dtd\">", "");
145145
fixedGrammar = fixedGrammar.replace("<!DOCTYPE adjectives SYSTEM \"adjectives.dtd\">", "");
@@ -180,46 +180,63 @@ public String nounify(String input, LanguageDictionary dictionary) {
180180
return new Nounifier(dictionary).nounifyString(input);
181181
}
182182

183-
/**
184-
* Set of locale langauges strings where the results are JDK dependent
183+
/*
184+
* Map of locale langauges strings where the results are JDK dependent.
185+
* Java 17 fixed legacy language code and autmatically replace it in {@code java.util.Locale} (JDK-8267069). This is
186+
* for backward compatibility.
185187
*/
186-
static final Set<String> JDK_DEPENDENT_LANGUAGE = ImmutableSet.of(LanguageConstants.YIDDISH_ISO,
187-
LanguageConstants.HEBREW_ISO, LanguageConstants.INDONESIAN_ISO);
188-
188+
static final Map<String, String> JDK_DEPENDENT_LANGUAGE = Map.of( //
189+
LanguageConstants.YIDDISH_ISO, LanguageConstants.YIDDISH, //
190+
LanguageConstants.HEBREW_ISO, LanguageConstants.HEBREW, //
191+
LanguageConstants.INDONESIAN_ISO, LanguageConstants.INDONESIAN);
189192

190-
public static List<URL> getFileNames(HumanLanguage language,URL rootDirectory, String basename ) {
193+
public static List<URL> getFileNames(HumanLanguage language, URL rootDirectory, String basename ) {
191194
List<URL> list = new ArrayList<>();
192195
try {
193-
Locale locale = language.getLocale();
194-
list.add(new URL(rootDirectory, locale.getLanguage() + '/' + basename));
196+
final Locale locale = language.getLocale();
197+
final String override = language.getOverrideLanguage();
198+
final boolean hasOverride = override != null && !locale.getLanguage().equals(override);
199+
200+
list.add(getUrl(rootDirectory, locale.getLanguage(), basename));
201+
// If the override language is set, add it
202+
if (hasOverride) list.add(getUrl(rootDirectory, override, basename));
195203
// If the iso code for the language changed between JDK versions, use the old isocode for the directory
196-
if (JDK_DEPENDENT_LANGUAGE.contains(locale.getLanguage())) {
197-
list.add(new URL(rootDirectory, language.getOverrideLanguage() + '/' + basename));
204+
if (JDK_DEPENDENT_LANGUAGE.containsKey(locale.getLanguage())) {
205+
list.add(getUrl(rootDirectory, JDK_DEPENDENT_LANGUAGE.get(locale.getLanguage()), basename));
206+
}
207+
208+
if (!locale.getCountry().isEmpty()) {
209+
/*
210+
* Code required because there is no Chinese traditional locale in jdk Locale.java and taiwan and Hong
211+
* kong are 2 different countries
212+
* We will assume that Hong Kong (HK country code) derive the Traditional Chinese from Taiwan (TW)
213+
* In the future, to define Hong Kong label, a new directory will need to be created zh/HK.
214+
*/
215+
if (language.getLocaleString().equals(LanguageConstants.CHINESE_HK)) {
216+
// adding Taiwan as fallback. assuming no override, or variant are set for this
217+
list.add(getUrl(rootDirectory, locale.getLanguage(), Locale.TRADITIONAL_CHINESE.getCountry(), basename));
218+
list.add(getUrl(rootDirectory, locale.getLanguage(), locale.getCountry(), basename));
219+
} else {
220+
list.add(getUrl(rootDirectory, locale.getLanguage(), locale.getCountry(), basename));
221+
if (hasOverride) list.add(getUrl(rootDirectory, override, locale.getCountry(), basename));
222+
223+
if (!locale.getVariant().isEmpty()) {
224+
list.add(getUrl(rootDirectory, locale.getLanguage(), locale.getCountry(), locale.getVariant(), basename));
225+
if (hasOverride) list.add(getUrl(rootDirectory, override, locale.getCountry(), locale.getVariant(), basename));
226+
}
227+
}
198228
}
199-
if (locale.getCountry().length() > 0) {
200-
/*
201-
* Code required because there is no Chinese traditional locale in jdk Locale.java and taiwan and Hong kong are 2 different countries
202-
* We will assume that Hong Kong (HK country code) derive the Traditional Chinese from Taiwan (TW)
203-
* In the future, to define Hong Kong label, a new directory will need to be created zh/HK.
204-
*/
205-
if(language.getLocaleString().equals(LanguageConstants.CHINESE_HK)){
206-
//adding Taiwan as fallback
207-
list.add(new URL(rootDirectory, locale.getLanguage() + '/'+ Locale.TRADITIONAL_CHINESE.getCountry() +'/'+ basename));
208-
list.add(new URL(rootDirectory, locale.getLanguage() + '/'+ locale.getCountry() + '/'+ basename));
209-
}else{
210-
list.add(new URL(rootDirectory, locale.getLanguage() + '/' + locale.getCountry() + '/' + basename));
211-
if (locale.getVariant().length() > 0) {
212-
list.add(new URL(rootDirectory, locale.getLanguage() + '/' + locale.getCountry() + '/' + locale.getVariant() + '/' + basename));
213-
}
214-
}
215-
}
216229
} catch (MalformedURLException e) {
217230
throw new IllegalArgumentException(e);
218231
}
219-
return list;
220-
}
232+
return list;
233+
}
234+
235+
private static URL getUrl(URL root, String... paths) throws MalformedURLException {
236+
return new URL(root, String.join("/", paths));
237+
}
221238

222-
private static final Pattern nonalphaPattern = Pattern.compile("\\W");
239+
private static final Pattern nonalphaPattern = Pattern.compile("\\W");
223240

224241
// TODO: Switch this to splitter.
225242
static List<String> tokenize(String input) {
@@ -244,7 +261,7 @@ static List<String> tokenize(String input) {
244261
* to determine if there should be some "tokenization" of the string.
245262
*/
246263
public static class Nounifier {
247-
private final static Set<String> EXCLUDED_NOUNS = ImmutableSet.of("Role", "Email", "Address", "{0}");
264+
private static final Set<String> EXCLUDED_NOUNS = ImmutableSet.of("Role", "Email", "Address", "{0}");
248265

249266
private final GenericTrieMatcher<String> nounMatcher;
250267
private final GenericTrieMatcher<String> adjMatcher;

src/main/java/com/force/i18n/commons/util/collection/IntHashMap.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
package com.force.i18n.commons.util.collection;
99

1010
import java.io.IOException;
11-
import java.io.Serializable;
1211
import java.util.*;
1312

1413
import com.google.common.annotations.Beta;
@@ -77,12 +76,12 @@
7776
* Beta class. Generally use {@link java.util.HashMap} or {@link java.util.EnumMap} instead.
7877
*
7978
* @author Based on Sun's java.util.HashMap (modified by koliver)
80-
* @see IntMap
81-
* @see java.util.HashMap
79+
* @see IntMap
80+
* @see java.util.HashMap
8281
*/
8382
@Beta
8483
@SuppressWarnings("rawtypes") // TODO Fix
85-
public class IntHashMap<V> extends AbstractIntMap<V> implements Serializable {
84+
public class IntHashMap<V> extends AbstractIntMap<V> {
8685
private static final long serialVersionUID = 0L;
8786

8887
private static final int DEFAULT_CAPACITY = 101;
@@ -186,7 +185,7 @@ public int size() {
186185
*
187186
* @param value value whose presence in this map is to be tested.
188187
*/
189-
@Override
188+
@Override
190189
public boolean containsValue(Object value) {
191190
IEntry[] tab = this.table;
192191

@@ -287,9 +286,9 @@ private void rehash() {
287286
* @param key key with which the specified value is to be associated.
288287
* @param value value to be associated with the specified key.
289288
* @return previous value associated with specified key, or {@code null}
290-
* if there was no mapping for key. A {@code null} return can
291-
* also indicate that the HashMap previously associated
292-
* {@code null} with the specified key.
289+
* if there was no mapping for key. A {@code null} return can
290+
* also indicate that the HashMap previously associated
291+
* {@code null} with the specified key.
293292
*/
294293
@Override
295294
public V put(int key, V value) {
@@ -328,9 +327,9 @@ public V put(int key, V value) {
328327
*
329328
* @param key key whose mapping is to be removed from the map.
330329
* @return previous value associated with specified key, or {@code null}
331-
* if there was no mapping for key. A {@code null} return can
332-
* also indicate that the map previously associated {@code null}
333-
* with the specified key.
330+
* if there was no mapping for key. A {@code null} return can
331+
* also indicate that the map previously associated {@code null}
332+
* with the specified key.
334333
*/
335334
@Override
336335
public V remove(int key) {
@@ -734,6 +733,20 @@ public int next() {
734733
}
735734
}
736735

736+
@Override
737+
public int hashCode() {
738+
return super.hashCode();
739+
}
740+
741+
@Override
742+
public boolean equals(Object other) {
743+
if (other instanceof IntHashMap) {
744+
// super compares table and count. that may be enough
745+
return super.equals(other);
746+
}
747+
return false;
748+
}
749+
737750
// Serialization
738751
private void writeObject(java.io.ObjectOutputStream s) throws IOException {
739752
// Write out the threshold, loadfactor, and any hidden stuff

src/main/java/com/force/i18n/grammar/LanguageDictionary.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public class LanguageDictionary implements Serializable {
6464
// TODO: These could all be made lists when serialized
6565

6666
// map to Noun
67-
protected GrammaticalTermMap<Noun> nounMap;
67+
protected GrammaticalTermMap<Noun> nounMap;
6868
// map to Noun
6969
protected GrammaticalTermMap<Noun> nounMapByPluralAlias;
7070
// map to Adjective
@@ -202,9 +202,9 @@ public GrammaticalTermMap<Noun> getNounByPluralAlias() {
202202
public GrammaticalTermMap<Adjective> getAdjectiveMap() {
203203
return adjectiveMap;
204204
}
205-
205+
206206
/**
207-
* get termMap of Article
207+
* get termMap of Article
208208
*/
209209
public GrammaticalTermMap<Article> getArticleMap() {
210210
return articleMap;
@@ -213,10 +213,10 @@ public GrammaticalTermMap<Article> getArticleMap() {
213213

214214
private void forAllTerms (TermType type, BiConsumer<String, GrammaticalTerm> f) {
215215
switch (type) {
216-
case Noun:
216+
case Noun:
217217
for(Map.Entry<String, Noun> e : nounMap.entrySet()) f.accept(e.getKey(), e.getValue());
218218
break;
219-
case Adjective:
219+
case Adjective:
220220
for(Map.Entry<String, Adjective> e : adjectiveMap.entrySet()) f.accept(e.getKey(), e.getValue());
221221
break;
222222
case Article:
@@ -226,14 +226,14 @@ private void forAllTerms (TermType type, BiConsumer<String, GrammaticalTerm> f)
226226
throw new AssertionError("Invalid term type " + type);
227227
}
228228
}
229-
229+
230230

231231

232232
public Set<String> getAllTermNames(TermType type) {
233233
switch (type) {
234-
case Noun:
234+
case Noun:
235235
return Collections.unmodifiableSet(nounMap.keySet());
236-
case Adjective:
236+
case Adjective:
237237
return Collections.unmodifiableSet(adjectiveMap.keySet());
238238
case Article:
239239
return Collections.unmodifiableSet(articleMap.keySet());
@@ -249,8 +249,8 @@ public Set<String> getAllTermNames(TermType type) {
249249
public Set<String> getAllInheritedTermNames(TermType type) {
250250
Set<String> result = new HashSet<String>();
251251
forAllTerms(type, (k,v) -> {
252-
if (v.isCopiedFromDefault()) result.add(k);
253-
});
252+
if (v.isCopiedFromDefault()) result.add(k);
253+
});
254254
return result;
255255
}
256256

@@ -669,12 +669,12 @@ public void writeJson(Appendable appendable, boolean useRenamedNouns, Collection
669669
* @throws IOException if an error happens during append
670670
*/
671671
public void writeJsonTerms(Appendable out, boolean useRenamedNouns, Collection<GrammaticalTerm> terms) throws IOException {
672-
Collection<String> termsToInclude =
673-
terms == null ? null :
672+
Collection<String> termsToInclude =
673+
terms == null ? null :
674674
terms.stream().map((t)->t.getName()).collect(Collectors.toSet());
675675
writeJson(out, useRenamedNouns, termsToInclude);
676676
}
677-
677+
678678

679679
private void writeObject(ObjectOutputStream out) throws IOException {
680680
makeSkinny();
@@ -686,7 +686,6 @@ protected void writeObjectInternal(ObjectOutputStream out) throws IOException {
686686
// do nothing here - for hook
687687
}
688688

689-
@SuppressWarnings("unchecked")
690689
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
691690
in.defaultReadObject();
692691

@@ -720,9 +719,9 @@ public Noun getNounOverride(Noun n) {
720719
}
721720

722721
private static class TreeSetSupplier<V> implements Supplier<SortedSet<V>>, Serializable {
723-
private static final long serialVersionUID = 1L;
722+
private static final long serialVersionUID = 1L;
724723

725-
@Override
724+
@Override
726725
public SortedSet<V> get() {
727726
return new TreeSet<V>();
728727
}

src/main/java/com/force/i18n/grammar/impl/ComplexGrammaticalForm.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import com.force.i18n.grammar.ModifierForm;
4040
import com.force.i18n.grammar.Noun;
4141
import com.force.i18n.grammar.NounForm;
42+
import com.google.common.base.Preconditions;
4243
import com.google.common.collect.ArrayListMultimap;
4344
import com.google.common.collect.ImmutableMap;
4445
import com.google.common.collect.Multimap;
@@ -137,7 +138,7 @@ protected Object readResolve() {
137138
case Adjective: formList = declension.getAdjectiveForms(); break;
138139
case Article: formList = declension.getArticleForms(); break;
139140
}
140-
assert formList != null;
141+
Preconditions.checkState(formList != null);
141142
return formList.get(this.ordinal);
142143
}
143144
}
@@ -273,7 +274,7 @@ static <T extends ComplexGrammaticalForm> void serializeFormMap(ObjectOutputStre
273274
} else {
274275
out.writeByte(values.size());
275276
for (Map.Entry<T,String> entry : values.entrySet()) {
276-
out.writeByte(entry.getKey().getOrdinal());
277+
out.writeByte(entry.getKey().getOrdinal());
277278
out.writeUTF(entry.getValue()); // Serialize the "object" because it's been uniquefied
278279
}
279280
}
@@ -292,7 +293,8 @@ static <T extends ComplexGrammaticalForm> Map<T, String> deserializeFormMap(Obje
292293
case Adjective: formList = (List<T>)declension.getAdjectiveForms(); break;
293294
case Article: formList = (List<T>)declension.getArticleForms(); break;
294295
}
295-
assert formList != null;
296+
Preconditions.checkState(formList != null);
297+
296298
for (int i = 0; i < size; i++) {
297299
int ordinal = in.readByte();
298300
String value = intern(in.readUTF());

src/main/java/com/force/i18n/grammar/impl/EnglishDeclension.java

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package com.force.i18n.grammar.impl;
99

1010
import static com.force.i18n.commons.util.settings.IniFileUtil.intern;
11+
import static com.google.common.base.Preconditions.checkArgument;
1112

1213
import java.io.IOException;
1314
import java.util.*;
@@ -25,18 +26,18 @@
2526
* @author stamm
2627
*/
2728
class EnglishDeclension extends ArticledDeclension {
28-
private static final Logger logger = Logger.getLogger(EnglishDeclension.class.getName());
29+
private static final Logger logger = Logger.getLogger(EnglishDeclension.class.getName());
2930

30-
public EnglishDeclension(HumanLanguage language) {
31-
super(language);
32-
assert language.getLocale().getLanguage().equals("en") : "Initializing a language that isn't english";
33-
}
31+
public EnglishDeclension(HumanLanguage language) {
32+
super(language);
33+
checkArgument(language.getLocale().getLanguage().equals("en"), "Initializing a language that isn't english");
34+
}
3435

3536
/**
3637
* The english articles are distinguished by whether the next noun starts with a vowel
3738
* sound or not (although the, unlike a/an is spelled the same).
3839
*/
39-
public static enum EnglishArticleForm implements ArticleForm {
40+
public enum EnglishArticleForm implements ArticleForm {
4041
SINGULAR(LanguageNumber.SINGULAR, LanguageStartsWith.CONSONANT),
4142
SINGULAR_V(LanguageNumber.SINGULAR, LanguageStartsWith.VOWEL),
4243
PLURAL(LanguageNumber.PLURAL, LanguageStartsWith.CONSONANT)
@@ -59,17 +60,17 @@ static EnglishArticleForm getForm(ModifierForm form) {
5960
(form.getStartsWith() == LanguageStartsWith.VOWEL ? SINGULAR_V : SINGULAR)
6061
: PLURAL;
6162
}
62-
@Override
63-
public String getKey() {
64-
return getNumber().getDbValue() + "-" + getStartsWith().getDbValue();
65-
}
66-
67-
@Override
68-
public void appendJsFormReplacement(Appendable a, String termFormVar, String genderVar, String startsWithVar)
69-
throws IOException {
70-
// The only variant is in the signular, so we don't want to screw up "the"
71-
a.append(termFormVar+".charAt(0)=='"+LanguageNumber.PLURAL.getDbValue()+"'?"+termFormVar+":'"+LanguageNumber.SINGULAR.getDbValue()+"-'+"+startsWithVar);
72-
}
63+
@Override
64+
public String getKey() {
65+
return getNumber().getDbValue() + "-" + getStartsWith().getDbValue();
66+
}
67+
68+
@Override
69+
public void appendJsFormReplacement(Appendable a, String termFormVar, String genderVar, String startsWithVar)
70+
throws IOException {
71+
// The only variant is in the signular, so we don't want to screw up "the"
72+
a.append(termFormVar+".charAt(0)=='"+LanguageNumber.PLURAL.getDbValue()+"'?"+termFormVar+":'"+LanguageNumber.SINGULAR.getDbValue()+"-'+"+startsWithVar);
73+
}
7374
}
7475

7576
/**

0 commit comments

Comments
 (0)