NLS.java 3.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
package jadx.gui.utils;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.Vector;

import jadx.core.utils.exceptions.JadxRuntimeException;

public class NLS {

20
	private static final Vector<LangLocale> LANG_LOCALES = new Vector<>();
21

22
	private static final Map<LangLocale, ResourceBundle> LANG_LOCALES_MAP = new HashMap<>();
23

24 25
	private static final ResourceBundle FALLBACK_MESSAGES_MAP;
	private static final LangLocale LOCAL_LOCALE;
26 27 28 29 30 31

	// Use these two fields to avoid invoking Map.get() method twice.
	private static ResourceBundle localizedMessagesMap;
	private static LangLocale currentLocale;

	static {
32
		LOCAL_LOCALE = new LangLocale(Locale.getDefault());
33

34 35
		LANG_LOCALES.add(new LangLocale("en", "US")); // As default language
		LANG_LOCALES.add(new LangLocale("zh", "CN"));
36
		LANG_LOCALES.add(new LangLocale("zh", "TW"));
37
		LANG_LOCALES.add(new LangLocale("es", "ES"));
38
		LANG_LOCALES.add(new LangLocale("de", "DE"));
39
		LANG_LOCALES.add(new LangLocale("ko", "KR"));
40
		LANG_LOCALES.add(new LangLocale("pt", "BR"));
41
		LANG_LOCALES.add(new LangLocale("ru", "RU"));
42

43
		LANG_LOCALES.forEach(NLS::load);
44

45 46 47
		LangLocale defLang = LANG_LOCALES.get(0);
		FALLBACK_MESSAGES_MAP = LANG_LOCALES_MAP.get(defLang);
		localizedMessagesMap = LANG_LOCALES_MAP.get(defLang);
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
	}

	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);
		if (bundleUrl == null) {
			throw new JadxRuntimeException("Locale resource not found: " + resName);
		}
		try (Reader reader = new InputStreamReader(bundleUrl.openStream(), StandardCharsets.UTF_8)) {
			bundle = new PropertyResourceBundle(reader);
		} catch (IOException e) {
			throw new JadxRuntimeException("Failed to load " + resName, e);
		}
66
		LANG_LOCALES_MAP.put(locale, bundle);
67 68
	}

69 70 71 72 73 74 75 76
	public static String str(String key) {
		try {
			return localizedMessagesMap.getString(key);
		} catch (Exception e) {
			return FALLBACK_MESSAGES_MAP.getString(key);
		}
	}

77
	public static String str(String key, Object... parameters) {
78
		return String.format(str(key), parameters);
79 80 81
	}

	public static String str(String key, LangLocale locale) {
82
		ResourceBundle bundle = LANG_LOCALES_MAP.get(locale);
83 84 85 86 87 88 89
		if (bundle != null) {
			try {
				return bundle.getString(key);
			} catch (MissingResourceException ignored) {
				// use fallback string
			}
		}
90
		return FALLBACK_MESSAGES_MAP.getString(key); // definitely exists
91 92 93
	}

	public static void setLocale(LangLocale locale) {
94
		if (LANG_LOCALES_MAP.containsKey(locale)) {
95 96
			currentLocale = locale;
		} else {
97
			currentLocale = LANG_LOCALES.get(0);
98
		}
99
		localizedMessagesMap = LANG_LOCALES_MAP.get(currentLocale);
100 101
	}

102 103
	public static Vector<LangLocale> getLangLocales() {
		return LANG_LOCALES;
104 105 106 107 108 109 110
	}

	public static LangLocale currentLocale() {
		return currentLocale;
	}

	public static LangLocale defaultLocale() {
111 112
		if (LANG_LOCALES_MAP.containsKey(LOCAL_LOCALE)) {
			return LOCAL_LOCALE;
113 114
		}
		// fallback to english if unsupported
115
		return LANG_LOCALES.get(0);
116 117
	}
}