Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jadx
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
jadx
Commits
4d3f2740
Commit
4d3f2740
authored
Aug 19, 2018
by
Donlon
Committed by
skylot
Aug 19, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Language switch supported
parent
f9e7a29c
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
259 additions
and
145 deletions
+259
-145
JadxGUI.java
jadx-gui/src/main/java/jadx/gui/JadxGUI.java
+7
-0
JadxSettings.java
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
+16
-1
JadxSettingsAdapter.java
.../src/main/java/jadx/gui/settings/JadxSettingsAdapter.java
+4
-7
JadxSettingsWindow.java
...i/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
+88
-116
AboutDialog.java
jadx-gui/src/main/java/jadx/gui/ui/AboutDialog.java
+1
-1
CommonSearchDialog.java
jadx-gui/src/main/java/jadx/gui/ui/CommonSearchDialog.java
+5
-2
LogViewer.java
jadx-gui/src/main/java/jadx/gui/ui/LogViewer.java
+2
-2
MainWindow.java
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
+2
-2
LangLocale.java
jadx-gui/src/main/java/jadx/gui/utils/LangLocale.java
+34
-0
NLS.java
jadx-gui/src/main/java/jadx/gui/utils/NLS.java
+76
-5
Messages_en_US.properties
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
+20
-9
Messages_zh_CN.properties
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
+4
-0
No files found.
jadx-gui/src/main/java/jadx/gui/JadxGUI.java
View file @
4d3f2740
...
@@ -2,6 +2,8 @@ package jadx.gui;
...
@@ -2,6 +2,8 @@ package jadx.gui;
import
javax.swing.*
;
import
javax.swing.*
;
import
jadx.gui.utils.LangLocale
;
import
jadx.gui.utils.NLS
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
...
@@ -10,6 +12,10 @@ import jadx.gui.settings.JadxSettingsAdapter;
...
@@ -10,6 +12,10 @@ import jadx.gui.settings.JadxSettingsAdapter;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.utils.logs.LogCollector
;
import
jadx.gui.utils.logs.LogCollector
;
import
java.util.Locale
;
import
java.util.prefs.BackingStoreException
;
import
java.util.prefs.Preferences
;
public
class
JadxGUI
{
public
class
JadxGUI
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
JadxGUI
.
class
);
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
JadxGUI
.
class
);
...
@@ -24,6 +30,7 @@ public class JadxGUI {
...
@@ -24,6 +30,7 @@ public class JadxGUI {
if
(!
tryDefaultLookAndFeel
())
{
if
(!
tryDefaultLookAndFeel
())
{
UIManager
.
setLookAndFeel
(
UIManager
.
getSystemLookAndFeelClassName
());
UIManager
.
setLookAndFeel
(
UIManager
.
getSystemLookAndFeelClassName
());
}
}
NLS
.
setLocale
(
settings
.
getLangLocale
());
SwingUtilities
.
invokeLater
(
new
MainWindow
(
settings
)::
open
);
SwingUtilities
.
invokeLater
(
new
MainWindow
(
settings
)::
open
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Error: {}"
,
e
.
getMessage
(),
e
);
LOG
.
error
(
"Error: {}"
,
e
.
getMessage
(),
e
);
...
...
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
View file @
4d3f2740
...
@@ -9,6 +9,8 @@ import java.util.List;
...
@@ -9,6 +9,8 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.Set
;
import
jadx.gui.utils.LangLocale
;
import
jadx.gui.utils.NLS
;
import
org.fife.ui.rsyntaxtextarea.RSyntaxTextArea
;
import
org.fife.ui.rsyntaxtextarea.RSyntaxTextArea
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
...
@@ -24,7 +26,7 @@ public class JadxSettings extends JadxCLIArgs {
...
@@ -24,7 +26,7 @@ public class JadxSettings extends JadxCLIArgs {
private
static
final
String
USER_HOME
=
System
.
getProperty
(
"user.home"
);
private
static
final
String
USER_HOME
=
System
.
getProperty
(
"user.home"
);
private
static
final
int
RECENT_FILES_COUNT
=
15
;
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
();
private
static
final
Font
DEFAULT_FONT
=
FONT_HACK
!=
null
?
FONT_HACK
:
new
RSyntaxTextArea
().
getFont
();
...
@@ -38,6 +40,7 @@ public class JadxSettings extends JadxCLIArgs {
...
@@ -38,6 +40,7 @@ public class JadxSettings extends JadxCLIArgs {
private
List
<
String
>
recentFiles
=
new
ArrayList
<>();
private
List
<
String
>
recentFiles
=
new
ArrayList
<>();
private
String
fontStr
=
""
;
private
String
fontStr
=
""
;
private
String
editorThemePath
=
""
;
private
String
editorThemePath
=
""
;
private
LangLocale
langLocale
=
NLS
.
defaultLocale
();
private
boolean
autoStartJobs
=
false
;
private
boolean
autoStartJobs
=
false
;
private
int
settingsVersion
=
0
;
private
int
settingsVersion
=
0
;
...
@@ -149,6 +152,14 @@ public class JadxSettings extends JadxCLIArgs {
...
@@ -149,6 +152,14 @@ public class JadxSettings extends JadxCLIArgs {
this
.
showInconsistentCode
=
showInconsistentCode
;
this
.
showInconsistentCode
=
showInconsistentCode
;
}
}
public
LangLocale
getLangLocale
(){
return
this
.
langLocale
;
}
public
void
setLangLocale
(
LangLocale
langLocale
)
{
this
.
langLocale
=
langLocale
;
}
public
void
setCfgOutput
(
boolean
cfgOutput
)
{
public
void
setCfgOutput
(
boolean
cfgOutput
)
{
this
.
cfgOutput
=
cfgOutput
;
this
.
cfgOutput
=
cfgOutput
;
}
}
...
@@ -253,6 +264,10 @@ public class JadxSettings extends JadxCLIArgs {
...
@@ -253,6 +264,10 @@ public class JadxSettings extends JadxCLIArgs {
if
(
getDeobfuscationMinLength
()
==
4
)
{
if
(
getDeobfuscationMinLength
()
==
4
)
{
setDeobfuscationMinLength
(
3
);
setDeobfuscationMinLength
(
3
);
}
}
fromVersion
++;
}
if
(
fromVersion
==
3
)
{
setLangLocale
(
NLS
.
defaultLocale
());
}
}
settingsVersion
=
CURRENT_SETTINGS_VERSION
;
settingsVersion
=
CURRENT_SETTINGS_VERSION
;
sync
();
sync
();
...
...
jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsAdapter.java
View file @
4d3f2740
...
@@ -48,8 +48,8 @@ public class JadxSettingsAdapter {
...
@@ -48,8 +48,8 @@ public class JadxSettingsAdapter {
if
(
settings
==
null
)
{
if
(
settings
==
null
)
{
return
new
JadxSettings
();
return
new
JadxSettings
();
}
}
LOG
.
debug
(
"Loaded settings: {}"
,
makeString
(
settings
));
settings
.
fixOnLoad
();
settings
.
fixOnLoad
();
LOG
.
debug
(
"Loaded settings: {}"
,
makeString
(
settings
));
return
settings
;
return
settings
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Error load settings"
,
e
);
LOG
.
error
(
"Error load settings"
,
e
);
...
@@ -81,11 +81,8 @@ public class JadxSettingsAdapter {
...
@@ -81,11 +81,8 @@ public class JadxSettingsAdapter {
}
}
private
static
<
T
>
void
populate
(
GsonBuilder
builder
,
String
json
,
Class
<
T
>
type
,
final
T
into
)
{
private
static
<
T
>
void
populate
(
GsonBuilder
builder
,
String
json
,
Class
<
T
>
type
,
final
T
into
)
{
builder
.
registerTypeAdapter
(
type
,
new
InstanceCreator
<
T
>()
{
builder
.
registerTypeAdapter
(
type
,
(
InstanceCreator
<
T
>)
t
->
into
)
@Override
.
create
()
public
T
createInstance
(
Type
t
)
{
.
fromJson
(
json
,
type
);
return
into
;
}
}).
create
().
fromJson
(
json
,
type
);
}
}
}
}
jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
View file @
4d3f2740
package
jadx
.
gui
.
settings
;
package
jadx
.
gui
.
settings
;
import
javax.swing.*
;
import
javax.swing.*
;
import
javax.swing.event.ChangeEvent
;
import
javax.swing.event.ChangeListener
;
import
java.awt.*
;
import
java.awt.*
;
import
java.awt.event.ActionEvent
;
import
java.awt.event.ActionListener
;
import
java.awt.event.ItemEvent
;
import
java.awt.event.ItemEvent
;
import
java.awt.event.ItemListener
;
import
java.awt.event.MouseAdapter
;
import
java.awt.event.MouseAdapter
;
import
java.awt.event.MouseEvent
;
import
java.awt.event.MouseEvent
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.stream.Stream
;
import
jadx.gui.utils.LangLocale
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
say.swing.JFontChooser
;
import
say.swing.JFontChooser
;
...
@@ -34,6 +29,7 @@ public class JadxSettingsWindow extends JDialog {
...
@@ -34,6 +29,7 @@ public class JadxSettingsWindow extends JDialog {
private
final
transient
MainWindow
mainWindow
;
private
final
transient
MainWindow
mainWindow
;
private
final
transient
JadxSettings
settings
;
private
final
transient
JadxSettings
settings
;
private
final
transient
String
startSettings
;
private
final
transient
String
startSettings
;
private
final
transient
LangLocale
prevLang
;
private
transient
boolean
needReload
=
false
;
private
transient
boolean
needReload
=
false
;
...
@@ -41,16 +37,17 @@ public class JadxSettingsWindow extends JDialog {
...
@@ -41,16 +37,17 @@ public class JadxSettingsWindow extends JDialog {
this
.
mainWindow
=
mainWindow
;
this
.
mainWindow
=
mainWindow
;
this
.
settings
=
settings
;
this
.
settings
=
settings
;
this
.
startSettings
=
JadxSettingsAdapter
.
makeString
(
settings
);
this
.
startSettings
=
JadxSettingsAdapter
.
makeString
(
settings
);
this
.
prevLang
=
settings
.
getLangLocale
();
initUI
();
initUI
();
registerBundledFonts
();
registerBundledFonts
();
setTitle
(
NLS
.
str
(
"preferences.title"
));
setTitle
(
NLS
.
str
(
"preferences.title"
));
setSize
(
400
,
550
);
setSize
(
400
,
550
);
setLocationRelativeTo
(
null
);
setDefaultCloseOperation
(
WindowConstants
.
DISPOSE_ON_CLOSE
);
setDefaultCloseOperation
(
WindowConstants
.
DISPOSE_ON_CLOSE
);
setModalityType
(
ModalityType
.
APPLICATION_MODAL
);
setModalityType
(
ModalityType
.
APPLICATION_MODAL
);
pack
();
pack
();
setLocationRelativeTo
(
null
);
}
}
public
static
void
registerBundledFonts
()
{
public
static
void
registerBundledFonts
()
{
...
@@ -70,39 +67,41 @@ public class JadxSettingsWindow extends JDialog {
...
@@ -70,39 +67,41 @@ public class JadxSettingsWindow extends JDialog {
panel
.
add
(
makeOtherGroup
());
panel
.
add
(
makeOtherGroup
());
JButton
saveBtn
=
new
JButton
(
NLS
.
str
(
"preferences.save"
));
JButton
saveBtn
=
new
JButton
(
NLS
.
str
(
"preferences.save"
));
saveBtn
.
addActionListener
(
new
ActionListener
()
{
saveBtn
.
addActionListener
(
event
->
{
public
void
actionPerformed
(
ActionEvent
event
)
{
settings
.
sync
();
settings
.
sync
();
if
(
needReload
)
{
if
(
needReload
)
{
mainWindow
.
reOpenFile
();
mainWindow
.
reOpenFile
();
}
}
if
(!
settings
.
getLangLocale
().
equals
(
prevLang
)){
dispose
();
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"
));
JButton
cancelButton
=
new
JButton
(
NLS
.
str
(
"preferences.cancel"
));
cancelButton
.
addActionListener
(
new
ActionListener
()
{
cancelButton
.
addActionListener
(
event
->
{
public
void
actionPerformed
(
ActionEvent
event
)
{
JadxSettingsAdapter
.
fill
(
settings
,
startSettings
);
JadxSettingsAdapter
.
fill
(
settings
,
startSettings
);
dispose
();
dispose
();
}
});
});
JButton
resetBtn
=
new
JButton
(
NLS
.
str
(
"preferences.reset"
));
JButton
resetBtn
=
new
JButton
(
NLS
.
str
(
"preferences.reset"
));
resetBtn
.
addActionListener
(
new
ActionListener
()
{
resetBtn
.
addActionListener
(
event
->
{
public
void
actionPerformed
(
ActionEvent
event
)
{
int
res
=
JOptionPane
.
showConfirmDialog
(
int
res
=
JOptionPane
.
showConfirmDialog
(
JadxSettingsWindow
.
this
,
JadxSettingsWindow
.
this
,
NLS
.
str
(
"preferences.reset_message"
),
NLS
.
str
(
"preferences.reset_message"
),
NLS
.
str
(
"preferences.reset_title"
),
NLS
.
str
(
"preferences.reset_title"
),
JOptionPane
.
YES_NO_OPTION
);
JOptionPane
.
YES_NO_OPTION
);
if
(
res
==
JOptionPane
.
YES_OPTION
)
{
if
(
res
==
JOptionPane
.
YES_OPTION
)
{
String
defaults
=
JadxSettingsAdapter
.
makeString
(
new
JadxSettings
());
String
defaults
=
JadxSettingsAdapter
.
makeString
(
new
JadxSettings
());
JadxSettingsAdapter
.
fill
(
settings
,
defaults
);
JadxSettingsAdapter
.
fill
(
settings
,
defaults
);
getContentPane
().
removeAll
();
getContentPane
().
removeAll
();
initUI
();
initUI
();
pack
();
pack
();
repaint
();
repaint
();
}
}
}
});
});
...
@@ -124,49 +123,37 @@ public class JadxSettingsWindow extends JDialog {
...
@@ -124,49 +123,37 @@ public class JadxSettingsWindow extends JDialog {
private
SettingsGroup
makeDeobfuscationGroup
()
{
private
SettingsGroup
makeDeobfuscationGroup
()
{
JCheckBox
deobfOn
=
new
JCheckBox
();
JCheckBox
deobfOn
=
new
JCheckBox
();
deobfOn
.
setSelected
(
settings
.
isDeobfuscationOn
());
deobfOn
.
setSelected
(
settings
.
isDeobfuscationOn
());
deobfOn
.
addItemListener
(
new
ItemListener
()
{
deobfOn
.
addItemListener
(
e
->
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setDeobfuscationOn
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
setDeobfuscationOn
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
needReload
();
}
});
});
JCheckBox
deobfForce
=
new
JCheckBox
();
JCheckBox
deobfForce
=
new
JCheckBox
();
deobfForce
.
setSelected
(
settings
.
isDeobfuscationForceSave
());
deobfForce
.
setSelected
(
settings
.
isDeobfuscationForceSave
());
deobfForce
.
addItemListener
(
new
ItemListener
()
{
deobfForce
.
addItemListener
(
e
->
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setDeobfuscationForceSave
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
setDeobfuscationForceSave
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
needReload
();
}
});
});
final
JSpinner
minLen
=
new
JSpinner
();
JSpinner
minLen
=
new
JSpinner
();
minLen
.
setValue
(
settings
.
getDeobfuscationMinLength
());
minLen
.
setValue
(
settings
.
getDeobfuscationMinLength
());
minLen
.
addChangeListener
(
new
ChangeListener
()
{
minLen
.
addChangeListener
(
e
->
{
@Override
settings
.
setDeobfuscationMinLength
((
Integer
)
minLen
.
getValue
());
public
void
stateChanged
(
ChangeEvent
e
)
{
needReload
();
settings
.
setDeobfuscationMinLength
((
Integer
)
minLen
.
getValue
());
needReload
();
}
});
});
final
JSpinner
maxLen
=
new
JSpinner
();
JSpinner
maxLen
=
new
JSpinner
();
maxLen
.
setValue
(
settings
.
getDeobfuscationMaxLength
());
maxLen
.
setValue
(
settings
.
getDeobfuscationMaxLength
());
maxLen
.
addChangeListener
(
new
ChangeListener
()
{
maxLen
.
addChangeListener
(
e
->
{
@Override
settings
.
setDeobfuscationMaxLength
((
Integer
)
maxLen
.
getValue
());
public
void
stateChanged
(
ChangeEvent
e
)
{
needReload
();
settings
.
setDeobfuscationMaxLength
((
Integer
)
maxLen
.
getValue
());
needReload
();
}
});
});
JCheckBox
deobfSourceAlias
=
new
JCheckBox
();
JCheckBox
deobfSourceAlias
=
new
JCheckBox
();
deobfSourceAlias
.
setSelected
(
settings
.
isDeobfuscationUseSourceNameAsAlias
());
deobfSourceAlias
.
setSelected
(
settings
.
isDeobfuscationUseSourceNameAsAlias
());
deobfSourceAlias
.
addItemListener
(
new
ItemListener
()
{
deobfSourceAlias
.
addItemListener
(
e
->
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setDeobfuscationUseSourceNameAsAlias
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
setDeobfuscationUseSourceNameAsAlias
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
needReload
();
}
});
});
SettingsGroup
deobfGroup
=
new
SettingsGroup
(
NLS
.
str
(
"preferences.deobfuscation"
));
SettingsGroup
deobfGroup
=
new
SettingsGroup
(
NLS
.
str
(
"preferences.deobfuscation"
));
...
@@ -206,7 +193,7 @@ public class JadxSettingsWindow extends JDialog {
...
@@ -206,7 +193,7 @@ public class JadxSettingsWindow extends JDialog {
});
});
EditorTheme
[]
editorThemes
=
CodeArea
.
getAllThemes
();
EditorTheme
[]
editorThemes
=
CodeArea
.
getAllThemes
();
final
JComboBox
<
EditorTheme
>
themesCbx
=
new
JComboBox
<>(
editorThemes
);
JComboBox
<
EditorTheme
>
themesCbx
=
new
JComboBox
<>(
editorThemes
);
for
(
EditorTheme
theme:
editorThemes
)
{
for
(
EditorTheme
theme:
editorThemes
)
{
if
(
theme
.
getPath
().
equals
(
settings
.
getEditorThemePath
()))
{
if
(
theme
.
getPath
().
equals
(
settings
.
getEditorThemePath
()))
{
themesCbx
.
setSelectedItem
(
theme
);
themesCbx
.
setSelectedItem
(
theme
);
...
@@ -230,66 +217,49 @@ public class JadxSettingsWindow extends JDialog {
...
@@ -230,66 +217,49 @@ public class JadxSettingsWindow extends JDialog {
private
SettingsGroup
makeDecompilationGroup
()
{
private
SettingsGroup
makeDecompilationGroup
()
{
JCheckBox
fallback
=
new
JCheckBox
();
JCheckBox
fallback
=
new
JCheckBox
();
fallback
.
setSelected
(
settings
.
isFallbackMode
());
fallback
.
setSelected
(
settings
.
isFallbackMode
());
fallback
.
addItemListener
(
new
ItemListener
()
{
fallback
.
addItemListener
(
e
->
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setFallbackMode
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
setFallbackMode
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
needReload
();
}
});
});
JCheckBox
showInconsistentCode
=
new
JCheckBox
();
JCheckBox
showInconsistentCode
=
new
JCheckBox
();
showInconsistentCode
.
setSelected
(
settings
.
isShowInconsistentCode
());
showInconsistentCode
.
setSelected
(
settings
.
isShowInconsistentCode
());
showInconsistentCode
.
addItemListener
(
new
ItemListener
()
{
showInconsistentCode
.
addItemListener
(
e
->
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setShowInconsistentCode
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
setShowInconsistentCode
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
needReload
();
}
});
});
JCheckBox
resourceDecode
=
new
JCheckBox
();
JCheckBox
resourceDecode
=
new
JCheckBox
();
resourceDecode
.
setSelected
(
settings
.
isSkipResources
());
resourceDecode
.
setSelected
(
settings
.
isSkipResources
());
resourceDecode
.
addItemListener
(
new
ItemListener
()
{
resourceDecode
.
addItemListener
(
e
->
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setSkipResources
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
setSkipResources
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
needReload
();
}
});
});
SpinnerNumberModel
spinnerModel
=
new
SpinnerNumberModel
(
SpinnerNumberModel
spinnerModel
=
new
SpinnerNumberModel
(
settings
.
getThreadsCount
(),
1
,
Runtime
.
getRuntime
().
availableProcessors
()
*
2
,
1
);
settings
.
getThreadsCount
(),
1
,
Runtime
.
getRuntime
().
availableProcessors
()
*
2
,
1
);
final
JSpinner
threadsCount
=
new
JSpinner
(
spinnerModel
);
JSpinner
threadsCount
=
new
JSpinner
(
spinnerModel
);
threadsCount
.
addChangeListener
(
new
ChangeListener
()
{
threadsCount
.
addChangeListener
(
e
->
{
@Override
settings
.
setThreadsCount
((
Integer
)
threadsCount
.
getValue
());
public
void
stateChanged
(
ChangeEvent
e
)
{
needReload
();
settings
.
setThreadsCount
((
Integer
)
threadsCount
.
getValue
());
needReload
();
}
});
});
JCheckBox
autoStartJobs
=
new
JCheckBox
();
JCheckBox
autoStartJobs
=
new
JCheckBox
();
autoStartJobs
.
setSelected
(
settings
.
isAutoStartJobs
());
autoStartJobs
.
setSelected
(
settings
.
isAutoStartJobs
());
autoStartJobs
.
addItemListener
(
new
ItemListener
()
{
autoStartJobs
.
addItemListener
(
e
->
settings
.
setAutoStartJobs
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
));
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setAutoStartJobs
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
}
});
JCheckBox
escapeUnicode
=
new
JCheckBox
();
JCheckBox
escapeUnicode
=
new
JCheckBox
();
escapeUnicode
.
setSelected
(
settings
.
escapeUnicode
());
escapeUnicode
.
setSelected
(
settings
.
escapeUnicode
());
escapeUnicode
.
addItemListener
(
new
ItemListener
()
{
escapeUnicode
.
addItemListener
(
e
->
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setEscapeUnicode
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
setEscapeUnicode
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
needReload
();
}
});
});
JCheckBox
replaceConsts
=
new
JCheckBox
();
JCheckBox
replaceConsts
=
new
JCheckBox
();
replaceConsts
.
setSelected
(
settings
.
isReplaceConsts
());
replaceConsts
.
setSelected
(
settings
.
isReplaceConsts
());
replaceConsts
.
addItemListener
(
new
ItemListener
()
{
replaceConsts
.
addItemListener
(
e
->
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setReplaceConsts
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
setReplaceConsts
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
needReload
();
}
});
});
SettingsGroup
other
=
new
SettingsGroup
(
NLS
.
str
(
"preferences.decompile"
));
SettingsGroup
other
=
new
SettingsGroup
(
NLS
.
str
(
"preferences.decompile"
));
...
@@ -304,33 +274,35 @@ public class JadxSettingsWindow extends JDialog {
...
@@ -304,33 +274,35 @@ public class JadxSettingsWindow extends JDialog {
}
}
private
SettingsGroup
makeOtherGroup
()
{
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
();
JCheckBox
update
=
new
JCheckBox
();
update
.
setSelected
(
settings
.
isCheckForUpdates
());
update
.
setSelected
(
settings
.
isCheckForUpdates
());
update
.
addItemListener
(
new
ItemListener
()
{
update
.
addItemListener
(
e
->
settings
.
setCheckForUpdates
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
));
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setCheckForUpdates
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
}
});
JCheckBox
cfg
=
new
JCheckBox
();
JCheckBox
cfg
=
new
JCheckBox
();
cfg
.
setSelected
(
settings
.
isCfgOutput
());
cfg
.
setSelected
(
settings
.
isCfgOutput
());
cfg
.
addItemListener
(
new
ItemListener
()
{
cfg
.
addItemListener
(
e
->
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setCfgOutput
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
setCfgOutput
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
needReload
();
}
});
});
JCheckBox
rawCfg
=
new
JCheckBox
();
JCheckBox
rawCfg
=
new
JCheckBox
();
rawCfg
.
setSelected
(
settings
.
isRawCfgOutput
());
rawCfg
.
setSelected
(
settings
.
isRawCfgOutput
());
rawCfg
.
addItemListener
(
new
ItemListener
()
{
rawCfg
.
addItemListener
(
e
->
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setRawCfgOutput
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
setRawCfgOutput
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
needReload
();
}
});
});
SettingsGroup
other
=
new
SettingsGroup
(
NLS
.
str
(
"preferences.other"
));
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.check_for_updates"
),
update
);
other
.
addRow
(
NLS
.
str
(
"preferences.cfg"
),
cfg
);
other
.
addRow
(
NLS
.
str
(
"preferences.cfg"
),
cfg
);
other
.
addRow
(
NLS
.
str
(
"preferences.raw_cfg"
),
rawCfg
);
other
.
addRow
(
NLS
.
str
(
"preferences.raw_cfg"
),
rawCfg
);
...
...
jadx-gui/src/main/java/jadx/gui/ui/AboutDialog.java
View file @
4d3f2740
...
@@ -55,7 +55,7 @@ class AboutDialog extends JDialog {
...
@@ -55,7 +55,7 @@ class AboutDialog extends JDialog {
setModalityType
(
ModalityType
.
APPLICATION_MODAL
);
setModalityType
(
ModalityType
.
APPLICATION_MODAL
);
setTitle
(
"About JADX"
);
setTitle
(
NLS
.
str
(
"about_dialog.title"
)
);
pack
();
pack
();
setDefaultCloseOperation
(
DISPOSE_ON_CLOSE
);
setDefaultCloseOperation
(
DISPOSE_ON_CLOSE
);
setLocationRelativeTo
(
null
);
setLocationRelativeTo
(
null
);
...
...
jadx-gui/src/main/java/jadx/gui/ui/CommonSearchDialog.java
View file @
4d3f2740
...
@@ -301,7 +301,10 @@ public abstract class CommonSearchDialog extends JDialog {
...
@@ -301,7 +301,10 @@ public abstract class CommonSearchDialog extends JDialog {
protected
static
class
ResultsModel
extends
AbstractTableModel
{
protected
static
class
ResultsModel
extends
AbstractTableModel
{
private
static
final
long
serialVersionUID
=
-
7821286846923903208L
;
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
ArrayList
<
JNode
>
rows
=
new
ArrayList
<>();
private
final
transient
ResultsTableCellRenderer
renderer
;
private
final
transient
ResultsTableCellRenderer
renderer
;
...
@@ -525,7 +528,7 @@ public abstract class CommonSearchDialog extends JDialog {
...
@@ -525,7 +528,7 @@ public abstract class CommonSearchDialog extends JDialog {
TextSearchIndex
textIndex
=
cache
.
getTextIndex
();
TextSearchIndex
textIndex
=
cache
.
getTextIndex
();
if
(
textIndex
==
null
)
{
if
(
textIndex
==
null
)
{
warnLabel
.
setText
(
"Index not initialized, search will be disabled!"
);
warnLabel
.
setText
(
NLS
.
str
(
"msg.index_not_initialized"
)
);
warnLabel
.
setVisible
(
true
);
warnLabel
.
setVisible
(
true
);
}
}
}
}
...
...
jadx-gui/src/main/java/jadx/gui/ui/LogViewer.java
View file @
4d3f2740
...
@@ -40,7 +40,7 @@ class LogViewer extends JDialog {
...
@@ -40,7 +40,7 @@ class LogViewer extends JDialog {
level
=
LEVEL_ITEMS
[
i
];
level
=
LEVEL_ITEMS
[
i
];
registerLogListener
();
registerLogListener
();
});
});
JLabel
levelLabel
=
new
JLabel
(
NLS
.
str
(
"log
.
level"
));
JLabel
levelLabel
=
new
JLabel
(
NLS
.
str
(
"log
_viewer.log_
level"
));
levelLabel
.
setLabelFor
(
cb
);
levelLabel
.
setLabelFor
(
cb
);
controlPane
.
add
(
levelLabel
);
controlPane
.
add
(
levelLabel
);
controlPane
.
add
(
cb
);
controlPane
.
add
(
cb
);
...
@@ -56,7 +56,7 @@ class LogViewer extends JDialog {
...
@@ -56,7 +56,7 @@ class LogViewer extends JDialog {
contentPane
.
add
(
scrollPane
,
BorderLayout
.
CENTER
);
contentPane
.
add
(
scrollPane
,
BorderLayout
.
CENTER
);
contentPane
.
add
(
close
,
BorderLayout
.
PAGE_END
);
contentPane
.
add
(
close
,
BorderLayout
.
PAGE_END
);
setTitle
(
"Log Viewer"
);
setTitle
(
NLS
.
str
(
"log_viewer.title"
)
);
pack
();
pack
();
setSize
(
800
,
600
);
setSize
(
800
,
600
);
setDefaultCloseOperation
(
DISPOSE_ON_CLOSE
);
setDefaultCloseOperation
(
DISPOSE_ON_CLOSE
);
...
...
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
View file @
4d3f2740
...
@@ -154,7 +154,7 @@ public class MainWindow extends JFrame {
...
@@ -154,7 +154,7 @@ public class MainWindow extends JFrame {
String
[]
exts
=
{
"apk"
,
"dex"
,
"jar"
,
"class"
,
"zip"
,
"aar"
,
"arsc"
};
String
[]
exts
=
{
"apk"
,
"dex"
,
"jar"
,
"class"
,
"zip"
,
"aar"
,
"arsc"
};
String
description
=
"supported files: "
+
Arrays
.
toString
(
exts
).
replace
(
'['
,
'('
).
replace
(
']'
,
')'
);
String
description
=
"supported files: "
+
Arrays
.
toString
(
exts
).
replace
(
'['
,
'('
).
replace
(
']'
,
')'
);
fileChooser
.
setFileFilter
(
new
FileNameExtensionFilter
(
description
,
exts
));
fileChooser
.
setFileFilter
(
new
FileNameExtensionFilter
(
description
,
exts
));
fileChooser
.
setToolTipText
(
NLS
.
str
(
"file.open"
));
fileChooser
.
setToolTipText
(
NLS
.
str
(
"file.open
_action
"
));
String
currentDirectory
=
settings
.
getLastOpenFilePath
();
String
currentDirectory
=
settings
.
getLastOpenFilePath
();
if
(!
currentDirectory
.
isEmpty
())
{
if
(!
currentDirectory
.
isEmpty
())
{
fileChooser
.
setCurrentDirectory
(
new
File
(
currentDirectory
));
fileChooser
.
setCurrentDirectory
(
new
File
(
currentDirectory
));
...
@@ -409,7 +409,7 @@ public class MainWindow extends JFrame {
...
@@ -409,7 +409,7 @@ public class MainWindow extends JFrame {
clsSearchAction
.
putValue
(
Action
.
SHORT_DESCRIPTION
,
NLS
.
str
(
"menu.class_search"
));
clsSearchAction
.
putValue
(
Action
.
SHORT_DESCRIPTION
,
NLS
.
str
(
"menu.class_search"
));
clsSearchAction
.
putValue
(
Action
.
ACCELERATOR_KEY
,
getKeyStroke
(
KeyEvent
.
VK_N
,
KeyEvent
.
CTRL_DOWN_MASK
));
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
@Override
public
void
actionPerformed
(
ActionEvent
e
)
{
public
void
actionPerformed
(
ActionEvent
e
)
{
toggleDeobfuscation
();
toggleDeobfuscation
();
...
...
jadx-gui/src/main/java/jadx/gui/utils/LangLocale.java
0 → 100644
View file @
4d3f2740
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
();
}
}
jadx-gui/src/main/java/jadx/gui/utils/NLS.java
View file @
4d3f2740
package
jadx
.
gui
.
utils
;
package
jadx
.
gui
.
utils
;
import
java.nio.charset.Charset
;
import
java.util.HashMap
;
import
java.util.Locale
;
import
java.util.Locale
;
import
java.util.Map
;
import
java.util.ResourceBundle
;
import
java.util.ResourceBundle
;
import
java.util.Vector
;
public
class
NLS
{
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
{
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
NLS
()
{
}
}
private
static
void
load
(
Locale
locale
)
{
private
static
void
load
(
LangLocale
locale
)
{
messages
=
ResourceBundle
.
getBundle
(
"i18n/Messages"
,
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
)
{
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
);
}
}
}
}
}
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
View file @
4d3f2740
language.name
=
English
menu.file
=
File
menu.file
=
File
menu.view
=
View
menu.view
=
View
menu.recent_files
=
Recent Files
menu.recent_files
=
Recent Files
...
@@ -9,14 +11,14 @@ menu.navigation=Navigation
...
@@ -9,14 +11,14 @@ menu.navigation=Navigation
menu.text_search
=
Text search
menu.text_search
=
Text search
menu.class_search
=
Class search
menu.class_search
=
Class search
menu.tools
=
Tools
menu.tools
=
Tools
menu.deobfuscation
=
Deobfuscation
menu.log
=
Log Viewer
menu.log
=
Log Viewer
menu.help
=
Help
menu.help
=
Help
menu.about
=
About
menu.about
=
About
menu.update_label
=
New version %s available!
menu.update_label
=
New version %s available!
file.open
=
Open file
file.open
_action
=
Open file...
file.open_title
=
Open file
file.open_title
=
Open file
file.open_action
=
Open file
file.save_all
=
Save all
file.save_all
=
Save all
file.export_gradle
=
Save as gradle project
file.export_gradle
=
Save as gradle project
file.save_all_msg
=
Select directory for save decompiled sources
file.save_all_msg
=
Select directory for save decompiled sources
...
@@ -45,26 +47,34 @@ nav.forward=Forward
...
@@ -45,26 +47,34 @@ nav.forward=Forward
search_dialog.open
=
Open
search_dialog.open
=
Open
search_dialog.cancel
=
Cancel
search_dialog.cancel
=
Cancel
search_dialog.open_by_name
=
Search for text
\
:
search_dialog.open_by_name
=
Search for text:
search_dialog.search_in
=
Search definitions of
\
:
search_dialog.search_in
=
Search definitions of:
search_dialog.class
=
Class
search_dialog.class
=
Class
search_dialog.method
=
Method
search_dialog.method
=
Method
search_dialog.field
=
Field
search_dialog.field
=
Field
search_dialog.code
=
Code
search_dialog.code
=
Code
search_dialog.options
=
Search options
\
:
search_dialog.options
=
Search options:
search_dialog.ignorecase
=
Case insensitive
search_dialog.ignorecase
=
Case insensitive
search_dialog.next_page
=
Show next page
search_dialog.next_page
=
Show next page
search_dialog.prev_page
=
Show previous page
search_dialog.prev_page
=
Show previous page
search_dialog.info_label
=
Showing results %d to %d of %d
search_dialog.info_label
=
Showing results %1$d to %2$d of %3$d
search_dialog.col_node
=
Node
search_dialog.col_code
=
Code
usage_dialog.title
=
Usage search
usage_dialog.title
=
Usage search
usage_dialog.label
=
Usage for:
usage_dialog.label
=
Usage for:
log_viewer.title
=
Log Viewer
log_viewer.log_level
=
Log level:
about_dialog.title
=
About JADX
preferences.title
=
Preferences
preferences.title
=
Preferences
preferences.deobfuscation
=
Deobfuscation
preferences.deobfuscation
=
Deobfuscation
preferences.editor
=
Editor
preferences.editor
=
Editor
preferences.decompile
=
Decompilation
preferences.decompile
=
Decompilation
preferences.other
=
Other
preferences.other
=
Other
preferences.language
=
Language
preferences.check_for_updates
=
Check for updates on startup
preferences.check_for_updates
=
Check for updates on startup
preferences.fallback
=
Fallback mode (simple dump)
preferences.fallback
=
Fallback mode (simple dump)
preferences.showInconsistentCode
=
Show inconsistent code
preferences.showInconsistentCode
=
Show inconsistent code
...
@@ -90,9 +100,10 @@ preferences.reset_message=Reset settings to default values?
...
@@ -90,9 +100,10 @@ preferences.reset_message=Reset settings to default values?
preferences.reset_title
=
Reset settings
preferences.reset_title
=
Reset settings
msg.open_file
=
Please open file
msg.open_file
=
Please open file
msg.saving_sources
=
Saving sources
msg.saving_sources
=
Saving sources...
msg.language_changed_title
=
Language changed
log.level
=
Log level:
msg.language_changed
=
New language will be displayed the next time application starts.
msg.index_not_initialized
=
Index not initialized, search will be disabled!
popup.undo
=
Undo
popup.undo
=
Undo
popup.redo
=
Redo
popup.redo
=
Redo
...
...
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
View file @
4d3f2740
language.name
=
中文(简体)
menu.file
=
文件
menu.file
=
文件
menu.view
=
视图
menu.view
=
视图
menu.recent_files
=
最近打开文件
menu.recent_files
=
最近打开文件
...
@@ -82,6 +84,8 @@ preferences.reset_title=重置设置
...
@@ -82,6 +84,8 @@ preferences.reset_title=重置设置
msg.open_file
=
请打开文件
msg.open_file
=
请打开文件
msg.saving_sources
=
保存资源
msg.saving_sources
=
保存资源
log.level
=
日志等级:
log.level
=
日志等级:
msg.language_changed_title
=
语言已更改
msg.language_changed
=
在下次启动时将会显示新的语言。
popup.undo
=
撤销
popup.undo
=
撤销
popup.redo
=
重复上一次操作
popup.redo
=
重复上一次操作
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment