feat: add gradle export templates, support android app/lib and simple java
This commit is contained in:
@@ -7,6 +7,7 @@ import javax.swing.JOptionPane;
|
||||
import jadx.api.ICodeCache;
|
||||
import jadx.api.utils.tasks.ITaskExecutor;
|
||||
import jadx.gui.JadxWrapper;
|
||||
import jadx.gui.cache.code.CodeCacheMode;
|
||||
import jadx.gui.cache.code.FixedCodeCache;
|
||||
import jadx.gui.ui.MainWindow;
|
||||
import jadx.gui.utils.NLS;
|
||||
@@ -42,9 +43,11 @@ public class ExportTask extends CancelableBackgroundTask {
|
||||
|
||||
private void wrapCodeCache() {
|
||||
uiCodeCache = wrapper.getArgs().getCodeCache();
|
||||
// do not save newly decompiled code in cache to not increase memory usage
|
||||
// TODO: maybe make memory limited cache?
|
||||
wrapper.getArgs().setCodeCache(new FixedCodeCache(uiCodeCache));
|
||||
if (mainWindow.getSettings().getCodeCacheMode() != CodeCacheMode.DISK) {
|
||||
// do not save newly decompiled code in cache to not increase memory usage
|
||||
// TODO: maybe make memory limited cache?
|
||||
wrapper.getArgs().setCodeCache(new FixedCodeCache(uiCodeCache));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,7 +32,7 @@ import jadx.gui.utils.UiUtils;
|
||||
|
||||
public class TreeExpansionService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TreeExpansionService.class);
|
||||
private static final boolean DEBUG = UiUtils.JADX_GUI_DEBUG;
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final Comparator<TreePath> PATH_LENGTH_REVERSE = Comparator.comparingInt(p -> -p.getPathCount());
|
||||
|
||||
|
||||
@@ -74,6 +74,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.formdev.flatlaf.extras.FlatInspector;
|
||||
import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
@@ -111,7 +114,6 @@ import jadx.gui.plugins.context.CommonGuiPluginsContext;
|
||||
import jadx.gui.plugins.context.TreePopupMenuEntry;
|
||||
import jadx.gui.plugins.mappings.RenameMappingsGui;
|
||||
import jadx.gui.plugins.quark.QuarkDialog;
|
||||
import jadx.gui.settings.ExportProjectProperties;
|
||||
import jadx.gui.settings.JadxProject;
|
||||
import jadx.gui.settings.JadxSettings;
|
||||
import jadx.gui.settings.ui.JadxSettingsWindow;
|
||||
@@ -132,9 +134,9 @@ import jadx.gui.ui.codearea.EditorViewState;
|
||||
import jadx.gui.ui.dialog.ADBDialog;
|
||||
import jadx.gui.ui.dialog.AboutDialog;
|
||||
import jadx.gui.ui.dialog.ExceptionDialog;
|
||||
import jadx.gui.ui.dialog.ExportProjectDialog;
|
||||
import jadx.gui.ui.dialog.LogViewerDialog;
|
||||
import jadx.gui.ui.dialog.SearchDialog;
|
||||
import jadx.gui.ui.export.ExportProjectDialog;
|
||||
import jadx.gui.ui.filedialog.FileDialogWrapper;
|
||||
import jadx.gui.ui.filedialog.FileOpenMode;
|
||||
import jadx.gui.ui.menu.HiddenMenuItem;
|
||||
@@ -798,25 +800,23 @@ public class MainWindow extends JFrame {
|
||||
backgroundExecutor.cancelAll();
|
||||
}
|
||||
|
||||
private void exportProject() {
|
||||
ExportProjectDialog dialog = new ExportProjectDialog(this, this::saveAll);
|
||||
public void exportProject() {
|
||||
ExportProjectDialog dialog = new ExportProjectDialog(this, props -> {
|
||||
JadxArgs args = wrapper.getArgs();
|
||||
if (props.isAsGradleMode()) {
|
||||
args.setExportGradleType(props.getExportGradleType());
|
||||
args.setSkipSources(false);
|
||||
args.setSkipResources(false);
|
||||
} else {
|
||||
args.setExportGradleType(null);
|
||||
args.setSkipSources(props.isSkipSources());
|
||||
args.setSkipResources(props.isSkipResources());
|
||||
}
|
||||
backgroundExecutor.execute(new ExportTask(this, wrapper, new File(props.getExportPath())));
|
||||
});
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
private void saveAll(ExportProjectProperties exportProjectProperties) {
|
||||
JadxArgs decompilerArgs = wrapper.getArgs();
|
||||
decompilerArgs.setExportAsGradleProject(exportProjectProperties.isAsGradleMode());
|
||||
if (exportProjectProperties.isAsGradleMode()) {
|
||||
decompilerArgs.setSkipSources(false);
|
||||
decompilerArgs.setSkipResources(false);
|
||||
} else {
|
||||
decompilerArgs.setSkipSources(exportProjectProperties.isSkipSources());
|
||||
decompilerArgs.setSkipResources(exportProjectProperties.isSkipResources());
|
||||
}
|
||||
File saveDir = new File(exportProjectProperties.getExportPath());
|
||||
backgroundExecutor.execute(new ExportTask(this, wrapper, saveDir));
|
||||
}
|
||||
|
||||
public void initTree() {
|
||||
treeRoot = new JRoot(wrapper);
|
||||
treeRoot.setFlatPackages(isFlattenPackage);
|
||||
@@ -1422,6 +1422,11 @@ public class MainWindow extends JFrame {
|
||||
mainPanel.add(bottomSplitPane, BorderLayout.CENTER);
|
||||
setContentPane(mainPanel);
|
||||
setTitle(DEFAULT_TITLE);
|
||||
|
||||
if (UiUtils.JADX_GUI_DEBUG) {
|
||||
FlatInspector.install("ctrl shift alt X");
|
||||
FlatUIDefaultsInspector.install("ctrl shift alt Y");
|
||||
}
|
||||
}
|
||||
|
||||
public void setLocationAndPosition() {
|
||||
|
||||
@@ -27,7 +27,7 @@ public abstract class CommonDialog extends JDialog {
|
||||
UiUtils.addEscapeShortCutToDispose(this);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
pack();
|
||||
UiUtils.uiRunAndWait(this::pack);
|
||||
Dimension minSize = getSize();
|
||||
setMinimumSize(minSize);
|
||||
if (!mainWindow.getSettings().loadWindowPos(this)) {
|
||||
|
||||
+94
-58
@@ -1,10 +1,9 @@
|
||||
package jadx.gui.ui.dialog;
|
||||
package jadx.gui.ui.export;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
@@ -12,16 +11,23 @@ import java.util.function.Consumer;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import jadx.gui.settings.ExportProjectProperties;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.core.export.ExportGradle;
|
||||
import jadx.core.export.ExportGradleType;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
import jadx.gui.JadxWrapper;
|
||||
import jadx.gui.ui.MainWindow;
|
||||
import jadx.gui.ui.dialog.CommonDialog;
|
||||
import jadx.gui.ui.filedialog.FileDialogWrapper;
|
||||
import jadx.gui.ui.filedialog.FileOpenMode;
|
||||
import jadx.gui.utils.NLS;
|
||||
@@ -29,6 +35,7 @@ import jadx.gui.utils.TextStandardActions;
|
||||
import jadx.gui.utils.ui.DocumentUpdateListener;
|
||||
|
||||
public class ExportProjectDialog extends CommonDialog {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ExportProjectDialog.class);
|
||||
|
||||
private final ExportProjectProperties exportProjectProperties = new ExportProjectProperties();
|
||||
private final Consumer<ExportProjectProperties> exportListener;
|
||||
@@ -40,31 +47,26 @@ public class ExportProjectDialog extends CommonDialog {
|
||||
}
|
||||
|
||||
private void initUI() {
|
||||
JPanel contentPane = makeContentPane();
|
||||
JPanel buttonPane = initButtonsPanel();
|
||||
Container container = getContentPane();
|
||||
container.add(contentPane, BorderLayout.CENTER);
|
||||
container.add(buttonPane, BorderLayout.PAGE_END);
|
||||
JPanel contentPanel = new JPanel();
|
||||
contentPanel.setLayout(new BorderLayout(5, 5));
|
||||
contentPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
contentPanel.add(makeContentPane(), BorderLayout.PAGE_START);
|
||||
contentPanel.add(initButtonsPanel(), BorderLayout.PAGE_END);
|
||||
getContentPane().add(contentPanel);
|
||||
|
||||
setTitle(NLS.str("export_dialog.title"));
|
||||
commonWindowInit();
|
||||
}
|
||||
|
||||
private JPanel makeContentPane() {
|
||||
// top layout
|
||||
JLabel label = new JLabel(NLS.str("export_dialog.save_path"));
|
||||
JLabel pathLbl = new JLabel(NLS.str("export_dialog.save_path"));
|
||||
JTextField pathField = new JTextField();
|
||||
pathField.setText(mainWindow.getSettings().getLastSaveFilePath().toString());
|
||||
pathField.getDocument().addDocumentListener(new DocumentUpdateListener(ev -> setExportProjectPath(pathField)));
|
||||
pathField.setText(mainWindow.getSettings().getLastSaveFilePath().toString());
|
||||
TextStandardActions.attach(pathField);
|
||||
|
||||
JButton browseButton = makeEditorBrowseButton(pathField);
|
||||
|
||||
// check box layout
|
||||
JPanel exportOptionsPanel = new JPanel();
|
||||
exportOptionsPanel.setBorder(BorderFactory.createTitledBorder(NLS.str("export_dialog.export_options")));
|
||||
exportOptionsPanel.setLayout(new BoxLayout(exportOptionsPanel, BoxLayout.PAGE_AXIS));
|
||||
|
||||
JCheckBox resourceDecode = new JCheckBox(NLS.str("preferences.skipResourcesDecode"));
|
||||
resourceDecode.setSelected(mainWindow.getSettings().isSkipResources());
|
||||
resourceDecode.addItemListener(e -> {
|
||||
@@ -77,55 +79,70 @@ public class ExportProjectDialog extends CommonDialog {
|
||||
exportProjectProperties.setSkipSources(e.getStateChange() == ItemEvent.SELECTED);
|
||||
});
|
||||
|
||||
JLabel exportTypeLbl = new JLabel(NLS.str("export_dialog.export_gradle_type"));
|
||||
JComboBox<ExportGradleType> exportTypeComboBox = new JComboBox<>(ExportGradleType.values());
|
||||
exportTypeLbl.setLabelFor(exportTypeComboBox);
|
||||
ExportGradleType initialExportType = getExportGradleType();
|
||||
exportProjectProperties.setExportGradleType(initialExportType);
|
||||
exportTypeComboBox.setSelectedItem(initialExportType);
|
||||
exportTypeComboBox.addItemListener(e -> {
|
||||
exportProjectProperties.setExportGradleType((ExportGradleType) e.getItem());
|
||||
});
|
||||
exportTypeComboBox.setEnabled(false);
|
||||
|
||||
JCheckBox exportAsGradleProject = new JCheckBox(NLS.str("export_dialog.export_gradle"));
|
||||
exportAsGradleProject.addItemListener(e -> {
|
||||
boolean isSelected = e.getStateChange() == ItemEvent.SELECTED;
|
||||
|
||||
exportProjectProperties.setAsGradleMode(isSelected);
|
||||
resourceDecode.setEnabled(!isSelected);
|
||||
skipSources.setEnabled(!isSelected);
|
||||
boolean enableGradle = e.getStateChange() == ItemEvent.SELECTED;
|
||||
exportProjectProperties.setAsGradleMode(enableGradle);
|
||||
exportTypeComboBox.setEnabled(enableGradle);
|
||||
resourceDecode.setEnabled(!enableGradle);
|
||||
skipSources.setEnabled(!enableGradle);
|
||||
});
|
||||
|
||||
JPanel pathPanel = new JPanel();
|
||||
pathPanel.setLayout(new BoxLayout(pathPanel, BoxLayout.LINE_AXIS));
|
||||
pathPanel.setAlignmentX(LEFT_ALIGNMENT);
|
||||
pathPanel.add(pathLbl);
|
||||
pathPanel.add(Box.createRigidArea(new Dimension(5, 0)));
|
||||
pathPanel.add(pathField);
|
||||
pathPanel.add(Box.createRigidArea(new Dimension(5, 0)));
|
||||
pathPanel.add(browseButton);
|
||||
|
||||
JPanel typePanel = new JPanel();
|
||||
typePanel.setLayout(new BoxLayout(typePanel, BoxLayout.LINE_AXIS));
|
||||
typePanel.setAlignmentX(LEFT_ALIGNMENT);
|
||||
typePanel.add(Box.createRigidArea(new Dimension(20, 0)));
|
||||
typePanel.add(exportTypeLbl);
|
||||
typePanel.add(Box.createRigidArea(new Dimension(5, 0)));
|
||||
typePanel.add(exportTypeComboBox);
|
||||
typePanel.add(Box.createHorizontalGlue());
|
||||
|
||||
JPanel exportOptionsPanel = new JPanel();
|
||||
exportOptionsPanel.setBorder(BorderFactory.createTitledBorder(NLS.str("export_dialog.export_options")));
|
||||
exportOptionsPanel.setLayout(new BoxLayout(exportOptionsPanel, BoxLayout.PAGE_AXIS));
|
||||
exportOptionsPanel.add(exportAsGradleProject);
|
||||
exportOptionsPanel.add(typePanel);
|
||||
exportOptionsPanel.add(resourceDecode);
|
||||
exportOptionsPanel.add(skipSources);
|
||||
|
||||
// build group box layout
|
||||
JPanel groupBoxPanel = new JPanel();
|
||||
GroupLayout groupBoxLayout = new GroupLayout(groupBoxPanel);
|
||||
groupBoxLayout.setAutoCreateGaps(true);
|
||||
groupBoxLayout.setAutoCreateContainerGaps(true);
|
||||
groupBoxPanel.setLayout(groupBoxLayout);
|
||||
|
||||
groupBoxLayout.setHorizontalGroup(groupBoxLayout.createParallelGroup()
|
||||
.addComponent(exportOptionsPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Integer.MAX_VALUE));
|
||||
groupBoxLayout.setVerticalGroup(groupBoxLayout.createSequentialGroup()
|
||||
.addComponent(exportOptionsPanel));
|
||||
|
||||
// main layout
|
||||
JPanel mainPanel = new JPanel();
|
||||
GroupLayout layout = new GroupLayout(mainPanel);
|
||||
mainPanel.setLayout(layout);
|
||||
layout.setAutoCreateGaps(true);
|
||||
layout.setAutoCreateContainerGaps(true);
|
||||
|
||||
// arrange components using GroupLayout
|
||||
layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(label)
|
||||
.addComponent(pathField)
|
||||
.addComponent(browseButton))
|
||||
.addComponent(groupBoxPanel));
|
||||
|
||||
layout.setVerticalGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(label)
|
||||
.addComponent(pathField)
|
||||
.addComponent(browseButton))
|
||||
.addComponent(groupBoxPanel));
|
||||
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
|
||||
mainPanel.add(pathPanel);
|
||||
mainPanel.add(Box.createRigidArea(new Dimension(0, 10)));
|
||||
mainPanel.add(exportOptionsPanel);
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
private ExportGradleType getExportGradleType() {
|
||||
try {
|
||||
JadxWrapper wrapper = mainWindow.getWrapper();
|
||||
return ExportGradle.detectExportType(wrapper.getRootNode(), wrapper.getResources());
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Failed to detect export type", e);
|
||||
return ExportGradleType.AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
private void setExportProjectPath(JTextField field) {
|
||||
String path = field.getText();
|
||||
if (!path.isEmpty()) {
|
||||
@@ -143,8 +160,6 @@ public class ExportProjectDialog extends CommonDialog {
|
||||
|
||||
JPanel buttonPane = new JPanel();
|
||||
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
|
||||
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
|
||||
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
buttonPane.add(Box.createHorizontalGlue());
|
||||
buttonPane.add(exportProjectButton);
|
||||
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
@@ -168,12 +183,33 @@ public class ExportProjectDialog extends CommonDialog {
|
||||
}
|
||||
|
||||
private void exportProject() {
|
||||
if (!new File(exportProjectProperties.getExportPath()).exists()) {
|
||||
String exportPathStr = exportProjectProperties.getExportPath();
|
||||
if (!validateAndMakeDir(exportPathStr)) {
|
||||
JOptionPane.showMessageDialog(this, NLS.str("message.enter_valid_path"),
|
||||
NLS.str("message.errorTitle"), JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
mainWindow.getSettings().setLastSaveFilePath(Path.of(exportPathStr));
|
||||
LOG.debug("Export properties: {}", exportProjectProperties);
|
||||
exportListener.accept(exportProjectProperties);
|
||||
dispose();
|
||||
}
|
||||
|
||||
private static boolean validateAndMakeDir(String exportPath) {
|
||||
if (exportPath == null || exportPath.isBlank()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Path path = Path.of(exportPath);
|
||||
if (Files.isRegularFile(path)) {
|
||||
// dir exists as a file
|
||||
return false;
|
||||
}
|
||||
FileUtils.makeDirs(path);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Export path validate error, path string:{}", exportPath, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
-1
@@ -1,9 +1,14 @@
|
||||
package jadx.gui.settings;
|
||||
package jadx.gui.ui.export;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.core.export.ExportGradleType;
|
||||
|
||||
public class ExportProjectProperties {
|
||||
private boolean skipSources;
|
||||
private boolean skipResources;
|
||||
private boolean asGradleMode;
|
||||
private @Nullable ExportGradleType exportGradleType;
|
||||
private String exportPath;
|
||||
|
||||
public boolean isSkipSources() {
|
||||
@@ -30,6 +35,14 @@ public class ExportProjectProperties {
|
||||
this.asGradleMode = asGradleMode;
|
||||
}
|
||||
|
||||
public @Nullable ExportGradleType getExportGradleType() {
|
||||
return exportGradleType;
|
||||
}
|
||||
|
||||
public void setExportGradleType(@Nullable ExportGradleType exportGradleType) {
|
||||
this.exportGradleType = exportGradleType;
|
||||
}
|
||||
|
||||
public String getExportPath() {
|
||||
return exportPath;
|
||||
}
|
||||
@@ -37,4 +50,14 @@ public class ExportProjectProperties {
|
||||
public void setExportPath(String exportPath) {
|
||||
this.exportPath = exportPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExportProjectProperties{exportPath='" + exportPath + '\''
|
||||
+ ", asGradleMode=" + asGradleMode
|
||||
+ ", exportGradleType=" + exportGradleType
|
||||
+ ", skipSources=" + skipSources
|
||||
+ ", skipResources=" + skipResources
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
@@ -180,6 +180,7 @@ export_dialog.save_path=Speicherpfad:
|
||||
export_dialog.browse=Durchsuchen
|
||||
export_dialog.export_options=Exportoptionen
|
||||
export_dialog.export_gradle=Als Gradle-Projekt exportieren
|
||||
#export_dialog.export_gradle_type=Gradle template:
|
||||
|
||||
log_viewer.title=Protokollanzeige
|
||||
log_viewer.log_level=Protokollstufe:
|
||||
|
||||
@@ -175,11 +175,12 @@ comment_dialog.usage=Use 'Shift + Enter' to start a new line
|
||||
|
||||
rename_dialog.class_help=Enter full name to move class to another package. Start with '.' to move to default (empty) package
|
||||
|
||||
export_dialog.title=Export to source code
|
||||
export_dialog.title=Export
|
||||
export_dialog.save_path=Save path:
|
||||
export_dialog.browse=Browse
|
||||
export_dialog.export_options=Export options
|
||||
export_dialog.export_gradle=Export as gradle project
|
||||
export_dialog.export_gradle=Export as a Gradle project
|
||||
export_dialog.export_gradle_type=Gradle template:
|
||||
|
||||
log_viewer.title=Log Viewer
|
||||
log_viewer.log_level=Log level:
|
||||
|
||||
@@ -180,6 +180,7 @@ usage_dialog.label=Usage for:
|
||||
#export_dialog.browse=Browse
|
||||
#export_dialog.export_options=Export options
|
||||
#export_dialog.export_gradle=Export as gradle project
|
||||
#export_dialog.export_gradle_type=Gradle template:
|
||||
|
||||
log_viewer.title=Visor log
|
||||
log_viewer.log_level=Nivel log:
|
||||
|
||||
@@ -180,6 +180,7 @@ comment_dialog.usage=Gunakan Shift + Enter untuk memulai baris baru
|
||||
#export_dialog.browse=Browse
|
||||
#export_dialog.export_options=Export options
|
||||
#export_dialog.export_gradle=Export as gradle project
|
||||
#export_dialog.export_gradle_type=Gradle template:
|
||||
|
||||
log_viewer.title=Pemantau Log
|
||||
log_viewer.log_level=Tingkat log:
|
||||
|
||||
@@ -180,6 +180,7 @@ comment_dialog.usage=Shift + Enter 를 입력해 새 라인에 입력
|
||||
#export_dialog.browse=Browse
|
||||
#export_dialog.export_options=Export options
|
||||
#export_dialog.export_gradle=Export as gradle project
|
||||
#export_dialog.export_gradle_type=Gradle template:
|
||||
|
||||
log_viewer.title=로그 뷰어
|
||||
log_viewer.log_level=로그 레벨:
|
||||
|
||||
@@ -180,6 +180,7 @@ comment_dialog.usage=Use Shift + Enter para pular uma linha
|
||||
#export_dialog.browse=Browse
|
||||
#export_dialog.export_options=Export options
|
||||
#export_dialog.export_gradle=Export as gradle project
|
||||
#export_dialog.export_gradle_type=Gradle template:
|
||||
|
||||
log_viewer.title=Visualizador de log
|
||||
log_viewer.log_level=Nível do log:
|
||||
|
||||
@@ -180,6 +180,7 @@ rename_dialog.class_help=Введите полный путь к пакету,
|
||||
#export_dialog.browse=Browse
|
||||
#export_dialog.export_options=Export options
|
||||
#export_dialog.export_gradle=Export as gradle project
|
||||
#export_dialog.export_gradle_type=Gradle template:
|
||||
|
||||
log_viewer.title=Просмотр логов
|
||||
log_viewer.log_level=Уровень лога:
|
||||
|
||||
@@ -180,6 +180,7 @@ export_dialog.save_path=保存路径:
|
||||
export_dialog.browse=浏览
|
||||
export_dialog.export_options=导出选项
|
||||
export_dialog.export_gradle=导出为 Gradle 项目
|
||||
#export_dialog.export_gradle_type=Gradle template:
|
||||
|
||||
log_viewer.title=日志查看器
|
||||
log_viewer.log_level=日志等级:
|
||||
|
||||
@@ -180,6 +180,7 @@ export_dialog.save_path=儲存路徑:
|
||||
export_dialog.browse=瀏覽
|
||||
export_dialog.export_options=匯出選項
|
||||
export_dialog.export_gradle=匯出成 Gradle 專案
|
||||
#export_dialog.export_gradle_type=Gradle template:
|
||||
|
||||
log_viewer.title=記錄檔檢視器
|
||||
log_viewer.log_level=記錄層級:
|
||||
|
||||
Reference in New Issue
Block a user