diff --git a/jadx-gui/src/main/java/jadx/gui/JadxGUI.java b/jadx-gui/src/main/java/jadx/gui/JadxGUI.java index 3a9327bd6a6..bb702cd630e 100644 --- a/jadx-gui/src/main/java/jadx/gui/JadxGUI.java +++ b/jadx-gui/src/main/java/jadx/gui/JadxGUI.java @@ -12,8 +12,8 @@ import jadx.gui.logs.LogCollector; import jadx.gui.settings.JadxSettings; import jadx.gui.settings.JadxSettingsAdapter; -import jadx.gui.ui.ExceptionDialog; import jadx.gui.ui.MainWindow; +import jadx.gui.ui.dialog.ExceptionDialog; import jadx.gui.utils.LafManager; import jadx.gui.utils.NLS; import jadx.gui.utils.SystemInfo; diff --git a/jadx-gui/src/main/java/jadx/gui/settings/ExportProjectProperties.java b/jadx-gui/src/main/java/jadx/gui/settings/ExportProjectProperties.java new file mode 100644 index 00000000000..64df78b1695 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/settings/ExportProjectProperties.java @@ -0,0 +1,53 @@ +package jadx.gui.settings; + +public class ExportProjectProperties { + private boolean skipSources; + private boolean skipResources; + private boolean asGradleMode; + private boolean useGradleKts; + private String exportPath; + + public ExportProjectProperties() { + + } + + public boolean isSkipSources() { + return skipSources; + } + + public void setSkipSources(boolean skipSources) { + this.skipSources = skipSources; + } + + public boolean isSkipResources() { + return skipResources; + } + + public void setSkipResources(boolean skipResources) { + this.skipResources = skipResources; + } + + public boolean isAsGradleMode() { + return asGradleMode; + } + + public void setAsGradleMode(boolean asGradleMode) { + this.asGradleMode = asGradleMode; + } + + public boolean isUseGradleKts() { + return useGradleKts; + } + + public void setUseGradleKts(boolean useGradleKts) { + this.useGradleKts = useGradleKts; + } + + public String getExportPath() { + return exportPath; + } + + public void setExportPath(String exportPath) { + this.exportPath = exportPath; + } +} 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 3f98d9bfcf5..3d04976e40e 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -20,6 +20,7 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.geom.AffineTransform; +import java.io.File; import java.io.InputStream; import java.net.URL; import java.nio.file.Files; @@ -107,6 +108,7 @@ import jadx.gui.logs.LogPanel; 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; @@ -126,6 +128,8 @@ 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.filedialog.FileDialogWrapper; @@ -160,7 +164,7 @@ import jadx.gui.utils.ui.ActionHandler; import jadx.gui.utils.ui.NodeLabel; -public class MainWindow extends JFrame { +public class MainWindow extends JFrame implements ExportProjectDialog.ExportProjectDialogListener { private static final Logger LOG = LoggerFactory.getLogger(MainWindow.class); private static final String DEFAULT_TITLE = "jadx-gui"; @@ -798,23 +802,23 @@ public void cancelBackgroundJobs() { backgroundExecutor.cancelAll(); } - private void saveAll(boolean export) { - FileDialogWrapper fileDialog = new FileDialogWrapper(this, FileOpenMode.EXPORT); - List saveDirs = fileDialog.show(); - if (saveDirs.isEmpty()) { - return; - } + private void exportProject() { + ExportProjectDialog dialog = new ExportProjectDialog(this, this); + dialog.setVisible(true); + } + + private void saveAll(ExportProjectProperties exportProjectProperties) { JadxArgs decompilerArgs = wrapper.getArgs(); - decompilerArgs.setExportAsGradleProject(export); - if (export) { + decompilerArgs.setExportAsGradleProject(exportProjectProperties.isAsGradleMode()); + if (exportProjectProperties.isAsGradleMode()) { decompilerArgs.setSkipSources(false); decompilerArgs.setSkipResources(false); } else { - decompilerArgs.setSkipSources(settings.isSkipSources()); - decompilerArgs.setSkipResources(settings.isSkipResources()); + decompilerArgs.setSkipSources(exportProjectProperties.isSkipSources()); + decompilerArgs.setSkipResources(exportProjectProperties.isSkipResources()); } - settings.setLastSaveFilePath(fileDialog.getCurrentDir()); - backgroundExecutor.execute(new ExportTask(this, wrapper, saveDirs.get(0).toFile())); + + backgroundExecutor.execute(new ExportTask(this, wrapper, new File(exportProjectProperties.getExportPath()))); } public void initTree() { @@ -1069,8 +1073,7 @@ private void initMenuAndToolbar() { liveReloadMenuItem = new JCheckBoxMenuItem(liveReloadAction); liveReloadMenuItem.setState(project.isEnableLiveReload()); - JadxGuiAction saveAllAction = new JadxGuiAction(ActionModel.SAVE_ALL, () -> saveAll(false)); - JadxGuiAction exportAction = new JadxGuiAction(ActionModel.EXPORT, () -> saveAll(true)); + JadxGuiAction exportAction = new JadxGuiAction(ActionModel.EXPORT, this::exportProject); JMenu recentProjects = new JadxMenu(NLS.str("menu.recent_projects"), shortcutsController); recentProjects.addMenuListener(new RecentProjectsMenuListener(this, recentProjects)); @@ -1161,7 +1164,6 @@ private void initMenuAndToolbar() { file.add(liveReloadMenuItem); renameMappings.addMenuActions(file); file.addSeparator(); - file.add(saveAllAction); file.add(exportAction); file.addSeparator(); file.add(recentProjects); @@ -1245,7 +1247,6 @@ public void actionPerformed(ActionEvent e) { toolbar.addSeparator(); toolbar.add(reloadAction); toolbar.addSeparator(); - toolbar.add(saveAllAction); toolbar.add(exportAction); toolbar.addSeparator(); toolbar.add(syncAction); @@ -1292,7 +1293,6 @@ public void actionPerformed(ActionEvent e) { forwardAction.setEnabled(loaded); forwardVariantAction.setEnabled(loaded); syncAction.setEnabled(loaded); - saveAllAction.setEnabled(loaded); exportAction.setEnabled(loaded); saveProjectAsAction.setEnabled(loaded); reloadAction.setEnabled(loaded); @@ -1790,4 +1790,9 @@ public CacheManager getCacheManager() { public JadxGuiEventsImpl events() { return events; } + + @Override + public void onProjectExportCalled(ExportProjectProperties exportProjectProperties) { + saveAll(exportProjectProperties); + } } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/action/ActionModel.java b/jadx-gui/src/main/java/jadx/gui/ui/action/ActionModel.java index d0b3a61b6e4..d398523f3d2 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/action/ActionModel.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/action/ActionModel.java @@ -37,7 +37,7 @@ public enum ActionModel { Shortcut.keyboard(KeyEvent.VK_F5, InputEvent.SHIFT_DOWN_MASK)), SAVE_ALL(MENU_TOOLBAR, "file.save_all", "file.save_all", "ui/menu-saveall", Shortcut.keyboard(KeyEvent.VK_E, UiUtils.ctrlButton())), - EXPORT(MENU_TOOLBAR, "file.export_gradle", "file.export_gradle", "ui/export", + EXPORT(MENU_TOOLBAR, "file.export", "file.export", "ui/export", Shortcut.keyboard(KeyEvent.VK_E, UiUtils.ctrlButton() | KeyEvent.SHIFT_DOWN_MASK)), PREFS(MENU_TOOLBAR, "menu.preferences", "menu.preferences", "ui/settings", Shortcut.keyboard(KeyEvent.VK_P, UiUtils.ctrlButton() | KeyEvent.SHIFT_DOWN_MASK)), diff --git a/jadx-gui/src/main/java/jadx/gui/ui/ExceptionDialog.java b/jadx-gui/src/main/java/jadx/gui/ui/dialog/ExceptionDialog.java similarity index 94% rename from jadx-gui/src/main/java/jadx/gui/ui/ExceptionDialog.java rename to jadx-gui/src/main/java/jadx/gui/ui/dialog/ExceptionDialog.java index 23c7fadfc27..30f6638732a 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/ExceptionDialog.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/dialog/ExceptionDialog.java @@ -1,4 +1,4 @@ -package jadx.gui.ui; +package jadx.gui.ui.dialog; import java.awt.BorderLayout; import java.awt.Color; @@ -18,7 +18,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import javax.swing.JButton; import javax.swing.JComponent; @@ -46,7 +45,7 @@ public class ExceptionDialog extends JDialog { private static final String FMT_DETAIL_LENGTH = "-13"; public static void registerUncaughtExceptionHandler() { - Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> showExceptionDialog(thread, ex)); + Thread.setDefaultUncaughtExceptionHandler(ExceptionDialog::showExceptionDialog); } public static void showExceptionDialog(Thread thread, Throwable ex) { @@ -78,7 +77,7 @@ public ExceptionDialog(Thread thread, Throwable ex) { try { // TODO: Use ProcessHandle.current().info().commandLine() once min Java is 9+ List args = ManagementFactory.getRuntimeMXBean().getInputArguments(); - details.put("Program args", args.stream().collect(Collectors.joining(" "))); + details.put("Program args", String.join(" ", args)); } catch (Throwable t) { LOG.error("failed to get program arguments", t); } @@ -89,7 +88,7 @@ public ExceptionDialog(Thread thread, Throwable ex) { String issueTitle; try { - issueTitle = URLEncoder.encode(ex.toString(), StandardCharsets.UTF_8.toString()); + issueTitle = URLEncoder.encode(ex.toString(), StandardCharsets.UTF_8); } catch (Exception e) { LOG.error("URL encoding of title failed", e); issueTitle = ex.getClass().getSimpleName(); @@ -105,7 +104,7 @@ public ExceptionDialog(Thread thread, Throwable ex) { String issueBody; try { - issueBody = URLEncoder.encode(body, StandardCharsets.UTF_8.toString()); + issueBody = URLEncoder.encode(body, StandardCharsets.UTF_8); } catch (Exception e) { LOG.error("URL encoding of body failed", e); issueBody = "Please copy the displayed text in the Jadx error dialog and paste it here"; @@ -126,7 +125,7 @@ public ExceptionDialog(Thread thread, Throwable ex) { StringBuilder detailsTextBuilder = new StringBuilder(); details.forEach((key, value) -> detailsTextBuilder.append(String.format("%" + FMT_DETAIL_LENGTH + "s: %s\n", key, value))); - messageArea.setText(detailsTextBuilder.toString() + "\n" + stackTrace); + messageArea.setText(detailsTextBuilder + "\n" + stackTrace); JPanel buttonPanel = new JPanel(); JButton exitButton = new JButton("Terminate Jadx"); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/dialog/ExportProjectDialog.java b/jadx-gui/src/main/java/jadx/gui/ui/dialog/ExportProjectDialog.java new file mode 100644 index 00000000000..f927625b285 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/ui/dialog/ExportProjectDialog.java @@ -0,0 +1,207 @@ +package jadx.gui.ui.dialog; + +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.Path; +import java.util.List; + +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.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.WindowConstants; + +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jadx.gui.settings.ExportProjectProperties; +import jadx.gui.ui.MainWindow; +import jadx.gui.ui.filedialog.FileDialogWrapper; +import jadx.gui.ui.filedialog.FileOpenMode; +import jadx.gui.utils.NLS; +import jadx.gui.utils.TextStandardActions; +import jadx.gui.utils.ui.DocumentUpdateListener; + +public class ExportProjectDialog extends JDialog { + + public interface ExportProjectDialogListener { + void onProjectExportCalled(ExportProjectProperties exportProjectProperties); + } + + private static final Logger LOG = LoggerFactory.getLogger(ExportProjectDialog.class); + private final ExportProjectDialogListener exportProjectDialogListener; + private final ExportProjectProperties exportProjectProperties = new ExportProjectProperties(); + private final MainWindow mainWindow; + private JTextField pathField; + + public ExportProjectDialog(MainWindow mainWindow, ExportProjectDialogListener exportProjectDialogListener) { + super(mainWindow); + this.mainWindow = mainWindow; + this.exportProjectDialogListener = exportProjectDialogListener; + initUI(); + } + + private void initUI() { + + JPanel contentPane = makeContentPane(); + + JPanel buttonPane = initButtonsPanel(); + + Container container = getContentPane(); + // contentPane.add(topPanel, BorderLayout.NORTH); + container.add(contentPane, BorderLayout.CENTER); + container.add(buttonPane, BorderLayout.PAGE_END); + + setTitle(NLS.str("export_dialog.title")); + + pack(); + setSize(400, 250); + setLocationRelativeTo(mainWindow); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setModalityType(ModalityType.MODELESS); + } + + private JPanel makeContentPane() { + + JPanel mainPanel = new JPanel(); + + // top layout + JLabel label = 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))); + new TextStandardActions(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 -> { + exportProjectProperties.setSkipResources(e.getStateChange() == ItemEvent.SELECTED); + }); + + JCheckBox skipSources = new JCheckBox(NLS.str("preferences.skipSourcesDecode")); + skipSources.setSelected(mainWindow.getSettings().isSkipSources()); + skipSources.addItemListener(e -> { + exportProjectProperties.setSkipSources(e.getStateChange() == ItemEvent.SELECTED); + }); + + 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); + }); + + exportOptionsPanel.add(resourceDecode); + exportOptionsPanel.add(skipSources); + exportOptionsPanel.add(exportAsGradleProject); + + // 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 + 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)); + + return mainPanel; + } + + private void setExportProjectPath(JTextField field) { + String path = field.getText(); + if (!path.isEmpty()) { + exportProjectProperties.setExportPath(field.getText()); + } + } + + @NotNull + protected JPanel initButtonsPanel() { + + JButton cancelButton = new JButton(NLS.str("common_dialog.cancel")); + cancelButton.addActionListener(event -> dispose()); + + JButton exportProjectButton = new JButton(NLS.str("common_dialog.ok")); + exportProjectButton.addActionListener(event -> exportProject()); + getRootPane().setDefaultButton(exportProjectButton); + + 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))); + buttonPane.add(cancelButton); + return buttonPane; + } + + private JButton makeEditorBrowseButton(final JTextField textField) { + JButton button = new JButton(NLS.str("export_dialog.browse")); + button.addActionListener(e -> { + FileDialogWrapper fileDialog = new FileDialogWrapper(mainWindow, FileOpenMode.EXPORT); + mainWindow.getSettings().setLastSaveFilePath(fileDialog.getCurrentDir()); + List saveDirs = fileDialog.show(); + if (saveDirs.isEmpty()) { + return; + } + String path = saveDirs.get(0).toString(); + textField.setText(path); + }); + return button; + } + + private void exportProject() { + if (!new File(exportProjectProperties.getExportPath()).exists()) { + JOptionPane.showMessageDialog(this, NLS.str("message.enter_valid_path"), + NLS.str("message.errorTitle"), JOptionPane.WARNING_MESSAGE); + return; + } + exportProjectDialogListener.onProjectExportCalled(exportProjectProperties); + setVisible(false); + } + +} diff --git a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties index 46cb1e9ed24..9238c008006 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties @@ -45,7 +45,7 @@ file.live_reload_desc=Dateien bei Änderungen autom. neuladen #file.close_mappings=Zuordnungen exportieren als… file.save_all=Alles speichern #file.save=Save -file.export_gradle=Als Gradle-Projekt speichern +#file.export=Export project file.save_all_msg=Verzeichnis für das Speichern dekompilierter Ressourcen auswählen file.exit=Beenden #file.export_node=Export file @@ -105,6 +105,7 @@ message.taskError=Die Aufgabe ist durch Fehler fehlgeschlagen (siehe Protokoll f message.errorTitle=Fehler message.load_errors=Laden fehlgeschlagen.\nAnzahl der Fehler: %d\nKlicke auf OK, um die Log-Ansicht zu öffnen. message.no_classes=Keine Klassen geladen, nichts zu dekompilieren! +#message.enter_valid_path=Enter valid path to save! message.saveIncomplete=Speichern unvollständig.
%s
%d Klassen oder Ressourcen wurden nicht gespeichert! message.indexIncomplete=Index einiger Klassen übersprungen.
%s
%d Klassen wurden nicht indiziert und werden nicht in den Suchergebnissen erscheinen! @@ -170,6 +171,12 @@ comment_dialog.usage=Shift + Enter verwenden, um eine neue Zeile zu beginnen #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.save_path=Save path: +#export_dialog.browse=Browse +#export_dialog.export_options=Export options +#export_dialog.export_gradle=Export as gradle project + log_viewer.title=Log-Anzeige log_viewer.log_level=Log-Level: #log_viewer.mode=Mode: @@ -213,6 +220,7 @@ preferences.inlineMethods=Inline-Methoden #preferences.restoreSwitchOverString=Restore switch over string preferences.fsCaseSensitive=Dateisystem unterscheidet zwischen Groß/Kleinschreibung preferences.skipResourcesDecode=Keine Ressourcen dekodieren +#preferences.skipSourcesDecode=Don't decompile source code preferences.useKotlinMethodsForVarNames=Kotlin-Methoden für die Umbenennung von Variablen verwenden preferences.commentsLevel=Level der Code Kommentierungen #preferences.saveOption=Auto-save settings diff --git a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties index 95f194b4909..561096507c1 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties @@ -45,7 +45,7 @@ file.save_mappings_as=Save mappings as... file.close_mappings=Close mappings file.save_all=Save all file.save=Save -file.export_gradle=Save as gradle project +file.export=Export project file.save_all_msg=Select directory for save decompiled sources file.exit=Exit file.export_node=Export file @@ -105,6 +105,7 @@ message.taskError=Task failed with error (check log for details). message.errorTitle=Error message.load_errors=Load failed.\nErrors count: %d\nClick OK to open log viewer. message.no_classes=No classes loaded, nothing to decompile! +message.enter_valid_path=Enter valid path to save! message.saveIncomplete=Save incomplete.
%s
%d classes or resources were not saved! message.indexIncomplete=Index of some classes skipped.
%s
%d classes were not indexed and will not appear in search results! @@ -170,6 +171,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.save_path=Save path: +export_dialog.browse=Browse +export_dialog.export_options=Export options +export_dialog.export_gradle=Export as gradle project + log_viewer.title=Log Viewer log_viewer.log_level=Log level: log_viewer.mode=Mode: @@ -213,6 +220,7 @@ preferences.extractFinally=Extract finally block preferences.restoreSwitchOverString=Restore switch over string preferences.fsCaseSensitive=File system is case-sensitive preferences.skipResourcesDecode=Don't decode resources +preferences.skipSourcesDecode=Don't decompile source code preferences.useKotlinMethodsForVarNames=Use kotlin methods for variables rename preferences.commentsLevel=Code comments level preferences.saveOption=Auto-save settings diff --git a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties index dfb5656346b..6724e1fde51 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties @@ -45,7 +45,7 @@ file.open_title=Abrir archivo #file.close_mappings=Close mappings file.save_all=Guardar todo #file.save=Save -file.export_gradle=Guardar como proyecto Gradle +#file.export=Export project file.save_all_msg=Seleccionar carpeta para guardar fuentes descompiladas file.exit=Salir #file.export_node=Export file @@ -105,6 +105,7 @@ nav.forward=Adelante #message.errorTitle=Error #message.load_errors=Load failed.\nErrors count: %d\nClick OK to open log viewer. #message.no_classes=No classes loaded, nothing to decompile! +#message.enter_valid_path=Enter valid path to save! #message.saveIncomplete=Save incomplete.
%s
%d classes or resources were not saved! #message.indexIncomplete=Index of some classes skipped.
%s
%d classes were not indexed and will not appear in search results! @@ -170,6 +171,12 @@ usage_dialog.label=Usage for: #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.save_path=Save path: +#export_dialog.browse=Browse +#export_dialog.export_options=Export options +#export_dialog.export_gradle=Export as gradle project + log_viewer.title=Visor log log_viewer.log_level=Nivel log: #log_viewer.mode=Mode: @@ -213,6 +220,7 @@ preferences.replaceConsts=Reemplazar constantes #preferences.restoreSwitchOverString=Restore switch over string #preferences.fsCaseSensitive=File system is case-sensitive preferences.skipResourcesDecode=No descodificar recursos +#preferences.skipSourcesDecode=Don't decompile source code #preferences.useKotlinMethodsForVarNames=Use kotlin methods for variables rename #preferences.commentsLevel=Code comments level #preferences.saveOption=Auto-save settings diff --git a/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties b/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties index a1c9318a162..423921636eb 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties @@ -45,7 +45,7 @@ file.save_mappings_as=Simpan pemetaan sebagai... file.close_mappings=Tutup pemetaan file.save_all=Simpan semua file.save=Simpan -file.export_gradle=Simpan sebagai proyek gradle +#file.export=Export project file.save_all_msg=Pilih direktori untuk menyimpan sumber yang telah didekompilasi file.exit=Keluar #file.export_node=Export file @@ -105,6 +105,7 @@ message.taskError=Tugas gagal dengan kesalahan (periksa log untuk detailnya). message.errorTitle=Kesalahan message.load_errors=Pemuatan gagal.\nJumlah kesalahan: %d\nKlik OK untuk membuka penampil log. message.no_classes=Tidak ada kelas yang dimuat, tidak ada yang dapat didekompilasi! +#message.enter_valid_path=Enter valid path to save! message.saveIncomplete=Simpan tidak lengkap.
%s
%d kelas atau sumber daya tidak disimpan! message.indexIncomplete=Indeks beberapa kelas dilewati.
%s
%d kelas tidak diindeks dan tidak akan muncul dalam hasil pencarian! @@ -170,6 +171,12 @@ comment_dialog.usage=Gunakan Shift + Enter untuk memulai baris baru #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.save_path=Save path: +#export_dialog.browse=Browse +#export_dialog.export_options=Export options +#export_dialog.export_gradle=Export as gradle project + log_viewer.title=Pemantau Log log_viewer.log_level=Tingkat log: log_viewer.mode=Mode: @@ -213,6 +220,7 @@ preferences.extractFinally=Ekstrak blok finally #preferences.restoreSwitchOverString=Restore switch over string preferences.fsCaseSensitive=File sistem bersifat sensitif huruf besar-kecil preferences.skipResourcesDecode=Jangan dekode sumber daya +#preferences.skipSourcesDecode=Don't decompile source code preferences.useKotlinMethodsForVarNames=Gunakan metode Kotlin untuk mengganti nama variabel preferences.commentsLevel=Tingkat komentar kode #preferences.saveOption=Auto-save settings diff --git a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties index c5a40a6f73e..538984d5167 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties @@ -45,7 +45,7 @@ file.save_mappings=다른 이름으로 매핑 내보내기... #file.close_mappings=다른 이름으로 매핑 내보내기... file.save_all=모두 저장 #file.save=Save -file.export_gradle=Gradle 프로젝트로 저장 +#file.export=Export project file.save_all_msg=디컴파일된 소스를 저장할 디렉토리 선택 file.exit=나가기 #file.export_node=Export file @@ -105,6 +105,7 @@ message.taskError=작업이 오류로 실패했습니다. (자세한 내용은 message.errorTitle=오류 message.load_errors=로드하지 못했습니다.\n오류 수: %d\n로그 뷰어를 열려면 확인을 클릭하십시오. message.no_classes=로드된 클래스 없음, 디컴파일 대상 존재하지 않음 +#message.enter_valid_path=Enter valid path to save! message.saveIncomplete=저장이 완료되지 않았습니다.
%s
%d개의 클래스 또는 리소스가 저장되지 않았습니다! message.indexIncomplete=일부 클래스의 색인을 건너뛰었습니다.
%s
%d개의 클래스는 색인이 생성되지 않았으며 검색 결과에 나타나지 않습니다. @@ -170,6 +171,12 @@ comment_dialog.usage=Shift + Enter 를 입력해 새 라인에 입력 #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.save_path=Save path: +#export_dialog.browse=Browse +#export_dialog.export_options=Export options +#export_dialog.export_gradle=Export as gradle project + log_viewer.title=로그 뷰어 log_viewer.log_level=로그 레벨: #log_viewer.mode=Mode: @@ -213,6 +220,7 @@ preferences.extractFinally=finally 블록 추출 #preferences.restoreSwitchOverString=Restore switch over string preferences.fsCaseSensitive=파일 시스템 대소문자 구별 preferences.skipResourcesDecode=리소스 디코딩 하지 않기 +#preferences.skipSourcesDecode=Don't decompile source code preferences.useKotlinMethodsForVarNames=변수 이름 바꾸기에 kotlin 메서드 사용 preferences.commentsLevel=코드 주석 수준 #preferences.saveOption=Auto-save settings diff --git a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties index 90fdf0587a5..a205688befd 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties @@ -45,7 +45,7 @@ file.live_reload_desc=Recarregar arquivos automaticamente ao serem alterados #file.close_mappings=Close mappings file.save_all=Salvar tudo #file.save=Save -file.export_gradle=Salvar como um projeto gradle +#file.export=Export project file.save_all_msg=Selecionar diretório para salvar arquivos descompilados file.exit=Sair #file.export_node=Export file @@ -105,6 +105,7 @@ message.taskError=Tarefa falhou com erro (cheque o log para detalhes). message.errorTitle=Erro message.load_errors=Carregamento falhou.\nNúmero de erros: %d\nClique em ok para abrir o visualizador de log. message.no_classes=Nenhuma classe carregada, nada para ser descompilado! +#message.enter_valid_path=Enter valid path to save! message.saveIncomplete=Operação não foi completa.
%s
%d classes ou recursos não foram salvos! message.indexIncomplete=Indexação de algumas classes foram ignoradas.
%s
%d classes não foram indexadas não vão aparecer nos resultados de busca! @@ -170,6 +171,12 @@ comment_dialog.usage=Use Shift + Enter para pular uma linha #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.save_path=Save path: +#export_dialog.browse=Browse +#export_dialog.export_options=Export options +#export_dialog.export_gradle=Export as gradle project + log_viewer.title=Visualizador de log log_viewer.log_level=Nível do log: #log_viewer.mode=Mode: @@ -213,6 +220,7 @@ preferences.extractFinally=Extrair blocos finally #preferences.restoreSwitchOverString=Restore switch over string preferences.fsCaseSensitive=Sistema de arquivo diferencia maiúsculas de minúsculas preferences.skipResourcesDecode=Não decodificar recursos +#preferences.skipSourcesDecode=Don't decompile source code preferences.useKotlinMethodsForVarNames=Usar métodos do kotlin para renomear variáveis preferences.commentsLevel=Nível de comentários do código #preferences.saveOption=Auto-save settings diff --git a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties index 0db5110e5b2..e94bfe92d74 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties @@ -45,7 +45,7 @@ file.save_mappings_as=Сохранить маппинги как... file.close_mappings=Закрыть маппинги file.save_all=Сохранить все file.save=Сохранить -file.export_gradle=Сохранить как Gradle проект +#file.export=Export project file.save_all_msg=Выбрать папку для декомпилированных проектов file.exit=Выход #file.export_node=Export file @@ -105,6 +105,7 @@ message.taskError=Выполнение задачи закончено с оши message.errorTitle=Ошибка message.load_errors=Ошибка прогрузки.\nКоличество ошибок: %d\nНажмите OK, чтобы открыть лог. message.no_classes=Классы не найдены, нечего декомпилировать! +#message.enter_valid_path=Enter valid path to save! message.saveIncomplete=Сохранение не завершено.
%s
%d классов или ресурсов не сохранено! message.indexIncomplete=Индексирование некоторых классов пропущено.
%s
%d классов не индексировано, и не будет отображаться в результатах поиска! @@ -170,6 +171,12 @@ comment_dialog.usage=Используйте Shift + Enter для перенос rename_dialog.class_help=Введите полный путь к пакету, в который вы хотите переместить этот класс. Введите '.' для перемещения в пакет по умолчанию (пустой) пакет +#export_dialog.title=Export to source code +#export_dialog.save_path=Save path: +#export_dialog.browse=Browse +#export_dialog.export_options=Export options +#export_dialog.export_gradle=Export as gradle project + log_viewer.title=Просмотр логов log_viewer.log_level=Уровень лога: log_viewer.mode=Режим: @@ -213,6 +220,7 @@ preferences.extractFinally=Вычленять finally блоки #preferences.restoreSwitchOverString=Restore switch over string preferences.fsCaseSensitive=Учитывать регистр в файловой системе preferences.skipResourcesDecode=Не декодировать ресурсы +#preferences.skipSourcesDecode=Don't decompile source code preferences.useKotlinMethodsForVarNames=Kotlin методы как имена полей preferences.commentsLevel=Уровень лога операций preferences.saveOption=Автосохранение настроек diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties index 9a2a3d10f68..728cfeba5de 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties @@ -45,7 +45,7 @@ file.save_mappings_as=映射另存为… file.close_mappings=关闭映射 file.save_all=全部保存(伪代码) file.save=保存 -file.export_gradle=另存为 Gradle 项目 +#file.export=Export project file.save_all_msg=请选择保存反编译资源的目录 file.exit=退出 file.export_node=导出文件 @@ -105,6 +105,7 @@ message.taskError=任务失败,出现错误(详情请查看日志)。 message.errorTitle=错误 message.load_errors=加载失败。\n错误数:%d\n点击确定查看日志 message.no_classes=无类被加载,没什么可反编译! +#message.enter_valid_path=Enter valid path to save! message.saveIncomplete=保存未完成。
%s
%d 类或资源未被保存! message.indexIncomplete=已跳过某些类索引。
%s
%d 类未被索引,不会出现在搜索结果中! @@ -170,6 +171,12 @@ comment_dialog.usage=使用 Shift + Enter 换行 rename_dialog.class_help=输入包名全路径,将类移动到另一个包。以'.'开始则移到默认(空)包下。 +#export_dialog.title=Export to source code +#export_dialog.save_path=Save path: +#export_dialog.browse=Browse +#export_dialog.export_options=Export options +#export_dialog.export_gradle=Export as gradle project + log_viewer.title=日志查看器 log_viewer.log_level=日志等级: log_viewer.mode=模式: @@ -213,6 +220,7 @@ preferences.extractFinally=提取finally块 preferences.restoreSwitchOverString=恢复switch字符串 preferences.fsCaseSensitive=文件系统区分大小写 preferences.skipResourcesDecode=不反编译资源文件 +#preferences.skipSourcesDecode=Don't decompile source code preferences.useKotlinMethodsForVarNames=使用Kotlin方法来重命名变量 preferences.commentsLevel=代码注释等级 preferences.saveOption=自动保存设置 diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties index e01ac3dcfac..c5c932fd0d5 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties @@ -45,7 +45,7 @@ file.save_mappings_as=儲存對映檔為... file.close_mappings=關閉對映檔 file.save_all=全部儲存 file.save=儲存 -file.export_gradle=另存為 gradle 專案 +#file.export=Export project file.save_all_msg=選擇儲存反編譯原始碼的路徑 file.exit=離開 #file.export_node=Export file @@ -105,6 +105,7 @@ message.taskError=工作發生錯誤 (查看記錄檔以了解詳情)。 message.errorTitle=錯誤 message.load_errors=載入失敗。\n錯誤數:%d\n點擊 OK 以開啟記錄檔檢視器 message.no_classes=未載入任何類別,沒有東西可以反編譯! +#message.enter_valid_path=Enter valid path to save! message.saveIncomplete=儲存未完成。
%s
%d 個類別或資源尚未儲存! message.indexIncomplete=某些類別的索引被略過。
%s
%d 個類別未被索引,故不會出現在搜尋結果中。 @@ -170,6 +171,12 @@ comment_dialog.usage=按下 Shift + Enter 來換行 #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.save_path=Save path: +#export_dialog.browse=Browse +#export_dialog.export_options=Export options +#export_dialog.export_gradle=Export as gradle project + log_viewer.title=記錄檔檢視器 log_viewer.log_level=記錄層級: log_viewer.mode=模式: @@ -213,6 +220,7 @@ preferences.extractFinally=擷取 finally 區塊 #preferences.restoreSwitchOverString=Restore switch over string preferences.fsCaseSensitive=檔案系統區分大小寫 preferences.skipResourcesDecode=不要為資源解碼 +#preferences.skipSourcesDecode=Don't decompile source code preferences.useKotlinMethodsForVarNames=使用 Kotlin 方法來為變數重新命名 preferences.commentsLevel=程式碼註解層級 #preferences.saveOption=Auto-save settings