fix(core): use translation strings for THP layouts
What changed, and why it matters
This commit replaces hard-coded English text in Trezor's on-screen pairing and connection prompts with proper translation keys. The visible messages stay the same in English, but the firmware can now display them in other languages. There is no security bug being fixed here; it is a routine internationalization cleanup.
No security action needed. Treat as a normal localization refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change moves THP (Trezor Host Protocol) UI strings from literal Python strings into the generated TR translation system. It adds new translation keys (thp__autoconnect_title, thp__code_entry, thp__code_title, thp__connect_title, thp__nfc_text, thp__pair_title, thp__qr_title), updates the generated Rust enum/qstr mappings, mock stubs, en.json, order.json, and the translations signature metadata. The only functional code change is in core/src/trezor/wire/thp/ui.py, where literal strings and an f-string are replaced by TR.* calls. No logic, permission, or cryptographic behavior changes.
Changed components
core/src/trezor/wire/thp/ui.pycore/embed/rust/src/translations/generated/translated_string.rscore/embed/rust/librust_qstr.hcore/mocks/trezortranslate_keys.pyicore/translations/en.jsoncore/translations/order.jsoncore/translations/signatures.jsonInspect captured patch +148 / −12
diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h
index e8ef936d..f011594a 100644
--- a/core/embed/rust/librust_qstr.h
+++ b/core/embed/rust/librust_qstr.h
@@ -837,10 +837,17 @@ static void _librust_qstrs(void) {
MP_QSTR_text_mono;
MP_QSTR_thp__autoconnect;
MP_QSTR_thp__autoconnect_app;
+ MP_QSTR_thp__autoconnect_title;
+ MP_QSTR_thp__code_entry;
+ MP_QSTR_thp__code_title;
MP_QSTR_thp__connect;
MP_QSTR_thp__connect_app;
+ MP_QSTR_thp__connect_title;
+ MP_QSTR_thp__nfc_text;
MP_QSTR_thp__pair;
MP_QSTR_thp__pair_app;
+ MP_QSTR_thp__pair_title;
+ MP_QSTR_thp__qr_title;
MP_QSTR_time_ms;
MP_QSTR_timer;
MP_QSTR_title;
diff --git a/core/embed/rust/src/translations/generated/translated_string.rs b/core/embed/rust/src/translations/generated/translated_string.rs
index 3d9e7ce1..e13792b0 100644
--- a/core/embed/rust/src/translations/generated/translated_string.rs
+++ b/core/embed/rust/src/translations/generated/translated_string.rs
@@ -1530,6 +1530,13 @@ pub enum TranslatedString {
thp__connect_app = 1138, // {"Bolt": "", "Caesar": "", "Delizia": "", "Eckhart": "Allow {0} on {1} to connect with this Trezor?"}
thp__pair = 1139, // {"Bolt": "", "Caesar": "", "Delizia": "", "Eckhart": "Allow {0} to pair with this Trezor?"}
thp__pair_app = 1140, // {"Bolt": "", "Caesar": "", "Delizia": "", "Eckhart": "Allow {0} on {1} to pair with this Trezor?"}
+ thp__autoconnect_title = 1141, // {"Bolt": "", "Caesar": "", "Delizia": "", "Eckhart": "Autoconnect credential"}
+ thp__code_entry = 1142, // {"Bolt": "", "Caesar": "", "Delizia": "", "Eckhart": "Enter this one-time security code on {0}"}
+ thp__code_title = 1143, // {"Bolt": "", "Caesar": "", "Delizia": "", "Eckhart": "One more step"}
+ thp__connect_title = 1144, // {"Bolt": "", "Caesar": "", "Delizia": "", "Eckhart": "Connection dialog"}
+ thp__nfc_text = 1145, // {"Bolt": "", "Caesar": "", "Delizia": "", "Eckhart": "Keep your Trezor near your phone to complete the setup."}
+ thp__pair_title = 1146, // {"Bolt": "", "Caesar": "", "Delizia": "", "Eckhart": "Before you continue"}
+ thp__qr_title = 1147, // {"Bolt": "", "Caesar": "", "Delizia": "", "Eckhart": "Scan QR code to pair"}
}
impl TranslatedString {
@@ -3427,6 +3434,62 @@ impl TranslatedString {
(Self::thp__pair_app, ""),
#[cfg(feature = "layout_eckhart")]
(Self::thp__pair_app, "Allow {0} on {1} to pair with this Trezor?"),
+ #[cfg(feature = "layout_bolt")]
+ (Self::thp__autoconnect_title, ""),
+ #[cfg(feature = "layout_caesar")]
+ (Self::thp__autoconnect_title, ""),
+ #[cfg(feature = "layout_delizia")]
+ (Self::thp__autoconnect_title, ""),
+ #[cfg(feature = "layout_eckhart")]
+ (Self::thp__autoconnect_title, "Autoconnect credential"),
+ #[cfg(feature = "layout_bolt")]
+ (Self::thp__code_entry, ""),
+ #[cfg(feature = "layout_caesar")]
+ (Self::thp__code_entry, ""),
+ #[cfg(feature = "layout_delizia")]
+ (Self::thp__code_entry, ""),
+ #[cfg(feature = "layout_eckhart")]
+ (Self::thp__code_entry, "Enter this one-time security code on {0}"),
+ #[cfg(feature = "layout_bolt")]
+ (Self::thp__code_title, ""),
+ #[cfg(feature = "layout_caesar")]
+ (Self::thp__code_title, ""),
+ #[cfg(feature = "layout_delizia")]
+ (Self::thp__code_title, ""),
+ #[cfg(feature = "layout_eckhart")]
+ (Self::thp__code_title, "One more step"),
+ #[cfg(feature = "layout_bolt")]
+ (Self::thp__connect_title, ""),
+ #[cfg(feature = "layout_caesar")]
+ (Self::thp__connect_title, ""),
+ #[cfg(feature = "layout_delizia")]
+ (Self::thp__connect_title, ""),
+ #[cfg(feature = "layout_eckhart")]
+ (Self::thp__connect_title, "Connection dialog"),
+ #[cfg(feature = "layout_bolt")]
+ (Self::thp__nfc_text, ""),
+ #[cfg(feature = "layout_caesar")]
+ (Self::thp__nfc_text, ""),
+ #[cfg(feature = "layout_delizia")]
+ (Self::thp__nfc_text, ""),
+ #[cfg(feature = "layout_eckhart")]
+ (Self::thp__nfc_text, "Keep your Trezor near your phone to complete the setup."),
+ #[cfg(feature = "layout_bolt")]
+ (Self::thp__pair_title, ""),
+ #[cfg(feature = "layout_caesar")]
+ (Self::thp__pair_title, ""),
+ #[cfg(feature = "layout_delizia")]
+ (Self::thp__pair_title, ""),
+ #[cfg(feature = "layout_eckhart")]
+ (Self::thp__pair_title, "Before you continue"),
+ #[cfg(feature = "layout_bolt")]
+ (Self::thp__qr_title, ""),
+ #[cfg(feature = "layout_caesar")]
+ (Self::thp__qr_title, ""),
+ #[cfg(feature = "layout_delizia")]
+ (Self::thp__qr_title, ""),
+ #[cfg(feature = "layout_eckhart")]
+ (Self::thp__qr_title, "Scan QR code to pair"),
];
#[cfg(feature = "micropython")]
@@ -4790,10 +4853,17 @@ impl TranslatedString {
(Qstr::MP_QSTR_tezos__submit_proposals, Self::tezos__submit_proposals),
(Qstr::MP_QSTR_thp__autoconnect, Self::thp__autoconnect),
(Qstr::MP_QSTR_thp__autoconnect_app, Self::thp__autoconnect_app),
+ (Qstr::MP_QSTR_thp__autoconnect_title, Self::thp__autoconnect_title),
+ (Qstr::MP_QSTR_thp__code_entry, Self::thp__code_entry),
+ (Qstr::MP_QSTR_thp__code_title, Self::thp__code_title),
(Qstr::MP_QSTR_thp__connect, Self::thp__connect),
(Qstr::MP_QSTR_thp__connect_app, Self::thp__connect_app),
+ (Qstr::MP_QSTR_thp__connect_title, Self::thp__connect_title),
+ (Qstr::MP_QSTR_thp__nfc_text, Self::thp__nfc_text),
(Qstr::MP_QSTR_thp__pair, Self::thp__pair),
(Qstr::MP_QSTR_thp__pair_app, Self::thp__pair_app),
+ (Qstr::MP_QSTR_thp__pair_title, Self::thp__pair_title),
+ (Qstr::MP_QSTR_thp__qr_title, Self::thp__qr_title),
(Qstr::MP_QSTR_tutorial__continue, Self::tutorial__continue),
(Qstr::MP_QSTR_tutorial__did_you_know, Self::tutorial__did_you_know),
(Qstr::MP_QSTR_tutorial__exit, Self::tutorial__exit),
diff --git a/core/mocks/trezortranslate_keys.pyi b/core/mocks/trezortranslate_keys.pyi
index 9cd60194..078ce93f 100644
--- a/core/mocks/trezortranslate_keys.pyi
+++ b/core/mocks/trezortranslate_keys.pyi
@@ -947,10 +947,17 @@ class TR:
tezos__submit_proposals: str = "Submit proposals"
thp__autoconnect: str = "Allow {0} to connect automatically to this Trezor?"
thp__autoconnect_app: str = "Allow {0} on {1} to connect automatically to this Trezor?"
+ thp__autoconnect_title: str = "Autoconnect credential"
+ thp__code_entry: str = "Enter this one-time security code on {0}"
+ thp__code_title: str = "One more step"
thp__connect: str = "Allow {0} to connect with this Trezor?"
thp__connect_app: str = "Allow {0} on {1} to connect with this Trezor?"
+ thp__connect_title: str = "Connection dialog"
+ thp__nfc_text: str = "Keep your Trezor near your phone to complete the setup."
thp__pair: str = "Allow {0} to pair with this Trezor?"
thp__pair_app: str = "Allow {0} on {1} to pair with this Trezor?"
+ thp__pair_title: str = "Before you continue"
+ thp__qr_title: str = "Scan QR code to pair"
tutorial__continue: str = "Continue tutorial"
tutorial__did_you_know: str = "Did you know?"
tutorial__exit: str = "Exit tutorial"
diff --git a/core/src/trezor/wire/thp/ui.py b/core/src/trezor/wire/thp/ui.py
index 609c8aac..c4e50db7 100644
--- a/core/src/trezor/wire/thp/ui.py
+++ b/core/src/trezor/wire/thp/ui.py
@@ -38,7 +38,7 @@ def show_autoconnect_credential_confirmation_screen(
return confirm_pairing(
br_name="thp_autoconnect_credential_request",
- title="Autoconnect credential",
+ title=TR.thp__autoconnect_title,
app_name=app_name,
host_name=host_name,
short_text=TR.thp__autoconnect,
@@ -51,7 +51,7 @@ def show_pairing_dialog(host_name: str | None, app_name: str | None) -> Awaitabl
return confirm_pairing(
br_name="thp_pairing_request",
- title="Before you continue",
+ title=TR.thp__pair_title,
app_name=app_name,
host_name=host_name,
short_text=TR.thp__pair,
@@ -66,7 +66,7 @@ def show_connection_dialog(
return confirm_pairing(
br_name="thp_connection_request",
- title="Connection dialog",
+ title=TR.thp__connect_title,
app_name=app_name,
host_name=host_name,
short_text=TR.thp__connect,
@@ -77,13 +77,14 @@ def show_connection_dialog(
async def show_code_entry_screen(
code_entry_str: str, host_name: str | None
) -> UiResult:
+ from trezor import TR
from trezor.ui.layouts.common import interact
from trezorui_api import show_thp_pairing_code
return await interact(
show_thp_pairing_code(
- title="One more step",
- description=f"Enter this one-time security code on {host_name}",
+ title=TR.thp__code_title,
+ description=TR.thp__code_entry.format(host_name),
code=code_entry_str,
),
br_name=None,
@@ -91,26 +92,28 @@ async def show_code_entry_screen(
async def show_nfc_screen() -> UiResult:
+ from trezor import TR
from trezor.ui.layouts.common import interact
from trezorui_api import show_simple
return await interact(
show_simple(
title=None,
- text="Keep your Trezor near your phone to complete the setup.",
- button="Cancel",
+ text=TR.thp__nfc_text,
+ button=TR.buttons__cancel,
),
br_name=None,
)
async def show_qr_code_screen(qr_code_str: str) -> UiResult:
+ from trezor import TR
from trezor.ui.layouts.common import interact
from trezorui_api import show_address_details
return await interact(
show_address_details( # noqa
- qr_title="Scan QR code to pair",
+ qr_title=TR.thp__qr_title,
address=qr_code_str,
case_sensitive=True,
details_title="",
diff --git a/core/translations/en.json b/core/translations/en.json
index 86273707..5339fe25 100644
--- a/core/translations/en.json
+++ b/core/translations/en.json
@@ -1174,6 +1174,24 @@
"Delizia": "",
"Eckhart": "Allow {0} on {1} to connect automatically to this Trezor?"
},
+ "thp__autoconnect_title": {
+ "Bolt": "",
+ "Caesar": "",
+ "Delizia": "",
+ "Eckhart": "Autoconnect credential"
+ },
+ "thp__code_entry": {
+ "Bolt": "",
+ "Caesar": "",
+ "Delizia": "",
+ "Eckhart": "Enter this one-time security code on {0}"
+ },
+ "thp__code_title": {
+ "Bolt": "",
+ "Caesar": "",
+ "Delizia": "",
+ "Eckhart": "One more step"
+ },
"thp__connect": {
"Bolt": "",
"Caesar": "",
@@ -1186,6 +1204,18 @@
"Delizia": "",
"Eckhart": "Allow {0} on {1} to connect with this Trezor?"
},
+ "thp__connect_title": {
+ "Bolt": "",
+ "Caesar": "",
+ "Delizia": "",
+ "Eckhart": "Connection dialog"
+ },
+ "thp__nfc_text": {
+ "Bolt": "",
+ "Caesar": "",
+ "Delizia": "",
+ "Eckhart": "Keep your Trezor near your phone to complete the setup."
+ },
"thp__pair": {
"Bolt": "",
"Caesar": "",
@@ -1198,6 +1228,18 @@
"Delizia": "",
"Eckhart": "Allow {0} on {1} to pair with this Trezor?"
},
+ "thp__pair_title": {
+ "Bolt": "",
+ "Caesar": "",
+ "Delizia": "",
+ "Eckhart": "Before you continue"
+ },
+ "thp__qr_title": {
+ "Bolt": "",
+ "Caesar": "",
+ "Delizia": "",
+ "Eckhart": "Scan QR code to pair"
+ },
"tutorial__continue": "Continue tutorial",
"tutorial__did_you_know": "Did you know?",
"tutorial__exit": "Exit tutorial",
diff --git a/core/translations/order.json b/core/translations/order.json
index 4c15d58a..26b6ff6c 100644
--- a/core/translations/order.json
+++ b/core/translations/order.json
@@ -1139,5 +1139,12 @@
"1137": "thp__connect",
"1138": "thp__connect_app",
"1139": "thp__pair",
- "1140": "thp__pair_app"
+ "1140": "thp__pair_app",
+ "1141": "thp__autoconnect_title",
+ "1142": "thp__code_entry",
+ "1143": "thp__code_title",
+ "1144": "thp__connect_title",
+ "1145": "thp__nfc_text",
+ "1146": "thp__pair_title",
+ "1147": "thp__qr_title"
}
diff --git a/core/translations/signatures.json b/core/translations/signatures.json
index b6b8ef9f..1b61bc78 100644
--- a/core/translations/signatures.json
+++ b/core/translations/signatures.json
@@ -1,8 +1,8 @@
{
"current": {
- "merkle_root": "a41b94ae2830a40308546c2d003a213527ae902b7daa8624058605a7d8a60d00",
- "datetime": "2025-09-08T07:55:12.193914+00:00",
- "commit": "7ac68d73a6dc1567290c9dad4c08d051ebac7462"
+ "merkle_root": "6109d557e311685c0a2655ab074e9a6251cfd9d006cda9be8286bd672eb20b06",
+ "datetime": "2025-09-11T12:45:33.717063+00:00",
+ "commit": "6673667e698074ee56d9ed7c08633c09ca37a190"
},
"history": [
{
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.