diff --git a/CMakeLists.txt b/CMakeLists.txt
index 48b4e1b..40cc03b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,6 +9,8 @@ set(CMAKE_MODULE_PATH ${GPUI_SOURCE_DIR}/cmake)
set(GPUI_DIR "${CMAKE_BINARY_DIR}")
+include(TranslationUtils)
+
if(UNIX)
include(GNUInstallDirs)
else()
diff --git a/cmake/TranslationUtils.cmake b/cmake/TranslationUtils.cmake
new file mode 100644
index 0000000..507575c
--- /dev/null
+++ b/cmake/TranslationUtils.cmake
@@ -0,0 +1,13 @@
+function(add_translation_resource out_file)
+ set(qm_files ${ARGN})
+ set(resource ${CMAKE_CURRENT_SOURCE_DIR}/translations.qrc)
+
+ file(WRITE ${resource} "\n \n")
+ foreach(LANG ${qm_files})
+ get_filename_component(file_name ${LANG} NAME)
+ file(APPEND ${resource} " ${file_name}\n")
+ endforeach()
+ file(APPEND ${resource} " \n\n")
+
+ set(${out_file} ${resource} PARENT_SCOPE)
+endfunction()
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 058d5c0..56896ea 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -1,4 +1,4 @@
-find_package(Qt5 COMPONENTS Widgets Qml REQUIRED)
+find_package(Qt5 COMPONENTS Widgets Qml LinguistTools REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
@@ -45,6 +45,15 @@ set(MOC_HEADERS
smbfilebrowser.h
)
+set(TS_FILES
+ i18n/gui_en.ts
+ i18n/gui_ru.ts
+)
+
+set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_SOURCE_DIR})
+
+qt5_add_translation(QM_FILES ${TS_FILES})
+
qt5_wrap_ui(UI_SOURCES ${UI_FORMS})
qt5_wrap_cpp(MOC_SOURCES ${MOC_HEADERS})
@@ -52,7 +61,11 @@ add_definitions(
-DGPUI_GUI_LIBRARY
)
-add_gpui_library(gpui-gui ${UI_SOURCES} ${MOC_SOURCES} ${SOURCES})
+add_translation_resource(RESOURCES_SRC ${QM_FILES})
+
+qt5_add_resources(LIB_RESOURCES ${RESOURCES_SRC})
+
+add_gpui_library(gpui-gui ${UI_SOURCES} ${MOC_SOURCES} ${SOURCES} ${LIB_RESOURCES})
target_link_libraries(gpui-gui Qt5::Widgets Qt5::Qml)
target_link_libraries(gpui-gui gpui-model gpui-io)
diff --git a/src/gui/commandlineparser.cpp b/src/gui/commandlineparser.cpp
index 7020edb..56ea4db 100644
--- a/src/gui/commandlineparser.cpp
+++ b/src/gui/commandlineparser.cpp
@@ -54,8 +54,8 @@ CommandLineParser::~CommandLineParser()
CommandLineParser::CommandLineParseResult CommandLineParser::parseCommandLine(CommandLineOptions *options, QString *errorMessage)
{
- const QCommandLineOption pathOption("p", "The full path of policy to edit.", "path");
- const QCommandLineOption bundleOption("b", "The full path of policy bundle to load.", "path");
+ const QCommandLineOption pathOption("p", QObject::tr("The full path of policy to edit."), QObject::tr("path"));
+ const QCommandLineOption bundleOption("b", QObject::tr("The full path of policy bundle to load."), QObject::tr("path"));
d->parser->setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
d->parser->addOption(pathOption);
diff --git a/src/gui/contentwidget.cpp b/src/gui/contentwidget.cpp
index b5bedc7..169516c 100644
--- a/src/gui/contentwidget.cpp
+++ b/src/gui/contentwidget.cpp
@@ -144,6 +144,11 @@ void ContentWidget::setPolicyWidgetState(ContentWidget::PolicyWidgetState state)
}
}
+void ContentWidget::onLanguageChaged()
+{
+ ui->retranslateUi(this);
+}
+
void ContentWidget::onListItemClicked(const QModelIndex &index)
{
d->currentIndex = index;
@@ -153,8 +158,8 @@ void ContentWidget::onListItemClicked(const QModelIndex &index)
if (d->commandGroup.canExecute() && !d->cancelFlag)
{
QMessageBox::StandardButton reply;
- reply = QMessageBox::question(this, "Save settings dialog",
- "Policy settings were modified do you want to save them?",
+ reply = QMessageBox::question(this, QObject::tr("Save settings dialog"),
+ QObject::tr("Policy settings were modified do you want to save them?"),
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes)
{
diff --git a/src/gui/contentwidget.h b/src/gui/contentwidget.h
index 0552d3e..54b9649 100644
--- a/src/gui/contentwidget.h
+++ b/src/gui/contentwidget.h
@@ -61,6 +61,8 @@ namespace gpui {
void setPolicyWidgetState(PolicyWidgetState state);
+ void onLanguageChaged();
+
signals:
void modelItemSelected(const QModelIndex& index);
void savePolicyChanges();
diff --git a/src/gui/i18n/gui_en.ts b/src/gui/i18n/gui_en.ts
new file mode 100644
index 0000000..2ccd1c4
--- /dev/null
+++ b/src/gui/i18n/gui_en.ts
@@ -0,0 +1,356 @@
+
+
+
+
+ ContentWidget
+
+
+ Form
+ Form
+
+
+
+ Local Policies
+ Local Policies
+
+
+
+ Policy State
+ Policy State
+
+
+
+ Not Configured
+ Not Configured
+
+
+
+ Enabled
+ Enabled
+
+
+
+ Disabled
+ Disabled
+
+
+
+ Help:
+ Help:
+
+
+
+ Supported on:
+ Supported on:
+
+
+
+ MainWindow
+
+
+ MainWindow
+ MainWindow
+
+
+
+ &File
+ &File
+
+
+
+ &Action
+ &Action
+
+
+
+ &View
+ &View
+
+
+
+ &Help
+ &Help
+
+
+
+ toolBar
+ toolBar
+
+
+
+ Go &Back
+ Go &Back
+
+
+
+ Go Back
+ Go Back
+
+
+
+ Alt+Left
+ Alt+Left
+
+
+
+ Go &Forward
+ Go &Forward
+
+
+
+ Go Forward
+ Go Forward
+
+
+
+ Alt+Right
+ Alt+Right
+
+
+
+ Go &Up
+ Go &Up
+
+
+
+ Go Up
+ Go Up
+
+
+
+ Alt+Up
+ Alt+Up
+
+
+
+ &Reload
+ &Reload
+
+
+
+ Reload
+ Reload
+
+
+
+
+ Ctrl+R
+ Ctrl+R
+
+
+
+ &Small Icon View
+ &Small Icon View
+
+
+
+ Small Icon View
+ Small Icon View
+
+
+
+ &Large Icon View
+ &Large Icon View
+
+
+
+ Large Icon View
+ Large Icon View
+
+
+
+ &Compact List View
+ &Compact List View
+
+
+
+ Compact List View
+ Compact List View
+
+
+
+ &Options
+ &Options
+
+
+
+ Options
+ Options
+
+
+
+ &Exit
+ &Exit
+
+
+
+ Exit
+ Exit
+
+
+
+ &Add/Remove Columns
+ &Add/Remove Columns
+
+
+
+ Add/Remove Columns
+ Add/Remove Columns
+
+
+
+ Ctrl+A
+ Ctrl+A
+
+
+
+ &Detailed List View
+ &Detailed List View
+
+
+
+ Detailed List View
+ Detailed List View
+
+
+
+ &Select DC
+ &Select DC
+
+
+
+ Select Domain Controller
+ Select Domain Controller
+
+
+
+ &Customize
+ &Customize
+
+
+
+ Customize
+ Customize
+
+
+
+ Open &Policy Directory
+ Open &Policy Directory
+
+
+
+ Ctrl+O
+ Ctrl+O
+
+
+
+ Open &User Registry Source
+ Open &User Registry Source
+
+
+
+ &Save Registry Source
+ &Save Registry Source
+
+
+
+ Ctrl+S
+ Ctrl+S
+
+
+
+ Open &Machine Registry Source
+ Open &Machine Registry Source
+
+
+
+ &Language
+ &Language
+
+
+
+ QObject
+
+
+ The full path of policy to edit.
+ The full path of policy to edit.
+
+
+
+
+ path
+ path
+
+
+
+ The full path of policy bundle to load.
+ The full path of policy bundle to load.
+
+
+
+ Save settings dialog
+ Save settings dialog
+
+
+
+ Policy settings were modified do you want to save them?
+ Policy settings were modified do you want to save them?
+
+
+
+ Description:
+ Description:
+
+
+
+ Options:
+ Options:
+
+
+
+ Machine
+ Machine
+
+
+
+ Machine level policies
+ Machine level policies
+
+
+
+ User
+ User
+
+
+
+ User level policies
+ User level policies
+
+
+
+ SmbFileBrowser
+
+
+ Dialog
+ Dialog
+
+
+
+ back
+ back
+
+
+
+ Up
+ Up
+
+
+
+ gpui::MainWindow
+
+
+ Open Directory
+ Open Directory
+
+
+
diff --git a/src/gui/i18n/gui_ru.ts b/src/gui/i18n/gui_ru.ts
new file mode 100644
index 0000000..7c524a5
--- /dev/null
+++ b/src/gui/i18n/gui_ru.ts
@@ -0,0 +1,356 @@
+
+
+
+
+ ContentWidget
+
+
+ Form
+ Форма
+
+
+
+ Local Policies
+ Локальные политики
+
+
+
+ Policy State
+ Состояние политики
+
+
+
+ Not Configured
+ Не настроено
+
+
+
+ Enabled
+ Включено
+
+
+
+ Disabled
+ Выключено
+
+
+
+ Help:
+ Помощь:
+
+
+
+ Supported on:
+ Поддерживается на:
+
+
+
+ MainWindow
+
+
+ MainWindow
+ Главное окно
+
+
+
+ &File
+ &Файл
+
+
+
+ &Action
+ &Действие
+
+
+
+ &View
+ &Вид
+
+
+
+ &Help
+ &Помощь
+
+
+
+ toolBar
+ панель инструментов
+
+
+
+ Go &Back
+ &Назад
+
+
+
+ Go Back
+ Назад
+
+
+
+ Alt+Left
+ Alt+Left
+
+
+
+ Go &Forward
+ &Вперёд
+
+
+
+ Go Forward
+ Вперёд
+
+
+
+ Alt+Right
+ Alt+Right
+
+
+
+ Go &Up
+ &Вверх
+
+
+
+ Go Up
+ Вверх
+
+
+
+ Alt+Up
+ Alt+Up
+
+
+
+ &Reload
+ &Обновить
+
+
+
+ Reload
+ Обновить
+
+
+
+
+ Ctrl+R
+ Ctrl+R
+
+
+
+ &Small Icon View
+ &Маленькие иконки
+
+
+
+ Small Icon View
+ Маленькие иконки
+
+
+
+ &Large Icon View
+ &Большие иконки
+
+
+
+ Large Icon View
+ Большие иконки
+
+
+
+ &Compact List View
+ &Компактный список
+
+
+
+ Compact List View
+ Компактный список
+
+
+
+ &Options
+ &Настройки
+
+
+
+ Options
+ Настройки
+
+
+
+ &Exit
+ &Выход
+
+
+
+ Exit
+ Выход
+
+
+
+ &Add/Remove Columns
+ &Добавить/Удалить колонки
+
+
+
+ Add/Remove Columns
+ Добавить/Удалить колонки
+
+
+
+ Ctrl+A
+ Ctrl+A
+
+
+
+ &Detailed List View
+ &Детальный список
+
+
+
+ Detailed List View
+ Детальный список
+
+
+
+ &Select DC
+ &Выберите контролер домена
+
+
+
+ Select Domain Controller
+ Выберите контролер домена
+
+
+
+ &Customize
+ &Настроить
+
+
+
+ Customize
+ Настроить
+
+
+
+ Open &Policy Directory
+ &Открыть папку с ADMX файлами
+
+
+
+ Ctrl+O
+ Ctrl+O
+
+
+
+ Open &User Registry Source
+ &Открыть пользовательский POL файл
+
+
+
+ &Save Registry Source
+ &Сохранить настройки
+
+
+
+ Ctrl+S
+ Ctrl+S
+
+
+
+ Open &Machine Registry Source
+ &Открыть машинный POL файл
+
+
+
+ &Language
+ &Язык
+
+
+
+ QObject
+
+
+ The full path of policy to edit.
+ Полный путь для редактируемой политики.
+
+
+
+
+ path
+ путь
+
+
+
+ The full path of policy bundle to load.
+ Полный путь к набору ADMX файлов.
+
+
+
+ Save settings dialog
+ Состояние настроек
+
+
+
+ Policy settings were modified do you want to save them?
+ Настройки политки были изменены, хотите сохранить их?
+
+
+
+ Description:
+ Описание:
+
+
+
+ Options:
+ Опции:
+
+
+
+ Machine
+ Компьютер
+
+
+
+ Machine level policies
+ Политики настройки компьютера
+
+
+
+ User
+ Пользователь
+
+
+
+ User level policies
+ Политики настройки пользователей
+
+
+
+ SmbFileBrowser
+
+
+ Dialog
+ Диалог
+
+
+
+ back
+ Назад
+
+
+
+ Up
+ Вверх
+
+
+
+ gpui::MainWindow
+
+
+ Open Directory
+ Открыть папку
+
+
+
diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp
index 8671d95..eb055fe 100644
--- a/src/gui/mainwindow.cpp
+++ b/src/gui/mainwindow.cpp
@@ -41,6 +41,11 @@
#include
+void registerResources()
+{
+ Q_INIT_RESOURCE(translations);
+}
+
namespace gpui {
class MainWindowPrivate {
@@ -59,6 +64,11 @@ public:
std::unique_ptr sortModel = nullptr;
+ std::vector> translators;
+ QString localeName;
+
+ CommandLineOptions options;
+
MainWindowPrivate()
: userRegistry(new model::registry::Registry())
, userRegistrySource(new model::registry::PolRegistrySource(userRegistry))
@@ -129,8 +139,21 @@ MainWindow::MainWindow(CommandLineOptions &options, QWidget *parent)
, d(new MainWindowPrivate())
, ui(new Ui::MainWindow())
{
+ registerResources();
+
+ QLocale locale;
+ std::unique_ptr qtTranslator = std::make_unique();
+ qtTranslator->load(locale, "gui", "_", ":/");
+ QCoreApplication::installTranslator(qtTranslator.get());
+ d->translators.push_back(std::move(qtTranslator));
+ d->localeName = locale.name().replace("_", "-");
+
+ d->options = options;
+
ui->setupUi(this);
+ createLanguageMenu();
+
d->contentWidget = new ContentWidget(this);
d->contentWidget->setMachineRegistrySource(d->machineRegistrySource.get());
d->contentWidget->setUserRegistrySource(d->userRegistrySource.get());
@@ -146,15 +169,17 @@ MainWindow::MainWindow(CommandLineOptions &options, QWidget *parent)
connect(ui->actionSaveRegistrySource, &QAction::triggered, this, &MainWindow::onRegistrySourceSave);
connect(ui->treeView, &QTreeView::clicked, d->contentWidget, &ContentWidget::modelItemSelected);
- if (!options.policyBundle.isEmpty())
+ if (d->options.policyBundle.isEmpty())
{
- loadPolicyBundleFolder(options.policyBundle);
+ d->options.policyBundle = "/usr/share/PolicyDefinitions";
}
- if (!options.path.isEmpty())
+ loadPolicyBundleFolder(d->options.policyBundle, d->localeName);
+
+ if (!d->options.path.isEmpty())
{
- d->userRegistryPath = options.path + "/User/Registry.pol";
- d->machineRegistryPath = options.path + "/Machine/Registry.pol";
+ d->userRegistryPath = d->options.path + "/User/Registry.pol";
+ d->machineRegistryPath = d->options.path + "/Machine/Registry.pol";
onPolFileOpen(d->userRegistryPath, d->userRegistry, d->userRegistrySource,
[&](model::registry::AbstractRegistrySource* source)
@@ -186,10 +211,10 @@ void MainWindow::closeEvent(QCloseEvent *event)
QMainWindow::closeEvent(event);
}
-void gpui::MainWindow::loadPolicyBundleFolder(const QString& path)
+void gpui::MainWindow::loadPolicyBundleFolder(const QString& path, const QString &locale)
{
auto bundle = std::make_unique();
- d->model = bundle->loadFolder(path.toStdString(), "ru-ru");
+ d->model = bundle->loadFolder(path.toStdString(), locale.toStdString());
d->sortModel = std::make_unique();
d->sortModel->setSourceModel(d->model.get());
@@ -205,13 +230,13 @@ void gpui::MainWindow::loadPolicyBundleFolder(const QString& path)
void MainWindow::onDirectoryOpen()
{
- QString directory = QFileDialog::getExistingDirectory(
- this,
- tr("Open Directory"),
- QDir::homePath(),
- QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+ d->options.policyBundle = QFileDialog::getExistingDirectory(
+ this,
+ tr("Open Directory"),
+ QDir::homePath(),
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
- loadPolicyBundleFolder(directory);
+ loadPolicyBundleFolder(d->options.policyBundle, d->localeName);
}
void MainWindow::onUserRegistrySourceOpen()
@@ -260,6 +285,34 @@ void MainWindow::on_actionExit_triggered()
QApplication::quit();
}
+void MainWindow::onLanguageChanged(QAction *action)
+{
+ for (const auto& translator : d->translators)
+ {
+ qApp->removeTranslator(translator.get());
+ }
+ d->translators.clear();
+
+ QString language = action->data().toString();
+
+ std::unique_ptr qtTranslator = std::make_unique();
+ bool loadResult = qtTranslator->load("gui_" + language + ".qm", ":/");
+ QCoreApplication::installTranslator(qtTranslator.get());
+ d->translators.push_back(std::move(qtTranslator));
+ qWarning() << "Load language " << language << loadResult;
+
+ QLocale locale(language);
+
+ d->localeName = locale.name().replace("_", "-");
+
+ loadPolicyBundleFolder(d->options.policyBundle, d->localeName);
+
+ d->contentWidget->onLanguageChaged();
+ ui->retranslateUi(this);
+
+ ui->treeView->selectionModel()->clearSelection();
+}
+
void MainWindow::onRegistrySourceOpen(std::shared_ptr& registry,
std::unique_ptr& source,
std::function callback)
@@ -325,4 +378,39 @@ void MainWindow::onPolFileOpen(const QString &path,
}
}
+void MainWindow::createLanguageMenu()
+{
+ QActionGroup* langGroup = new QActionGroup(this);
+ langGroup->setExclusive(true);
+
+ connect(langGroup, &QActionGroup::triggered, this, &MainWindow::onLanguageChanged);
+
+ QString defaultLocale = QLocale::system().name().left(QLocale::system().name().lastIndexOf('_'));
+ QDir dir(":/");
+ QStringList fileNames = dir.entryList(QStringList("gui_*.qm"));
+
+ QMenu* menu = new QMenu(this);
+ ui->actionLanguage->setMenu(menu);
+
+ for (QString locale : fileNames)
+ {
+ locale.truncate(locale.lastIndexOf('.'));
+ locale.remove(0, locale.lastIndexOf('_') + 1);
+
+ QString language = QLocale::languageToString(QLocale(locale).language());
+
+ QAction *action = new QAction(language, this);
+ action->setCheckable(true);
+ action->setData(locale);
+
+ menu->addAction(action);
+ langGroup->addAction(action);
+
+ if (defaultLocale == locale)
+ {
+ action->setChecked(true);
+ }
+ }
+}
+
}
diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h
index 86bb88b..1380428 100644
--- a/src/gui/mainwindow.h
+++ b/src/gui/mainwindow.h
@@ -66,6 +66,8 @@ namespace gpui {
void on_actionExit_triggered();
+ void onLanguageChanged(QAction *action);
+
private:
void onRegistrySourceOpen(std::shared_ptr& registry,
std::unique_ptr& source,
@@ -76,7 +78,9 @@ namespace gpui {
std::unique_ptr& source,
std::function callback);
- void loadPolicyBundleFolder(const QString& path);
+ void loadPolicyBundleFolder(const QString& path, const QString& locale);
+
+ void createLanguageMenu();
};
}
diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui
index ebcb801..329c22a 100644
--- a/src/gui/mainwindow.ui
+++ b/src/gui/mainwindow.ui
@@ -100,6 +100,7 @@
+
diff --git a/src/gui/presentationbuilder.cpp b/src/gui/presentationbuilder.cpp
index db9a67e..8ab14ca 100644
--- a/src/gui/presentationbuilder.cpp
+++ b/src/gui/presentationbuilder.cpp
@@ -87,8 +87,8 @@ namespace gui
QHBoxLayout* createCaptions()
{
QHBoxLayout* horizontalLayout = new QHBoxLayout();
- QLabel* descriptionLabel = new QLabel("Description:");
- QLabel* optionLabel = new QLabel("Options:");
+ QLabel* descriptionLabel = new QLabel(QObject::tr("Description:"));
+ QLabel* optionLabel = new QLabel(QObject::tr("Options:"));
horizontalLayout->addWidget(descriptionLabel);
horizontalLayout->addWidget(optionLabel);
return horizontalLayout;
@@ -200,9 +200,26 @@ namespace gui
virtual void visit(ListBox &widget) const override
{
- QListWidget* listWidget = new QListWidget();
+ QListWidget* listBox = new QListWidget();
- QLayoutItem* container = createAndAttachLabel(listWidget, QString::fromStdString(widget.label));
+ QLayoutItem* container = createAndAttachLabel(listBox, QString::fromStdString(widget.label));
+
+ if (m_policy && m_source)
+ {
+ std::pair keyValuePair = findKeyAndValueName();
+
+ if (m_source->isValuePresent(keyValuePair.first, keyValuePair.second))
+ {
+ QString items = m_source->getValue(keyValuePair.first, keyValuePair.second).value();
+ listBox->addItems(items.split('\0', QString::SplitBehavior::SkipEmptyParts));
+ }
+
+ listBox->connect(listBox, &QListWidget::itemChanged, [=](QListWidgetItem *item) {
+ createCommand([=](){
+ QString items = m_source->getValue(keyValuePair.first, keyValuePair.second).value();
+ });
+ });
+ }
addToLayout(container);
}
diff --git a/src/gui/translations.qrc b/src/gui/translations.qrc
new file mode 100644
index 0000000..364ad03
--- /dev/null
+++ b/src/gui/translations.qrc
@@ -0,0 +1,6 @@
+
+
+ gui_en.qm
+ gui_ru.qm
+
+
diff --git a/src/model/bundle/policybundle.cpp b/src/model/bundle/policybundle.cpp
index 4dd5a08..4db4243 100644
--- a/src/model/bundle/policybundle.cpp
+++ b/src/model/bundle/policybundle.cpp
@@ -88,8 +88,8 @@ std::unique_ptr PolicyBundle::loadFolder(const std::string&
QStandardItem* rootItem = d->treeModel->invisibleRootItem();
- d->rootMachineItem = createItem("Machine", "folder", "Machine level policies");
- d->rootUserItem = createItem("User", "folder", "User level policies");
+ d->rootMachineItem = createItem(QObject::tr("Machine"), "folder", QObject::tr("Machine level policies"));
+ d->rootUserItem = createItem(QObject::tr("User"), "folder", QObject::tr("User level policies"));
rootItem->appendRow(d->rootMachineItem);
rootItem->appendRow(d->rootUserItem);