Skip to content

Commit 9523edc

Browse files
committed
Support localizing command names
Only supported by manually editing the INI file. ```ini [Command] Name = ... Name_cs = ... Name_fr = ... Name_pt_BR = ... Name_pt = ... ``` Fixes #3032
1 parent f52e3d5 commit 9523edc

File tree

7 files changed

+119
-52
lines changed

7 files changed

+119
-52
lines changed

src/common/command.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "command.h"
44

55
#include <QDataStream>
6+
#include <QLocale>
67

78
bool Command::operator==(const Command &other) const
89
{
@@ -29,7 +30,8 @@ bool Command::operator==(const Command &other) const
2930
&& globalShortcuts == other.globalShortcuts
3031
&& tab == other.tab
3132
&& outputTab == other.outputTab
32-
&& internalId == other.internalId;
33+
&& internalId == other.internalId
34+
&& nameLocalization == other.nameLocalization;
3335
}
3436

3537
bool Command::operator!=(const Command &other) const {
@@ -57,6 +59,23 @@ int Command::type() const
5759
return type;
5860
}
5961

62+
QString Command::localizedName() const
63+
{
64+
static const QLocale locale;
65+
static const QString code1 = locale.name();
66+
static const int i = code1.indexOf('_');
67+
static const QString code2 = i == -1 ? QString() : code1.mid(0, i);
68+
69+
const auto value = nameLocalization.value(code1);
70+
if (!value.isEmpty())
71+
return value;
72+
73+
if (code2.isEmpty())
74+
return name;
75+
76+
return nameLocalization.value(code2, name);
77+
}
78+
6079
QDataStream &operator<<(QDataStream &out, const Command &command)
6180
{
6281
out << command.name
@@ -82,7 +101,8 @@ QDataStream &operator<<(QDataStream &out, const Command &command)
82101
<< command.globalShortcuts
83102
<< command.tab
84103
<< command.outputTab
85-
<< command.internalId;
104+
<< command.internalId
105+
<< command.nameLocalization;
86106
Q_ASSERT(out.status() == QDataStream::Ok);
87107
return out;
88108
}
@@ -112,7 +132,8 @@ QDataStream &operator>>(QDataStream &in, Command &command)
112132
>> command.globalShortcuts
113133
>> command.tab
114134
>> command.outputTab
115-
>> command.internalId;
135+
>> command.internalId
136+
>> command.nameLocalization;
116137
Q_ASSERT(in.status() == QDataStream::Ok);
117138
return in;
118139
}

src/common/command.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#ifndef COMMAND_H
44
#define COMMAND_H
55

6+
#include <QMap>
67
#include <QString>
78
#include <QStringList>
89
#include <QRegularExpression>
@@ -36,6 +37,8 @@ struct Command {
3637

3738
int type() const;
3839

40+
QString localizedName() const;
41+
3942
/** Name or short description. Used for menu item. */
4043
QString name;
4144

@@ -117,6 +120,8 @@ struct Command {
117120
QString outputTab;
118121

119122
QString internalId;
123+
124+
QMap<QString, QString> nameLocalization;
120125
};
121126

122127
QDataStream &operator<<(QDataStream &out, const Command &command);

src/common/commandstore.cpp

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ namespace {
1717

1818
const QLatin1String falseString("false");
1919
const QLatin1String trueString("true");
20+
const QRegularExpression nameLocalizationRe(R"(^Name(?:_(.*))?$)");
2021

2122
void normalizeLineBreaks(QString &cmd)
2223
{
@@ -32,51 +33,70 @@ void normalizeLineBreaks(QString &cmd)
3233
void loadCommand(const QSettings &settings, Commands *commands)
3334
{
3435
Command c;
35-
c.enable = settings.value(QStringLiteral("Enable"), true).toBool();
36-
37-
c.name = settings.value(QStringLiteral("Name")).toString();
38-
c.re = QRegularExpression( settings.value(QStringLiteral("Match")).toString() );
39-
c.wndre = QRegularExpression( settings.value(QStringLiteral("Window")).toString() );
40-
c.matchCmd = settings.value(QStringLiteral("MatchCommand")).toString();
41-
c.cmd = settings.value(QStringLiteral("Command")).toString();
42-
c.sep = settings.value(QStringLiteral("Separator")).toString();
43-
44-
c.input = settings.value(QStringLiteral("Input")).toString();
45-
if (c.input == falseString || c.input == trueString)
46-
c.input = c.input == trueString ? mimeText : QLatin1String();
47-
48-
c.output = settings.value(QStringLiteral("Output")).toString();
49-
if (c.output == falseString || c.output == trueString)
50-
c.output = c.output == trueString ? mimeText : QLatin1String();
51-
52-
c.wait = settings.value(QStringLiteral("Wait")).toBool();
53-
c.automatic = settings.value(QStringLiteral("Automatic")).toBool();
54-
c.display = settings.value(QStringLiteral("Display")).toBool();
55-
c.transform = settings.value(QStringLiteral("Transform")).toBool();
56-
c.hideWindow = settings.value(QStringLiteral("HideWindow")).toBool();
57-
c.icon = settings.value(QStringLiteral("Icon")).toString();
58-
c.shortcuts = settings.value(QStringLiteral("Shortcut")).toStringList();
59-
c.globalShortcuts = settings.value(QStringLiteral("GlobalShortcut")).toStringList();
60-
c.tab = settings.value(QStringLiteral("Tab")).toString();
61-
c.outputTab = settings.value(QStringLiteral("OutputTab")).toString();
62-
c.internalId = settings.value(QStringLiteral("InternalId")).toString();
63-
c.inMenu = settings.value(QStringLiteral("InMenu")).toBool();
64-
c.isScript = settings.value(QStringLiteral("IsScript")).toBool();
65-
66-
const auto globalShortcutsOption = settings.value(QStringLiteral("IsGlobalShortcut"));
67-
if ( globalShortcutsOption.isValid() ) {
68-
c.isGlobalShortcut = globalShortcutsOption.toBool();
69-
} else {
70-
// Backwards compatibility with v3.1.2 and below.
71-
if ( c.globalShortcuts.contains(QLatin1String("DISABLED")) )
72-
c.globalShortcuts.clear();
73-
c.isGlobalShortcut = !c.globalShortcuts.isEmpty();
74-
}
7536

76-
if (settings.value(QStringLiteral("Ignore")).toBool())
77-
c.remove = c.automatic = true;
78-
else
79-
c.remove = settings.value(QStringLiteral("Remove")).toBool();
37+
for (auto &&key : settings.childKeys()) {
38+
if (key == QLatin1String("Enable")) {
39+
c.enable = settings.value(key).toBool();
40+
} else if (auto match = nameLocalizationRe.match(key); match.hasMatch()) {
41+
const QString languageCode = match.captured(1);
42+
const QString value = settings.value(key).toString();
43+
if (languageCode.isEmpty())
44+
c.name = value;
45+
else
46+
c.nameLocalization[languageCode] = value;
47+
} else if (key == QLatin1String("Match")) {
48+
c.re = QRegularExpression( settings.value(key).toString() );
49+
} else if (key == QLatin1String("Window")) {
50+
c.wndre = QRegularExpression( settings.value(key).toString() );
51+
} else if (key == QLatin1String("MatchCommand")) {
52+
c.matchCmd = settings.value(key).toString();
53+
} else if (key == QLatin1String("Command")) {
54+
c.cmd = settings.value(key).toString();
55+
} else if (key == QLatin1String("Separator")) {
56+
c.sep = settings.value(key).toString();
57+
} else if (key == QLatin1String("Input")) {
58+
c.input = settings.value(key).toString();
59+
if (c.input == falseString || c.input == trueString)
60+
c.input = c.input == trueString ? mimeText : QLatin1String();
61+
} else if (key == QLatin1String("Output")) {
62+
c.output = settings.value(key).toString();
63+
if (c.output == falseString || c.output == trueString)
64+
c.output = c.output == trueString ? mimeText : QLatin1String();
65+
} else if (key == QLatin1String("Wait")) {
66+
c.wait = settings.value(key).toBool();
67+
} else if (key == QLatin1String("Automatic")) {
68+
c.automatic = settings.value(key).toBool();
69+
} else if (key == QLatin1String("Display")) {
70+
c.display = settings.value(key).toBool();
71+
} else if (key == QLatin1String("Transform")) {
72+
c.transform = settings.value(key).toBool();
73+
} else if (key == QLatin1String("HideWindow")) {
74+
c.hideWindow = settings.value(key).toBool();
75+
} else if (key == QLatin1String("Icon")) {
76+
c.icon = settings.value(key).toString();
77+
} else if (key == QLatin1String("Shortcut")) {
78+
c.shortcuts = settings.value(key).toStringList();
79+
} else if (key == QLatin1String("GlobalShortcut")) {
80+
c.globalShortcuts = settings.value(key).toStringList();
81+
} else if (key == QLatin1String("Tab")) {
82+
c.tab = settings.value(key).toString();
83+
} else if (key == QLatin1String("OutputTab")) {
84+
c.outputTab = settings.value(key).toString();
85+
} else if (key == QLatin1String("InternalId")) {
86+
c.internalId = settings.value(key).toString();
87+
} else if (key == QLatin1String("InMenu")) {
88+
c.inMenu = settings.value(key).toBool();
89+
} else if (key == QLatin1String("IsScript")) {
90+
c.isScript = settings.value(key).toBool();
91+
} else if (key == QLatin1String("IsGlobalShortcut")) {
92+
c.isGlobalShortcut = settings.value(key).toBool();
93+
} else if (key == QLatin1String("Remove")) {
94+
c.remove = settings.value(key).toBool();
95+
} else if (key == QLatin1String("Ignore")) {
96+
if (settings.value(key).toBool())
97+
c.remove = c.automatic = true;
98+
}
99+
}
80100

81101
commands->append(c);
82102
}
@@ -130,6 +150,11 @@ void saveCommand(const Command &c, QSettings *settings)
130150
saveNewValue(QStringLiteral("Tab"), c, &Command::tab, settings);
131151
saveNewValue(QStringLiteral("OutputTab"), c, &Command::outputTab, settings);
132152
saveNewValue(QStringLiteral("InternalId"), c, &Command::internalId, settings);
153+
154+
for (auto it = c.nameLocalization.constBegin(); it != c.nameLocalization.constEnd(); ++it) {
155+
const auto key = QStringLiteral("Name_%1").arg(it.key());
156+
saveValue(key, it.value(), settings);
157+
}
133158
}
134159

135160
Commands importCommands(QSettings *settings)

src/gui/commandwidget.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ Command CommandWidget::command() const
145145
c.tab = ui->comboBoxCopyToTab->currentText();
146146
c.outputTab = ui->comboBoxOutputTab->currentText();
147147
c.internalId = m_internalId;
148+
c.nameLocalization = m_nameLocalization;
148149

149150
return c;
150151
}
@@ -154,6 +155,8 @@ void CommandWidget::setCommand(const Command &c)
154155
m_internalId = c.internalId;
155156
const bool isEditable = !m_internalId.startsWith(QLatin1String("copyq_"));
156157

158+
m_nameLocalization = c.nameLocalization;
159+
157160
ui->scrollAreaWidgetContents->setEnabled(isEditable);
158161
ui->commandEdit->setReadOnly(!isEditable);
159162
ui->lineEditName->setReadOnly(!isEditable);

src/gui/commandwidget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#ifndef COMMANDWIDGET_H
44
#define COMMANDWIDGET_H
55

6+
#include <QMap>
67
#include <QWidget>
78

89
namespace Ui {
@@ -64,6 +65,7 @@ class CommandWidget final : public QWidget
6465
Ui::CommandWidget *ui;
6566
bool m_showAdvanced = true;
6667
QString m_internalId;
68+
QMap<QString, QString> m_nameLocalization;
6769
};
6870

6971
#endif // COMMANDWIDGET_H

src/gui/mainwindow.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,7 +1346,7 @@ void MainWindow::onActionDialogAccepted(const Command &command, const QStringLis
13461346
auto act = new Action();
13471347
act->setCommand(command.cmd, arguments);
13481348
act->setInputWithFormat(data, command.input);
1349-
act->setName(command.name);
1349+
act->setName(command.localizedName());
13501350
act->setData(data);
13511351

13521352
if ( !command.output.isEmpty() ) {
@@ -1582,7 +1582,7 @@ void MainWindow::addCommandsToItemMenu(ClipboardBrowser *c)
15821582
const auto commands = commandsForMenu(data, c->tabName(), m_menuCommands);
15831583

15841584
for (const auto &command : commands) {
1585-
QString name = command.name;
1585+
QString name = command.localizedName();
15861586
QMenu *_rootMenu, *currentMenu;
15871587
std::tie(_rootMenu, currentMenu) = createSubMenus(&name, m_menuItem);
15881588
auto act = new CommandAction(command, name, currentMenu);
@@ -1617,7 +1617,7 @@ void MainWindow::addCommandsToTrayMenu(const QVariantMap &clipboardData, QList<Q
16171617
QList<QKeySequence> usedShortcuts;
16181618

16191619
for (const auto &command : commands) {
1620-
QString name = command.name;
1620+
QString name = command.localizedName();
16211621
QMenu *rootMenu, *currentMenu;
16221622
std::tie(rootMenu, currentMenu) = createSubMenus(&name, m_trayMenu);
16231623
auto act = new CommandAction(command, name, currentMenu);
@@ -4071,7 +4071,7 @@ Action *MainWindow::action(const QVariantMap &data, const Command &cmd, const QM
40714071
auto act = new Action();
40724072
act->setCommand( cmd.cmd, QStringList(getTextData(data)) );
40734073
act->setInputWithFormat(data, cmd.input);
4074-
act->setName(cmd.name);
4074+
act->setName(cmd.localizedName());
40754075
act->setData(data);
40764076

40774077
if ( !cmd.output.isEmpty() ) {

src/scriptable/scriptvaluefactory.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,11 @@ struct ScriptValueFactory<Command> {
241241
value.setProperty(QStringLiteral("outputTab"), command.outputTab);
242242
value.setProperty(QStringLiteral("internalId"), command.internalId);
243243

244+
QVariantMap nameLocalization;
245+
for (auto it = command.nameLocalization.constBegin(); it != command.nameLocalization.constEnd(); ++it)
246+
nameLocalization[it.key()] = it.value();
247+
value.setProperty(QStringLiteral("nameLocalization"), ::toScriptValue(nameLocalization, engine));
248+
244249
return value;
245250
}
246251

@@ -273,6 +278,13 @@ struct ScriptValueFactory<Command> {
273278
::fromScriptValueIfValid( value.property("outputTab"), engine, &command.outputTab );
274279
::fromScriptValueIfValid( value.property("internalId"), engine, &command.internalId );
275280

281+
QJSValue nameLocalization = value.property("nameLocalization");
282+
QJSValueIterator it(nameLocalization);
283+
while (it.hasNext()) {
284+
it.next();
285+
command.nameLocalization[it.name()] = it.value().toString();
286+
}
287+
276288
return command;
277289
}
278290
};
@@ -338,4 +350,3 @@ struct ScriptValueFactory<QVariant> {
338350
return variant;
339351
}
340352
};
341-

0 commit comments

Comments
 (0)