aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorMichal Labedzki <michal.labedzki@tieto.com>2013-12-21 17:55:43 +0100
committerMichal Labedzki <michal.labedzki@tieto.com>2014-11-04 08:21:55 +0000
commit5025bc258cdeabbd498919d5c6b4554accdad842 (patch)
tree53301fcaa347e0a933086ce102b56b27e13aeee9 /ui
parent15e78de432f55f5478f1b3994f3d7e060b60508d (diff)
Qt: Dynamic languages
- get language as soon as possible (before creating any Qt objects) to make all translations working - dynamic list of supported languages - runtime change of GUI language (no need to restart application) - add flags icons support - search for *.qm languages in buildin resources, then data dir called "languages" (main directory in sources or /usr/share/wireshark/languages), then user directory (UNIX: ~/.wireshark/languages); "languages" directory should contains files wireshark_xx.qm where xx is language code (en, en_GB, etc.), and optional xx.svg for flag icon - try to fix some untranslated manually-created UI items (need manual reset text of those components) Change-Id: I62ca8a8cddce47cec9dbcad6b0bd68b6cfd92229 Reviewed-on: https://code.wireshark.org/review/5041 Tested-by: Michal Labedzki <michal.labedzki@tieto.com> Reviewed-by: Michal Labedzki <michal.labedzki@tieto.com>
Diffstat (limited to 'ui')
-rw-r--r--ui/CMakeLists.txt1
-rw-r--r--ui/Makefile.common2
-rw-r--r--ui/language.c135
-rw-r--r--ui/language.h53
-rw-r--r--ui/qt/CMakeLists.txt1
-rw-r--r--ui/qt/Makefile.common1
-rw-r--r--ui/qt/Wireshark.pro1
-rw-r--r--ui/qt/capture_interfaces_dialog.cpp16
-rw-r--r--ui/qt/capture_interfaces_dialog.h1
-rw-r--r--ui/qt/display_filter_edit.cpp22
-rw-r--r--ui/qt/display_filter_edit.h2
-rw-r--r--ui/qt/main.cpp48
-rw-r--r--ui/qt/main_welcome.cpp16
-rw-r--r--ui/qt/main_welcome.h1
-rw-r--r--ui/qt/main_window.cpp13
-rw-r--r--ui/qt/main_window.h2
-rw-r--r--ui/qt/main_window.ui30
-rw-r--r--ui/qt/main_window_preferences_frame.cpp58
-rw-r--r--ui/qt/main_window_preferences_frame.h1
-rw-r--r--ui/qt/main_window_preferences_frame.ui48
-rw-r--r--ui/qt/packet_list.cpp59
-rw-r--r--ui/qt/preferences_dialog.cpp6
-rw-r--r--ui/qt/proto_tree.cpp40
-rw-r--r--ui/qt/proto_tree.h6
-rw-r--r--ui/qt/search_frame.cpp16
-rw-r--r--ui/qt/search_frame.h4
-rw-r--r--ui/qt/summary_dialog.cpp16
-rw-r--r--ui/qt/summary_dialog.h1
-rw-r--r--ui/qt/wireshark_application.cpp40
-rw-r--r--ui/qt/wireshark_application.h6
30 files changed, 516 insertions, 130 deletions
diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt
index f964c3a3cc..12deadfed4 100644
--- a/ui/CMakeLists.txt
+++ b/ui/CMakeLists.txt
@@ -36,6 +36,7 @@ set(COMMON_UI_SRC
help_url.c
iface_lists.c
io_graph_item.c
+ language.c
packet_list_utils.c
persfilepath_opt.c
preference_utils.c
diff --git a/ui/Makefile.common b/ui/Makefile.common
index 9da5fb17ba..1be7dc1c59 100644
--- a/ui/Makefile.common
+++ b/ui/Makefile.common
@@ -56,6 +56,7 @@ WIRESHARK_UI_SRC = \
follow.c \
iface_lists.c \
io_graph_item.c \
+ language.c \
help_url.c \
packet_list_utils.c \
persfilepath_opt.c \
@@ -92,6 +93,7 @@ noinst_HEADERS = \
packet_list_utils.h \
iface_lists.h \
io_graph_item.h \
+ language.h \
main_statusbar.h \
persfilepath_opt.h \
preference_utils.h \
diff --git a/ui/language.c b/ui/language.c
new file mode 100644
index 0000000000..9e6af04f72
--- /dev/null
+++ b/ui/language.c
@@ -0,0 +1,135 @@
+/* language.c
+ * Language "preference" handling routines
+ * Copyright 2014, Michal Labedzki for Tieto Corporation
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <epan/epan.h>
+#include <epan/prefs.h>
+#include <epan/prefs-int.h>
+
+#include <wsutil/filesystem.h>
+#include <wsutil/file_util.h>
+
+#include "ui/language.h"
+#include "ui/simple_dialog.h"
+
+#define LANGUAGE_FILE_NAME "language"
+#define LANGUAGE_PREF_LANGUAGE "language"
+
+char *language = NULL;
+
+/* set one user's recent common file key/value pair */
+static prefs_set_pref_e
+read_language_pref(gchar *key, const gchar *value,
+ void *private_data _U_, gboolean return_range_errors _U_)
+{
+ if (strcmp(key, LANGUAGE_PREF_LANGUAGE) == 0) {
+ if (language)
+ g_free(language);
+ if (!value || (value && !*value))
+ language = g_strdup("auto");
+ else
+ language = g_strdup(value);
+ }
+
+ return PREFS_SET_OK;
+}
+
+void
+read_language_prefs(void)
+{
+ char *rf_path;
+ FILE *rf;
+
+ rf_path = get_persconffile_path(LANGUAGE_FILE_NAME, FALSE);
+
+ if ((rf = ws_fopen(rf_path, "r")) != NULL) {
+ read_prefs_file(rf_path, rf, read_language_pref, NULL);
+
+ fclose(rf);
+ }
+
+ g_free(rf_path);
+}
+
+gboolean
+write_language_prefs(void)
+{
+ char *pf_dir_path;
+ char *rf_path;
+ FILE *rf;
+
+ /* To do:
+ * - Split output lines longer than MAX_VAL_LEN
+ * - Create a function for the preference directory check/creation
+ * so that duplication can be avoided with filter.c
+ */
+
+ /* Create the directory that holds personal configuration files, if
+ necessary. */
+ if (create_persconffile_dir(&pf_dir_path) == -1) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Can't create directory\n\"%s\"\nfor language file: %s.", pf_dir_path,
+ g_strerror(errno));
+ g_free(pf_dir_path);
+ return FALSE;
+ }
+
+ rf_path = get_persconffile_path(LANGUAGE_FILE_NAME, FALSE);
+ if ((rf = ws_fopen(rf_path, "w")) == NULL) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Can't open recent file\n\"%s\": %s.", rf_path,
+ g_strerror(errno));
+ g_free(rf_path);
+ return FALSE;
+ }
+ g_free(rf_path);
+
+ fputs("# Language settings file for Wireshark " VERSION ".\n"
+ "#\n"
+ "# This file is regenerated each time Wireshark is quit.\n"
+ "# So be careful, if you want to make manual changes here.\n"
+ "\n", rf);
+
+ fprintf(rf, LANGUAGE_PREF_LANGUAGE ": %s\n", language);
+
+ fclose(rf);
+
+ return TRUE;
+}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/language.h b/ui/language.h
new file mode 100644
index 0000000000..8b94d23f69
--- /dev/null
+++ b/ui/language.h
@@ -0,0 +1,53 @@
+/* language.h
+ *
+ * Copyright 2014, Michal Labedzki for Tieto Corporation
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __LANGUAGE_H__
+#define __LANGUAGE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+extern char *language;
+
+extern void read_language_prefs(void);
+extern int write_language_prefs(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* language.h */
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index 0192d47feb..dc01df4f08 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -280,6 +280,7 @@ endif()
set(WIRESHARK_QT_QRC
../../image/about.qrc
../../image/display_filter.qrc
+ ../../image/languages/languages.qrc
../../image/layout.qrc
../../image/status.qrc
../../image/toolbar.qrc
diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common
index 250aac0ae2..a32ca8bc1c 100644
--- a/ui/qt/Makefile.common
+++ b/ui/qt/Makefile.common
@@ -261,6 +261,7 @@ MOC_SRC = $(MOC_HDRS:.h=.moc.cpp)
QRC_FILES = \
../../image/about.qrc \
../../image/display_filter.qrc \
+ ../../image/languages/languages.qrc \
../../image/layout.qrc \
../../image/status.qrc \
../../image/toolbar.qrc \
diff --git a/ui/qt/Wireshark.pro b/ui/qt/Wireshark.pro
index 9a6f775b93..4c3e4db3a8 100644
--- a/ui/qt/Wireshark.pro
+++ b/ui/qt/Wireshark.pro
@@ -496,6 +496,7 @@ win32 {
RESOURCES += \
../../image/about.qrc \
../../image/display_filter.qrc \
+ ../../image/languages/languages.qrc \
../../image/layout.qrc \
../../image/status.qrc \
../../image/toolbar.qrc \
diff --git a/ui/qt/capture_interfaces_dialog.cpp b/ui/qt/capture_interfaces_dialog.cpp
index 3da8e79a05..34f305174d 100644
--- a/ui/qt/capture_interfaces_dialog.cpp
+++ b/ui/qt/capture_interfaces_dialog.cpp
@@ -851,6 +851,22 @@ void CaptureInterfacesDialog::on_manage_clicked()
}
}
+void CaptureInterfacesDialog::changeEvent(QEvent* event)
+{
+ if (0 != event)
+ {
+ switch (event->type())
+ {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+ }
+ QDialog::changeEvent(event);
+}
+
//
// InterfaceTreeItem
//
diff --git a/ui/qt/capture_interfaces_dialog.h b/ui/qt/capture_interfaces_dialog.h
index f46842d0d3..5ec54d7f6a 100644
--- a/ui/qt/capture_interfaces_dialog.h
+++ b/ui/qt/capture_interfaces_dialog.h
@@ -99,6 +99,7 @@ private slots:
void refreshInterfaceList();
void updateLocalInterfaces();
void on_browseButton_clicked();
+ void changeEvent(QEvent* event);
signals:
void startCapture();
diff --git a/ui/qt/display_filter_edit.cpp b/ui/qt/display_filter_edit.cpp
index ea01dcca14..7d80f76697 100644
--- a/ui/qt/display_filter_edit.cpp
+++ b/ui/qt/display_filter_edit.cpp
@@ -327,6 +327,28 @@ void DisplayFilterEdit::displayFilterSuccess(bool success)
apply_button_->setEnabled(!success);
}
+void DisplayFilterEdit::changeEvent(QEvent* event)
+{
+ if (0 != event)
+ {
+ switch (event->type())
+ {
+ case QEvent::LanguageChange:
+ if (plain_) {
+ empty_filter_message_ = QString(tr("Enter a display filter %1")).
+ arg(UTF8_HORIZONTAL_ELLIPSIS);
+ } else {
+ empty_filter_message_ = QString(tr("Apply a display filter %1 <%2/>"))
+ .arg(UTF8_HORIZONTAL_ELLIPSIS).arg(DEFAULT_MODIFIER);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ SyntaxLineEdit::changeEvent(event);
+}
+
/*
* Editor modelines
*
diff --git a/ui/qt/display_filter_edit.h b/ui/qt/display_filter_edit.h
index 72cde11aa7..896b9da09d 100644
--- a/ui/qt/display_filter_edit.h
+++ b/ui/qt/display_filter_edit.h
@@ -22,6 +22,7 @@
#ifndef DISPLAYFILTEREDIT_H
#define DISPLAYFILTEREDIT_H
+#include <QEvent>
#include <QToolButton>
#include "syntax_line_edit.h"
@@ -45,6 +46,7 @@ private slots:
void checkFilter(const QString &text);
void bookmarkClicked();
void clearFilter();
+ void changeEvent(QEvent* event);
private:
bool plain_;
diff --git a/ui/qt/main.cpp b/ui/qt/main.cpp
index 0db57b1899..d1256f642c 100644
--- a/ui/qt/main.cpp
+++ b/ui/qt/main.cpp
@@ -101,6 +101,7 @@
#endif
#include "ui/console.h"
#include "ui/iface_lists.h"
+#include "ui/language.h"
#include "ui/main_statusbar.h"
#include "ui/persfilepath_opt.h"
#include "ui/recent.h"
@@ -141,7 +142,6 @@
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
#include <QTextCodec>
#endif
-#include <QTranslator>
#include "conversation_dialog.h"
#include "endpoint_dialog.h"
@@ -783,6 +783,13 @@ int main(int argc, char *argv[])
optind = optind_initial;
opterr = 1;
+ // Initialize our language
+ read_language_prefs();
+ locale = QString(language);
+ wsApp->loadLanguage(locale);
+
+ g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", locale.toStdString().c_str());
+
// Init the main window (and splash)
main_w = new(MainWindow);
main_w->show();
@@ -884,45 +891,8 @@ int main(int argc, char *argv[])
}
splash_update(RA_PREFERENCES, NULL, NULL);
- prefs_p = ws_app.readConfigurationFiles (&gdp_path, &dp_path);
- // Initialize our language
-
- /*TODO: Enhance... may be get the locale from the enum gui_qt_language */
- switch(prefs_p->gui_qt_language){
- case 1: /* English */
- locale = "en";
- break;
- case 2: /* French */
- locale = "fr";
- break;
- case 3: /* German */
- locale = "de";
- break;
- case 4: /* Chinese */
- locale = "zh_CN";
- break;
- case 5: /* Polish */
- locale = "pl";
- break;
- case 6: /* Japanese */
- locale = "ja_JP";
- break;
- case 7: /* Italian */
- locale = "it";
- break;
- default: /* Auto-Detect */
- locale = QLocale::system().name();
- break;
- }
- g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Translator %s", locale.toStdString().c_str());
- QTranslator translator;
- translator.load(QString(":/i18n/wireshark_") + locale);
- wsApp->installTranslator(&translator);
-
- QTranslator qtTranslator;
- qtTranslator.load("qt_" + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
- wsApp->installTranslator(&qtTranslator);
+ prefs_p = ws_app.readConfigurationFiles (&gdp_path, &dp_path);
/* Now get our args */
while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
diff --git a/ui/qt/main_welcome.cpp b/ui/qt/main_welcome.cpp
index 7c28bcde57..91c6954106 100644
--- a/ui/qt/main_welcome.cpp
+++ b/ui/qt/main_welcome.cpp
@@ -248,6 +248,22 @@ void MainWelcome::resizeEvent(QResizeEvent *event)
QFrame::resizeEvent(event);
}
+void MainWelcome::changeEvent(QEvent* event)
+{
+ if (0 != event)
+ {
+ switch (event->type())
+ {
+ case QEvent::LanguageChange:
+ welcome_ui_->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+ }
+ QFrame::changeEvent(event);
+}
+
/*
* Editor modelines
*
diff --git a/ui/qt/main_welcome.h b/ui/qt/main_welcome.h
index 4f987eac44..3092c7d5c6 100644
--- a/ui/qt/main_welcome.h
+++ b/ui/qt/main_welcome.h
@@ -67,6 +67,7 @@ private slots:
void interfaceDoubleClicked(QTreeWidgetItem *item, int column);
void updateRecentFiles();
void openRecentItem(QListWidgetItem *item);
+ void changeEvent(QEvent* event);
};
#endif // MAIN_WELCOME_H
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index ccc04a5e32..886b8395a4 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -1765,19 +1765,24 @@ void MainWindow::updateForUnsavedChanges() {
void MainWindow::changeEvent(QEvent* event)
{
- if(0 != event)
+ if (0 != event)
{
- switch(event->type())
+ switch (event->type())
{
- // this event is send if a translator is loaded
case QEvent::LanguageChange:
main_ui_->retranslateUi(this);
break;
+ case QEvent::LocaleChange:{
+ QString locale = QLocale::system().name();
+ locale.truncate(locale.lastIndexOf('_'));
+ wsApp->loadLanguage(locale);
+ }
+ break;
default:
break;
}
}
- QMainWindow::changeEvent(event);
+ QMainWindow::changeEvent(event);
}
/* Update main window items based on whether there's a capture in progress. */
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 64426a8adf..5014dd51c8 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -87,7 +87,7 @@ public:
protected:
bool eventFilter(QObject *obj, QEvent *event);
void keyPressEvent(QKeyEvent *event);
- void closeEvent (QCloseEvent *event);
+ void closeEvent(QCloseEvent *event);
private:
// XXX Move to FilterUtils
diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui
index 59d7c912c6..72f46fba4a 100644
--- a/ui/qt/main_window.ui
+++ b/ui/qt/main_window.ui
@@ -2103,6 +2103,36 @@
<string>Show or hide the packet bytes</string>
</property>
</action>
+ <action name="actionFollow">
+ <property name="text">
+ <string>Follow...</string>
+ </property>
+ </action>
+ <action name="actionSCTP">
+ <property name="text">
+ <string>SCTP</string>
+ </property>
+ </action>
+ <action name="actionApply_as_Filter">
+ <property name="text">
+ <string>Apply as Filter</string>
+ </property>
+ </action>
+ <action name="actionPrepare_a_Filter">
+ <property name="text">
+ <string>Prepare a Filter</string>
+ </property>
+ </action>
+ <action name="actionCopy">
+ <property name="text">
+ <string>Copy</string>
+ </property>
+ </action>
+ <action name="actionBytes">
+ <property name="text">
+ <string>Bytes</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
diff --git a/ui/qt/main_window_preferences_frame.cpp b/ui/qt/main_window_preferences_frame.cpp
index fca0479835..db4f5cabad 100644
--- a/ui/qt/main_window_preferences_frame.cpp
+++ b/ui/qt/main_window_preferences_frame.cpp
@@ -19,10 +19,15 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include "wireshark_application.h"
#include "main_window_preferences_frame.h"
+#include "qt_ui_utils.h"
+
#include "ui_main_window_preferences_frame.h"
+#include "ui/language.h"
#include <epan/prefs-int.h>
+#include <wsutil/filesystem.h>
#include <QFileDialog>
#include <QDebug>
@@ -45,7 +50,6 @@ MainWindowPreferencesFrame::MainWindowPreferencesFrame(QWidget *parent) :
pref_auto_scroll_percentage_ = prefFromPrefPtr(&prefs.gui_auto_scroll_percentage);
pref_toolbar_main_style_ = prefFromPrefPtr(&prefs.gui_toolbar_main_style);
pref_toolbar_filter_style_ = prefFromPrefPtr(&prefs.gui_toolbar_filter_style);
- pref_qt_language_ = prefFromPrefPtr(&prefs.gui_qt_language);
QStyleOption style_opt;
QString indent_ss = QString(
@@ -64,6 +68,44 @@ MainWindowPreferencesFrame::MainWindowPreferencesFrame(QWidget *parent) :
ui->maxFilterLineEdit->setMaximumWidth(num_entry_width);
ui->maxRecentLineEdit->setMaximumWidth(num_entry_width);
ui->autoScrollPercentageLineEdit->setMaximumWidth(num_entry_width);
+
+ QString globalLanguagesPath(QString(get_datafile_dir()) + "/languages/");
+ QString userLanguagesPath(gchar_free_to_qstring(get_persconffile_path("languages/", FALSE)));
+
+
+
+ QStringList filenames = QDir(":/i18n/").entryList(QStringList("wireshark_*.qm"));
+ filenames += QDir(globalLanguagesPath).entryList(QStringList("wireshark_*.qm"));
+ filenames += QDir(userLanguagesPath).entryList(QStringList("wireshark_*.qm"));
+
+ for (int i = 0; i < filenames.size(); i += 1) {
+ QString locale;
+ locale = filenames[i];
+ locale.truncate(locale.lastIndexOf('.'));
+ locale.remove(0, locale.indexOf('_') + 1);
+
+ QString lang = QLocale::languageToString(QLocale(locale).language());
+ QIcon ico = QIcon();
+ if (QFile::exists(QString(":/languages/%1.svg").arg(locale)))
+ ico.addFile(QString(":/languages/%1.svg").arg(locale));
+ if (QFile::exists(globalLanguagesPath + locale + ".svg"))
+ ico.addFile(globalLanguagesPath + locale + ".svg");
+ if (QFile::exists(userLanguagesPath + locale + ".svg"))
+ ico.addFile(userLanguagesPath + locale + ".svg");
+
+ ui->languageComboBox->addItem(ico, lang, locale);
+ }
+
+ ui->languageComboBox->setItemData(0, "auto");
+ ui->languageComboBox->model()->sort(0);
+
+ for (int i = 0; i < ui->languageComboBox->count(); i += 1) {
+ if (QString(language) == ui->languageComboBox->itemData(i).toString()) {
+ ui->languageComboBox->setCurrentIndex(i);
+ break;
+ }
+ }
+
}
MainWindowPreferencesFrame::~MainWindowPreferencesFrame()
@@ -102,7 +144,14 @@ void MainWindowPreferencesFrame::updateWidgets()
ui->mainToolbarComboBox->setCurrentIndex(pref_toolbar_main_style_->stashed_val.enumval);
ui->filterToolbarComboBox->setCurrentIndex(pref_toolbar_filter_style_->stashed_val.enumval);
- ui->languageComboBox->setCurrentIndex(pref_qt_language_->stashed_val.enumval);
+
+ QStringList filenames = QDir(":/i18n/").entryList(QStringList("wireshark_*.qm"));
+ for (int i = 0; i < ui->languageComboBox->count(); i += 1) {
+ if (QString(language) == ui->languageComboBox->itemData(i).toString()) {
+ ui->languageComboBox->setCurrentIndex(i);
+ break;
+ }
+ }
}
void MainWindowPreferencesFrame::on_geometryCheckBox_toggled(bool checked)
@@ -186,7 +235,10 @@ void MainWindowPreferencesFrame::on_filterToolbarComboBox_currentIndexChanged(in
void MainWindowPreferencesFrame::on_languageComboBox_currentIndexChanged(int index)
{
- pref_qt_language_->stashed_val.enumval = index;
+ if (language)
+ delete language;
+
+ language = strdup(ui->languageComboBox->itemData(index).toString().toStdString().c_str());
}
/*
diff --git a/ui/qt/main_window_preferences_frame.h b/ui/qt/main_window_preferences_frame.h
index 178b5dd3ad..a29793dfc7 100644
--- a/ui/qt/main_window_preferences_frame.h
+++ b/ui/qt/main_window_preferences_frame.h
@@ -56,7 +56,6 @@ private:
pref_t *pref_auto_scroll_percentage_;
pref_t *pref_toolbar_main_style_;
pref_t *pref_toolbar_filter_style_;
- pref_t *pref_qt_language_;
void updateWidgets();
private slots:
diff --git a/ui/qt/main_window_preferences_frame.ui b/ui/qt/main_window_preferences_frame.ui
index eeb1517425..043d9924c6 100644
--- a/ui/qt/main_window_preferences_frame.ui
+++ b/ui/qt/main_window_preferences_frame.ui
@@ -312,51 +312,9 @@
</property>
<item>
<property name="text">
- <string>Auto-Detect</string>
+ <string>Auto</string>
</property>
</item>
- <item>
- <property name="text">
- <string>English</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Français</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Deutsch</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Chinese</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Polski</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Japanese</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Italiano</string>
- </property>
- </item>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>You need to restart Wireshark for this change to take effect</string>
- </property>
</widget>
</item>
<item>
@@ -389,7 +347,9 @@
</item>
</layout>
</widget>
- <resources/>
+ <resources>
+ <include location="../../image/languages/languages.qrc"/>
+ </resources>
<connections/>
<buttongroups>
<buttongroup name="openInButtonGroup"/>
diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp
index ea7409aba9..685db9fd04 100644
--- a/ui/qt/packet_list.cpp
+++ b/ui/qt/packet_list.cpp
@@ -235,6 +235,7 @@ PacketList::PacketList(QWidget *parent) :
ctx_column_(-1)
{
QMenu *submenu, *subsubmenu;
+ QAction *action;
setItemsExpandable(false);
setRootIsDecorated(false);
@@ -256,26 +257,36 @@ PacketList::PacketList(QWidget *parent) :
ctx_menu_.addAction(window()->findChild<QAction *>("actionEditPacketComment"));
ctx_menu_.addSeparator();
- submenu = new QMenu(tr("Follow..."));
- ctx_menu_.addMenu(submenu);
+
+ action = window()->findChild<QAction *>("actionFollow");
+ submenu = new QMenu();
+ action->setMenu(submenu);
+ ctx_menu_.addAction(action);
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowTCPStream"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowUDPStream"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowSSLStream"));
+
filter_actions_ << submenu->actions();
- // " <menuitem name='FollowTCPStream' action='/Follow TCP Stream'/>\n"
- // " <menuitem name='FollowUDPStream' action='/Follow UDP Stream'/>\n"
- // " <menuitem name='FollowSSLStream' action='/Follow SSL Stream'/>\n"
- submenu = new QMenu(tr("SCTP"));
+
+ action = window()->findChild<QAction *>("actionSCTP");
+ submenu = new QMenu();
+ action->setMenu(submenu);
+ ctx_menu_.addAction(action);
ctx_menu_.addMenu(submenu);
submenu->addAction(window()->findChild<QAction *>("actionSCTPAnalyseThisAssociation"));
submenu->addAction(window()->findChild<QAction *>("actionSCTPShowAllAssociations"));
submenu->addAction(window()->findChild<QAction *>("actionSCTPFilterThisAssociation"));
filter_actions_ << submenu->actions();
+
ctx_menu_.addSeparator();
+
// " <menuitem name='ManuallyResolveAddress' action='/ManuallyResolveAddress'/>\n"
- ctx_menu_.addSeparator();
- submenu = new QMenu(tr("Apply as Filter"));
- ctx_menu_.addMenu(submenu);
+// ctx_menu_.addSeparator();
+
+ action = window()->findChild<QAction *>("actionApply_as_Filter");
+ submenu = new QMenu();
+ action->setMenu(submenu);
+ ctx_menu_.addAction(action);
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFAndSelected"));
@@ -283,8 +294,11 @@ PacketList::PacketList(QWidget *parent) :
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFAndNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFOrNotSelected"));
filter_actions_ << submenu->actions();
- submenu = new QMenu(tr("Prepare a Filter"));
- ctx_menu_.addMenu(submenu);
+
+ action = window()->findChild<QAction *>("actionPrepare_a_Filter");
+ submenu = new QMenu();
+ action->setMenu(submenu);
+ ctx_menu_.addAction(action);
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFAndSelected"));
@@ -292,7 +306,11 @@ PacketList::PacketList(QWidget *parent) :
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFAndNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFOrNotSelected"));
filter_actions_ << submenu->actions();
- submenu = new QMenu(tr("Colorize with Filter"));
+
+// action = window()->findChild<QAction *>("actionColorize_with_Filter");
+// submenu = new QMenu();
+// action->setMenu(submenu);
+// ctx_menu_.addAction(action);
// " <menu name= 'ConversationFilter' action='/Conversation Filter'>\n"
// " <menuitem name='Ethernet' action='/Conversation Filter/Ethernet'/>\n"
// " <menuitem name='IP' action='/Conversation Filter/IP'/>\n"
@@ -367,20 +385,25 @@ PacketList::PacketList(QWidget *parent) :
// " <menuitem name='FollowUDPStream' action='/Follow UDP Stream'/>\n"
// " <menuitem name='FollowSSLStream' action='/Follow SSL Stream'/>\n"
ctx_menu_.addSeparator();
-// " <menu name= 'Copy' action='/Copy'>\n"
- submenu = new QMenu(tr("Copy"));
- ctx_menu_.addMenu(submenu);
+
+ action = window()->findChild<QAction *>("actionCopy");
+ submenu = new QMenu();
+ action->setMenu(submenu);
+ ctx_menu_.addAction(action);
// " <menuitem name='SummaryTxt' action='/Copy/SummaryTxt'/>\n"
// " <menuitem name='SummaryCSV' action='/Copy/SummaryCSV'/>\n"
submenu->addAction(window()->findChild<QAction *>("actionEditCopyAsFilter"));
filter_actions_ << window()->findChild<QAction *>("actionEditCopyAsFilter");
submenu->addSeparator();
- subsubmenu = new QMenu(tr("Bytes"));
- submenu->addMenu(subsubmenu);
+
+ action = window()->findChild<QAction *>("actionBytes");
+ subsubmenu = new QMenu();
+ action->setMenu(subsubmenu);
+ submenu->addAction(action);
// " <menuitem name='OffsetHexText' action='/Copy/Bytes/OffsetHexText'/>\n"
// " <menuitem name='OffsetHex' action='/Copy/Bytes/OffsetHex'/>\n"
// " <menuitem name='PrintableTextOnly' action='/Copy/Bytes/PrintableTextOnly'/>\n"
- ctx_menu_.addSeparator();
+// ctx_menu_.addSeparator();
// " <menuitem name='HexStream' action='/Copy/Bytes/HexStream'/>\n"
// " <menuitem name='BinaryStream' action='/Copy/Bytes/BinaryStream'/>\n"
ctx_menu_.addSeparator();
diff --git a/ui/qt/preferences_dialog.cpp b/ui/qt/preferences_dialog.cpp
index 663b33b96c..4702c664f1 100644
--- a/ui/qt/preferences_dialog.cpp
+++ b/ui/qt/preferences_dialog.cpp
@@ -31,8 +31,9 @@
#endif /* HAVE_LIBPCAP */
#include <epan/prefs-int.h>
-
+#include <ui/language.h>
#include <ui/preference_utils.h>
+#include <main_window.h>
#include "module_preferences_scroll_area.h"
#include "syntax_line_edit.h"
@@ -797,6 +798,9 @@ void PreferencesDialog::on_buttonBox_accepted()
prefs_main_write();
+ write_language_prefs();
+ wsApp->loadLanguage(QString(language));
+
#ifdef HAVE_AIRPCAP
/*
* Load the Wireshark decryption keys (just set) and save
diff --git a/ui/qt/proto_tree.cpp b/ui/qt/proto_tree.cpp
index 36e597dc5a..ecef518e3b 100644
--- a/ui/qt/proto_tree.cpp
+++ b/ui/qt/proto_tree.cpp
@@ -159,6 +159,7 @@ ProtoTree::ProtoTree(QWidget *parent) :
decode_as_(NULL)
{
QMenu *submenu, *subsubmenu;
+ QAction *action;
setAccessibleName(tr("Packet details"));
setUniformRowHeights(true);
@@ -170,25 +171,32 @@ ProtoTree::ProtoTree(QWidget *parent) :
ctx_menu_.addAction(window()->findChild<QAction *>("actionViewCollapseAll"));
ctx_menu_.addSeparator();
// " <menuitem name='CreateAColumn' action='/Create a Column'/>\n"
- ctx_menu_.addSeparator();
- submenu = new QMenu(tr("Apply as Filter"));
- ctx_menu_.addMenu(submenu);
+ action = window()->findChild<QAction *>("actionApply_as_Filter");
+ submenu = new QMenu();
+ action->setMenu(submenu);
+ ctx_menu_.addAction(action);
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFAndSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFOrSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFAndNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFOrNotSelected"));
- submenu = new QMenu(tr("Prepare a Filter"));
- ctx_menu_.addMenu(submenu);
+
+ action = window()->findChild<QAction *>("actionPrepare_a_Filter");
+ submenu = new QMenu();
+ action->setMenu(submenu);
+ ctx_menu_.addAction(action);
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFAndSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFOrSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFAndNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFOrNotSelected"));
- submenu = new QMenu(tr("Colorize with Filter"));
- ctx_menu_.addMenu(submenu);
+
+// action = window()->findChild<QAction *>("actionColorize_with_Filter");
+// submenu = new QMenu();
+// action->setMenu(submenu);
+// ctx_menu_.addAction(action);
// " <menuitem name='Color1' action='/Colorize with Filter/Color 1'/>\n"
// " <menuitem name='Color2' action='/Colorize with Filter/Color 2'/>\n"
// " <menuitem name='Color3' action='/Colorize with Filter/Color 3'/>\n"
@@ -205,15 +213,21 @@ ProtoTree::ProtoTree(QWidget *parent) :
// " <menuitem name='FollowUDPStream' action='/Follow UDP Stream'/>\n"
// " <menuitem name='FollowSSLStream' action='/Follow SSL Stream'/>\n"
ctx_menu_.addSeparator();
- submenu = new QMenu(tr("Copy"));
- ctx_menu_.addMenu(submenu);
+
+ action = window()->findChild<QAction *>("actionCopy");
+ submenu = new QMenu();
+ action->setMenu(submenu);
+ ctx_menu_.addAction(action);
submenu->addAction(window()->findChild<QAction *>("actionEditCopyDescription"));
submenu->addAction(window()->findChild<QAction *>("actionEditCopyFieldName"));
submenu->addAction(window()->findChild<QAction *>("actionEditCopyValue"));
submenu->addSeparator();
submenu->addAction(window()->findChild<QAction *>("actionEditCopyAsFilter"));
- subsubmenu = new QMenu(tr("Bytes"));
- submenu->addMenu(subsubmenu);
+
+ action = window()->findChild<QAction *>("actionBytes");
+ subsubmenu = new QMenu();
+ action->setMenu(subsubmenu);
+ submenu->addAction(action);
subsubmenu->addSeparator();
// " <menu name= 'Bytes' action='/Copy/Bytes'>\n"
// " <menuitem name='OffsetHexText' action='/Copy/Bytes/OffsetHexText'/>\n"
@@ -225,12 +239,12 @@ ProtoTree::ProtoTree(QWidget *parent) :
// " </menu>\n"
// " </menu>\n"
// " <menuitem name='ExportSelectedPacketBytes' action='/ExportSelectedPacketBytes'/>\n"
- ctx_menu_.addSeparator();
+// ctx_menu_.addSeparator();
// " <menuitem name='WikiProtocolPage' action='/WikiProtocolPage'/>\n"
// " <menuitem name='FilterFieldReference' action='/FilterFieldReference'/>\n"
// " <menuitem name='ProtocolHelp' action='/ProtocolHelp'/>\n"
// " <menuitem name='ProtocolPreferences' action='/ProtocolPreferences'/>\n"
- ctx_menu_.addSeparator();
+// ctx_menu_.addSeparator();
decode_as_ = window()->findChild<QAction *>("actionAnalyzeDecodeAs");
ctx_menu_.addAction(decode_as_);
// " <menuitem name='DisableProtocol' action='/DisableProtocol'/>\n"
diff --git a/ui/qt/proto_tree.h b/ui/qt/proto_tree.h
index 6f7bd0d678..54d081bd4d 100644
--- a/ui/qt/proto_tree.h
+++ b/ui/qt/proto_tree.h
@@ -44,9 +44,9 @@ protected:
void contextMenuEvent(QContextMenuEvent *event);
private:
- QMenu ctx_menu_;
- QAction *decode_as_;
- QFont mono_font_;
+ QMenu ctx_menu_;
+ QAction *decode_as_;
+ QFont mono_font_;
signals:
void protoItemSelected(QString &);
diff --git a/ui/qt/search_frame.cpp b/ui/qt/search_frame.cpp
index ca37afb54d..68f22d76f9 100644
--- a/ui/qt/search_frame.cpp
+++ b/ui/qt/search_frame.cpp
@@ -340,6 +340,22 @@ void SearchFrame::on_cancelButton_clicked()
animatedHide();
}
+void SearchFrame::changeEvent(QEvent* event)
+{
+ if (0 != event)
+ {
+ switch (event->type())
+ {
+ case QEvent::LanguageChange:
+ sf_ui_->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+ }
+ AccordionFrame::changeEvent(event);
+}
+
/*
* Editor modelines
*
diff --git a/ui/qt/search_frame.h b/ui/qt/search_frame.h
index a45d055076..f8c91a31ba 100644
--- a/ui/qt/search_frame.h
+++ b/ui/qt/search_frame.h
@@ -61,12 +61,10 @@ private:
private slots:
void on_searchTypeComboBox_currentIndexChanged(int index);
-
void on_searchLineEdit_textChanged(const QString &search_string);
-
void on_findButton_clicked();
-
void on_cancelButton_clicked();
+ void changeEvent(QEvent* event);
};
#endif // SEARCH_FRAME_H
diff --git a/ui/qt/summary_dialog.cpp b/ui/qt/summary_dialog.cpp
index bc6f73ff0e..36b82f4707 100644
--- a/ui/qt/summary_dialog.cpp
+++ b/ui/qt/summary_dialog.cpp
@@ -744,6 +744,22 @@ SummaryDialog::~SummaryDialog()
delete ui;
}
+void SummaryDialog::changeEvent(QEvent* event)
+{
+ if (0 != event)
+ {
+ switch (event->type())
+ {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+ }
+ QDialog::changeEvent(event);
+}
+
/*
* Editor modelines
diff --git a/ui/qt/summary_dialog.h b/ui/qt/summary_dialog.h
index 6c5f667c6d..5d13990d1a 100644
--- a/ui/qt/summary_dialog.h
+++ b/ui/qt/summary_dialog.h
@@ -73,6 +73,7 @@ protected slots:
void HelpButton();
void CopyComment();
void on_tabWidget_currentChanged(int index);
+ void changeEvent(QEvent* event);
private:
diff --git a/ui/qt/wireshark_application.cpp b/ui/qt/wireshark_application.cpp
index 1362ca7f6b..a4f3595438 100644
--- a/ui/qt/wireshark_application.cpp
+++ b/ui/qt/wireshark_application.cpp
@@ -61,6 +61,8 @@
#include <QEvent>
#include <QFileOpenEvent>
#include <QFontMetrics>
+#include <QLibraryInfo>
+#include <QLocale>
#include <QMutableListIterator>
#include <QTimer>
#include <QUrl>
@@ -570,6 +572,7 @@ WiresharkApplication::WiresharkApplication(int &argc, char **argv) :
Q_INIT_RESOURCE(status);
Q_INIT_RESOURCE(toolbar);
Q_INIT_RESOURCE(wsicon);
+ Q_INIT_RESOURCE(languages);
#ifdef Q_OS_WIN
/* RichEd20.DLL is needed for native file dialog filter entries. */
@@ -866,6 +869,43 @@ void WiresharkApplication::addRecentItem(const QString &filename, qint64 size, b
itemStatusFinished(filename, size, accessible);
}
+static void switchTranslator(QTranslator& myTranslator, const QString& filename,
+ const QString& searchPath)
+{
+ wsApp->removeTranslator(&myTranslator);
+
+ if (myTranslator.load(filename, searchPath))
+ wsApp->installTranslator(&myTranslator);
+}
+
+void WiresharkApplication::loadLanguage(const QString& newLanguage)
+{
+ QLocale locale;
+ QString localeLanguage;
+
+ if (newLanguage.isEmpty() || newLanguage == "auto") {
+ localeLanguage = QLocale::system().name();
+ } else {
+ localeLanguage = newLanguage;
+ }
+
+ locale = QLocale(localeLanguage);
+ QLocale::setDefault(locale);
+ switchTranslator(wsApp->translator,
+ QString("wireshark_%1.qm").arg(localeLanguage), QString(":/i18n/"));
+ if (QFile::exists(QString("%1/%2/wireshark_%3.qm")
+ .arg(get_datafile_dir()).arg("languages").arg(localeLanguage)))
+ switchTranslator(wsApp->translator,
+ QString("wireshark_%1.qm").arg(localeLanguage), QString(get_datafile_dir()) + QString("/languages"));
+ if (QFile::exists(QString("%1/wireshark_%3.qm")
+ .arg(gchar_free_to_qstring(get_persconffile_path("languages", FALSE))).arg(localeLanguage)))
+ switchTranslator(wsApp->translator,
+ QString("wireshark_%1.qm").arg(localeLanguage), gchar_free_to_qstring(get_persconffile_path("languages", FALSE)));
+ switchTranslator(wsApp->translatorQt,
+ QString("qt_%1.qm").arg(localeLanguage),
+ QLibraryInfo::location(QLibraryInfo::TranslationsPath));
+}
+
/*
* Editor modelines
*
diff --git a/ui/qt/wireshark_application.h b/ui/qt/wireshark_application.h
index a56d6c6c7f..a6764cf137 100644
--- a/ui/qt/wireshark_application.h
+++ b/ui/qt/wireshark_application.h
@@ -43,6 +43,8 @@
#include <QSocketNotifier>
#include <QThread>
#include <QTimer>
+#include <QTranslator>
+
// Recent items:
// - Read from prefs
@@ -93,6 +95,10 @@ public:
const QIcon &normalIcon() const { return normal_icon_; }
const QIcon &captureIcon() const { return capture_icon_; }
+ QTranslator translator;
+ QTranslator translatorQt;
+ void loadLanguage(const QString& language);
+
private:
bool initialized_;
QFont mono_font_;