From 23de7b166ea5e4e2b62ed4a5ce98ef05c0e98fb3 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Fri, 8 Jul 2022 20:25:54 -0700 Subject: [PATCH] UI: Internationalization support (#21212) * 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 * update names * Add Chinese (Simplified) translations * Do missing French translations * unit tests caught that :) * fix test * fix other test (on PC) * add entries to dialog to test * add cancel button, clean up a bit * just chinese * some clean up * use quotes * clean up * Just quit, set timeout to 0 * half a second * use exitcode * don't print if it's expected * this comment is outdated * update translations * Update translations * re-order input classes * Update line numbers * use enabled property for button style * Get rid of ListWidget * Update line numbers * Log failed to load language * Log failed to load language * Move to utils and fix english logging extra line * Update translations * spacing * looks a bit better * try this instead of exitcode fixes fix * only one function * comment * Update line numbers * fixup some japanese translations * clean up multi option dialog * Update line numbers old-commit-hash: 949de4d2b6b293d9f77d83c58212f5dee176cbf1 --- common/params.cc | 1 + common/watchdog.cc | 5 +- common/watchdog.h | 4 +- selfdrive/ui/main.cc | 9 ++ selfdrive/ui/qt/offroad/settings.cc | 14 ++ selfdrive/ui/qt/util.cc | 16 +++ selfdrive/ui/qt/util.h | 1 + selfdrive/ui/qt/widgets/input.cc | 86 ++++++++++++ selfdrive/ui/qt/widgets/input.h | 9 ++ selfdrive/ui/tests/test_translations.cc | 1 + selfdrive/ui/translations/main_ja.ts | 6 +- selfdrive/ui/translations/main_ko.qm | 4 +- selfdrive/ui/translations/main_ko.ts | 167 ++++++++++++----------- selfdrive/ui/translations/main_zh-CHS.qm | 4 +- selfdrive/ui/translations/main_zh-CHS.ts | 167 ++++++++++++----------- selfdrive/ui/translations/main_zh-CHT.qm | 4 +- selfdrive/ui/translations/main_zh-CHT.ts | 167 ++++++++++++----------- selfdrive/ui/ui.cc | 2 +- selfdrive/ui/update_translations.py | 2 +- 19 files changed, 410 insertions(+), 259 deletions(-) diff --git a/common/params.cc b/common/params.cc index f93c87cd98..c4f65a9e02 100644 --- a/common/params.cc +++ b/common/params.cc @@ -129,6 +129,7 @@ std::unordered_map keys = { {"IsUpdateAvailable", CLEAR_ON_MANAGER_START}, {"JoystickDebugMode", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_OFF}, {"LaikadEphemeris", PERSISTENT | DONT_LOG}, + {"LanguageSetting", PERSISTENT}, {"LastAthenaPingTime", CLEAR_ON_MANAGER_START}, {"LastGPSPosition", PERSISTENT}, {"LastManagerExitReason", CLEAR_ON_MANAGER_START}, diff --git a/common/watchdog.cc b/common/watchdog.cc index 5a10207828..920df4030a 100644 --- a/common/watchdog.cc +++ b/common/watchdog.cc @@ -1,12 +1,9 @@ #include "common/watchdog.h" -#include "common/timing.h" #include "common/util.h" const std::string watchdog_fn_prefix = "/dev/shm/wd_"; // + -bool watchdog_kick() { +bool watchdog_kick(uint64_t ts) { static std::string fn = watchdog_fn_prefix + std::to_string(getpid()); - - uint64_t ts = nanos_since_boot(); return util::write_file(fn.c_str(), &ts, sizeof(ts), O_WRONLY | O_CREAT) > 0; } diff --git a/common/watchdog.h b/common/watchdog.h index 7ed23aa0d9..12dd2ca035 100644 --- a/common/watchdog.h +++ b/common/watchdog.h @@ -1,3 +1,5 @@ #pragma once -bool watchdog_kick(); +#include + +bool watchdog_kick(uint64_t ts); diff --git a/selfdrive/ui/main.cc b/selfdrive/ui/main.cc index 1eecd78b19..ed54d5aa19 100644 --- a/selfdrive/ui/main.cc +++ b/selfdrive/ui/main.cc @@ -1,6 +1,7 @@ #include #include +#include #include "system/hardware/hw.h" #include "selfdrive/ui/qt/qt_window.h" @@ -13,7 +14,15 @@ int main(int argc, char *argv[]) { qInstallMessageHandler(swagLogMessageHandler); initApp(argc, argv); + QTranslator translator; + QString translation_file = QString::fromStdString(Params().get("LanguageSetting")); + if (!translator.load(translation_file, "translations") && translation_file.length()) { + qCritical() << "Failed to load translation file:" << translation_file; + } + QApplication a(argc, argv); + a.installTranslator(&translator); + MainWindow w; setMainWindow(&w); a.installEventFilter(&w); diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index a03af23951..6bcdd55b0a 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -13,6 +13,7 @@ #endif #include "common/params.h" +#include "common/watchdog.h" #include "common/util.h" #include "system/hardware/hw.h" #include "selfdrive/ui/qt/widgets/controls.h" @@ -133,6 +134,19 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) { addItem(regulatoryBtn); } + auto translateBtn = new ButtonControl(tr("Change Language"), tr("CHANGE"), ""); + connect(translateBtn, &ButtonControl::clicked, [=]() { + QMap langs = getSupportedLanguages(); + QString selection = MultiOptionDialog::getSelection(tr("Select a language"), langs.keys(), this); + if (!selection.isEmpty()) { + // put language setting, exit Qt UI, and trigger fast restart + Params().put("LanguageSetting", langs[selection].toStdString()); + qApp->exit(18); + watchdog_kick(0); + } + }); + addItem(translateBtn); + QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { for (auto btn : findChildren()) { btn->setEnabled(offroad); diff --git a/selfdrive/ui/qt/util.cc b/selfdrive/ui/qt/util.cc index cab7299cd6..a7d5438ae4 100644 --- a/selfdrive/ui/qt/util.cc +++ b/selfdrive/ui/qt/util.cc @@ -1,6 +1,9 @@ #include "selfdrive/ui/qt/util.h" #include +#include +#include +#include #include #include #include @@ -36,6 +39,19 @@ std::optional getDongleId() { } } +QMap getSupportedLanguages() { + QFile f("translations/languages.json"); + f.open(QIODevice::ReadOnly | QIODevice::Text); + QString val = f.readAll(); + + QJsonObject obj = QJsonDocument::fromJson(val.toUtf8()).object(); + QMap map; + for (auto key : obj.keys()) { + map[key] = obj[key].toString(); + } + return map; +} + void configFont(QPainter &p, const QString &family, int size, const QString &style) { QFont f(family); f.setPixelSize(size); diff --git a/selfdrive/ui/qt/util.h b/selfdrive/ui/qt/util.h index 9491c6798e..f0e57526c8 100644 --- a/selfdrive/ui/qt/util.h +++ b/selfdrive/ui/qt/util.h @@ -14,6 +14,7 @@ QString getBrand(); QString getBrandVersion(); QString getUserAgent(); std::optional getDongleId(); +QMap getSupportedLanguages(); void configFont(QPainter &p, const QString &family, int size, const QString &style); void clearLayout(QLayout* layout); void setQtSurfaceFormat(); diff --git a/selfdrive/ui/qt/widgets/input.cc b/selfdrive/ui/qt/widgets/input.cc index 755ccfe8c5..a130a8e935 100644 --- a/selfdrive/ui/qt/widgets/input.cc +++ b/selfdrive/ui/qt/widgets/input.cc @@ -1,6 +1,7 @@ #include "selfdrive/ui/qt/widgets/input.h" #include +#include #include "system/hardware/hw.h" #include "selfdrive/ui/qt/util.h" @@ -257,3 +258,88 @@ bool RichTextDialog::alert(const QString &prompt_text, QWidget *parent) { auto d = RichTextDialog(prompt_text, tr("Ok"), parent); return d.exec(); } + +// MultiOptionDialog + +MultiOptionDialog::MultiOptionDialog(const QString &prompt_text, QStringList l, QWidget *parent) : QDialogBase(parent) { + QFrame *container = new QFrame(this); + container->setStyleSheet(R"( + QFrame { background-color: #1B1B1B; } + #confirm_btn[enabled="false"] { background-color: #2B2B2B; } + #confirm_btn:enabled { background-color: #465BEA; } + #confirm_btn:enabled:pressed { background-color: #3049F4; } + )"); + + QVBoxLayout *main_layout = new QVBoxLayout(container); + main_layout->setContentsMargins(55, 50, 55, 50); + + QLabel *title = new QLabel(prompt_text, this); + title->setStyleSheet("font-size: 70px; font-weight: 500;"); + main_layout->addWidget(title, 0, Qt::AlignLeft | Qt::AlignTop); + main_layout->addSpacing(25); + + QWidget *listWidget = new QWidget(this); + QVBoxLayout *listLayout = new QVBoxLayout(listWidget); + listLayout->setSpacing(20); + listWidget->setStyleSheet(R"( + QPushButton { + height: 135; + padding: 0px 50px; + text-align: left; + font-size: 55px; + font-weight: 300; + border-radius: 10px; + background-color: #4F4F4F; + } + QPushButton:checked { background-color: #465BEA; } + )"); + + QButtonGroup *group = new QButtonGroup(listWidget); + group->setExclusive(true); + + QPushButton *confirm_btn = new QPushButton(tr("Select")); + confirm_btn->setObjectName("confirm_btn"); + confirm_btn->setEnabled(false); + + for (QString &s : l) { + QPushButton *selectionLabel = new QPushButton(s); + selectionLabel->setCheckable(true); + QObject::connect(selectionLabel, &QPushButton::toggled, [=](bool checked) { + if (checked) selection = s; + confirm_btn->setEnabled(true); + }); + + group->addButton(selectionLabel); + listLayout->addWidget(selectionLabel); + } + + ScrollView *scroll_view = new ScrollView(listWidget, this); + scroll_view->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + + main_layout->addWidget(scroll_view); + main_layout->addStretch(1); + main_layout->addSpacing(35); + + // cancel + confirm buttons + QHBoxLayout *blayout = new QHBoxLayout; + main_layout->addLayout(blayout); + blayout->setSpacing(50); + + QPushButton *cancel_btn = new QPushButton(tr("Cancel")); + QObject::connect(cancel_btn, &QPushButton::clicked, this, &ConfirmationDialog::reject); + QObject::connect(confirm_btn, &QPushButton::clicked, this, &ConfirmationDialog::accept); + blayout->addWidget(cancel_btn); + blayout->addWidget(confirm_btn); + + QVBoxLayout *outer_layout = new QVBoxLayout(this); + outer_layout->setContentsMargins(50, 50, 50, 50); + outer_layout->addWidget(container); +} + +QString MultiOptionDialog::getSelection(const QString &prompt_text, const QStringList l, QWidget *parent) { + MultiOptionDialog d = MultiOptionDialog(prompt_text, l, parent); + if (d.exec()) { + return d.selection; + } + return ""; +} diff --git a/selfdrive/ui/qt/widgets/input.h b/selfdrive/ui/qt/widgets/input.h index f81211d0ee..47d8b74efd 100644 --- a/selfdrive/ui/qt/widgets/input.h +++ b/selfdrive/ui/qt/widgets/input.h @@ -68,3 +68,12 @@ public: explicit RichTextDialog(const QString &prompt_text, const QString &btn_text, QWidget* parent); static bool alert(const QString &prompt_text, QWidget *parent); }; + +class MultiOptionDialog : public QDialogBase { + Q_OBJECT + +public: + explicit MultiOptionDialog(const QString &prompt_text, const QStringList l, QWidget *parent); + static QString getSelection(const QString &prompt_text, const QStringList l, QWidget *parent); + QString selection; +}; diff --git a/selfdrive/ui/tests/test_translations.cc b/selfdrive/ui/tests/test_translations.cc index fecb9da44a..ba0612b4c0 100644 --- a/selfdrive/ui/tests/test_translations.cc +++ b/selfdrive/ui/tests/test_translations.cc @@ -41,6 +41,7 @@ void checkWidgetTrWrap(MainWindow &w) { // Tests all strings in the UI are wrapped with tr() TEST_CASE("UI: test all strings wrapped") { + Params().remove("LanguageSetting"); Params().remove("HardwareSerial"); Params().remove("DongleId"); qputenv("TICI", "1"); diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index fbb654bc4c..5c0f54a314 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -528,12 +528,12 @@ location set ✓ SUBSCRIBED - ✓ 購読 + ✓ 購読しました comma prime - コンマプライム + comma prime @@ -543,7 +543,7 @@ location set COMMA POINTS - コンマポイント + COMMA POINTS diff --git a/selfdrive/ui/translations/main_ko.qm b/selfdrive/ui/translations/main_ko.qm index 6b01185a21..f43a809720 100644 --- a/selfdrive/ui/translations/main_ko.qm +++ b/selfdrive/ui/translations/main_ko.qm @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17e593ed333ec26105a924caa274616318933560dbf30c40ec8e734b4ecf2e6c -size 19159 +oid sha256:194b46eb36b6b4c98d9d0a6db7bf926099dbb8d72dcb1d50566c4b26cf540c8d +size 19449 diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index fd643224cc..91685383f7 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -76,13 +76,13 @@ ConfirmationDialog - - + + Ok 확인 - + Cancel 취소 @@ -108,149 +108,152 @@ DevicePanel - + Dongle ID Dongle ID - + N/A N/A - + Serial Serial - + Driver Camera 운전자 카메라 - + PREVIEW 미리보기 - + Preview the driver facing camera to help optimize device mounting position for best driver monitoring experience. (vehicle must be off) 운전자 카메라를 미리 보면서 최적의 운전자 모니터링 경험을 위해 기기 장착 위치를 최적화할수 있습니다. (차량은 반드시 닫아야 합니다) - + Reset Calibration 캘리브레이션 재설정 - + RESET 재설정 - + Are you sure you want to reset calibration? 캘리브레이션을 재설정하시겠습니까? - + Review Training Guide 트레이닝 가이드 다시보기 - + REVIEW 다시보기 - + Review the rules, features, and limitations of openpilot openpilot의 규칙, 기능, 제한 다시보기 - + Are you sure you want to review the training guide? 트레이닝 가이드를 다시보시겠습니까? - + Regulatory 규제 - + VIEW 보기 + Change Language - 언어변경 + 언어변경 + CHANGE - 변경 + 변경 + Select a language - 언어선택 + 언어선택 - + Reboot 재부팅 - + Power Off 전원 종료 - + openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. openpilot은 장치를 왼쪽 또는 오른쪽 4° 이내, 위쪽 5° 또는 아래쪽 8° 이내로 설치해야 합니다. openpilot은 지속적으로 보정되므로 리셋이 거의 필요하지 않습니다. - + Your device is pointed %1° %2 and %3° %4. 사용자의 기기가 %1° %2 및 %3° %4를 가리키고 있습니다. - + down 아래 - + up - + left 왼쪽 - + right 오른쪽 - + Are you sure you want to reboot? 재부팅 하시겠습니까? - + Disengage to Reboot 재부팅 하려면 해제하세요 - + Are you sure you want to power off? 전원을 종료하시겠습니까? - + Disengage to Power Off 전원을 종료하려면 해제하세요 @@ -299,17 +302,17 @@ InputDialog - + Cancel 취소 - + Need at least 최소 필요 - + characters! 문자! @@ -389,12 +392,14 @@ location set MultiOptionDialog + Select - 선택 + 선택 + Cancel - 취소 + 취소 @@ -564,27 +569,27 @@ location set 종료 - + dashcam dashcam - + openpilot openpilot - + %1 minute%2 ago %1 분%2 전 - + %1 hour%2 ago %1 시간%2 전 - + %1 day%2 ago %1 일%2 전 @@ -640,7 +645,7 @@ location set RichTextDialog - + Ok 확인 @@ -648,33 +653,33 @@ location set SettingsWindow - + × × - + Device 장치 - - + + Network 네트워크 - + Toggles 토글 - + Software 소프트웨어 - + Navigation 네비게이션 @@ -913,68 +918,68 @@ location set SoftwarePanel - + Git Branch Git 브렌치 - + Git Commit Git 커밋 - + OS Version OS 버전 - + Version 버전 - + Last Update Check 최신 업데이트 검사 - + The last time openpilot successfully checked for an update. The updater only runs while the car is off. 이전에 openpilot에서 업데이트를 성공적으로 확인한 시간입니다. 업데이트 프로그램은 차량 연결이 해제되었을때만 작동합니다. - + Check for Update 업데이트 확인 - + CHECKING 검사중 - + Uninstall 삭제 - + UNINSTALL 삭제 - + Are you sure you want to uninstall? 삭제하시겠습니까? - + failed to fetch update 업데이트를 가져올수없습니다 - - + + CHECK 확인 @@ -1062,82 +1067,82 @@ location set TogglesPanel - + Enable openpilot openpilot 사용 - + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. 어댑티브 크루즈 컨트롤 및 차선 유지 운전자 보조를 위해 openpilot 시스템을 사용하십시오. 이 기능을 사용하려면 항상 주의를 기울여야 합니다. 이 설정을 변경하면 차량 전원이 꺼질 때 적용됩니다. - + Enable Lane Departure Warnings 차선 이탈 경고 사용 - + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). 차량이 50km/h(31mph) 이상의 속도로 주행하는 동안 방향 지시등이 활성화되지 않은 상태에서 감지된 차선 위를 주행할 경우 차선이탈 경고를 사용합니다. - + Enable Right-Hand Drive 우측핸들 사용 - + Allow openpilot to obey left-hand traffic conventions and perform driver monitoring on right driver seat. openpilot이 좌측 교통 규칙을 준수하고 우측 운전석에서 운전자 모니터링을 수행합니다. - + Use Metric System 미터법 사용 - + Display speed in km/h instead of mph. mph가 아닌 km/h로 속도 표시. - + Record and Upload Driver Camera 운전자 카메라 기록 및 업로드 - + Upload data from the driver facing camera and help improve the driver monitoring algorithm. 운전자 카메라에서 데이터를 업로드하고 운전자 모니터링 알고리즘을 개선합니다. - + Disengage On Accelerator Pedal 가속페달 조작시 해제 - + When enabled, pressing the accelerator pedal will disengage openpilot. 활성화된 경우 가속 페달을 누르면 openpilot이 해제됩니다. - + Show ETA in 24h format 24시간 형식으로 ETA 표시 - + Use 24h format instead of am/pm 오전/오후 대신 24시간 형식 사용 - + openpilot Longitudinal Control openpilot Longitudinal Control - + openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! openpilot은 차량'의 레이더를 무력화시키고 가속페달과 브레이크의 제어를 인계받을 것이다. 경고: AEB를 비활성화합니다! diff --git a/selfdrive/ui/translations/main_zh-CHS.qm b/selfdrive/ui/translations/main_zh-CHS.qm index 144100345d..2ad0b2e8d6 100644 --- a/selfdrive/ui/translations/main_zh-CHS.qm +++ b/selfdrive/ui/translations/main_zh-CHS.qm @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df73115bb4badb41c4b5e4ec40701df8e09f6efd4f7028fc940f0eb07a00e20c -size 17629 +oid sha256:ef08cf58d66497a054c8bf978aebeffa3bb74772b80cfa07cfcbc49e2b111e17 +size 17919 diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index b187794058..1bcb30142c 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -76,13 +76,13 @@ ConfirmationDialog - - + + Ok 好的 - + Cancel 取消 @@ -108,149 +108,152 @@ DevicePanel - + Dongle ID 加密狗 ID - + N/A 不适用 - + Serial 串行 - + Driver Camera 司机摄像头 - + PREVIEW 预习 - + Preview the driver facing camera to help optimize device mounting position for best driver monitoring experience. (vehicle must be off) 预览面向驾驶员的摄像头,以帮助优化设备安装位置以获得最佳驾驶员监控体验。 (车辆必须关闭) - + Reset Calibration 重置校准 - + RESET 重置 - + Are you sure you want to reset calibration? 您确定要重置校准吗? - + Review Training Guide 查看培训指南 - + REVIEW 重新查看 - + Review the rules, features, and limitations of openpilot 查看 openpilot 的规则、功能和限制 - + Are you sure you want to review the training guide? 您确定要查看培训指南吗? - + Regulatory 监管 - + VIEW 查看 + Change Language - 切换语言 + 切换语言 + CHANGE - 切换 + 切换 + Select a language - 选择语言 + 选择语言 - + Reboot 重启 - + Power Off 关机 - + openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. openpilot 要求设备安装在左或右 4° 以内,上 5° 或下 8° 以内。 openpilot 会持续校准,很少需要重置。 - + Your device is pointed %1° %2 and %3° %4. 您的设备指向 %1° %2 和 %3° %4。 - + down - + up 向上 - + left 向左 - + right 向右 - + Are you sure you want to reboot? 您确定要重新启动吗? - + Disengage to Reboot 脱离以重新启动 - + Are you sure you want to power off? 您确定要关闭电源吗? - + Disengage to Power Off 脱离以关闭电源 @@ -299,17 +302,17 @@ InputDialog - + Cancel 取消 - + Need at least 需要至少 - + characters! 字符! @@ -389,12 +392,14 @@ location set MultiOptionDialog + Select - 选择 + 选择 + Cancel - 取消 + 取消 @@ -564,27 +569,27 @@ location set 退出 - + dashcam 行车记录器 - + openpilot openpilot - + %1 minute%2 ago %1 分钟%2 前 - + %1 hour%2 ago %1 小时%2 前 - + %1 day%2 ago %1 天%2 前 @@ -640,7 +645,7 @@ location set RichTextDialog - + Ok 好的 @@ -648,33 +653,33 @@ location set SettingsWindow - + × × - + Device 设备 - - + + Network 网络 - + Toggles 切换 - + Software 软件 - + Navigation 导航 @@ -913,68 +918,68 @@ location set SoftwarePanel - + Git Branch Git 分支 - + Git Commit Git 提交 - + OS Version 操作系统版本 - + Version 版本 - + Last Update Check 最后更新检查 - + The last time openpilot successfully checked for an update. The updater only runs while the car is off. 上次 openpilot 成功检查更新的时间。 更新程序仅在汽车关闭时运行。 - + Check for Update 检查更新 - + CHECKING 正在检查 - + Uninstall 卸载 - + UNINSTALL 卸载 - + Are you sure you want to uninstall? 您确定要卸载吗? - + failed to fetch update 未能获取更新 - - + + CHECK 查看 @@ -1062,82 +1067,82 @@ location set TogglesPanel - + Enable openpilot 启用 openpilot - + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. 使用 openpilot 系统进行自适应巡航控制和车道保持驾驶员辅助。 任何时候都需要您注意使用此功能。 更改此设置在汽车断电时生效。 - + Enable Lane Departure Warnings 启用车道偏离警告 - + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). 当您的车辆在以超过 31 英里/小时(50 公里/小时)的速度行驶时在检测到的车道线上漂移而没有激活转向信号时,接收提醒以返回车道。 - + Enable Right-Hand Drive 启用右舵模式 - + Allow openpilot to obey left-hand traffic conventions and perform driver monitoring on right driver seat. 允许 openpilot 遵守左侧交通惯例并在右侧驾驶座上执行驾驶员监控。 - + Use Metric System 使用公制 - + Display speed in km/h instead of mph. 以公里/小时而不是英里/小时显示速度。 - + Record and Upload Driver Camera 记录和上传司机摄像头 - + Upload data from the driver facing camera and help improve the driver monitoring algorithm. 从面向驾驶员的摄像头上传数据,帮助改进驾驶员监控算法。 - + Disengage On Accelerator Pedal 踩油门解除 - + When enabled, pressing the accelerator pedal will disengage openpilot. 启用后,踩下油门踏板将解除 openpilot。 - + Show ETA in 24h format 以 24 小时格式显示 ETA - + Use 24h format instead of am/pm 使用 24 小时制代替上午/下午 - + openpilot Longitudinal Control openpilot 纵向控制 - + openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! openpilot 将禁用汽车的雷达并接管油门和刹车的控制。 警告:这会禁用 AEB! diff --git a/selfdrive/ui/translations/main_zh-CHT.qm b/selfdrive/ui/translations/main_zh-CHT.qm index 158d6c550c..137759dae5 100644 --- a/selfdrive/ui/translations/main_zh-CHT.qm +++ b/selfdrive/ui/translations/main_zh-CHT.qm @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f08c65839c552bab3f835d3384a1374158cb53e988bdc516b5e9d9a2da0e2715 -size 17741 +oid sha256:a8a04d85bc163299f9f79b45e5e9b1d44ade7926c9a254d57b1edd4372f51948 +size 18031 diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index 29b5f26b2b..2aff3334d9 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -76,13 +76,13 @@ ConfirmationDialog - - + + Ok 確定 - + Cancel 取消 @@ -108,149 +108,152 @@ DevicePanel - + Dongle ID Dongle ID - + N/A 無法使用 - + Serial 序號 - + Driver Camera 駕駛監控 - + PREVIEW 預覽 - + Preview the driver facing camera to help optimize device mounting position for best driver monitoring experience. (vehicle must be off) 預覽駕駛監控鏡頭畫面,方便調整設備安裝的位置,以提供更準確的駕駛監控。(車子必須保持在熄火的狀態) - + Reset Calibration 重置校準 - + RESET 重置 - + Are you sure you want to reset calibration? 您確定要重置校準嗎? - + Review Training Guide 觀看使用教學 - + REVIEW 觀看 - + Review the rules, features, and limitations of openpilot 觀看 openpilot 的使用規則、功能和限制 - + Are you sure you want to review the training guide? 您確定要觀看使用教學嗎? - + Regulatory 法規/監管 - + VIEW 觀看 + Change Language - 更改語言 + 更改語言 + CHANGE - 更改 + 更改 + Select a language - 選擇語言 + 選擇語言 - + Reboot 重新啟動 - + Power Off 關機 - + openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. openpilot 需要將裝置固定在左右偏差 4° 以內,朝上偏差 5° 以内或朝下偏差 8° 以内。鏡頭在後台會持續自動校準,很少有需要重置的情况。 - + Your device is pointed %1° %2 and %3° %4. 你的設備目前朝%2 %1° 以及朝%4 %3° 。 - + down - + up - + left - + right - + Are you sure you want to reboot? 您確定要重新啟動嗎? - + Disengage to Reboot 請先取消控車才能重新啟動 - + Are you sure you want to power off? 您確定您要關機嗎? - + Disengage to Power Off 請先取消控車才能關機 @@ -299,17 +302,17 @@ InputDialog - + Cancel 取消 - + Need at least 需要至少 - + characters! 個字元! @@ -394,12 +397,14 @@ location set MultiOptionDialog + Select - 選擇 + 選擇 + Cancel - 取消 + 取消 @@ -569,29 +574,29 @@ location set 離開 - + dashcam 行車記錄器 - + openpilot openpilot - + %1 minute%2 ago we don't need %2 %1 分鐘前 - + %1 hour%2 ago we don't need %2 %1 小時前 - + %1 day%2 ago we don't need %2 %1 天前 @@ -648,7 +653,7 @@ location set RichTextDialog - + Ok 確定 @@ -656,33 +661,33 @@ location set SettingsWindow - + × × - + Device 設備 - - + + Network 網路 - + Toggles 設定 - + Software 軟體 - + Navigation 導航 @@ -921,68 +926,68 @@ location set SoftwarePanel - + Git Branch Git 分支 - + Git Commit Git 提交 - + OS Version 系統版本 - + Version 版本 - + Last Update Check 上次檢查時間 - + The last time openpilot successfully checked for an update. The updater only runs while the car is off. 上次成功檢查更新的時間。更新系統只會在車子熄火時執行。 - + Check for Update 檢查更新 - + CHECKING 檢查中 - + Uninstall 卸載 - + UNINSTALL 卸載 - + Are you sure you want to uninstall? 您確定您要卸載嗎? - + failed to fetch update 下載更新失敗 - - + + CHECK 檢查 @@ -1070,82 +1075,82 @@ location set TogglesPanel - + Enable openpilot 啟用 openpilot - + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. 使用 openpilot 的主動式巡航和車道保持功能,開啟後您需要持續集中注意力,設定變更在重新啟動車輛後生效。 - + Enable Lane Departure Warnings 啟用車道偏離警告 - + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). 車速在時速 50 公里 (31 英里) 以上且未打方向燈的情況下,如果偵測到車輛駛出目前車道線時,發出車道偏離警告。 - + Enable Right-Hand Drive 啟用右駕模式 - + Allow openpilot to obey left-hand traffic conventions and perform driver monitoring on right driver seat. openpilot 將對右側駕駛進行監控 (但仍遵守靠左駕的交通慣例)。 - + Use Metric System 使用公制單位 - + Display speed in km/h instead of mph. 啟用後,速度單位顯示將從 mp/h 改為 km/h。 - + Record and Upload Driver Camera 記錄並上傳駕駛監控影像 - + Upload data from the driver facing camera and help improve the driver monitoring algorithm. 上傳駕駛監控的錄像來協助我們提升駕駛監控的準確率。 - + Disengage On Accelerator Pedal 油門取消控車 - + When enabled, pressing the accelerator pedal will disengage openpilot. 啟用後,踩踏油門將會取消 openpilot 控制。 - + Show ETA in 24h format 預計到達時間單位改用 24 小時制 - + Use 24h format instead of am/pm 使用 24 小時制。(預設值為 12 小時制) - + openpilot Longitudinal Control openpilot 縱向控制 - + openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! openpilot 將會關閉雷達訊號並接管油門和剎車的控制。注意:這也會關閉自動緊急煞車 (AEB) 系統! diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 6fe1d838ed..7922714c17 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -246,7 +246,7 @@ void UIState::update() { updateStatus(); if (sm->frame % UI_FREQ == 0) { - watchdog_kick(); + watchdog_kick(nanos_since_boot()); } emit uiUpdate(*this); } diff --git a/selfdrive/ui/update_translations.py b/selfdrive/ui/update_translations.py index 263eb5e670..d872be0d86 100755 --- a/selfdrive/ui/update_translations.py +++ b/selfdrive/ui/update_translations.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import argparse -import os import json +import os from common.basedir import BASEDIR