From 98036249fb304b47eec236df30e72c0faac69365 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Sun, 4 Feb 2024 15:13:46 -0500 Subject: [PATCH] armoury: Support localization --- armoury/src/cmpeditor.cpp | 3 +- armoury/src/fullmodelviewer.cpp | 53 +++++++++++++++++---------------- armoury/src/gearlistmodel.cpp | 3 +- armoury/src/gearlistwidget.cpp | 3 +- armoury/src/gearview.cpp | 1 + armoury/src/main.cpp | 6 ++-- armoury/src/mainwindow.cpp | 19 ++++++------ armoury/src/singlegearview.cpp | 23 +++++++------- 8 files changed, 60 insertions(+), 51 deletions(-) diff --git a/armoury/src/cmpeditor.cpp b/armoury/src/cmpeditor.cpp index 956521e..1ae8cd0 100644 --- a/armoury/src/cmpeditor.cpp +++ b/armoury/src/cmpeditor.cpp @@ -2,11 +2,12 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "cmpeditor.h" +#include CmpEditor::CmpEditor(GameData *data, QWidget *parent) : CmpPart(data, parent) { - setWindowTitle(QStringLiteral("CMP Editor")); + setWindowTitle(i18nc("@title:window CMP is an abbreviation", "CMP Editor")); load(physis_gamedata_extract_file(data, "chara/xls/charamake/human.cmp")); } diff --git a/armoury/src/fullmodelviewer.cpp b/armoury/src/fullmodelviewer.cpp index 1c8886f..240c06c 100644 --- a/armoury/src/fullmodelviewer.cpp +++ b/armoury/src/fullmodelviewer.cpp @@ -5,6 +5,7 @@ #include "boneeditor.h" #include "magic_enum.hpp" +#include #include #include #include @@ -17,7 +18,7 @@ FullModelViewer::FullModelViewer(GameData *data, FileCache &cache, QWidget *pare : QMainWindow(parent) , data(data) { - setWindowTitle(QStringLiteral("Full Model Viewer")); + setWindowTitle(i18nc("@title:window", "Full Model Viewer")); setMinimumWidth(1280); setMinimumHeight(720); setAttribute(Qt::WA_DeleteOnClose, false); @@ -28,13 +29,15 @@ FullModelViewer::FullModelViewer(GameData *data, FileCache &cache, QWidget *pare auto layout = new QVBoxLayout(); dummyWidget->setLayout(layout); - auto fileMenu = menuBar()->addMenu(QStringLiteral("File")); + auto fileMenu = menuBar()->addMenu(i18nc("@title:menu", "File")); - auto datOpenAction = fileMenu->addAction(QStringLiteral("Load character DAT...")); + auto datOpenAction = fileMenu->addAction(i18nc("@action:inmenu DAT is an abbreviation", "Load Character DAT...")); datOpenAction->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); connect(datOpenAction, &QAction::triggered, [this] { - auto fileName = - QFileDialog::getOpenFileName(nullptr, QStringLiteral("Open DAT File"), QStringLiteral("~"), QStringLiteral("FFXIV Character DAT File (*.dat)")); + auto fileName = QFileDialog::getOpenFileName(nullptr, + i18nc("@title:window DAT is an abbreviation", "Open DAT File"), + QStringLiteral("~"), + i18nc("DAT is an abbreviation", "FFXIV Character DAT File (*.dat)")); auto buffer = physis_read_file(fileName.toStdString().c_str()); @@ -72,7 +75,7 @@ FullModelViewer::FullModelViewer(GameData *data, FileCache &cache, QWidget *pare const float scale = (float)position / 100.0f; updateHeightScaling(scale); }); - characterEditorLayout->addRow(QStringLiteral("Height"), characterHeight); + characterEditorLayout->addRow(i18nc("@label:slider Character height", "Height"), characterHeight); auto bustSize = new QSlider(); bustSize->setOrientation(Qt::Horizontal); @@ -81,7 +84,7 @@ FullModelViewer::FullModelViewer(GameData *data, FileCache &cache, QWidget *pare const float scale = (float)position / 100.0f; updateBustScaling(scale); }); - characterEditorLayout->addRow(QStringLiteral("Bust Size"), bustSize); + characterEditorLayout->addRow(i18nc("@label:slider Character breast size", "Bust Size"), bustSize); characterEditorLayout->addWidget(addFaceGroup()); characterEditorLayout->addWidget(addHairGroup()); @@ -89,8 +92,8 @@ FullModelViewer::FullModelViewer(GameData *data, FileCache &cache, QWidget *pare characterEditorLayout->addWidget(addTailGroup()); auto tabWidget = new QTabWidget(); - tabWidget->addTab(new BoneEditor(gearView), QStringLiteral("Bone Editor")); - tabWidget->addTab(characterEditorWidget, QStringLiteral("Character Editor")); + tabWidget->addTab(new BoneEditor(gearView), i18nc("@title:tab", "Bone Editor")); + tabWidget->addTab(characterEditorWidget, i18nc("@title:tab", "Character Editor")); viewportLayout->addWidget(tabWidget); auto controlLayout = new QHBoxLayout(); @@ -291,23 +294,23 @@ void FullModelViewer::updateSupportedSubraces() QGroupBox *FullModelViewer::addFaceGroup() { - auto faceGroup = new QGroupBox(QStringLiteral("Face")); + auto faceGroup = new QGroupBox(i18nc("@title:group", "Face")); auto faceGroupLayout = new QVBoxLayout(); faceGroup->setLayout(faceGroupLayout); - auto faceRadio1 = new QRadioButton(QStringLiteral("Face 1")); + auto faceRadio1 = new QRadioButton(i18nc("@option:radio", "Face 1")); connect(faceRadio1, &QRadioButton::clicked, this, [this] { gearView->setFace(1); }); faceGroupLayout->addWidget(faceRadio1); - auto faceRadio2 = new QRadioButton(QStringLiteral("Face 2")); + auto faceRadio2 = new QRadioButton(i18nc("@option:radio", "Face 2")); connect(faceRadio2, &QRadioButton::clicked, this, [this] { gearView->setFace(2); }); faceGroupLayout->addWidget(faceRadio2); - auto faceRadio3 = new QRadioButton(QStringLiteral("Face 3")); + auto faceRadio3 = new QRadioButton(i18nc("@option:radio", "Face 3")); connect(faceRadio3, &QRadioButton::clicked, this, [this] { gearView->setFace(3); }); @@ -318,23 +321,23 @@ QGroupBox *FullModelViewer::addFaceGroup() QGroupBox *FullModelViewer::addHairGroup() { - auto hairGroup = new QGroupBox(QStringLiteral("Hair")); + auto hairGroup = new QGroupBox(i18nc("@title:group", "Hair")); auto hairGroupLayout = new QVBoxLayout(); hairGroup->setLayout(hairGroupLayout); - auto hairRadio1 = new QRadioButton(QStringLiteral("Hair 1")); + auto hairRadio1 = new QRadioButton(i18nc("@option:radio", "Hair 1")); connect(hairRadio1, &QRadioButton::clicked, this, [this] { gearView->setHair(1); }); hairGroupLayout->addWidget(hairRadio1); - auto hairRadio2 = new QRadioButton(QStringLiteral("Hair 2")); + auto hairRadio2 = new QRadioButton(i18nc("@option:radio", "Hair 2")); connect(hairRadio2, &QRadioButton::clicked, this, [this] { gearView->setHair(2); }); hairGroupLayout->addWidget(hairRadio2); - auto hairRadio3 = new QRadioButton(QStringLiteral("Hair 3")); + auto hairRadio3 = new QRadioButton(i18nc("@option:radio", "Hair 3")); connect(hairRadio3, &QRadioButton::clicked, this, [this] { gearView->setHair(3); }); @@ -345,23 +348,23 @@ QGroupBox *FullModelViewer::addHairGroup() QGroupBox *FullModelViewer::addEarGroup() { - auto earGroup = new QGroupBox(QStringLiteral("Ears")); + auto earGroup = new QGroupBox(i18nc("@title:group", "Ears")); auto earGroupLayout = new QVBoxLayout(); earGroup->setLayout(earGroupLayout); - auto earRadio1 = new QRadioButton(QStringLiteral("Ears 1")); + auto earRadio1 = new QRadioButton(i18nc("@option:radio", "Ears 1")); connect(earRadio1, &QRadioButton::clicked, this, [this] { gearView->setEar(1); }); earGroupLayout->addWidget(earRadio1); - auto earRadio2 = new QRadioButton(QStringLiteral("Ears 2")); + auto earRadio2 = new QRadioButton(i18nc("@option:radio", "Ears 2")); connect(earRadio2, &QRadioButton::clicked, this, [this] { gearView->setEar(2); }); earGroupLayout->addWidget(earRadio2); - auto earRadio3 = new QRadioButton(QStringLiteral("Ears 3")); + auto earRadio3 = new QRadioButton(i18nc("@option:radio", "Ears 3")); connect(earRadio3, &QRadioButton::clicked, this, [this] { gearView->setEar(3); }); @@ -372,23 +375,23 @@ QGroupBox *FullModelViewer::addEarGroup() QGroupBox *FullModelViewer::addTailGroup() { - auto tailGroup = new QGroupBox(QStringLiteral("Tail")); + auto tailGroup = new QGroupBox(i18nc("@title:group", "Tail")); auto tailGroupLayout = new QVBoxLayout(); tailGroup->setLayout(tailGroupLayout); - auto tailRadio1 = new QRadioButton(QStringLiteral("Tail 1")); + auto tailRadio1 = new QRadioButton(i18nc("@option:radio", "Tail 1")); connect(tailRadio1, &QRadioButton::clicked, this, [this] { gearView->setTail(1); }); tailGroupLayout->addWidget(tailRadio1); - auto tailRadio2 = new QRadioButton(QStringLiteral("Tail 2")); + auto tailRadio2 = new QRadioButton(i18nc("@option:radio", "Tail 2")); connect(tailRadio2, &QRadioButton::clicked, this, [this] { gearView->setTail(2); }); tailGroupLayout->addWidget(tailRadio2); - auto tailRadio3 = new QRadioButton(QStringLiteral("Tail 3")); + auto tailRadio3 = new QRadioButton(i18nc("@option:radio", "Tail 3")); connect(tailRadio3, &QRadioButton::clicked, this, [this] { gearView->setTail(3); }); diff --git a/armoury/src/gearlistmodel.cpp b/armoury/src/gearlistmodel.cpp index 341b4d4..aaeaa17 100644 --- a/armoury/src/gearlistmodel.cpp +++ b/armoury/src/gearlistmodel.cpp @@ -3,6 +3,7 @@ #include "gearlistmodel.h" +#include #include #include @@ -128,7 +129,7 @@ QVariant GearListModel::headerData(int section, Qt::Orientation orientation, int { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { if (section == 0) { - return QStringLiteral("Name"); + return i18nc("@title:column Item name", "Name"); } } diff --git a/armoury/src/gearlistwidget.cpp b/armoury/src/gearlistwidget.cpp index 1f7ab93..e459024 100644 --- a/armoury/src/gearlistwidget.cpp +++ b/armoury/src/gearlistwidget.cpp @@ -3,6 +3,7 @@ #include "gearlistwidget.h" +#include #include #include #include @@ -24,7 +25,7 @@ GearListWidget::GearListWidget(GameData *data, QWidget *parent) searchModel->setFilterCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive); auto searchEdit = new QLineEdit(); - searchEdit->setPlaceholderText(QStringLiteral("Search...")); + searchEdit->setPlaceholderText(i18nc("@info:placeholder Search through items", "Search…")); searchEdit->setClearButtonEnabled(true); searchEdit->setProperty("_breeze_borders_sides", QVariant::fromValue(QFlags{Qt::BottomEdge})); connect(searchEdit, &QLineEdit::textChanged, this, [=](const QString &text) { diff --git a/armoury/src/gearview.cpp b/armoury/src/gearview.cpp index 7aa0eee..1560da4 100644 --- a/armoury/src/gearview.cpp +++ b/armoury/src/gearview.cpp @@ -34,6 +34,7 @@ GearView::GearView(GameData *data, FileCache &cache, QWidget *parent) ImGui::SetWindowPos(ImVec2(0, 0)); ImGui::SetWindowSize(io.DisplaySize); + // TODO: localize const char *loadingLabel{"Loading gear..."}; ImGui::SetCursorPosX((io.DisplaySize.x - ImGui::CalcTextSize(loadingLabel).x) * 0.5f); ImGui::SetCursorPosY((io.DisplaySize.y - ImGui::CalcTextSize(loadingLabel).y) * 0.5f); diff --git a/armoury/src/main.cpp b/armoury/src/main.cpp index 504b173..a0d085d 100644 --- a/armoury/src/main.cpp +++ b/armoury/src/main.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2023 Joshua Goins // SPDX-License-Identifier: GPL-3.0-or-later +#include #include #include @@ -13,10 +14,7 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); - customizeAboutData(QStringLiteral("armoury"), - QStringLiteral("zone.xiv.armoury"), - QStringLiteral("Gear Editor"), - QStringLiteral("Program to view FFXIV gear.")); + customizeAboutData(QStringLiteral("armoury"), QStringLiteral("zone.xiv.armoury"), QStringLiteral("Gear Editor"), i18n("Program to view FFXIV gear.")); // Default to a sensible message pattern if (qEnvironmentVariableIsEmpty("QT_MESSAGE_PATTERN")) { diff --git a/armoury/src/mainwindow.cpp b/armoury/src/mainwindow.cpp index 93a93c1..66a20b0 100644 --- a/armoury/src/mainwindow.cpp +++ b/armoury/src/mainwindow.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -53,9 +54,9 @@ MainWindow::MainWindow(GameData *in_data) metadataView = new MetadataView(&data); auto tabWidget = new QTabWidget(); - tabWidget->addTab(gearView, QStringLiteral("Models")); - tabWidget->addTab(materialView, QStringLiteral("Materials")); - tabWidget->addTab(metadataView, QStringLiteral("Metadata")); + tabWidget->addTab(gearView, i18nc("@title:tab", "Models")); + tabWidget->addTab(materialView, i18nc("@title:tab", "Materials")); + tabWidget->addTab(metadataView, i18nc("@title:tab", "Metadata")); tabWidget->setDocumentMode(true); // Don't draw the borders tabWidget->tabBar()->setExpanding(true); dummyWidget->addWidget(tabWidget); @@ -68,18 +69,18 @@ MainWindow::MainWindow(GameData *in_data) void MainWindow::setupAdditionalMenus(QMenuBar *menuBar) { - auto toolsMenu = menuBar->addMenu(QStringLiteral("Tools")); + auto toolsMenu = menuBar->addMenu(i18nc("@title:menu", "Tools")); - auto cmpEditorMenu = toolsMenu->addAction(QStringLiteral("CMP Editor")); + auto cmpEditorMenu = toolsMenu->addAction(i18nc("@action:inmenu CMP is an abbreviation", "CMP Editor")); cmpEditorMenu->setIcon(QIcon::fromTheme(QStringLiteral("document-edit"))); connect(cmpEditorMenu, &QAction::triggered, [this] { auto cmpEditor = new CmpEditor(&data); cmpEditor->show(); }); - auto windowMenu = menuBar->addMenu(QStringLiteral("Window")); + auto windowMenu = menuBar->addMenu(i18nc("@title:menu", "Window")); - auto fmvMenu = windowMenu->addAction(QStringLiteral("Full Model viewer")); + auto fmvMenu = windowMenu->addAction(i18nc("@action:inmenu", "Full Model Viewer")); fmvMenu->setCheckable(true); fmvMenu->setIcon(QIcon::fromTheme(QStringLiteral("user-symbolic"))); connect(fmvMenu, &QAction::toggled, [this](bool toggled) { @@ -93,9 +94,9 @@ void MainWindow::setupAdditionalMenus(QMenuBar *menuBar) fmvMenu->setChecked(fullModelViewer->isVisible()); }); - auto settingsMenu = menuBar->addMenu(QStringLiteral("Settings")); + auto settingsMenu = menuBar->addMenu(i18nc("@title:menu", "Settings")); - auto settingsAction = settingsMenu->addAction(QStringLiteral("Configure Armoury...")); + auto settingsAction = settingsMenu->addAction(i18nc("@action:inmenu", "Configure Armoury…")); settingsAction->setIcon(QIcon::fromTheme(QStringLiteral("configure-symbolic"))); connect(settingsAction, &QAction::triggered, [this] { auto settingsWindow = new SettingsWindow(); diff --git a/armoury/src/singlegearview.cpp b/armoury/src/singlegearview.cpp index 0b2dea2..6e0a28a 100644 --- a/armoury/src/singlegearview.cpp +++ b/armoury/src/singlegearview.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -83,7 +84,7 @@ SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent }); controlLayout->addWidget(lodCombo); - addToFMVButton = new QPushButton(QStringLiteral("Add to FMV")); + addToFMVButton = new QPushButton(i18nc("@action:button FMV is an abbreviation for Full Model Viewer", "Add to FMV")); addToFMVButton->setIcon(QIcon::fromTheme(QStringLiteral("list-add-user"))); connect(addToFMVButton, &QPushButton::clicked, this, [this](bool) { if (currentGear.has_value()) { @@ -91,7 +92,7 @@ SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent } }); - editButton = new QPushButton(QStringLiteral("Edit")); + editButton = new QPushButton(i18nc("@action:button", "Edit")); editButton->setIcon(QIcon::fromTheme(QStringLiteral("document-edit"))); connect(editButton, &QPushButton::clicked, this, [this](bool) { // Export in default location @@ -134,7 +135,7 @@ SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent }); topControlLayout->addWidget(editButton); - importButton = new QPushButton(QStringLiteral("Import...")); + importButton = new QPushButton(i18nc("@action:button", "Import…")); importButton->setIcon(QIcon::fromTheme(QStringLiteral("document-import"))); connect(importButton, &QPushButton::clicked, this, [this](bool) { if (currentGear.has_value()) { @@ -157,7 +158,7 @@ SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent if (!QDir().exists(path)) QDir().mkpath(path); - const QString fileName = QFileDialog::getOpenFileName(this, tr("Import Model"), path, tr("glTF Binary File (*.glb)")); + const QString fileName = QFileDialog::getOpenFileName(this, i18nc("@title:window", "Import Model"), path, i18n("glTF Binary File (*.glb)")); if (!fileName.isEmpty()) { importModel(fileName); } @@ -166,7 +167,7 @@ SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent topControlLayout->addWidget(importButton); auto testMenu = new QMenu(); - auto gltfAction = testMenu->addAction(QStringLiteral("glTF")); + auto gltfAction = testMenu->addAction(i18nc("@action:inmenu", "glTF")); connect(gltfAction, &QAction::triggered, this, [this](bool) { if (currentGear.has_value()) { // TODO: deduplicate @@ -194,7 +195,7 @@ SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent gearView->exportModel(fileName); } }); - auto mdlAction = testMenu->addAction(QStringLiteral("MDL")); + auto mdlAction = testMenu->addAction(i18nc("@action:inmenu", "MDL")); connect(mdlAction, &QAction::triggered, this, [this, data](bool) { if (currentGear.has_value()) { // TODO: deduplicate @@ -202,8 +203,10 @@ SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent return QString(mdlPath).section(QLatin1Char('/'), -1); }; - const QString fileName = - QFileDialog::getSaveFileName(this, tr("Export Model"), sanitizeMdlPath(gearView->getLoadedGearPath()), tr("MDL File (*.mdl)")); + const QString fileName = QFileDialog::getSaveFileName(this, + i18nc("@title:window", "Export Model"), + sanitizeMdlPath(gearView->getLoadedGearPath()), + i18n("MDL File (*.mdl)")); auto buffer = physis_gamedata_extract_file(data, gearView->getLoadedGearPath().toStdString().c_str()); @@ -214,7 +217,7 @@ SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent } }); - exportButton = new QPushButton(QStringLiteral("Export")); + exportButton = new QPushButton(i18nc("@action:button", "Export")); exportButton->setMenu(testMenu); exportButton->setIcon(QIcon::fromTheme(QStringLiteral("document-export"))); @@ -386,7 +389,7 @@ void SingleGearView::reloadGear() lodCombo->clear(); for (int i = 0; i < gearView->lodCount(); i++) { - lodCombo->addItem(QStringLiteral("LOD %1").arg(i), i); + lodCombo->addItem(i18nc("@action:inmenu LOD stands for Level of Detail", "LOD %1").arg(i), i); } if (oldLod < gearView->lodCount()) { lodCombo->setCurrentIndex(oldLod);