mirror of
https://github.com/SeedSigner/seedsigner.git
synced 2026-10-05 15:08:25 +00:00
Additional translation strings; separate Babel deps
This commit is contained in:
+520
-333
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
Babel==2.16.0
|
||||
@@ -1,4 +1,3 @@
|
||||
Babel==2.16.0
|
||||
embit==0.7.0
|
||||
numpy==1.25.2
|
||||
Pillow==9.4.0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[extract_messages]
|
||||
add_comments = TRANSLATOR_NOTE:
|
||||
strip_comments = yes
|
||||
add_location = file
|
||||
add_location = full
|
||||
input_dirs = src
|
||||
output_file = babel/messages.pot
|
||||
|
||||
|
||||
@@ -866,11 +866,14 @@ class BtcAmount(BaseComponent):
|
||||
denomination = Settings.get_instance().get_value(SettingsConstants.SETTING__BTC_DENOMINATION)
|
||||
network = Settings.get_instance().get_value(SettingsConstants.SETTING__NETWORK)
|
||||
|
||||
btc_unit = "tBtc"
|
||||
sats_unit = "tSats"
|
||||
# TRANSLATOR_NOTE: Testnet bitcoin
|
||||
btc_unit = _("tBtc")
|
||||
|
||||
# TRANSLATOR_NOTE: Testnet sats
|
||||
sats_unit = _("tSats")
|
||||
if network == SettingsConstants.MAINNET:
|
||||
btc_unit = "btc"
|
||||
sats_unit = "sats"
|
||||
btc_unit = _("btc")
|
||||
sats_unit = _("sats")
|
||||
btc_color = GUIConstants.ACCENT_COLOR
|
||||
|
||||
elif network == SettingsConstants.TESTNET:
|
||||
|
||||
@@ -99,7 +99,7 @@ class ScanScreen(BaseScreen):
|
||||
cur_time = time.time()
|
||||
cur_fps = num_frames / (cur_time - start_time)
|
||||
if self.decoder and self.decoder.get_percent_complete() > 0 and self.decoder.is_psbt:
|
||||
scan_text = str(self.decoder.get_percent_complete()) + "% Complete"
|
||||
scan_text = _("{}% Complete").format(str(self.decoder.get_percent_complete()))
|
||||
if show_framerate:
|
||||
scan_text += f" {cur_fps:0.2f} | {self.decoder_fps}"
|
||||
else:
|
||||
|
||||
@@ -724,10 +724,12 @@ class QRDisplayScreen(BaseScreen):
|
||||
)
|
||||
chevron_down_icon.render()
|
||||
|
||||
# TRANSLATOR_NOTE: Increase QR code screen brightness
|
||||
text = _("Brighter")
|
||||
TextArea(
|
||||
image_draw=img_draw,
|
||||
canvas=rectangle,
|
||||
text="Brighter",
|
||||
text=text,
|
||||
font_size=GUIConstants.get_body_font_size(),
|
||||
font_name=GUIConstants.get_button_font_name(),
|
||||
background_color=(0, 0, 0, overlay_opacity),
|
||||
@@ -740,10 +742,12 @@ class QRDisplayScreen(BaseScreen):
|
||||
allow_text_overflow=False
|
||||
).render()
|
||||
|
||||
# TRANSLATOR_NOTE: Decrease QR code screen brightness
|
||||
text = _("Darker")
|
||||
TextArea(
|
||||
image_draw=img_draw,
|
||||
canvas=rectangle,
|
||||
text="Darker",
|
||||
text=text,
|
||||
font_size=GUIConstants.get_body_font_size(),
|
||||
font_name=GUIConstants.get_button_font_name(),
|
||||
background_color=(0, 0, 0, overlay_opacity),
|
||||
@@ -1037,8 +1041,9 @@ class PowerOffNotRequiredScreen(BaseTopNavScreen):
|
||||
self.show_back_button = True
|
||||
super().__post_init__()
|
||||
|
||||
text = _("It is safe to disconnect power at any time.")
|
||||
self.components.append(TextArea(
|
||||
text="It is safe to disconnect power at any time.",
|
||||
text=text,
|
||||
screen_y=self.top_nav.height,
|
||||
height=self.canvas_height - self.top_nav.height,
|
||||
))
|
||||
|
||||
@@ -16,6 +16,7 @@ from seedsigner.views.view import BackStackView, MainMenuView, NotYetImplemented
|
||||
|
||||
|
||||
class PSBTSelectSeedView(View):
|
||||
# TODO: Class-level attrs vs dynamic gettext calls
|
||||
SCAN_SEED = ("Scan a seed", SeedSignerIconConstants.QRCODE)
|
||||
TYPE_12WORD = ("Enter 12-word seed", FontAwesomeIconConstants.KEYBOARD)
|
||||
TYPE_24WORD = ("Enter 24-word seed", FontAwesomeIconConstants.KEYBOARD)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import re
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
from embit.descriptor import Descriptor
|
||||
|
||||
from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON
|
||||
@@ -20,8 +22,8 @@ class ScanView(View):
|
||||
dedicated errors when an unexpected QR type is scanned (e.g. Scan PSBT was
|
||||
selected but a SeedQR was scanned).
|
||||
"""
|
||||
instructions_text = "Scan a QR code"
|
||||
invalid_qr_type_message = "QRCode not recognized or not yet supported."
|
||||
instructions_text = _("Scan a QR code")
|
||||
invalid_qr_type_message = _("QRCode not recognized or not yet supported.")
|
||||
|
||||
|
||||
def __init__(self):
|
||||
@@ -56,7 +58,7 @@ class ScanView(View):
|
||||
# `seed__compactseedqr` as "seed: compactseedqr").
|
||||
return Destination(ErrorView, view_args=dict(
|
||||
title="Error",
|
||||
status_headline="Wrong QR Type",
|
||||
status_headline=_("Wrong QR Type"),
|
||||
text=self.invalid_qr_type_message + f""", received "{self.decoder.qr_type.replace("__", ": ").replace("_", " ")}\" format""",
|
||||
button_text="Back",
|
||||
next_destination=Destination(BackStackView, skip_current_view=True),
|
||||
@@ -155,10 +157,10 @@ class ScanView(View):
|
||||
# start everything over.
|
||||
self.controller.resume_main_flow = None
|
||||
return Destination(ErrorView, view_args=dict(
|
||||
title="Error",
|
||||
status_headline="Unknown QR Type",
|
||||
text="QRCode is invalid or is a data format not yet supported.",
|
||||
button_text="Done",
|
||||
title=_("Error"),
|
||||
status_headline=_("Unknown QR Type"),
|
||||
text=_("QRCode is invalid or is a data format not yet supported."),
|
||||
button_text=_("Done"),
|
||||
next_destination=Destination(MainMenuView, clear_history=True),
|
||||
))
|
||||
|
||||
@@ -167,8 +169,8 @@ class ScanView(View):
|
||||
|
||||
|
||||
class ScanPSBTView(ScanView):
|
||||
instructions_text = "Scan PSBT"
|
||||
invalid_qr_type_message = "Expected a PSBT"
|
||||
instructions_text = _("Scan PSBT")
|
||||
invalid_qr_type_message = _("Expected a PSBT")
|
||||
|
||||
@property
|
||||
def is_valid_qr_type(self):
|
||||
@@ -177,8 +179,8 @@ class ScanPSBTView(ScanView):
|
||||
|
||||
|
||||
class ScanSeedQRView(ScanView):
|
||||
instructions_text = "Scan SeedQR"
|
||||
invalid_qr_type_message = f"Expected a SeedQR"
|
||||
instructions_text = _("Scan SeedQR")
|
||||
invalid_qr_type_message = _("Expected a SeedQR")
|
||||
|
||||
@property
|
||||
def is_valid_qr_type(self):
|
||||
@@ -187,8 +189,8 @@ class ScanSeedQRView(ScanView):
|
||||
|
||||
|
||||
class ScanWalletDescriptorView(ScanView):
|
||||
instructions_text = "Scan descriptor"
|
||||
invalid_qr_type_message = "Expected a wallet descriptor QR"
|
||||
instructions_text = _("Scan descriptor")
|
||||
invalid_qr_type_message = _("Expected a wallet descriptor QR")
|
||||
|
||||
@property
|
||||
def is_valid_qr_type(self):
|
||||
@@ -197,8 +199,8 @@ class ScanWalletDescriptorView(ScanView):
|
||||
|
||||
|
||||
class ScanAddressView(ScanView):
|
||||
instructions_text = "Scan address QR"
|
||||
invalid_qr_type_message = "Expected an address QR"
|
||||
instructions_text = _("Scan address QR")
|
||||
invalid_qr_type_message = _("Expected an address QR")
|
||||
|
||||
@property
|
||||
def is_valid_qr_type(self):
|
||||
|
||||
@@ -94,7 +94,7 @@ class SeedSelectSeedView(View):
|
||||
seeds = self.controller.storage.seeds
|
||||
|
||||
if self.flow == Controller.FLOW__VERIFY_SINGLESIG_ADDR:
|
||||
title = "Verify Address"
|
||||
title = _("Verify Address")
|
||||
if not seeds:
|
||||
text = _("Load the seed to verify")
|
||||
else:
|
||||
@@ -433,11 +433,13 @@ class SeedDiscardView(View):
|
||||
button_data = [self.KEEP, self.DISCARD]
|
||||
|
||||
fingerprint = self.seed.get_fingerprint(self.settings.get_value(SettingsConstants.SETTING__NETWORK))
|
||||
# TRANSLATOR_NOTE: Inserts the seed fingerprint
|
||||
text = _("Wipe seed {} from the device?").format(fingerprint)
|
||||
selected_menu_num = self.run_screen(
|
||||
WarningScreen,
|
||||
title=_("Discard Seed?"),
|
||||
status_headline=None,
|
||||
text=_("Wipe seed {} from the device?").format(fingerprint),
|
||||
text=text,
|
||||
show_back_button=False,
|
||||
button_data=button_data,
|
||||
)
|
||||
@@ -1003,6 +1005,7 @@ class SeedWordsView(View):
|
||||
|
||||
if self.bip85_data is not None:
|
||||
mnemonic = self.seed.get_bip85_child_mnemonic(self.bip85_data["child_index"], self.bip85_data["num_words"]).split()
|
||||
# TRANSLATOR_NOTE: Inserts the child index (e.g. "Child #0")
|
||||
title = _("Child #{}").format(self.bip85_data["child_index"])
|
||||
else:
|
||||
mnemonic = self.seed.mnemonic_display_list
|
||||
@@ -1222,8 +1225,10 @@ class SeedWordsBackupTestView(View):
|
||||
button_data = [real_word, fake_word1, fake_word2, fake_word3]
|
||||
random.shuffle(button_data)
|
||||
|
||||
# TRANSLATOR_NOTE: Inserts the word number (e.g. "Verify Word #1")
|
||||
title = _("Verify Word #{}").format(self.cur_index + 1)
|
||||
selected_menu_num = ButtonListScreen(
|
||||
title=_("Verify Word #{}").format(self.cur_index + 1),
|
||||
title=title,
|
||||
show_back_button=False,
|
||||
button_data=button_data,
|
||||
is_bottom_list=True,
|
||||
@@ -1275,12 +1280,18 @@ class SeedWordsBackupTestMistakeView(View):
|
||||
RETRY = _("Try Again")
|
||||
button_data = [REVIEW, RETRY]
|
||||
|
||||
# TRANSLATOR_NOTE: Inserts the word number and the word (e.g. "Word #1 is not "apple"!")
|
||||
text = _("Word #{} is not \"{}\"!").format(self.cur_index + 1, self.wrong_word)
|
||||
|
||||
# TRANSLATOR_NOTE: User selected the wrong word during the mnemonic backup test (e.g. incorrectly said the 5th word was "zoo")
|
||||
status_headline = _("Wrong Word!")
|
||||
|
||||
selected_menu_num = DireWarningScreen(
|
||||
title=_("Verification Error"),
|
||||
show_back_button=False,
|
||||
status_headline=_("Wrong Word!"),
|
||||
text=_("Word #{} is not \"{}\"!").format(self.cur_index + 1, self.wrong_word),
|
||||
status_headline=status_headline,
|
||||
button_data=button_data,
|
||||
text=text,
|
||||
).display()
|
||||
|
||||
if button_data[selected_menu_num] == REVIEW:
|
||||
@@ -1870,11 +1881,25 @@ class AddressVerificationSuccessView(View):
|
||||
if sig_type == SettingsConstants.MULTISIG:
|
||||
source = _("multisig")
|
||||
else:
|
||||
# TRANSLATOR_NOTE: Inserts the seed fingerprint
|
||||
source = _("seed {}").format(self.seed.get_fingerprint())
|
||||
|
||||
# TRANSLATOR_NOTE: Used in a sentence describing the address type (change or receive)
|
||||
change_text = _("change")
|
||||
|
||||
# TRANSLATOR_NOTE: Used in a sentence describing the address type (change or receive)
|
||||
receive_text = _("receive")
|
||||
|
||||
# TRANSLATOR_NOTE: Address verification success message (e.g. "bc1qabc = seed 12345678's receive address #0.")
|
||||
text = _("{} = {}'s {} address #{}.""").format(
|
||||
address[:7],
|
||||
source,
|
||||
change_text if verified_index_is_change else receive_text,
|
||||
verified_index
|
||||
)
|
||||
LargeIconStatusScreen(
|
||||
status_headline=_("Address Verified"),
|
||||
text=f"""{address[:7]} = {source}'s {"change" if verified_index_is_change else "receive"} address #{verified_index}.""",
|
||||
text=text,
|
||||
show_back_button=False,
|
||||
).display()
|
||||
|
||||
@@ -1981,12 +2006,17 @@ class SeedSignMessageStartView(View):
|
||||
# calculate the actual receive address
|
||||
addr_format = embit_utils.parse_derivation_path(derivation_path)
|
||||
if not addr_format["clean_match"]:
|
||||
raise NotYetImplementedView("Signing messages for custom derivation paths not supported")
|
||||
raise NotYetImplementedView(_("Signing messages for custom derivation paths not supported"))
|
||||
|
||||
# Note: addr_format["network"] can be MAINNET or [TESTNET, REGTEST]
|
||||
if self.settings.get_value(SettingsConstants.SETTING__NETWORK) not in addr_format["network"]:
|
||||
from seedsigner.views.view import NetworkMismatchErrorView
|
||||
self.set_redirect(Destination(NetworkMismatchErrorView, view_args=dict(text=f"Current network setting ({self.settings.get_value_display_name(SettingsConstants.SETTING__NETWORK)}) doesn't match {self.derivation_path}")))
|
||||
# TRANSLATOR_NOTE: Inserts mainnet/testnet/regtest and derivation path
|
||||
text = _("Current network setting ({}) doesn't match {}").format(
|
||||
self.settings.get_value_display_name(SettingsConstants.SETTING__NETWORK),
|
||||
self.derivation_path,
|
||||
)
|
||||
self.set_redirect(Destination(NetworkMismatchErrorView, view_args=dict(text=text)))
|
||||
|
||||
# cleanup. Note: We could leave this in place so the user can resume the
|
||||
# flow, but for now we avoid complications and keep things simple.
|
||||
@@ -2063,7 +2093,7 @@ class SeedSignMessageConfirmAddressView(View):
|
||||
seed = self.controller.storage.seeds[seed_num]
|
||||
addr_format = embit_utils.parse_derivation_path(self.derivation_path)
|
||||
if not addr_format["clean_match"] or addr_format["script_type"] == SettingsConstants.CUSTOM_DERIVATION:
|
||||
raise Exception("Signing messages for custom derivation paths not supported")
|
||||
raise Exception(_("Signing messages for custom derivation paths not supported"))
|
||||
|
||||
if addr_format["network"] != SettingsConstants.MAINNET:
|
||||
# We're in either Testnet or Regtest or...?
|
||||
@@ -2071,7 +2101,11 @@ class SeedSignMessageConfirmAddressView(View):
|
||||
addr_format["network"] = self.settings.get_value(SettingsConstants.SETTING__NETWORK)
|
||||
else:
|
||||
from seedsigner.views.view import NetworkMismatchErrorView
|
||||
self.set_redirect(Destination(NetworkMismatchErrorView, view_args=dict(text=f"Current network setting ({self.settings.get_value_display_name(SettingsConstants.SETTING__NETWORK)}) doesn't match {self.derivation_path}")))
|
||||
text = _("Current network setting ({}) doesn't match {}").format(
|
||||
self.settings.get_value_display_name(SettingsConstants.SETTING__NETWORK),
|
||||
self.derivation_path,
|
||||
)
|
||||
self.set_redirect(Destination(NetworkMismatchErrorView, view_args=dict(text=text)))
|
||||
|
||||
# cleanup. Note: We could leave this in place so the user can resume the
|
||||
# flow, but for now we avoid complications and keep things simple.
|
||||
|
||||
@@ -650,8 +650,8 @@ class ToolsAddressExplorerAddressListView(View):
|
||||
data[addr_storage_key].append(address)
|
||||
else:
|
||||
# TODO: Custom derivation path
|
||||
raise Exception("Custom Derivation address explorer not yet implemented")
|
||||
|
||||
raise Exception(_("Custom Derivation address explorer not yet implemented"))
|
||||
|
||||
elif "wallet_descriptor" in data:
|
||||
descriptor: Descriptor = data["wallet_descriptor"]
|
||||
if descriptor.is_basic_multisig:
|
||||
@@ -661,7 +661,7 @@ class ToolsAddressExplorerAddressListView(View):
|
||||
data[addr_storage_key].append(address)
|
||||
|
||||
else:
|
||||
raise Exception("Single sig descriptors not yet supported")
|
||||
raise Exception(_("Single sig descriptors not yet supported"))
|
||||
finally:
|
||||
# Everything is set. Stop the loading screen
|
||||
self.loading_screen.stop()
|
||||
@@ -679,6 +679,7 @@ class ToolsAddressExplorerAddressListView(View):
|
||||
end_digits = -4
|
||||
button_data.append(f"{cur_index}:{address[:8]}...{address[end_digits:]}")
|
||||
|
||||
# TRANSLATOR_NOTE: Insert the number of addrs displayed per screen (e.g. "Next 10")
|
||||
button_data.append((_("Next {}").format(addrs_per_screen), None, None, None, SeedSignerIconConstants.CHEVRON_RIGHT))
|
||||
|
||||
selected_menu_num = self.run_screen(
|
||||
|
||||
@@ -347,7 +347,10 @@ class NetworkMismatchErrorView(ErrorView):
|
||||
self.title = _("Network Mismatch")
|
||||
self.button_text = _("Change Setting")
|
||||
if not self.text:
|
||||
self.text = f"Current network setting ({self.settings.get_value_display_name(SettingsConstants.SETTING__NETWORK)}) doesn't match current action."
|
||||
# TRANSLATOR_NOTE: Inserts mainnet/testnet/regtest
|
||||
self.text = _("Current network setting ({}) doesn't match current action.").format(
|
||||
self.settings.get_value_display_name(SettingsConstants.SETTING__NETWORK),
|
||||
)
|
||||
|
||||
if not self.next_destination:
|
||||
from seedsigner.views.settings_views import SettingsEntryUpdateSelectionView
|
||||
@@ -382,7 +385,11 @@ class OptionDisabledView(View):
|
||||
self.UPDATE_SETTING = _("Update Setting")
|
||||
self.DONE = _("Done")
|
||||
self.settings_entry = SettingsDefinition.get_settings_entry(self.settings_attr)
|
||||
self.error_msg = f"\"{self.settings_entry.display_name}\" is currently disabled in Settings."
|
||||
|
||||
# TRANSLATOR_NOTE: Inserts the name of a settings option (e.g. "Persistent Settings" is currently...)
|
||||
self.error_msg = _("\"{}\" is currently disabled in Settings.").format(
|
||||
self.settings_entry.display_name,
|
||||
)
|
||||
|
||||
|
||||
def run(self):
|
||||
|
||||
Reference in New Issue
Block a user