8016127: NLS: logging.properties translatability recommendation
authordfuchs
Mon, 02 Sep 2013 18:28:50 +0200
changeset 19795 6c628e165476
parent 19794 c5a8e71fbdb6
child 19796 9e39f7e1506b
8016127: NLS: logging.properties translatability recommendation 8024131: Issues with cached localizedLevelName in java.util.logging.Level Summary: This fix updates logging.properties resource bundles to follow internationalization guidelines. It also fixes a caching issue with localizedLevelName. The regression test that was added needs both fixes to pass. Reviewed-by: mchung, alanb
jdk/src/share/classes/java/util/logging/Level.java
jdk/src/share/classes/sun/util/logging/resources/logging.properties
jdk/src/share/classes/sun/util/logging/resources/logging_de.properties
jdk/src/share/classes/sun/util/logging/resources/logging_es.properties
jdk/src/share/classes/sun/util/logging/resources/logging_fr.properties
jdk/src/share/classes/sun/util/logging/resources/logging_it.properties
jdk/src/share/classes/sun/util/logging/resources/logging_ja.properties
jdk/src/share/classes/sun/util/logging/resources/logging_ko.properties
jdk/src/share/classes/sun/util/logging/resources/logging_pt_BR.properties
jdk/src/share/classes/sun/util/logging/resources/logging_sv.properties
jdk/src/share/classes/sun/util/logging/resources/logging_zh_CN.properties
jdk/src/share/classes/sun/util/logging/resources/logging_zh_TW.properties
jdk/test/java/util/logging/LocalizedLevelName.java
--- a/jdk/src/share/classes/java/util/logging/Level.java	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/java/util/logging/Level.java	Mon Sep 02 18:28:50 2013 +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;
     }
--- a/jdk/src/share/classes/sun/util/logging/resources/logging.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging.properties	Mon Sep 02 18:28:50 2013 +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
--- a/jdk/src/share/classes/sun/util/logging/resources/logging_de.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging_de.properties	Mon Sep 02 18:28:50 2013 +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
--- a/jdk/src/share/classes/sun/util/logging/resources/logging_es.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging_es.properties	Mon Sep 02 18:28:50 2013 +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
--- a/jdk/src/share/classes/sun/util/logging/resources/logging_fr.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging_fr.properties	Mon Sep 02 18:28:50 2013 +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
--- a/jdk/src/share/classes/sun/util/logging/resources/logging_it.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging_it.properties	Mon Sep 02 18:28:50 2013 +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
--- a/jdk/src/share/classes/sun/util/logging/resources/logging_ja.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging_ja.properties	Mon Sep 02 18:28:50 2013 +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
--- a/jdk/src/share/classes/sun/util/logging/resources/logging_ko.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging_ko.properties	Mon Sep 02 18:28:50 2013 +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
--- a/jdk/src/share/classes/sun/util/logging/resources/logging_pt_BR.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging_pt_BR.properties	Mon Sep 02 18:28:50 2013 +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
--- a/jdk/src/share/classes/sun/util/logging/resources/logging_sv.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging_sv.properties	Mon Sep 02 18:28:50 2013 +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
--- a/jdk/src/share/classes/sun/util/logging/resources/logging_zh_CN.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging_zh_CN.properties	Mon Sep 02 18:28:50 2013 +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
--- a/jdk/src/share/classes/sun/util/logging/resources/logging_zh_TW.properties	Mon Sep 02 14:02:35 2013 +0100
+++ b/jdk/src/share/classes/sun/util/logging/resources/logging_zh_TW.properties	Mon Sep 02 18:28:50 2013 +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	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LocalizedLevelName.java	Mon Sep 02 18:28:50 2013 +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 8024131
+ * @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<namesMap.length; i += 4) {
+            final String key = (String) namesMap[i];
+            final Locale locale = (Locale) namesMap[i+1];
+            final String expectedTranslation = (String) namesMap[i+2];
+            final Level level = (Level) namesMap[i+3];
+
+            final String en = getLocalizedMessage(Locale.ENGLISH, key);
+            final String other = getLocalizedMessage(locale, key);
+
+            System.out.println(locale + ": " + key + "=" + expectedTranslation
+                    + ", (Level." + level.getName() + ")");
+            System.out.println("     => 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);
+    }
+}