Merge branch 'master' into pq-upstream

pull/24768/head
Jason Young 3 years ago
commit ed23d65fbc
  1. 2
      docs/CARS.md
  2. 2
      opendbc
  3. 2
      selfdrive/car/docs.py
  4. 18
      selfdrive/car/hyundai/values.py
  5. 12
      selfdrive/car/subaru/carcontroller.py
  6. 6
      selfdrive/car/subaru/carstate.py
  7. 6
      selfdrive/car/subaru/subarucan.py
  8. 3
      selfdrive/car/volkswagen/values.py
  9. 24
      selfdrive/test/setup_device_ci.sh
  10. 5
      selfdrive/ui/qt/offroad/settings.cc
  11. 30
      selfdrive/ui/tests/test_translations.cc
  12. 11
      selfdrive/ui/tests/test_translations.py
  13. 21
      selfdrive/ui/translations/README.md
  14. BIN
      selfdrive/ui/translations/main_ja.qm
  15. 536
      selfdrive/ui/translations/main_ja.ts
  16. 34
      selfdrive/ui/translations/main_ko.ts
  17. 34
      selfdrive/ui/translations/main_zh-CHS.ts
  18. 34
      selfdrive/ui/translations/main_zh-CHT.ts
  19. 10
      selfdrive/ui/update_translations.py

@ -100,7 +100,7 @@ How We Rate The Cars
|Kia|Niro Electric 2022|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>| |Kia|Niro Electric 2022|All|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|Kia|Niro Hybrid 2021|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>| |Kia|Niro Hybrid 2021|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|Kia|Niro Hybrid 2022|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>| |Kia|Niro Hybrid 2022|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|Kia|Niro Plug-in Hybrid 2019|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>| |Kia|Niro Plug-in Hybrid 2018-19|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|Kia|Optima 2017|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>| |Kia|Optima 2017|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|Kia|Optima 2019|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>| |Kia|Optima 2019|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|Kia|Seltos 2021|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>| |Kia|Seltos 2021|SCC + LKAS|<a href="##"><img valign="top" src="assets/icon-star-empty.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="##"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|

@ -1 +1 @@
Subproject commit aaf397ed51f3040b2fb3f2bb17feaadb8c6ba743 Subproject commit e2465cc701e878fdae5b4e363496c2fa5d2f7c08

@ -58,7 +58,7 @@ def generate_cars_md(all_car_info: List[CarInfo], template_fn: str, only_tier_co
for c in hide_cols: for c in hide_cols:
del car.row[c] del car.row[c]
footnotes = [fn.value.text for fn in ALL_FOOTNOTES] footnotes = [fn.value.text for fn in ALL_FOOTNOTES if fn.value.column in cols]
cars_md: str = template.render(all_car_info=all_car_info, cars_md: str = template.render(all_car_info=all_car_info,
footnotes=footnotes, Star=Star, Column=cols, star_descriptions=STAR_DESCRIPTIONS) footnotes=footnotes, Star=Star, Column=cols, star_descriptions=STAR_DESCRIPTIONS)
return cars_md return cars_md

@ -136,7 +136,7 @@ CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = {
HyundaiCarInfo("Kia Niro Electric 2021", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo", harness=Harness.hyundai_c), HyundaiCarInfo("Kia Niro Electric 2021", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo", harness=Harness.hyundai_c),
HyundaiCarInfo("Kia Niro Electric 2022", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo", harness=Harness.hyundai_h), HyundaiCarInfo("Kia Niro Electric 2022", "All", video_link="https://www.youtube.com/watch?v=lT7zcG6ZpGo", harness=Harness.hyundai_h),
], ],
CAR.KIA_NIRO_HEV: HyundaiCarInfo("Kia Niro Plug-in Hybrid 2019", min_enable_speed=10. * CV.MPH_TO_MS, harness=Harness.hyundai_c), CAR.KIA_NIRO_HEV: HyundaiCarInfo("Kia Niro Plug-in Hybrid 2018-19", min_enable_speed=10. * CV.MPH_TO_MS, harness=Harness.hyundai_c),
CAR.KIA_NIRO_HEV_2021: [ CAR.KIA_NIRO_HEV_2021: [
HyundaiCarInfo("Kia Niro Hybrid 2021", harness=Harness.hyundai_f), # TODO: could be hyundai_d, verify HyundaiCarInfo("Kia Niro Hybrid 2021", harness=Harness.hyundai_f), # TODO: could be hyundai_d, verify
HyundaiCarInfo("Kia Niro Hybrid 2022", harness=Harness.hyundai_h), HyundaiCarInfo("Kia Niro Hybrid 2022", harness=Harness.hyundai_h),
@ -986,20 +986,24 @@ FW_VERSIONS = {
}, },
CAR.KIA_NIRO_HEV: { CAR.KIA_NIRO_HEV: {
(Ecu.engine, 0x7e0, None): [ (Ecu.engine, 0x7e0, None): [
b'\xf1\x816H6F4051\000\000\000\000\000\000\000\000', b'\xf1\x816H6F4051\x00\x00\x00\x00\x00\x00\x00\x00',
b'\xf1\x816H6D1051\x00\x00\x00\x00\x00\x00\x00\x00',
], ],
(Ecu.transmission, 0x7e1, None): [ (Ecu.transmission, 0x7e1, None): [
b"\xf1\x816U3J2051\000\000\xf1\0006U3H0_C2\000\0006U3J2051\000\000PDE0G16NS2\xf4\'\\\x91", b"\xf1\x816U3J2051\x00\x00\xf1\x006U3H0_C2\x00\x006U3J2051\x00\x00PDE0G16NS2\xf4'\\\x91",
b'\xf1\x816U3J2051\000\000\xf1\0006U3H0_C2\000\0006U3J2051\000\000PDE0G16NS2\000\000\000\000', b'\xf1\x816U3J2051\x00\x00\xf1\x006U3H0_C2\x00\x006U3J2051\x00\x00PDE0G16NS2\x00\x00\x00\x00',
b'\xf1\x816U3H3051\x00\x00\xf1\x006U3H0_C2\x00\x006U3H3051\x00\x00PDE0G16NS1\x00\x00\x00\x00',
b'\xf1\x816U3H3051\x00\x00\xf1\x006U3H0_C2\x00\x006U3H3051\x00\x00PDE0G16NS1\x13\xcd\x88\x92',
], ],
(Ecu.eps, 0x7D4, None): [ (Ecu.eps, 0x7D4, None): [
b'\xf1\000DE MDPS C 1.00 1.09 56310G5301\000 4DEHC109', b'\xf1\x00DE MDPS C 1.00 1.09 56310G5301\x00 4DEHC109',
], ],
(Ecu.fwdCamera, 0x7C4, None): [ (Ecu.fwdCamera, 0x7C4, None): [
b'\xf1\000DEP MFC AT USA LHD 1.00 1.01 95740-G5010 170424', b'\xf1\x00DEP MFC AT USA LHD 1.00 1.01 95740-G5010 170424',
b'\xf1\x00DEP MFC AT USA LHD 1.00 1.00 95740-G5010 170117',
], ],
(Ecu.fwdRadar, 0x7D0, None): [ (Ecu.fwdRadar, 0x7D0, None): [
b'\xf1\000DEhe SCC H-CUP 1.01 1.02 96400-G5100 ', b'\xf1\x00DEhe SCC H-CUP 1.01 1.02 96400-G5100 ',
], ],
}, },
CAR.KIA_NIRO_HEV_2021: { CAR.KIA_NIRO_HEV_2021: {

@ -49,7 +49,7 @@ class CarController:
# *** alerts and pcm cancel *** # *** alerts and pcm cancel ***
if self.CP.carFingerprint in PREGLOBAL_CARS: if self.CP.carFingerprint in PREGLOBAL_CARS:
if self.es_distance_cnt != CS.es_distance_msg["Counter"]: if self.es_distance_cnt != CS.es_distance_msg["COUNTER"]:
# 1 = main, 2 = set shallow, 3 = set deep, 4 = resume shallow, 5 = resume deep # 1 = main, 2 = set shallow, 3 = set deep, 4 = resume shallow, 5 = resume deep
# disengage ACC when OP is disengaged # disengage ACC when OP is disengaged
if pcm_cancel_cmd: if pcm_cancel_cmd:
@ -66,16 +66,16 @@ class CarController:
self.cruise_button_prev = cruise_button self.cruise_button_prev = cruise_button
can_sends.append(subarucan.create_preglobal_es_distance(self.packer, cruise_button, CS.es_distance_msg)) can_sends.append(subarucan.create_preglobal_es_distance(self.packer, cruise_button, CS.es_distance_msg))
self.es_distance_cnt = CS.es_distance_msg["Counter"] self.es_distance_cnt = CS.es_distance_msg["COUNTER"]
else: else:
if self.es_distance_cnt != CS.es_distance_msg["Counter"]: if self.es_distance_cnt != CS.es_distance_msg["COUNTER"]:
can_sends.append(subarucan.create_es_distance(self.packer, CS.es_distance_msg, pcm_cancel_cmd)) can_sends.append(subarucan.create_es_distance(self.packer, CS.es_distance_msg, pcm_cancel_cmd))
self.es_distance_cnt = CS.es_distance_msg["Counter"] self.es_distance_cnt = CS.es_distance_msg["COUNTER"]
if self.es_lkas_cnt != CS.es_lkas_msg["Counter"]: if self.es_lkas_cnt != CS.es_lkas_msg["COUNTER"]:
can_sends.append(subarucan.create_es_lkas(self.packer, CS.es_lkas_msg, CC.enabled, hud_control.visualAlert, hud_control.leftLaneVisible, hud_control.rightLaneVisible, hud_control.leftLaneDepart, hud_control.rightLaneDepart)) can_sends.append(subarucan.create_es_lkas(self.packer, CS.es_lkas_msg, CC.enabled, hud_control.visualAlert, hud_control.leftLaneVisible, hud_control.rightLaneVisible, hud_control.leftLaneDepart, hud_control.rightLaneDepart))
self.es_lkas_cnt = CS.es_lkas_msg["Counter"] self.es_lkas_cnt = CS.es_lkas_msg["COUNTER"]
new_actuators = actuators.copy() new_actuators = actuators.copy()
new_actuators.steer = self.apply_steer_last / self.p.STEER_MAX new_actuators.steer = self.apply_steer_last / self.p.STEER_MAX

@ -173,7 +173,7 @@ class CarState(CarStateBase):
("Standstill_2", "ES_Distance"), ("Standstill_2", "ES_Distance"),
("Cruise_Fault", "ES_Distance"), ("Cruise_Fault", "ES_Distance"),
("Signal5", "ES_Distance"), ("Signal5", "ES_Distance"),
("Counter", "ES_Distance"), ("COUNTER", "ES_Distance"),
("Signal6", "ES_Distance"), ("Signal6", "ES_Distance"),
("Cruise_Button", "ES_Distance"), ("Cruise_Button", "ES_Distance"),
("Signal7", "ES_Distance"), ("Signal7", "ES_Distance"),
@ -188,7 +188,7 @@ class CarState(CarStateBase):
("Cruise_Set_Speed", "ES_DashStatus"), ("Cruise_Set_Speed", "ES_DashStatus"),
("Conventional_Cruise", "ES_DashStatus"), ("Conventional_Cruise", "ES_DashStatus"),
("Counter", "ES_Distance"), ("COUNTER", "ES_Distance"),
("Signal1", "ES_Distance"), ("Signal1", "ES_Distance"),
("Cruise_Fault", "ES_Distance"), ("Cruise_Fault", "ES_Distance"),
("Cruise_Throttle", "ES_Distance"), ("Cruise_Throttle", "ES_Distance"),
@ -206,7 +206,7 @@ class CarState(CarStateBase):
("Cruise_Resume", "ES_Distance"), ("Cruise_Resume", "ES_Distance"),
("Signal6", "ES_Distance"), ("Signal6", "ES_Distance"),
("Counter", "ES_LKAS_State"), ("COUNTER", "ES_LKAS_State"),
("LKAS_Alert_Msg", "ES_LKAS_State"), ("LKAS_Alert_Msg", "ES_LKAS_State"),
("Signal1", "ES_LKAS_State"), ("Signal1", "ES_LKAS_State"),
("LKAS_ACTIVE", "ES_LKAS_State"), ("LKAS_ACTIVE", "ES_LKAS_State"),

@ -8,13 +8,12 @@ def create_steering_control(packer, apply_steer, frame, steer_step):
idx = (frame / steer_step) % 16 idx = (frame / steer_step) % 16
values = { values = {
"Counter": idx,
"LKAS_Output": apply_steer, "LKAS_Output": apply_steer,
"LKAS_Request": 1 if apply_steer != 0 else 0, "LKAS_Request": 1 if apply_steer != 0 else 0,
"SET_1": 1 "SET_1": 1
} }
return packer.make_can_msg("ES_LKAS", 0, values) return packer.make_can_msg("ES_LKAS", 0, values, idx)
def create_steering_status(packer, apply_steer, frame, steer_step): def create_steering_status(packer, apply_steer, frame, steer_step):
return packer.make_can_msg("ES_LKAS_State", 0, {}) return packer.make_can_msg("ES_LKAS_State", 0, {})
@ -72,13 +71,12 @@ def create_preglobal_steering_control(packer, apply_steer, frame, steer_step):
idx = (frame / steer_step) % 8 idx = (frame / steer_step) % 8
values = { values = {
"Counter": idx,
"LKAS_Command": apply_steer, "LKAS_Command": apply_steer,
"LKAS_Active": 1 if apply_steer != 0 else 0 "LKAS_Active": 1 if apply_steer != 0 else 0
} }
values["Checksum"] = subaru_preglobal_checksum(packer, values, "ES_LKAS") values["Checksum"] = subaru_preglobal_checksum(packer, values, "ES_LKAS")
return packer.make_can_msg("ES_LKAS", 0, values) return packer.make_can_msg("ES_LKAS", 0, values, idx)
def create_preglobal_es_distance(packer, cruise_button, es_distance_msg): def create_preglobal_es_distance(packer, cruise_button, es_distance_msg):

@ -294,6 +294,7 @@ FW_VERSIONS = {
b'\xf1\x8704E906023BN\xf1\x894518', b'\xf1\x8704E906023BN\xf1\x894518',
b'\xf1\x8704E906024K \xf1\x896811', b'\xf1\x8704E906024K \xf1\x896811',
b'\xf1\x8704E906027GR\xf1\x892394', b'\xf1\x8704E906027GR\xf1\x892394',
b'\xf1\x8704E906027HD\xf1\x892603',
b'\xf1\x8704E906027HD\xf1\x893742', b'\xf1\x8704E906027HD\xf1\x893742',
b'\xf1\x8704E906027MA\xf1\x894958', b'\xf1\x8704E906027MA\xf1\x894958',
b'\xf1\x8704L906021DT\xf1\x895520', b'\xf1\x8704L906021DT\xf1\x895520',
@ -331,6 +332,7 @@ FW_VERSIONS = {
(Ecu.transmission, 0x7e1, None): [ (Ecu.transmission, 0x7e1, None): [
b'\xf1\x8709G927749AP\xf1\x892943', b'\xf1\x8709G927749AP\xf1\x892943',
b'\xf1\x8709S927158A \xf1\x893585', b'\xf1\x8709S927158A \xf1\x893585',
b'\xf1\x870CW300040H \xf1\x890606',
b'\xf1\x870CW300041H \xf1\x891010', b'\xf1\x870CW300041H \xf1\x891010',
b'\xf1\x870CW300042F \xf1\x891604', b'\xf1\x870CW300042F \xf1\x891604',
b'\xf1\x870CW300043B \xf1\x891601', b'\xf1\x870CW300043B \xf1\x891601',
@ -407,6 +409,7 @@ FW_VERSIONS = {
b'\xf1\x875Q0909144L \xf1\x891021\xf1\x82\x0521A00502A0', b'\xf1\x875Q0909144L \xf1\x891021\xf1\x82\x0521A00502A0',
b'\xf1\x875Q0909144P \xf1\x891043\xf1\x82\00511A00403A0', b'\xf1\x875Q0909144P \xf1\x891043\xf1\x82\00511A00403A0',
b'\xf1\x875Q0909144R \xf1\x891061\xf1\x82\00516A00604A1', b'\xf1\x875Q0909144R \xf1\x891061\xf1\x82\00516A00604A1',
b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\x0516A00404A1',
b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\00516A00604A1', b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\00516A00604A1',
b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\00516A07A02A1', b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\00516A07A02A1',
b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\00521A00507A1', b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\00521A00507A1',

@ -21,28 +21,26 @@ umount /data/safe_staging/merged/ || true
sudo umount /data/safe_staging/merged/ || true sudo umount /data/safe_staging/merged/ || true
rm -rf /data/safe_staging/* || true rm -rf /data/safe_staging/* || true
export KEYS_PARAM_PATH="/data/params/d/GithubSshKeys" CONTINUE_PATH="/data/continue.sh"
export KEYS_PATH="/usr/comma/setup_keys"
export CONTINUE_PATH="/data/continue.sh"
if ! grep -F "$KEYS_PATH" /etc/ssh/sshd_config; then
echo "setting up keys"
sudo mount -o rw,remount /
sudo systemctl enable ssh
sudo sed -i "s,$KEYS_PARAM_PATH,$KEYS_PATH," /etc/ssh/sshd_config
sudo mount -o ro,remount /
fi
tee $CONTINUE_PATH << EOF tee $CONTINUE_PATH << EOF
#!/usr/bin/bash #!/usr/bin/bash
sudo abctl --set_success sudo abctl --set_success
# patch sshd config
sudo mount -o rw,remount /
sudo sed -i "s,/data/params/d/GithubSshKeys,/usr/comma/setup_keys," /etc/ssh/sshd_config
sudo systemctl daemon-reload
sudo systemctl restart ssh
sudo systemctl disable ssh-param-watcher.path
sudo systemctl disable ssh-param-watcher.service
sudo mount -o ro,remount /
while true; do while true; do
if ! sudo systemctl is-active -q ssh; then if ! sudo systemctl is-active -q ssh; then
sudo systemctl start ssh sudo systemctl start ssh
fi fi
sleep 10s sleep 5s
done done
sleep infinity sleep infinity

@ -256,9 +256,10 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) {
}); });
connect(uiState(), &UIState::offroadTransition, updateBtn, &QPushButton::setEnabled); connect(uiState(), &UIState::offroadTransition, updateBtn, &QPushButton::setEnabled);
branchSwitcherBtn = new ButtonControl(tr("Switch Branch"), tr("ENTER")); branchSwitcherBtn = new ButtonControl(tr("Switch Branch"), tr("ENTER"), tr("The new branch will be pulled the next time the updater runs."));
connect(branchSwitcherBtn, &ButtonControl::clicked, [=]() { connect(branchSwitcherBtn, &ButtonControl::clicked, [=]() {
QString branch = InputDialog::getText(tr("Enter name of new branch"), this); QString branch = InputDialog::getText(tr("Enter branch name"), this, tr("The new branch will be pulled the next time the updater runs."),
false, -1, QString::fromStdString(params.get("SwitchToBranch")));
if (branch.isEmpty()) { if (branch.isEmpty()) {
params.remove("SwitchToBranch"); params.remove("SwitchToBranch");
} else { } else {

@ -17,25 +17,21 @@ QStringList getParentWidgets(QWidget* widget){
template <typename T> template <typename T>
void checkWidgetTrWrap(MainWindow &w) { void checkWidgetTrWrap(MainWindow &w) {
int i = 0;
for (auto widget : w.findChildren<T>()) { for (auto widget : w.findChildren<T>()) {
const QString text = widget->text(); const QString text = widget->text();
SECTION(text.toStdString() + "-" + std::to_string(i)) { bool isNumber = RE_NUM.exactMatch(text);
bool isNumber = RE_NUM.exactMatch(text); bool wrapped = text.contains(TEST_TEXT);
bool wrapped = text.contains(TEST_TEXT); QString parentWidgets = getParentWidgets(widget).join("->");
QString parentWidgets = getParentWidgets(widget).join("->");
if (!text.isEmpty() && !isNumber && !wrapped) {
if (!text.isEmpty() && !isNumber && !wrapped) { FAIL(("\"" + text + "\" must be wrapped. Parent widgets: " + parentWidgets).toStdString());
FAIL(("\"" + text + "\" must be wrapped. Parent widgets: " + parentWidgets).toStdString()); }
}
// warn if source string wrapped, but UI adds text
// warn if source string wrapped, but UI adds text // TODO: add way to ignore this
// TODO: add way to ignore this if (wrapped && text != TEST_TEXT) {
if (wrapped && text != TEST_TEXT) { WARN(("\"" + text + "\" is dynamic and needs a custom retranslate function. Parent widgets: " + parentWidgets).toStdString());
WARN(("\"" + text + "\" is dynamic and needs a custom retranslate function. Parent widgets: " + parentWidgets).toStdString());
}
} }
i++;
} }
} }

@ -35,13 +35,12 @@ class TestTranslations(unittest.TestCase):
if not len(file): if not len(file):
self.skipTest(f"{name} translation has no defined file") self.skipTest(f"{name} translation has no defined file")
self.assertTrue(os.path.exists(os.path.join(TRANSLATIONS_DIR, f"{file}.ts")), if not (os.path.exists(os.path.join(TRANSLATIONS_DIR, f"{file}.ts")) and
f"{name} has no XML translation file, run selfdrive/ui/update_translations.py") os.path.exists(os.path.join(TRANSLATIONS_DIR, f"{file}.qm"))):
self.assertTrue(os.path.exists(os.path.join(TRANSLATIONS_DIR, f"{file}.qm")), self.fail(f"{name} is missing translation files, run selfdrive/ui/update_translations.py")
f"{name} has no compiled QM translation file, run selfdrive/ui/update_translations.py --release")
def test_translations_updated(self): def test_translations_updated(self):
update_translations(release=True, translations_dir=TMP_TRANSLATIONS_DIR) update_translations(translations_dir=TMP_TRANSLATIONS_DIR)
for name, file in self.translation_files.items(): for name, file in self.translation_files.items():
with self.subTest(name=name, file=file): with self.subTest(name=name, file=file):
@ -59,7 +58,7 @@ class TestTranslations(unittest.TestCase):
new_translations = self._read_translation_file(TMP_TRANSLATIONS_DIR, file, file_ext) new_translations = self._read_translation_file(TMP_TRANSLATIONS_DIR, file, file_ext)
self.assertEqual(cur_translations, new_translations, self.assertEqual(cur_translations, new_translations,
f"{file} ({name}) {file_ext.upper()} translation file out of date. Run selfdrive/ui/update_translations.py --release to update the translation files") f"{file} ({name}) {file_ext.upper()} translation file out of date. Run selfdrive/ui/update_translations.py to update the translation files")
@unittest.skip("Only test unfinished translations before going to release") @unittest.skip("Only test unfinished translations before going to release")
def test_unfinished_translations(self): def test_unfinished_translations(self):

@ -1,7 +1,5 @@
# Multilanguage # Multilanguage
![multilanguage_onroad](https://user-images.githubusercontent.com/25857203/178912800-2c798af8-78e3-498e-9e19-35906e0bafff.png)
## Contributing ## Contributing
Before getting started, make sure you have set up the openpilot Ubuntu development environment by reading the [tools README.md](/tools/README.md). Before getting started, make sure you have set up the openpilot Ubuntu development environment by reading the [tools README.md](/tools/README.md).
@ -28,12 +26,25 @@ openpilot provides a few tools to help contributors manage their translations an
Follow the steps above, omitting steps 1. and 2. Any time you edit translations you'll want to make sure to compile them. Follow the steps above, omitting steps 1. and 2. Any time you edit translations you'll want to make sure to compile them.
### Updating the UI
Any time you edit source code in the UI, you need to update and compile the translations to ensure the line numbers and contexts are up to date (last step above).
### Testing ### Testing
openpilot has a unit test to make sure all translations are up to date with the text in openpilot and that all translations are completed. openpilot has a few unit tests to make sure all translations are up to date and that all strings are wrapped in a translation marker.
Run and fix any issues: Tests translation files up to date:
```python ```shell
selfdrive/ui/tests/test_translations.py selfdrive/ui/tests/test_translations.py
``` ```
Tests all static source strings are wrapped:
```shell
selfdrive/ui/tests/create_test_translations.sh && selfdrive/ui/tests/test_translations
```
---
![multilanguage_onroad](https://user-images.githubusercontent.com/25857203/178912800-2c798af8-78e3-498e-9e19-35906e0bafff.png)

File diff suppressed because it is too large Load Diff

@ -710,33 +710,33 @@ location set</source>
<context> <context>
<name>SettingsWindow</name> <name>SettingsWindow</name>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="337"/> <location filename="../qt/offroad/settings.cc" line="338"/>
<source>×</source> <source>×</source>
<translation>×</translation> <translation>×</translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="363"/> <location filename="../qt/offroad/settings.cc" line="364"/>
<source>Device</source> <source>Device</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="364"/> <location filename="../qt/offroad/settings.cc" line="365"/>
<location filename="../qt/offroad/settings.cc" line="403"/> <location filename="../qt/offroad/settings.cc" line="404"/>
<source>Network</source> <source>Network</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="365"/> <location filename="../qt/offroad/settings.cc" line="366"/>
<source>Toggles</source> <source>Toggles</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="366"/> <location filename="../qt/offroad/settings.cc" line="367"/>
<source>Software</source> <source>Software</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="371"/> <location filename="../qt/offroad/settings.cc" line="372"/>
<source>Navigation</source> <source>Navigation</source>
<translation></translation> <translation></translation>
</message> </message>
@ -1025,33 +1025,39 @@ location set</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="259"/>
<location filename="../qt/offroad/settings.cc" line="261"/> <location filename="../qt/offroad/settings.cc" line="261"/>
<source>Enter name of new branch</source> <source>The new branch will be pulled the next time the updater runs.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="271"/> <location filename="../qt/offroad/settings.cc" line="261"/>
<source>Enter branch name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qt/offroad/settings.cc" line="272"/>
<source>UNINSTALL</source> <source>UNINSTALL</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="271"/> <location filename="../qt/offroad/settings.cc" line="272"/>
<source>Uninstall %1</source> <source>Uninstall %1</source>
<translation> %1</translation> <translation> %1</translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="273"/> <location filename="../qt/offroad/settings.cc" line="274"/>
<source>Are you sure you want to uninstall?</source> <source>Are you sure you want to uninstall?</source>
<translation>?</translation> <translation>?</translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="290"/> <location filename="../qt/offroad/settings.cc" line="291"/>
<source>failed to fetch update</source> <source>failed to fetch update</source>
<translation> </translation> <translation> </translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="291"/> <location filename="../qt/offroad/settings.cc" line="292"/>
<location filename="../qt/offroad/settings.cc" line="312"/> <location filename="../qt/offroad/settings.cc" line="313"/>
<source>CHECK</source> <source>CHECK</source>
<translation></translation> <translation></translation>
</message> </message>

@ -708,33 +708,33 @@ location set</source>
<context> <context>
<name>SettingsWindow</name> <name>SettingsWindow</name>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="337"/> <location filename="../qt/offroad/settings.cc" line="338"/>
<source>×</source> <source>×</source>
<translation>×</translation> <translation>×</translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="363"/> <location filename="../qt/offroad/settings.cc" line="364"/>
<source>Device</source> <source>Device</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="364"/> <location filename="../qt/offroad/settings.cc" line="365"/>
<location filename="../qt/offroad/settings.cc" line="403"/> <location filename="../qt/offroad/settings.cc" line="404"/>
<source>Network</source> <source>Network</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="365"/> <location filename="../qt/offroad/settings.cc" line="366"/>
<source>Toggles</source> <source>Toggles</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="366"/> <location filename="../qt/offroad/settings.cc" line="367"/>
<source>Software</source> <source>Software</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="371"/> <location filename="../qt/offroad/settings.cc" line="372"/>
<source>Navigation</source> <source>Navigation</source>
<translation></translation> <translation></translation>
</message> </message>
@ -1023,33 +1023,39 @@ location set</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="259"/>
<location filename="../qt/offroad/settings.cc" line="261"/> <location filename="../qt/offroad/settings.cc" line="261"/>
<source>Enter name of new branch</source> <source>The new branch will be pulled the next time the updater runs.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="271"/> <location filename="../qt/offroad/settings.cc" line="261"/>
<source>Enter branch name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qt/offroad/settings.cc" line="272"/>
<source>UNINSTALL</source> <source>UNINSTALL</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="271"/> <location filename="../qt/offroad/settings.cc" line="272"/>
<source>Uninstall %1</source> <source>Uninstall %1</source>
<translation> %1</translation> <translation> %1</translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="273"/> <location filename="../qt/offroad/settings.cc" line="274"/>
<source>Are you sure you want to uninstall?</source> <source>Are you sure you want to uninstall?</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="290"/> <location filename="../qt/offroad/settings.cc" line="291"/>
<source>failed to fetch update</source> <source>failed to fetch update</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="291"/> <location filename="../qt/offroad/settings.cc" line="292"/>
<location filename="../qt/offroad/settings.cc" line="312"/> <location filename="../qt/offroad/settings.cc" line="313"/>
<source>CHECK</source> <source>CHECK</source>
<translation></translation> <translation></translation>
</message> </message>

@ -713,33 +713,33 @@ location set</source>
<context> <context>
<name>SettingsWindow</name> <name>SettingsWindow</name>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="337"/> <location filename="../qt/offroad/settings.cc" line="338"/>
<source>×</source> <source>×</source>
<translation>×</translation> <translation>×</translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="363"/> <location filename="../qt/offroad/settings.cc" line="364"/>
<source>Device</source> <source>Device</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="364"/> <location filename="../qt/offroad/settings.cc" line="365"/>
<location filename="../qt/offroad/settings.cc" line="403"/> <location filename="../qt/offroad/settings.cc" line="404"/>
<source>Network</source> <source>Network</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="365"/> <location filename="../qt/offroad/settings.cc" line="366"/>
<source>Toggles</source> <source>Toggles</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="366"/> <location filename="../qt/offroad/settings.cc" line="367"/>
<source>Software</source> <source>Software</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="371"/> <location filename="../qt/offroad/settings.cc" line="372"/>
<source>Navigation</source> <source>Navigation</source>
<translation></translation> <translation></translation>
</message> </message>
@ -1028,33 +1028,39 @@ location set</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="259"/>
<location filename="../qt/offroad/settings.cc" line="261"/> <location filename="../qt/offroad/settings.cc" line="261"/>
<source>Enter name of new branch</source> <source>The new branch will be pulled the next time the updater runs.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="271"/> <location filename="../qt/offroad/settings.cc" line="261"/>
<source>Enter branch name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../qt/offroad/settings.cc" line="272"/>
<source>UNINSTALL</source> <source>UNINSTALL</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="271"/> <location filename="../qt/offroad/settings.cc" line="272"/>
<source>Uninstall %1</source> <source>Uninstall %1</source>
<translation> %1</translation> <translation> %1</translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="273"/> <location filename="../qt/offroad/settings.cc" line="274"/>
<source>Are you sure you want to uninstall?</source> <source>Are you sure you want to uninstall?</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="290"/> <location filename="../qt/offroad/settings.cc" line="291"/>
<source>failed to fetch update</source> <source>failed to fetch update</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qt/offroad/settings.cc" line="291"/> <location filename="../qt/offroad/settings.cc" line="292"/>
<location filename="../qt/offroad/settings.cc" line="312"/> <location filename="../qt/offroad/settings.cc" line="313"/>
<source>CHECK</source> <source>CHECK</source>
<translation></translation> <translation></translation>
</message> </message>

@ -10,7 +10,7 @@ TRANSLATIONS_DIR = os.path.join(UI_DIR, "translations")
LANGUAGES_FILE = os.path.join(TRANSLATIONS_DIR, "languages.json") LANGUAGES_FILE = os.path.join(TRANSLATIONS_DIR, "languages.json")
def update_translations(release=False, vanish=False, translations_dir=TRANSLATIONS_DIR): def update_translations(vanish=False, translations_dir=TRANSLATIONS_DIR):
with open(LANGUAGES_FILE, "r") as f: with open(LANGUAGES_FILE, "r") as f:
translation_files = json.load(f) translation_files = json.load(f)
@ -26,16 +26,14 @@ def update_translations(release=False, vanish=False, translations_dir=TRANSLATIO
ret = os.system(args) ret = os.system(args)
assert ret == 0 assert ret == 0
if release: ret = os.system(f"lrelease {tr_file}")
ret = os.system(f"lrelease {tr_file}") assert ret == 0
assert ret == 0
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Update translation files for UI", parser = argparse.ArgumentParser(description="Update translation files for UI",
formatter_class=argparse.ArgumentDefaultsHelpFormatter) formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--release", action="store_true", help="Create compiled QM translation files used by UI")
parser.add_argument("--vanish", action="store_true", help="Remove translations with source text no longer found") parser.add_argument("--vanish", action="store_true", help="Remove translations with source text no longer found")
args = parser.parse_args() args = parser.parse_args()
update_translations(args.release, args.vanish) update_translations(args.vanish)

Loading…
Cancel
Save