Skip to content

Commit 879a7c3

Browse files
authored
UI: wrap all text for translation (#24961)
* rough multiple language demo * more wrappings * stash * add some bad translations * updates * map from french to spanish still has same problem of needing to call setText on everything * add files * restart UI * use return code * relative path * more translations * don't loop restart * Toggle and prime translations * try on device * try QComboBox with readable style * stash * not yet scrollable * stash * dynamic translations (doesn't work for dynamic widget strings yet) * clean up multiple option selector * store languages in json * try transparent * Try transparent popup * see how this looks * tweaks * clean up * clean up * clean up 2 and missing tr * wrap more strings * missing updater * fixes * add basic test to ensure all strings wrapped * try in CI * clean up * test name * fix test * always install qt dev tools * fix deps * fast test * add section so it prints multiple errors * debug * debug get rid of those * make any difference? * comment * oh... * run with offscreen platform * try out section * clean up * fix missing wrappings (it works!) * move down * space * clear relevant params, set TICI=1
1 parent bef5350 commit 879a7c3

28 files changed

+282
-191
lines changed

.github/workflows/selfdrive_tests.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ jobs:
305305
$UNIT_TEST selfdrive/hardware/tici && \
306306
$UNIT_TEST selfdrive/modeld && \
307307
$UNIT_TEST tools/lib/tests && \
308+
./selfdrive/ui/tests/create_test_translations.sh && \
309+
QT_QPA_PLATFORM=offscreen ./selfdrive/ui/tests/test_translations && \
308310
./common/tests/test_util && \
309311
./common/tests/test_swaglog && \
310312
./selfdrive/boardd/tests/test_boardd_usbprotocol && \

selfdrive/ui/SConscript

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ qt_src = ["main.cc", "qt/sidebar.cc", "qt/onroad.cc", "qt/body.cc",
5858
"qt/window.cc", "qt/home.cc", "qt/offroad/settings.cc",
5959
"qt/offroad/onboarding.cc", "qt/offroad/driverview.cc"]
6060
qt_env.Program("_ui", qt_src + [asset_obj], LIBS=qt_libs)
61+
if GetOption('test'):
62+
qt_src.remove("main.cc") # replaced by test_runner
63+
qt_env.Program('tests/test_translations', [asset_obj, 'tests/test_runner.cc', 'tests/test_translations.cc'] + qt_src, LIBS=qt_libs)
6164

6265

6366
# setup and factory resetter

selfdrive/ui/installer/installer.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Installer::Installer(QWidget *parent) : QWidget(parent) {
5353
layout->setContentsMargins(150, 290, 150, 150);
5454
layout->setSpacing(0);
5555

56-
QLabel *title = new QLabel("Installing...");
56+
QLabel *title = new QLabel(tr("Installing..."));
5757
title->setStyleSheet("font-size: 90px; font-weight: 600;");
5858
layout->addWidget(title, 0, Qt::AlignTop);
5959

@@ -141,9 +141,9 @@ void Installer::cachedFetch(const QString &cache) {
141141
void Installer::readProgress() {
142142
const QVector<QPair<QString, int>> stages = {
143143
// prefix, weight in percentage
144-
{"Receiving objects: ", 91},
145-
{"Resolving deltas: ", 2},
146-
{"Updating files: ", 7},
144+
{tr("Receiving objects: "), 91},
145+
{tr("Resolving deltas: "), 2},
146+
{tr("Updating files: "), 7},
147147
};
148148

149149
auto line = QString(proc.readAllStandardError());

selfdrive/ui/qt/home.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
111111
date = new QLabel();
112112
header_layout->addWidget(date, 1, Qt::AlignHCenter | Qt::AlignLeft);
113113

114-
update_notif = new QPushButton("UPDATE");
114+
update_notif = new QPushButton(tr("UPDATE"));
115115
update_notif->setVisible(false);
116116
update_notif->setStyleSheet("background-color: #364DEF;");
117117
QObject::connect(update_notif, &QPushButton::clicked, [=]() { center_layout->setCurrentIndex(1); });
@@ -202,6 +202,6 @@ void OffroadHome::refresh() {
202202
update_notif->setVisible(updateAvailable);
203203
alert_notif->setVisible(alerts);
204204
if (alerts) {
205-
alert_notif->setText(QString::number(alerts) + (alerts > 1 ? " ALERTS" : " ALERT"));
205+
alert_notif->setText(QString::number(alerts) + (alerts > 1 ? tr(" ALERTS") : tr(" ALERT")));
206206
}
207207
}

selfdrive/ui/qt/maps/map_settings.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ MapPanel::MapPanel(QWidget* parent) : QWidget(parent) {
5959
current_widget = new QWidget(this);
6060
QVBoxLayout *current_layout = new QVBoxLayout(current_widget);
6161

62-
QLabel *title = new QLabel("Current Destination");
62+
QLabel *title = new QLabel(tr("Current Destination"));
6363
title->setStyleSheet("font-size: 55px");
6464
current_layout->addWidget(title);
6565

66-
current_route = new ButtonControl("", "CLEAR");
66+
current_route = new ButtonControl("", tr("CLEAR"));
6767
current_route->setStyleSheet("padding-left: 40px;");
6868
current_layout->addWidget(current_route);
6969
QObject::connect(current_route, &ButtonControl::clicked, [=]() {
@@ -78,7 +78,7 @@ MapPanel::MapPanel(QWidget* parent) : QWidget(parent) {
7878
main_layout->addWidget(current_widget);
7979

8080
// Recents
81-
QLabel *recents_title = new QLabel("Recent Destinations");
81+
QLabel *recents_title = new QLabel(tr("Recent Destinations"));
8282
recents_title->setStyleSheet("font-size: 55px");
8383
main_layout->addWidget(recents_title);
8484
main_layout->addSpacing(20);
@@ -92,7 +92,7 @@ MapPanel::MapPanel(QWidget* parent) : QWidget(parent) {
9292
QWidget * no_prime_widget = new QWidget;
9393
{
9494
QVBoxLayout *no_prime_layout = new QVBoxLayout(no_prime_widget);
95-
QLabel *signup_header = new QLabel("Try the Navigation Beta");
95+
QLabel *signup_header = new QLabel(tr("Try the Navigation Beta"));
9696
signup_header->setStyleSheet(R"(font-size: 75px; color: white; font-weight:600;)");
9797
signup_header->setAlignment(Qt::AlignCenter);
9898

@@ -104,7 +104,7 @@ MapPanel::MapPanel(QWidget* parent) : QWidget(parent) {
104104
screenshot->setPixmap(pm.scaledToWidth(1080, Qt::SmoothTransformation));
105105
no_prime_layout->addWidget(screenshot, 0, Qt::AlignHCenter);
106106

107-
QLabel *signup = new QLabel("Get turn-by-turn directions displayed and more with a comma \nprime subscription. Sign up now: https://connect.comma.ai");
107+
QLabel *signup = new QLabel(tr("Get turn-by-turn directions displayed and more with a comma \nprime subscription. Sign up now: https://connect.comma.ai"));
108108
signup->setStyleSheet(R"(font-size: 45px; color: white; font-weight:300;)");
109109
signup->setAlignment(Qt::AlignCenter);
110110

@@ -161,12 +161,12 @@ void MapPanel::showEvent(QShowEvent *event) {
161161
void MapPanel::clear() {
162162
home_button->setIcon(QPixmap("../assets/navigation/home_inactive.png"));
163163
home_address->setStyleSheet(R"(font-size: 50px; color: grey;)");
164-
home_address->setText("No home\nlocation set");
164+
home_address->setText(tr("No home\nlocation set"));
165165
home_button->disconnect();
166166

167167
work_button->setIcon(QPixmap("../assets/navigation/work_inactive.png"));
168168
work_address->setStyleSheet(R"(font-size: 50px; color: grey;)");
169-
work_address->setText("No work\nlocation set");
169+
work_address->setText(tr("No work\nlocation set"));
170170
work_button->disconnect();
171171

172172
clearLayout(recent_layout);
@@ -279,7 +279,7 @@ void MapPanel::parseResponse(const QString &response, bool success) {
279279
}
280280

281281
if (!has_recents) {
282-
QLabel *no_recents = new QLabel("no recent destinations");
282+
QLabel *no_recents = new QLabel(tr("no recent destinations"));
283283
no_recents->setStyleSheet(R"(font-size: 50px; color: #9c9c9c)");
284284
recent_layout->addWidget(no_recents);
285285
}

selfdrive/ui/qt/offroad/driverview.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void DriverViewScene::paintEvent(QPaintEvent* event) {
5353
p.setPen(Qt::white);
5454
p.setRenderHint(QPainter::TextAntialiasing);
5555
configFont(p, "Inter", 100, "Bold");
56-
p.drawText(geometry(), Qt::AlignCenter, "camera starting");
56+
p.drawText(geometry(), Qt::AlignCenter, tr("camera starting"));
5757
return;
5858
}
5959

selfdrive/ui/qt/offroad/networking.cc

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Networking::Networking(QWidget* parent, bool show_advanced) : QFrame(parent) {
2727
QVBoxLayout* vlayout = new QVBoxLayout(wifiScreen);
2828
vlayout->setContentsMargins(20, 20, 20, 20);
2929
if (show_advanced) {
30-
QPushButton* advancedSettings = new QPushButton("Advanced");
30+
QPushButton* advancedSettings = new QPushButton(tr("Advanced"));
3131
advancedSettings->setObjectName("advanced_btn");
3232
advancedSettings->setStyleSheet("margin-right: 30px;");
3333
advancedSettings->setFixedSize(400, 100);
@@ -84,7 +84,7 @@ void Networking::connectToNetwork(const Network &n) {
8484
} else if (n.security_type == SecurityType::OPEN) {
8585
wifi->connect(n);
8686
} else if (n.security_type == SecurityType::WPA) {
87-
QString pass = InputDialog::getText("Enter password", this, "for \"" + n.ssid + "\"", true, 8);
87+
QString pass = InputDialog::getText(tr("Enter password"), this, tr("for \"") + n.ssid + "\"", true, 8);
8888
if (!pass.isEmpty()) {
8989
wifi->connect(n, pass);
9090
}
@@ -94,7 +94,7 @@ void Networking::connectToNetwork(const Network &n) {
9494
void Networking::wrongPassword(const QString &ssid) {
9595
if (wifi->seenNetworks.contains(ssid)) {
9696
const Network &n = wifi->seenNetworks.value(ssid);
97-
QString pass = InputDialog::getText("Wrong password", this, "for \"" + n.ssid +"\"", true, 8);
97+
QString pass = InputDialog::getText(tr("Wrong password"), this, tr("for \"") + n.ssid +"\"", true, 8);
9898
if (!pass.isEmpty()) {
9999
wifi->connect(n, pass);
100100
}
@@ -118,30 +118,30 @@ AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWid
118118
main_layout->setSpacing(20);
119119

120120
// Back button
121-
QPushButton* back = new QPushButton("Back");
121+
QPushButton* back = new QPushButton(tr("Back"));
122122
back->setObjectName("back_btn");
123123
back->setFixedSize(400, 100);
124124
connect(back, &QPushButton::clicked, [=]() { emit backPress(); });
125125
main_layout->addWidget(back, 0, Qt::AlignLeft);
126126

127127
ListWidget *list = new ListWidget(this);
128128
// Enable tethering layout
129-
tetheringToggle = new ToggleControl("Enable Tethering", "", "", wifi->isTetheringEnabled());
129+
tetheringToggle = new ToggleControl(tr("Enable Tethering"), "", "", wifi->isTetheringEnabled());
130130
list->addItem(tetheringToggle);
131131
QObject::connect(tetheringToggle, &ToggleControl::toggleFlipped, this, &AdvancedNetworking::toggleTethering);
132132

133133
// Change tethering password
134-
ButtonControl *editPasswordButton = new ButtonControl("Tethering Password", "EDIT");
134+
ButtonControl *editPasswordButton = new ButtonControl(tr("Tethering Password"), tr("EDIT"));
135135
connect(editPasswordButton, &ButtonControl::clicked, [=]() {
136-
QString pass = InputDialog::getText("Enter new tethering password", this, "", true, 8, wifi->getTetheringPassword());
136+
QString pass = InputDialog::getText(tr("Enter new tethering password"), this, "", true, 8, wifi->getTetheringPassword());
137137
if (!pass.isEmpty()) {
138138
wifi->changeTetheringPassword(pass);
139139
}
140140
});
141141
list->addItem(editPasswordButton);
142142

143143
// IP address
144-
ipLabel = new LabelControl("IP Address", wifi->ipv4_address);
144+
ipLabel = new LabelControl(tr("IP Address"), wifi->ipv4_address);
145145
list->addItem(ipLabel);
146146

147147
// SSH keys
@@ -150,19 +150,19 @@ AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWid
150150

151151
// Roaming toggle
152152
const bool roamingEnabled = params.getBool("GsmRoaming");
153-
ToggleControl *roamingToggle = new ToggleControl("Enable Roaming", "", "", roamingEnabled);
153+
ToggleControl *roamingToggle = new ToggleControl(tr("Enable Roaming"), "", "", roamingEnabled);
154154
QObject::connect(roamingToggle, &SshToggle::toggleFlipped, [=](bool state) {
155155
params.putBool("GsmRoaming", state);
156156
wifi->updateGsmSettings(state, QString::fromStdString(params.get("GsmApn")));
157157
});
158158
list->addItem(roamingToggle);
159159

160160
// APN settings
161-
ButtonControl *editApnButton = new ButtonControl("APN Setting", "EDIT");
161+
ButtonControl *editApnButton = new ButtonControl(tr("APN Setting"), tr("EDIT"));
162162
connect(editApnButton, &ButtonControl::clicked, [=]() {
163163
const bool roamingEnabled = params.getBool("GsmRoaming");
164164
const QString cur_apn = QString::fromStdString(params.get("GsmApn"));
165-
QString apn = InputDialog::getText("Enter APN", this, "leave blank for automatic configuration", false, -1, cur_apn).trimmed();
165+
QString apn = InputDialog::getText(tr("Enter APN"), this, tr("leave blank for automatic configuration"), false, -1, cur_apn).trimmed();
166166

167167
if (apn.isEmpty()) {
168168
params.remove("GsmApn");
@@ -207,7 +207,7 @@ WifiUI::WifiUI(QWidget *parent, WifiManager* wifi) : QWidget(parent), wifi(wifi)
207207
checkmark = QPixmap(ASSET_PATH + "offroad/icon_checkmark.svg").scaledToWidth(49, Qt::SmoothTransformation);
208208
circled_slash = QPixmap(ASSET_PATH + "img_circled_slash.svg").scaledToWidth(49, Qt::SmoothTransformation);
209209

210-
QLabel *scanning = new QLabel("Scanning for networks...");
210+
QLabel *scanning = new QLabel(tr("Scanning for networks..."));
211211
scanning->setStyleSheet("font-size: 65px;");
212212
main_layout->addWidget(scanning, 0, Qt::AlignCenter);
213213

@@ -260,7 +260,7 @@ void WifiUI::refresh() {
260260
clearLayout(main_layout);
261261

262262
if (wifi->seenNetworks.size() == 0) {
263-
QLabel *scanning = new QLabel("Scanning for networks...");
263+
QLabel *scanning = new QLabel(tr("Scanning for networks..."));
264264
scanning->setStyleSheet("font-size: 65px;");
265265
main_layout->addWidget(scanning, 0, Qt::AlignCenter);
266266
return;
@@ -286,17 +286,17 @@ void WifiUI::refresh() {
286286
hlayout->addWidget(ssidLabel, network.connected == ConnectedType::CONNECTING ? 0 : 1);
287287

288288
if (network.connected == ConnectedType::CONNECTING) {
289-
QPushButton *connecting = new QPushButton("CONNECTING...");
289+
QPushButton *connecting = new QPushButton(tr("CONNECTING..."));
290290
connecting->setObjectName("connecting");
291291
hlayout->addWidget(connecting, 2, Qt::AlignLeft);
292292
}
293293

294294
// Forget button
295295
if (wifi->isKnownConnection(network.ssid) && !wifi->isTetheringEnabled()) {
296-
QPushButton *forgetBtn = new QPushButton("FORGET");
296+
QPushButton *forgetBtn = new QPushButton(tr("FORGET"));
297297
forgetBtn->setObjectName("forgetBtn");
298298
QObject::connect(forgetBtn, &QPushButton::clicked, [=]() {
299-
if (ConfirmationDialog::confirm("Forget Wi-Fi Network \"" + QString::fromUtf8(network.ssid) + "\"?", this)) {
299+
if (ConfirmationDialog::confirm(tr("Forget Wi-Fi Network \"") + QString::fromUtf8(network.ssid) + "\"?", this)) {
300300
wifi->forgetConnection(network.ssid);
301301
}
302302
});

selfdrive/ui/qt/offroad/onboarding.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ void TermsPage::showEvent(QShowEvent *event) {
7676
main_layout->setContentsMargins(45, 35, 45, 45);
7777
main_layout->setSpacing(0);
7878

79-
QLabel *title = new QLabel("Terms & Conditions");
79+
QLabel *title = new QLabel(tr("Terms & Conditions"));
8080
title->setStyleSheet("font-size: 90px; font-weight: 600;");
8181
main_layout->addWidget(title);
8282

@@ -104,11 +104,11 @@ void TermsPage::showEvent(QShowEvent *event) {
104104
buttons->setSpacing(45);
105105
main_layout->addLayout(buttons);
106106

107-
QPushButton *decline_btn = new QPushButton("Decline");
107+
QPushButton *decline_btn = new QPushButton(tr("Decline"));
108108
buttons->addWidget(decline_btn);
109109
QObject::connect(decline_btn, &QPushButton::clicked, this, &TermsPage::declinedTerms);
110110

111-
accept_btn = new QPushButton("Scroll to accept");
111+
accept_btn = new QPushButton(tr("Scroll to accept"));
112112
accept_btn->setEnabled(false);
113113
accept_btn->setStyleSheet(R"(
114114
QPushButton {
@@ -123,7 +123,7 @@ void TermsPage::showEvent(QShowEvent *event) {
123123
}
124124

125125
void TermsPage::enableAccept() {
126-
accept_btn->setText("Agree");
126+
accept_btn->setText(tr("Agree"));
127127
accept_btn->setEnabled(true);
128128
}
129129

@@ -137,7 +137,7 @@ void DeclinePage::showEvent(QShowEvent *event) {
137137
main_layout->setSpacing(40);
138138

139139
QLabel *text = new QLabel(this);
140-
text->setText("You must accept the Terms and Conditions in order to use openpilot.");
140+
text->setText(tr("You must accept the Terms and Conditions in order to use openpilot."));
141141
text->setStyleSheet(R"(font-size: 80px; font-weight: 300; margin: 200px;)");
142142
text->setWordWrap(true);
143143
main_layout->addWidget(text, 0, Qt::AlignCenter);
@@ -146,12 +146,12 @@ void DeclinePage::showEvent(QShowEvent *event) {
146146
buttons->setSpacing(45);
147147
main_layout->addLayout(buttons);
148148

149-
QPushButton *back_btn = new QPushButton("Back");
149+
QPushButton *back_btn = new QPushButton(tr("Back"));
150150
buttons->addWidget(back_btn);
151151

152152
QObject::connect(back_btn, &QPushButton::clicked, this, &DeclinePage::getBack);
153153

154-
QPushButton *uninstall_btn = new QPushButton(QString("Decline, uninstall %1").arg(getBrand()));
154+
QPushButton *uninstall_btn = new QPushButton(QString(tr("Decline, uninstall %1")).arg(getBrand()));
155155
uninstall_btn->setStyleSheet("background-color: #B73D3D");
156156
buttons->addWidget(uninstall_btn);
157157
QObject::connect(uninstall_btn, &QPushButton::clicked, [=]() {

0 commit comments

Comments
 (0)