--- old/src/share/classes/java/util/logging/Level.java 2013-09-02 12:20:08.000000000 +0200 +++ new/src/share/classes/java/util/logging/Level.java 2013-09-02 12:20:07.000000000 +0200 @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; @@ -63,7 +64,7 @@ */ public class Level implements java.io.Serializable { - private static String defaultBundle = "sun.util.logging.resources.logging"; + private static final String defaultBundle = "sun.util.logging.resources.logging"; /** * @serial The non-localized name of the level. @@ -81,7 +82,8 @@ private final String resourceBundleName; // localized level name - private String localizedLevelName; + private transient String localizedLevelName; + private transient Locale cachedLocale; /** * OFF is a special level that can be used to turn off logging. @@ -209,6 +211,7 @@ this.value = value; this.resourceBundleName = resourceBundleName; this.localizedLevelName = resourceBundleName == null ? name : null; + this.cachedLocale = null; KnownLevel.add(this); } @@ -250,17 +253,71 @@ return this.name; } - final synchronized String getLocalizedLevelName() { + private String computeLocalizedLevelName(Locale newLocale) { + ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName, newLocale); + final String localizedName = rb.getString(name); + + final boolean isDefaultBundle = defaultBundle.equals(resourceBundleName); + if (!isDefaultBundle) return localizedName; + + // This is a trick to determine whether the name has been translated + // or not. If it has not been translated, we need to use Locale.ROOT + // when calling toUpperCase(). + final Locale rbLocale = rb.getLocale(); + final Locale locale = + Locale.ROOT.equals(rbLocale) + || name.equals(localizedName.toUpperCase(Locale.ROOT)) + ? Locale.ROOT : rbLocale; + + // ALL CAPS in a resource bundle's message indicates no translation + // needed per Oracle translation guideline. To workaround this + // in Oracle JDK implementation, convert the localized level name + // to uppercase for compatibility reason. + return Locale.ROOT.equals(locale) ? name : localizedName.toUpperCase(locale); + } + + // Avoid looking up the localizedLevelName twice if we already + // have it. + final String getCachedLocalizedLevelName() { + if (localizedLevelName != null) { - return localizedLevelName; + if (cachedLocale != null) { + if (cachedLocale.equals(Locale.getDefault())) { + // OK: our cached value was looked up with the same + // locale. We can use it. + return localizedLevelName; + } + } + } + + if (resourceBundleName == null) { + // No resource bundle: just use the name. + return name; + } + + // We need to compute the localized name. + // Either because it's the first time, or because our cached + // value is for a different locale. Just return null. + return null; + } + + final synchronized String getLocalizedLevelName() { + + // See if we have a cached localized name + final String cachedLocalizedName = getCachedLocalizedLevelName(); + if (cachedLocalizedName != null) { + return cachedLocalizedName; } + // No cached localized name or cache invalid. + // Need to compute the localized name. + final Locale newLocale = Locale.getDefault(); try { - ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName); - localizedLevelName = rb.getString(name); + localizedLevelName = computeLocalizedLevelName(newLocale); } catch (Exception ex) { localizedLevelName = name; } + cachedLocale = newLocale; return localizedLevelName; } @@ -318,6 +375,7 @@ * * @return the non-localized name of the Level, for example "INFO". */ + @Override public final String toString() { return name; } @@ -420,6 +478,7 @@ * Compare two objects for value equality. * @return true if and only if the two objects have the same level value. */ + @Override public boolean equals(Object ox) { try { Level lx = (Level)ox; @@ -433,6 +492,7 @@ * Generate a hashcode. * @return a hashcode based on the level value */ + @Override public int hashCode() { return this.value; } --- old/src/share/classes/sun/util/logging/resources/logging.properties 2013-09-02 12:20:09.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging.properties 2013-09-02 12:20:09.000000000 +0200 @@ -27,20 +27,20 @@ # these are the same as the non-localized level name. # The following ALL CAPS words should be translated. -ALL=ALL +ALL=All # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=Severe # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=Warning # The following ALL CAPS words should be translated. -INFO=INFO +INFO=Info # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= Config # The following ALL CAPS words should be translated. -FINE=FINE +FINE=Fine # The following ALL CAPS words should be translated. -FINER=FINER +FINER=Finer # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=Finest # The following ALL CAPS words should be translated. -OFF=OFF +OFF=Off --- old/src/share/classes/sun/util/logging/resources/logging_de.properties 2013-09-02 12:20:11.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging_de.properties 2013-09-02 12:20:11.000000000 +0200 @@ -27,20 +27,20 @@ # these are the same as the non-localized level name. # The following ALL CAPS words should be translated. -ALL=ALL +ALL=Alle # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=Schwerwiegend # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=Warnung # The following ALL CAPS words should be translated. -INFO=INFO +INFO=Information # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= Konfiguration # The following ALL CAPS words should be translated. -FINE=FINE +FINE=Fein # The following ALL CAPS words should be translated. -FINER=FINER +FINER=Feiner # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=Am feinsten # The following ALL CAPS words should be translated. -OFF=OFF +OFF=Deaktiviert --- old/src/share/classes/sun/util/logging/resources/logging_es.properties 2013-09-02 12:20:12.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging_es.properties 2013-09-02 12:20:12.000000000 +0200 @@ -27,20 +27,20 @@ # these are the same as the non-localized level name. # The following ALL CAPS words should be translated. -ALL=ALL +ALL=Todo # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=Grave # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=Advertencia # The following ALL CAPS words should be translated. -INFO=INFO +INFO=Informaci\u00F3n # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= Configurar # The following ALL CAPS words should be translated. -FINE=FINE +FINE=Detallado # The following ALL CAPS words should be translated. -FINER=FINER +FINER=Muy Detallado # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=M\u00E1s Detallado # The following ALL CAPS words should be translated. -OFF=OFF +OFF=Desactivado --- old/src/share/classes/sun/util/logging/resources/logging_fr.properties 2013-09-02 12:20:14.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging_fr.properties 2013-09-02 12:20:13.000000000 +0200 @@ -27,20 +27,20 @@ # these are the same as the non-localized level name. # The following ALL CAPS words should be translated. -ALL=ALL +ALL=Tout # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=Grave # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=Avertissement # The following ALL CAPS words should be translated. -INFO=INFO +INFO=Infos # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= Config # The following ALL CAPS words should be translated. -FINE=FINE +FINE=Pr\u00E9cis # The following ALL CAPS words should be translated. -FINER=FINER +FINER=Plus pr\u00E9cis # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=Le plus pr\u00E9cis # The following ALL CAPS words should be translated. -OFF=OFF +OFF=D\u00E9sactiv\u00E9 --- old/src/share/classes/sun/util/logging/resources/logging_it.properties 2013-09-02 12:20:15.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging_it.properties 2013-09-02 12:20:15.000000000 +0200 @@ -27,20 +27,20 @@ # these are the same as the non-localized level name. # The following ALL CAPS words should be translated. -ALL=ALL +ALL=Tutto # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=Grave # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=Avvertenza # The following ALL CAPS words should be translated. -INFO=INFO +INFO=Informazioni # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= Configurazione # The following ALL CAPS words should be translated. -FINE=FINE +FINE=Buono # The following ALL CAPS words should be translated. -FINER=FINER +FINER=Migliore # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=Ottimale # The following ALL CAPS words should be translated. -OFF=OFF +OFF=Non attivo --- old/src/share/classes/sun/util/logging/resources/logging_ja.properties 2013-09-02 12:20:17.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging_ja.properties 2013-09-02 12:20:16.000000000 +0200 @@ -29,18 +29,18 @@ # The following ALL CAPS words should be translated. ALL=\u3059\u3079\u3066 # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=\u91CD\u5927 # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=\u8B66\u544A # The following ALL CAPS words should be translated. INFO=\u60C5\u5831 # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= \u69CB\u6210 # The following ALL CAPS words should be translated. -FINE=\u8A73\u7D30\u30EC\u30D9\u30EB(\u4F4E) +FINE=\u666E\u901A # The following ALL CAPS words should be translated. -FINER=FINER +FINER=\u8A73\u7D30 # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=\u6700\u3082\u8A73\u7D30 # The following ALL CAPS words should be translated. OFF=\u30AA\u30D5 --- old/src/share/classes/sun/util/logging/resources/logging_ko.properties 2013-09-02 12:20:18.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging_ko.properties 2013-09-02 12:20:18.000000000 +0200 @@ -27,20 +27,20 @@ # these are the same as the non-localized level name. # The following ALL CAPS words should be translated. -ALL=ALL +ALL=\uBAA8\uB450 # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=\uC2EC\uAC01 # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=\uACBD\uACE0 # The following ALL CAPS words should be translated. -INFO=INFO +INFO=\uC815\uBCF4 # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= \uAD6C\uC131 # The following ALL CAPS words should be translated. -FINE=FINE +FINE=\uBBF8\uC138 # The following ALL CAPS words should be translated. -FINER=FINER +FINER=\uBCF4\uB2E4 \uBBF8\uC138 # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=\uAC00\uC7A5 \uBBF8\uC138 # The following ALL CAPS words should be translated. -OFF=OFF +OFF=\uD574\uC81C --- old/src/share/classes/sun/util/logging/resources/logging_pt_BR.properties 2013-09-02 12:20:20.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging_pt_BR.properties 2013-09-02 12:20:19.000000000 +0200 @@ -27,20 +27,20 @@ # these are the same as the non-localized level name. # The following ALL CAPS words should be translated. -ALL=ALL +ALL=Tudo # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=Grave # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=Advert\u00EAncia # The following ALL CAPS words should be translated. -INFO=INFO +INFO=Informa\u00E7\u00F5es # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= Configura\u00E7\u00E3o # The following ALL CAPS words should be translated. -FINE=FINE +FINE=Detalhado # The following ALL CAPS words should be translated. -FINER=FINER +FINER=Mais Detalhado # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=O Mais Detalhado # The following ALL CAPS words should be translated. -OFF=OFF +OFF=Desativado --- old/src/share/classes/sun/util/logging/resources/logging_sv.properties 2013-09-02 12:20:21.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging_sv.properties 2013-09-02 12:20:21.000000000 +0200 @@ -27,20 +27,20 @@ # these are the same as the non-localized level name. # The following ALL CAPS words should be translated. -ALL=ALLA +ALL=Alla # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=Allvarlig # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=Varning # The following ALL CAPS words should be translated. -INFO=INFO +INFO=Info # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= Konfig # The following ALL CAPS words should be translated. -FINE=FINE +FINE=Fin # The following ALL CAPS words should be translated. -FINER=FINER +FINER=Finare # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=Finaste # The following ALL CAPS words should be translated. -OFF=OFF +OFF=Av --- old/src/share/classes/sun/util/logging/resources/logging_zh_CN.properties 2013-09-02 12:20:22.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging_zh_CN.properties 2013-09-02 12:20:22.000000000 +0200 @@ -27,20 +27,20 @@ # these are the same as the non-localized level name. # The following ALL CAPS words should be translated. -ALL=ALL +ALL=\u5168\u90E8 # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=\u4E25\u91CD # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=\u8B66\u544A # The following ALL CAPS words should be translated. -INFO=INFO +INFO=\u4FE1\u606F # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= \u914D\u7F6E # The following ALL CAPS words should be translated. -FINE=FINE +FINE=\u8BE6\u7EC6 # The following ALL CAPS words should be translated. -FINER=FINER +FINER=\u8F83\u8BE6\u7EC6 # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=\u975E\u5E38\u8BE6\u7EC6 # The following ALL CAPS words should be translated. -OFF=OFF +OFF=\u7981\u7528 --- old/src/share/classes/sun/util/logging/resources/logging_zh_TW.properties 2013-09-02 12:20:24.000000000 +0200 +++ new/src/share/classes/sun/util/logging/resources/logging_zh_TW.properties 2013-09-02 12:20:24.000000000 +0200 @@ -27,20 +27,20 @@ # these are the same as the non-localized level name. # The following ALL CAPS words should be translated. -ALL=\u6240\u6709 +ALL=\u5168\u90E8 # The following ALL CAPS words should be translated. -SEVERE=SEVERE +SEVERE=\u56B4\u91CD # The following ALL CAPS words should be translated. -WARNING=WARNING +WARNING=\u8B66\u544A # The following ALL CAPS words should be translated. INFO=\u8CC7\u8A0A # The following ALL CAPS words should be translated. -CONFIG= CONFIG +CONFIG= \u7D44\u614B # The following ALL CAPS words should be translated. FINE=\u8A73\u7D30 # The following ALL CAPS words should be translated. -FINER=FINER +FINER=\u8F03\u8A73\u7D30 # The following ALL CAPS words should be translated. -FINEST=FINEST +FINEST=\u6700\u8A73\u7D30 # The following ALL CAPS words should be translated. OFF=\u95DC\u9589 --- /dev/null 2013-09-02 12:20:25.000000000 +0200 +++ new/test/java/util/logging/LocalizedLevelName.java 2013-09-02 12:20:25.000000000 +0200 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013, 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. + */ + +import java.util.*; +import java.util.logging.*; + +/* + * @test + * @bug 8016127 + * @summary test logging.properties localized + * @run main/othervm LocalizedLevelName + */ + +public class LocalizedLevelName { + private static Object[] namesMap = { + "SEVERE", Locale.ENGLISH, "Severe", Level.SEVERE, + "WARNING", Locale.FRENCH, "Avertissement", Level.WARNING, + "INFO", Locale.ITALIAN, "Informazioni", Level.INFO, + "SEVERE", Locale.FRENCH, "Grave", Level.SEVERE, + "CONFIG", Locale.GERMAN, "Konfiguration", Level.CONFIG, + "ALL", Locale.ROOT, "All", Level.ALL, + "SEVERE", Locale.ROOT, "Severe", Level.SEVERE, + "WARNING", Locale.ROOT, "Warning", Level.WARNING, + "CONFIG", Locale.ROOT, "Config", Level.CONFIG, + "INFO", Locale.ROOT, "Info", Level.INFO, + "FINE", Locale.ROOT, "Fine", Level.FINE, + "FINER", Locale.ROOT, "Finer", Level.FINER, + "FINEST", Locale.ROOT, "Finest", Level.FINEST + }; + + public static void main(String args[]) throws Exception { + Locale defaultLocale = Locale.getDefault(); + for (int i=0; i localized(" + Locale.ENGLISH + ", " + + key + ")=" + en); + System.out.println(" => localized(" + locale + ", " + key + + ")=" + other); + if (!key.equals(en.toUpperCase(Locale.ROOT))) { + throw new RuntimeException("Expect " + key + + " equals upperCase(" + en + ")"); + } + if (!Locale.ENGLISH.equals(locale) && !Locale.ROOT.equals(locale) + && key.equals(other.toUpperCase(Locale.ROOT))) { + throw new RuntimeException("Expect " + key + + " not equals upperCase(" + other +")"); + } + if ((Locale.ENGLISH.equals(locale) || Locale.ROOT.equals(locale)) + && !key.equals(other.toUpperCase(Locale.ROOT))) { + throw new RuntimeException("Expect " + key + + " equals upperCase(" + other +")"); + } + if (!other.equals(expectedTranslation)) { + throw new RuntimeException("Expected \"" + expectedTranslation + + "\" for '" + locale + "' but got \"" + other + "\""); + } + Locale.setDefault(locale); + final String levelName = level.getLocalizedName(); + System.out.println("Level.getLocalizedName() is: " + levelName); + if (!levelName.equals(other.toUpperCase(locale))) { + throw new RuntimeException("Expected \"" + + other.toUpperCase(locale) + "\" for '" + + locale + "' but got \"" + levelName + "\""); + } + Locale.setDefault(defaultLocale); + } + } + + private static final String RBNAME = "sun.util.logging.resources.logging"; + private static String getLocalizedMessage(Locale locale, String key) { + ResourceBundle rb = ResourceBundle.getBundle(RBNAME, locale); + return rb.getString(key); + } +}