Language switch supported
This commit is contained in:
@@ -2,6 +2,8 @@ package jadx.gui;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import jadx.gui.utils.LangLocale;
|
||||
import jadx.gui.utils.NLS;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -10,6 +12,10 @@ import jadx.gui.settings.JadxSettingsAdapter;
|
||||
import jadx.gui.ui.MainWindow;
|
||||
import jadx.gui.utils.logs.LogCollector;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
public class JadxGUI {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JadxGUI.class);
|
||||
|
||||
@@ -24,6 +30,7 @@ public class JadxGUI {
|
||||
if (!tryDefaultLookAndFeel()) {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
}
|
||||
NLS.setLocale(settings.getLangLocale());
|
||||
SwingUtilities.invokeLater(new MainWindow(settings)::open);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error: {}", e.getMessage(), e);
|
||||
|
||||
@@ -9,6 +9,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jadx.gui.utils.LangLocale;
|
||||
import jadx.gui.utils.NLS;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -24,7 +26,7 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
|
||||
private static final String USER_HOME = System.getProperty("user.home");
|
||||
private static final int RECENT_FILES_COUNT = 15;
|
||||
private static final int CURRENT_SETTINGS_VERSION = 3;
|
||||
private static final int CURRENT_SETTINGS_VERSION = 4;
|
||||
|
||||
private static final Font DEFAULT_FONT = FONT_HACK != null ? FONT_HACK : new RSyntaxTextArea().getFont();
|
||||
|
||||
@@ -38,6 +40,7 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
private List<String> recentFiles = new ArrayList<>();
|
||||
private String fontStr = "";
|
||||
private String editorThemePath = "";
|
||||
private LangLocale langLocale = NLS.defaultLocale();
|
||||
private boolean autoStartJobs = false;
|
||||
|
||||
private int settingsVersion = 0;
|
||||
@@ -149,6 +152,14 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
this.showInconsistentCode = showInconsistentCode;
|
||||
}
|
||||
|
||||
public LangLocale getLangLocale(){
|
||||
return this.langLocale;
|
||||
}
|
||||
|
||||
public void setLangLocale(LangLocale langLocale) {
|
||||
this.langLocale = langLocale;
|
||||
}
|
||||
|
||||
public void setCfgOutput(boolean cfgOutput) {
|
||||
this.cfgOutput = cfgOutput;
|
||||
}
|
||||
@@ -253,6 +264,10 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
if (getDeobfuscationMinLength() == 4) {
|
||||
setDeobfuscationMinLength(3);
|
||||
}
|
||||
fromVersion++;
|
||||
}
|
||||
if (fromVersion == 3) {
|
||||
setLangLocale(NLS.defaultLocale());
|
||||
}
|
||||
settingsVersion = CURRENT_SETTINGS_VERSION;
|
||||
sync();
|
||||
|
||||
@@ -48,8 +48,8 @@ public class JadxSettingsAdapter {
|
||||
if (settings == null) {
|
||||
return new JadxSettings();
|
||||
}
|
||||
LOG.debug("Loaded settings: {}", makeString(settings));
|
||||
settings.fixOnLoad();
|
||||
LOG.debug("Loaded settings: {}", makeString(settings));
|
||||
return settings;
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error load settings", e);
|
||||
@@ -81,11 +81,8 @@ public class JadxSettingsAdapter {
|
||||
}
|
||||
|
||||
private static <T> void populate(GsonBuilder builder, String json, Class<T> type, final T into) {
|
||||
builder.registerTypeAdapter(type, new InstanceCreator<T>() {
|
||||
@Override
|
||||
public T createInstance(Type t) {
|
||||
return into;
|
||||
}
|
||||
}).create().fromJson(json, type);
|
||||
builder.registerTypeAdapter(type, (InstanceCreator<T>) t -> into)
|
||||
.create()
|
||||
.fromJson(json, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
package jadx.gui.settings;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jadx.gui.utils.LangLocale;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import say.swing.JFontChooser;
|
||||
@@ -34,6 +29,7 @@ public class JadxSettingsWindow extends JDialog {
|
||||
private final transient MainWindow mainWindow;
|
||||
private final transient JadxSettings settings;
|
||||
private final transient String startSettings;
|
||||
private final transient LangLocale prevLang;
|
||||
|
||||
private transient boolean needReload = false;
|
||||
|
||||
@@ -41,16 +37,17 @@ public class JadxSettingsWindow extends JDialog {
|
||||
this.mainWindow = mainWindow;
|
||||
this.settings = settings;
|
||||
this.startSettings = JadxSettingsAdapter.makeString(settings);
|
||||
this.prevLang = settings.getLangLocale();
|
||||
|
||||
initUI();
|
||||
registerBundledFonts();
|
||||
|
||||
setTitle(NLS.str("preferences.title"));
|
||||
setSize(400, 550);
|
||||
setLocationRelativeTo(null);
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
pack();
|
||||
setLocationRelativeTo(null);
|
||||
}
|
||||
|
||||
public static void registerBundledFonts() {
|
||||
@@ -70,39 +67,41 @@ public class JadxSettingsWindow extends JDialog {
|
||||
panel.add(makeOtherGroup());
|
||||
|
||||
JButton saveBtn = new JButton(NLS.str("preferences.save"));
|
||||
saveBtn.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
settings.sync();
|
||||
if (needReload) {
|
||||
mainWindow.reOpenFile();
|
||||
}
|
||||
dispose();
|
||||
saveBtn.addActionListener(event -> {
|
||||
settings.sync();
|
||||
if (needReload) {
|
||||
mainWindow.reOpenFile();
|
||||
}
|
||||
if (!settings.getLangLocale().equals(prevLang)){
|
||||
JOptionPane.showMessageDialog(
|
||||
this,
|
||||
NLS.str("msg.language_changed", settings.getLangLocale()),
|
||||
NLS.str("msg.language_changed_title", settings.getLangLocale()),
|
||||
JOptionPane.INFORMATION_MESSAGE
|
||||
);
|
||||
}
|
||||
dispose();
|
||||
});
|
||||
JButton cancelButton = new JButton(NLS.str("preferences.cancel"));
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
JadxSettingsAdapter.fill(settings, startSettings);
|
||||
dispose();
|
||||
}
|
||||
cancelButton.addActionListener(event -> {
|
||||
JadxSettingsAdapter.fill(settings, startSettings);
|
||||
dispose();
|
||||
});
|
||||
|
||||
JButton resetBtn = new JButton(NLS.str("preferences.reset"));
|
||||
resetBtn.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
int res = JOptionPane.showConfirmDialog(
|
||||
JadxSettingsWindow.this,
|
||||
NLS.str("preferences.reset_message"),
|
||||
NLS.str("preferences.reset_title"),
|
||||
JOptionPane.YES_NO_OPTION);
|
||||
if (res == JOptionPane.YES_OPTION) {
|
||||
String defaults = JadxSettingsAdapter.makeString(new JadxSettings());
|
||||
JadxSettingsAdapter.fill(settings, defaults);
|
||||
getContentPane().removeAll();
|
||||
initUI();
|
||||
pack();
|
||||
repaint();
|
||||
}
|
||||
resetBtn.addActionListener(event -> {
|
||||
int res = JOptionPane.showConfirmDialog(
|
||||
JadxSettingsWindow.this,
|
||||
NLS.str("preferences.reset_message"),
|
||||
NLS.str("preferences.reset_title"),
|
||||
JOptionPane.YES_NO_OPTION);
|
||||
if (res == JOptionPane.YES_OPTION) {
|
||||
String defaults = JadxSettingsAdapter.makeString(new JadxSettings());
|
||||
JadxSettingsAdapter.fill(settings, defaults);
|
||||
getContentPane().removeAll();
|
||||
initUI();
|
||||
pack();
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -124,49 +123,37 @@ public class JadxSettingsWindow extends JDialog {
|
||||
private SettingsGroup makeDeobfuscationGroup() {
|
||||
JCheckBox deobfOn = new JCheckBox();
|
||||
deobfOn.setSelected(settings.isDeobfuscationOn());
|
||||
deobfOn.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setDeobfuscationOn(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
}
|
||||
deobfOn.addItemListener(e -> {
|
||||
settings.setDeobfuscationOn(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
JCheckBox deobfForce = new JCheckBox();
|
||||
deobfForce.setSelected(settings.isDeobfuscationForceSave());
|
||||
deobfForce.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setDeobfuscationForceSave(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
}
|
||||
deobfForce.addItemListener(e -> {
|
||||
settings.setDeobfuscationForceSave(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
final JSpinner minLen = new JSpinner();
|
||||
JSpinner minLen = new JSpinner();
|
||||
minLen.setValue(settings.getDeobfuscationMinLength());
|
||||
minLen.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
settings.setDeobfuscationMinLength((Integer) minLen.getValue());
|
||||
needReload();
|
||||
}
|
||||
minLen.addChangeListener(e -> {
|
||||
settings.setDeobfuscationMinLength((Integer) minLen.getValue());
|
||||
needReload();
|
||||
});
|
||||
|
||||
final JSpinner maxLen = new JSpinner();
|
||||
JSpinner maxLen = new JSpinner();
|
||||
maxLen.setValue(settings.getDeobfuscationMaxLength());
|
||||
maxLen.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
settings.setDeobfuscationMaxLength((Integer) maxLen.getValue());
|
||||
needReload();
|
||||
}
|
||||
maxLen.addChangeListener(e -> {
|
||||
settings.setDeobfuscationMaxLength((Integer) maxLen.getValue());
|
||||
needReload();
|
||||
});
|
||||
|
||||
JCheckBox deobfSourceAlias = new JCheckBox();
|
||||
deobfSourceAlias.setSelected(settings.isDeobfuscationUseSourceNameAsAlias());
|
||||
deobfSourceAlias.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setDeobfuscationUseSourceNameAsAlias(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
}
|
||||
deobfSourceAlias.addItemListener(e -> {
|
||||
settings.setDeobfuscationUseSourceNameAsAlias(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
SettingsGroup deobfGroup = new SettingsGroup(NLS.str("preferences.deobfuscation"));
|
||||
@@ -206,7 +193,7 @@ public class JadxSettingsWindow extends JDialog {
|
||||
});
|
||||
|
||||
EditorTheme[] editorThemes = CodeArea.getAllThemes();
|
||||
final JComboBox<EditorTheme> themesCbx = new JComboBox<>(editorThemes);
|
||||
JComboBox<EditorTheme> themesCbx = new JComboBox<>(editorThemes);
|
||||
for (EditorTheme theme: editorThemes) {
|
||||
if (theme.getPath().equals(settings.getEditorThemePath())) {
|
||||
themesCbx.setSelectedItem(theme);
|
||||
@@ -230,66 +217,49 @@ public class JadxSettingsWindow extends JDialog {
|
||||
private SettingsGroup makeDecompilationGroup() {
|
||||
JCheckBox fallback = new JCheckBox();
|
||||
fallback.setSelected(settings.isFallbackMode());
|
||||
fallback.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setFallbackMode(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
}
|
||||
fallback.addItemListener(e -> {
|
||||
settings.setFallbackMode(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
JCheckBox showInconsistentCode = new JCheckBox();
|
||||
showInconsistentCode.setSelected(settings.isShowInconsistentCode());
|
||||
showInconsistentCode.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setShowInconsistentCode(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
}
|
||||
showInconsistentCode.addItemListener(e -> {
|
||||
settings.setShowInconsistentCode(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
JCheckBox resourceDecode = new JCheckBox();
|
||||
resourceDecode.setSelected(settings.isSkipResources());
|
||||
resourceDecode.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setSkipResources(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
}
|
||||
resourceDecode.addItemListener(e -> {
|
||||
settings.setSkipResources(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
SpinnerNumberModel spinnerModel = new SpinnerNumberModel(
|
||||
settings.getThreadsCount(), 1, Runtime.getRuntime().availableProcessors() * 2, 1);
|
||||
final JSpinner threadsCount = new JSpinner(spinnerModel);
|
||||
threadsCount.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
settings.setThreadsCount((Integer) threadsCount.getValue());
|
||||
needReload();
|
||||
}
|
||||
JSpinner threadsCount = new JSpinner(spinnerModel);
|
||||
threadsCount.addChangeListener(e -> {
|
||||
settings.setThreadsCount((Integer) threadsCount.getValue());
|
||||
needReload();
|
||||
});
|
||||
|
||||
JCheckBox autoStartJobs = new JCheckBox();
|
||||
autoStartJobs.setSelected(settings.isAutoStartJobs());
|
||||
autoStartJobs.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setAutoStartJobs(e.getStateChange() == ItemEvent.SELECTED);
|
||||
}
|
||||
});
|
||||
autoStartJobs.addItemListener(e -> settings.setAutoStartJobs(e.getStateChange() == ItemEvent.SELECTED));
|
||||
|
||||
JCheckBox escapeUnicode = new JCheckBox();
|
||||
escapeUnicode.setSelected(settings.escapeUnicode());
|
||||
escapeUnicode.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setEscapeUnicode(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
}
|
||||
escapeUnicode.addItemListener(e -> {
|
||||
settings.setEscapeUnicode(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
JCheckBox replaceConsts = new JCheckBox();
|
||||
replaceConsts.setSelected(settings.isReplaceConsts());
|
||||
replaceConsts.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setReplaceConsts(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
}
|
||||
replaceConsts.addItemListener(e -> {
|
||||
settings.setReplaceConsts(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
SettingsGroup other = new SettingsGroup(NLS.str("preferences.decompile"));
|
||||
@@ -304,33 +274,35 @@ public class JadxSettingsWindow extends JDialog {
|
||||
}
|
||||
|
||||
private SettingsGroup makeOtherGroup() {
|
||||
JComboBox<LangLocale> languageCbx = new JComboBox<>(NLS.getI18nLocales());
|
||||
for (LangLocale locale: NLS.getI18nLocales()) {
|
||||
if (locale.equals(settings.getLangLocale())) {
|
||||
languageCbx.setSelectedItem(locale);
|
||||
break;
|
||||
}
|
||||
}
|
||||
languageCbx.addActionListener(e -> settings.setLangLocale((LangLocale) languageCbx.getSelectedItem()));
|
||||
|
||||
JCheckBox update = new JCheckBox();
|
||||
update.setSelected(settings.isCheckForUpdates());
|
||||
update.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setCheckForUpdates(e.getStateChange() == ItemEvent.SELECTED);
|
||||
}
|
||||
});
|
||||
update.addItemListener(e -> settings.setCheckForUpdates(e.getStateChange() == ItemEvent.SELECTED));
|
||||
|
||||
JCheckBox cfg = new JCheckBox();
|
||||
cfg.setSelected(settings.isCfgOutput());
|
||||
cfg.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setCfgOutput(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
}
|
||||
cfg.addItemListener(e -> {
|
||||
settings.setCfgOutput(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
JCheckBox rawCfg = new JCheckBox();
|
||||
rawCfg.setSelected(settings.isRawCfgOutput());
|
||||
rawCfg.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
settings.setRawCfgOutput(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
}
|
||||
rawCfg.addItemListener(e -> {
|
||||
settings.setRawCfgOutput(e.getStateChange() == ItemEvent.SELECTED);
|
||||
needReload();
|
||||
});
|
||||
|
||||
SettingsGroup other = new SettingsGroup(NLS.str("preferences.other"));
|
||||
other.addRow(NLS.str("preferences.language"), languageCbx);
|
||||
other.addRow(NLS.str("preferences.check_for_updates"), update);
|
||||
other.addRow(NLS.str("preferences.cfg"), cfg);
|
||||
other.addRow(NLS.str("preferences.raw_cfg"), rawCfg);
|
||||
|
||||
@@ -55,7 +55,7 @@ class AboutDialog extends JDialog {
|
||||
|
||||
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
|
||||
setTitle("About JADX");
|
||||
setTitle(NLS.str("about_dialog.title"));
|
||||
pack();
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
@@ -301,7 +301,10 @@ public abstract class CommonSearchDialog extends JDialog {
|
||||
|
||||
protected static class ResultsModel extends AbstractTableModel {
|
||||
private static final long serialVersionUID = -7821286846923903208L;
|
||||
private static final String[] COLUMN_NAMES = {"Node", "Code"};
|
||||
private static final String[] COLUMN_NAMES = {
|
||||
NLS.str("search_dialog.col_node"),
|
||||
NLS.str("search_dialog.col_code")
|
||||
};
|
||||
|
||||
private final transient ArrayList<JNode> rows = new ArrayList<>();
|
||||
private final transient ResultsTableCellRenderer renderer;
|
||||
@@ -525,7 +528,7 @@ public abstract class CommonSearchDialog extends JDialog {
|
||||
|
||||
TextSearchIndex textIndex = cache.getTextIndex();
|
||||
if (textIndex == null) {
|
||||
warnLabel.setText("Index not initialized, search will be disabled!");
|
||||
warnLabel.setText(NLS.str("msg.index_not_initialized"));
|
||||
warnLabel.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class LogViewer extends JDialog {
|
||||
level = LEVEL_ITEMS[i];
|
||||
registerLogListener();
|
||||
});
|
||||
JLabel levelLabel = new JLabel(NLS.str("log.level"));
|
||||
JLabel levelLabel = new JLabel(NLS.str("log_viewer.log_level"));
|
||||
levelLabel.setLabelFor(cb);
|
||||
controlPane.add(levelLabel);
|
||||
controlPane.add(cb);
|
||||
@@ -56,7 +56,7 @@ class LogViewer extends JDialog {
|
||||
contentPane.add(scrollPane, BorderLayout.CENTER);
|
||||
contentPane.add(close, BorderLayout.PAGE_END);
|
||||
|
||||
setTitle("Log Viewer");
|
||||
setTitle(NLS.str("log_viewer.title"));
|
||||
pack();
|
||||
setSize(800, 600);
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
|
||||
@@ -154,7 +154,7 @@ public class MainWindow extends JFrame {
|
||||
String[] exts = {"apk", "dex", "jar", "class", "zip", "aar", "arsc"};
|
||||
String description = "supported files: " + Arrays.toString(exts).replace('[', '(').replace(']', ')');
|
||||
fileChooser.setFileFilter(new FileNameExtensionFilter(description, exts));
|
||||
fileChooser.setToolTipText(NLS.str("file.open"));
|
||||
fileChooser.setToolTipText(NLS.str("file.open_action"));
|
||||
String currentDirectory = settings.getLastOpenFilePath();
|
||||
if (!currentDirectory.isEmpty()) {
|
||||
fileChooser.setCurrentDirectory(new File(currentDirectory));
|
||||
@@ -409,7 +409,7 @@ public class MainWindow extends JFrame {
|
||||
clsSearchAction.putValue(Action.SHORT_DESCRIPTION, NLS.str("menu.class_search"));
|
||||
clsSearchAction.putValue(Action.ACCELERATOR_KEY, getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK));
|
||||
|
||||
Action deobfAction = new AbstractAction(NLS.str("preferences.deobfuscation"), ICON_DEOBF) {
|
||||
Action deobfAction = new AbstractAction(NLS.str("menu.deobfuscation"), ICON_DEOBF) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
toggleDeobfuscation();
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package jadx.gui.utils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class LangLocale {
|
||||
private Locale locale;
|
||||
|
||||
public LangLocale(Locale locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public LangLocale(String l, String c) {
|
||||
this.locale = new Locale(l, c);
|
||||
}
|
||||
|
||||
public Locale get() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return NLS.str("language.name", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof LangLocale && locale.equals(((LangLocale) obj).get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return locale.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,95 @@
|
||||
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;
|
||||
|
||||
public class NLS {
|
||||
private static Vector<LangLocale> i18nLocales = new Vector<>();
|
||||
|
||||
private static ResourceBundle messages;
|
||||
private static Map<LangLocale, Map<String, String>> i18nMessagesMap;
|
||||
|
||||
// Use these two fields to avoid invoking Map.get() method twice.
|
||||
private static Map<String, String> localizedMessagesMap;
|
||||
private static Map<String, String> fallbackMessagesMap;
|
||||
|
||||
private static LangLocale currentLocale;
|
||||
private static LangLocale localLocale;
|
||||
|
||||
private static Charset javaCharset;
|
||||
private static Charset utf8Charset;
|
||||
|
||||
static {
|
||||
load(new Locale("en", "US"));
|
||||
javaCharset = Charset.forName("ISO-8859-1");
|
||||
utf8Charset = Charset.forName("UTF-8");
|
||||
i18nMessagesMap = new HashMap<>();
|
||||
|
||||
localLocale = new LangLocale(Locale.getDefault());
|
||||
|
||||
i18nLocales.add(new LangLocale("en", "US")); // As default language
|
||||
i18nLocales.add(new LangLocale("zh", "CN"));
|
||||
|
||||
i18nLocales.forEach(NLS::load);
|
||||
|
||||
fallbackMessagesMap = i18nMessagesMap.get(i18nLocales.get(0));
|
||||
localizedMessagesMap = i18nMessagesMap.get(i18nLocales.get(0));
|
||||
}
|
||||
|
||||
private NLS() {
|
||||
}
|
||||
|
||||
private static void load(Locale locale) {
|
||||
messages = ResourceBundle.getBundle("i18n/Messages", locale);
|
||||
private static void load(LangLocale locale) {
|
||||
ResourceBundle bundle = ResourceBundle.getBundle("i18n/Messages", locale.get());
|
||||
Map<String, String> resMap = new HashMap<>();
|
||||
|
||||
for(String key : bundle.keySet()){
|
||||
resMap.put(key, new String(
|
||||
bundle.getString(key).getBytes(javaCharset),
|
||||
utf8Charset));
|
||||
}
|
||||
i18nMessagesMap.put(locale, resMap);
|
||||
}
|
||||
|
||||
public static String str(String key) {
|
||||
return messages.getString(key);
|
||||
if(localizedMessagesMap.containsKey(key)){
|
||||
return localizedMessagesMap.get(key);
|
||||
}
|
||||
return fallbackMessagesMap.get(key);// definitely exists
|
||||
}
|
||||
|
||||
public static String str(String key, LangLocale locale) {
|
||||
if(i18nMessagesMap.get(locale).containsKey(key)){
|
||||
return i18nMessagesMap.get(locale).get(key);
|
||||
}
|
||||
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<LangLocale> getI18nLocales(){
|
||||
return i18nLocales;
|
||||
}
|
||||
|
||||
public static LangLocale currentLocale() {
|
||||
return currentLocale;
|
||||
}
|
||||
|
||||
public static LangLocale defaultLocale(){
|
||||
if(i18nMessagesMap.containsKey(localLocale)){
|
||||
return localLocale;
|
||||
} else {
|
||||
// fallback to english if unsupported
|
||||
return i18nLocales.get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user