diff --git a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java index 9abcf03123486c283131904209643854def5a664..5b8bf67c8e0951f95edd8d8327438cb24d17f8e2 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -340,7 +340,7 @@ public class MainWindow extends JFrame { openFile(); } }; - openAction.putValue(Action.SHORT_DESCRIPTION, NLS.str("file.open")); + openAction.putValue(Action.SHORT_DESCRIPTION, NLS.str("file.open_action")); openAction.putValue(Action.ACCELERATOR_KEY, getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_DOWN_MASK)); Action saveAllAction = new AbstractAction(NLS.str("file.save_all"), ICON_SAVE_ALL) { diff --git a/jadx-gui/src/main/java/jadx/gui/utils/NLS.java b/jadx-gui/src/main/java/jadx/gui/utils/NLS.java index 3247bf01b455a6cce1030b971e33f846c9de3241..4e30a67278a0d2e40140f693c80940167d35c4b1 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/NLS.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/NLS.java @@ -1,102 +1,99 @@ -package jadx.gui.utils; - -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.ResourceBundle; -import java.util.Vector; - -import org.jetbrains.annotations.NotNull; - -public class NLS { - private static final Charset JAVA_CHARSET = Charset.forName("ISO-8859-1"); - private static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); - - private static Vector i18nLocales = new Vector<>(); - - private static Map> i18nMessagesMap = new HashMap<>(); - - // Use these two fields to avoid invoking Map.get() method twice. - private static Map localizedMessagesMap; - private static Map fallbackMessagesMap; - - private static LangLocale currentLocale; - private static LangLocale localLocale; - - static { - localLocale = new LangLocale(Locale.getDefault()); - - i18nLocales.add(new LangLocale("en", "US")); // As default language - i18nLocales.add(new LangLocale("zh", "CN")); - i18nLocales.add(new LangLocale("es", "ES")); - - i18nLocales.forEach(NLS::load); - - LangLocale defLang = i18nLocales.get(0); - fallbackMessagesMap = i18nMessagesMap.get(defLang); - localizedMessagesMap = i18nMessagesMap.get(defLang); - } - - private NLS() { - } - - private static void load(LangLocale locale) { - ResourceBundle bundle = ResourceBundle.getBundle("i18n/Messages", locale.get()); - Map resMap = new HashMap<>(); - for (String key : bundle.keySet()) { - String str = bundle.getString(key); - resMap.put(key, convertCharset(str)); - } - i18nMessagesMap.put(locale, resMap); - } - - @NotNull - private static String convertCharset(String str) { - return new String(str.getBytes(JAVA_CHARSET), UTF8_CHARSET); - } - - public static String str(String key) { - String str = localizedMessagesMap.get(key); - if (str != null) { - return str; - } - return fallbackMessagesMap.get(key); // definitely exists - } - - public static String str(String key, LangLocale locale) { - Map strings = i18nMessagesMap.get(locale); - if (strings != null) { - String str = strings.get(key); - if (str != null) { - return str; - } - } - return fallbackMessagesMap.get(key); // definitely exists - } - - public static void setLocale(LangLocale locale) { - if (i18nMessagesMap.containsKey(locale)) { - currentLocale = locale; - } else { - currentLocale = i18nLocales.get(0); - } - localizedMessagesMap = i18nMessagesMap.get(currentLocale); - } - - public static Vector getI18nLocales() { - return i18nLocales; - } - - public static LangLocale currentLocale() { - return currentLocale; - } - - public static LangLocale defaultLocale() { - if (i18nMessagesMap.containsKey(localLocale)) { - return localLocale; - } - // fallback to english if unsupported - return i18nLocales.get(0); - } -} +package jadx.gui.utils; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.*; + +import org.jetbrains.annotations.NotNull; + +public class NLS { + + private static Vector i18nLocales = new Vector<>(); + + private static Map i18nMessagesMap = new HashMap<>(); + + // Use these two fields to avoid invoking Map.get() method twice. + private static ResourceBundle localizedMessagesMap; + private static ResourceBundle fallbackMessagesMap; + + private static LangLocale currentLocale; + private static LangLocale localLocale; + + static { + localLocale = new LangLocale(Locale.getDefault()); + + i18nLocales.add(new LangLocale("en", "US")); // As default language + i18nLocales.add(new LangLocale("zh", "CN")); + i18nLocales.add(new LangLocale("es", "ES")); + + i18nLocales.forEach(NLS::load); + + LangLocale defLang = i18nLocales.get(0); + fallbackMessagesMap = i18nMessagesMap.get(defLang); + localizedMessagesMap = i18nMessagesMap.get(defLang); + } + + private NLS() { + } + + private static void load(LangLocale locale) { + ResourceBundle bundle; + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); + String resName = String.format("i18n/Messages_%s.properties", locale.get()); + URL bundleUrl = classLoader.getResource(resName); + try (Reader reader = new InputStreamReader(bundleUrl.openStream(), StandardCharsets.UTF_8)) { + bundle = new PropertyResourceBundle(reader); + } catch (IOException e) { + throw new RuntimeException("Failed to load " + resName, e); + } + i18nMessagesMap.put(locale, bundle); + } + + public static String str(String key) { + try { + return localizedMessagesMap.getString(key); + } catch (MissingResourceException e) { + return fallbackMessagesMap.getString(key); // definitely exists + } + } + + public static String str(String key, LangLocale locale) { + ResourceBundle bundle = i18nMessagesMap.get(locale); + if (bundle != null) { + try { + return bundle.getString(key); + } catch (MissingResourceException e) { + } + } + return fallbackMessagesMap.getString(key); // definitely exists + } + + public static void setLocale(LangLocale locale) { + if (i18nMessagesMap.containsKey(locale)) { + currentLocale = locale; + } else { + currentLocale = i18nLocales.get(0); + } + localizedMessagesMap = i18nMessagesMap.get(currentLocale); + } + + public static Vector getI18nLocales() { + return i18nLocales; + } + + public static LangLocale currentLocale() { + return currentLocale; + } + + public static LangLocale defaultLocale() { + if (i18nMessagesMap.containsKey(localLocale)) { + return localLocale; + } + // fallback to english if unsupported + return i18nLocales.get(0); + } +}