WIP - extend language field to full BCP47 tag

grdddj-fw-translations-rebased
matejcik 4 months ago
parent d175d0d282
commit 5a9ccec920

@ -217,7 +217,7 @@ impl<'a> Translations<'a> {
pub struct TranslationsHeader<'a> {
/// Raw content of the header, for signature verification
pub header_bytes: &'a [u8],
/// Human readable language identifier (e.g. "cs" of "fr")
/// BCP 47 language tag (cs-CZ, en-US, ...)
pub language: &'a str,
/// 4 bytes of version (major, minor, patch, build)
pub version: [u8; 4],
@ -290,7 +290,6 @@ impl<'a> TranslationsHeader<'a> {
return Err(value_error!("bad header magic"));
}
let language = read_fixedsize_str(&mut header_reader, 4)?;
let model = read_fixedsize_str(&mut header_reader, 4)?;
if model != crate::trezorhal::model::INTERNAL_NAME {
@ -304,6 +303,10 @@ impl<'a> TranslationsHeader<'a> {
let data_hash: sha256::Digest =
unwrap!(header_reader.read(sha256::DIGEST_SIZE)?.try_into());
let language = read_pascal_str(&mut header_reader)?;
if language.len() > 8 {
return Err(value_error!("invalid language"));
}
let change_language_title = read_pascal_str(&mut header_reader)?;
let change_language_prompt = read_pascal_str(&mut header_reader)?;

@ -8,7 +8,7 @@ mod translated_string;
pub use blob::MAX_HEADER_LEN;
pub use translated_string::TranslatedString as TR;
pub const DEFAULT_LANGUAGE: &str = "enUS";
pub const DEFAULT_LANGUAGE: &str = "en-US";
/// # Safety
///

@ -619,7 +619,7 @@ async def show_warning(
# (we know it will fit one page)
# TODO: figure out some better and non-intrusive way to do this
# (check if the content fits one page with the newline, and if not, do not add it)
if content and subheader and translations.get_language() == "enUS":
if content and subheader and translations.get_language() == "en-US":
content = content + "\n"
await interact(

@ -18,7 +18,7 @@
"header": {
"change_language_prompt": "Zmenit jazyk na cestinu?",
"change_language_title": "ZMENA JAZYKA",
"language": "csCZ",
"language": "cs-CZ",
"version": "2.6.5"
},
"translations": {

@ -18,7 +18,7 @@
"header": {
"change_language_prompt": "Sprache andern?",
"change_language_title": "SPRACHE",
"language": "deDE",
"language": "de-DE",
"version": "2.6.5"
},
"translations": {

@ -1,6 +1,6 @@
{
"header": {
"language": "enUS",
"language": "en-US",
"version": "2.6.5"
},
"translations": {

@ -18,7 +18,7 @@
"header": {
"change_language_prompt": "Cambiar el idioma?",
"change_language_title": "IDIOMA",
"language": "esES",
"language": "es-ES",
"version": "2.6.5"
},
"translations": {

@ -18,7 +18,7 @@
"header": {
"change_language_prompt": "Changer de langue en francais?",
"change_language_title": "CHANGER LA LANGUE",
"language": "frFR",
"language": "fr-FR",
"version": "2.6.5"
},
"translations": {

@ -69,11 +69,12 @@ class Header(Struct):
# fmt: off
SUBCON = c.Struct(
"magic" / c.Const(b"TR"),
"language" / c.PaddedString(4, "ascii"), # locale specifier without dash, enUS esES geDE etc
"model" / EnumAdapter(c.Bytes(4), Model),
"firmware_version" / TupleAdapter(c.Int8ul, c.Int8ul, c.Int8ul, c.Int8ul),
"data_len" / c.Int16ul,
"data_hash" / c.Bytes(32),
"language" / c.PascalString(c.Int8ul, "ascii"), # BCP47 language tag
c.Check(c.len_(c.this.language) <= 8),
"change_language_title" / c.PascalString(c.Int8ul, "utf8"),
"change_language_prompt" / c.PascalString(c.Int8ul, "utf8"),
ALIGN_SUBCON,

@ -72,7 +72,7 @@ def _check_ping_screen_texts(client: Client, title: str, right_button: str) -> N
def test_change_language_errors(client: Client):
assert client.features.language == "enUS"
assert client.features.language == "en-US"
# # Translations too short
# # Sending less data than the header length
@ -81,7 +81,7 @@ def test_change_language_errors(client: Client):
# ), client:
# bad_data = (translations.HEADER_LEN - 1) * b"a"
# device.change_language(client, language_data=bad_data)
# assert client.features.language == "enUS"
# assert client.features.language == "en-US"
# Translations too long
# Sending more than allowed by the flash capacity
@ -89,7 +89,7 @@ def test_change_language_errors(client: Client):
with pytest.raises(exceptions.TrezorFailure, match="Translations too long"), client:
bad_data = (max_length + 1) * b"a"
device.change_language(client, language_data=bad_data)
assert client.features.language == "enUS"
assert client.features.language == "en-US"
# Invalid header data length
# Sending more data than advertised in the header
@ -99,7 +99,7 @@ def test_change_language_errors(client: Client):
good_data = build_and_sign_blob("cs", client.model)
bad_data = good_data + b"abcd"
device.change_language(client, language_data=bad_data)
assert client.features.language == "enUS"
assert client.features.language == "en-US"
# Invalid header magic
# Does not match the expected magic
@ -107,7 +107,7 @@ def test_change_language_errors(client: Client):
good_data = build_and_sign_blob("cs", client.model)
bad_data = 4 * b"a" + good_data[4:]
device.change_language(client, language_data=bad_data)
assert client.features.language == "enUS"
assert client.features.language == "en-US"
# # Invalid header data
# # Putting non-zero bytes where zero is expected
@ -119,7 +119,7 @@ def test_change_language_errors(client: Client):
# client,
# language_data=bad_data,
# )
# assert client.features.language == "enUS"
# assert client.features.language == "en-US"
# Invalid data hash
# Changing the data after their hash has been calculated
@ -130,7 +130,7 @@ def test_change_language_errors(client: Client):
client,
language_data=bad_data,
)
assert client.features.language == "enUS"
assert client.features.language == "en-US"
# Invalid translations version
# Change the version to one not matching the current device
@ -143,7 +143,7 @@ def test_change_language_errors(client: Client):
client,
language_data=build_and_sign_blob(data, client.model),
)
assert client.features.language == "enUS"
assert client.features.language == "en-US"
# Invalid header version
# Version is not a valid semver with integers
@ -154,7 +154,7 @@ def test_change_language_errors(client: Client):
client,
language_data=build_and_sign_blob(data, client.model),
)
assert client.features.language == "enUS"
assert client.features.language == "en-US"
# # Invalid translations signature
# # Modifying the signature part of the header
@ -173,14 +173,14 @@ def test_change_language_errors(client: Client):
# client,
# language_data=bad_data,
# )
# assert client.features.language == "enUS"
# assert client.features.language == "en-US"
_check_ping_screen_texts(client, get_confirm("en"), get_confirm("en"))
@pytest.mark.parametrize("lang", LANGUAGES)
def test_full_language_change(client: Client, lang: str):
assert client.features.language == "enUS"
assert client.features.language == "en-US"
# Setting selected language
set_language(client, lang)
@ -189,24 +189,24 @@ def test_full_language_change(client: Client, lang: str):
# Setting the default language via empty data
set_language(client, "en")
assert client.features.language == "enUS"
assert client.features.language == "en-US"
_check_ping_screen_texts(client, get_confirm("en"), get_confirm("en"))
def test_language_stays_after_wipe(client: Client):
assert client.features.language == "enUS"
assert client.features.language == "en-US"
_check_ping_screen_texts(client, get_confirm("en"), get_confirm("en"))
# Setting cs language
set_language(client, "cs")
assert client.features.language == "csCZ"
assert client.features.language == "cs-CZ"
_check_ping_screen_texts(client, get_confirm("cs"), get_confirm("cs"))
# Wipe device
device.wipe(client)
assert client.features.language == "csCZ"
assert client.features.language == "cs-CZ"
# Load it again
debuglink.load_device(
@ -216,7 +216,7 @@ def test_language_stays_after_wipe(client: Client):
passphrase_protection=False,
label="test",
)
assert client.features.language == "csCZ"
assert client.features.language == "cs-CZ"
_check_ping_screen_texts(client, get_confirm("cs"), get_confirm("cs"))
@ -225,14 +225,14 @@ def test_translations_renders_on_screen(client: Client):
czech_data = get_lang_json("cs")
# Setting some values of words__confirm key and checking that in ping screen title
assert client.features.language == "enUS"
assert client.features.language == "en-US"
# Normal english
_check_ping_screen_texts(client, get_confirm("en"), get_confirm("en"))
# Normal czech
set_language(client, "cs")
assert client.features.language == "csCZ"
assert client.features.language == "cs-CZ"
_check_ping_screen_texts(client, get_confirm("cs"), get_confirm("cs"))
# Modified czech - changed value

Loading…
Cancel
Save