diff --git a/babel/README.md b/babel/README.md new file mode 100644 index 000000000..9510f92fc --- /dev/null +++ b/babel/README.md @@ -0,0 +1,178 @@ +# Babel multi-language support + + +## For Translators +Many of you translator volunteers will be new to git/github so we'll start with the basics: + + +### Create github account, install Github Desktop +Install the [Github Desktop app](https://desktop.github.com/). This is an easy way to manage your changes to an open source project. + +When Github Desktop starts up it'll ask you to log in to your github account. If you don't already have an account, create one now. + + +### Clone the Specter Desktop repo +Now you're going to grab a copy of the full Specter Desktop source code, which includes the translation files. + +Open the Github Desktop app and add the Specter Desktop repo via "Clone a Repository". On the "URL" tab type in ~~"cryptoadvance/specter-desktop"~~ (**for now we have to point to my work-in-progress repo: "kdmukai/specter-desktop"**): + + + +Select where you want to save the source code on your local computer and hit "Clone". + +When you're presented with the following choice, select "For my own purposes": + + + +_When the clone is finished, click on the "Current Branch" button at the top middle and change to "origin/babel_integration" to point to my work-in-progress branch_ + + +### Editing a translation file +Before you begin editing, ALWAYS go to Github Desktop and click the "Fetch origin" button at the top right. This pulls down all the latest changes from the repo. We'll all try our best to make sure that only one person is making changes at a time on a given translation file but if a change is submitted ahead of you, "Fetch origin" will grab it and get you in sync. We want to avoid messy conflicts where two or more people have edited the same translation file. + +You'll be working with a `messages.po` file for each specific language. This file lists all the text that is displayed in Specter in English as a series of "msgid"s. Your job is to complete the matching translation in the "msgstr" field. + +The `messages.po` text format is fairly straightforward but can be a little hard to work with, especially for multi-line phrases. Instead, we recommend that translators use the free tool [Poedit](https://poedit.net/download). + +Once it's installed, go to Poedit preferences and uncheck "Wrap at": + + + +Navigate to the directory where you cloned the repo. The translation files can be found organized by two-letter language code (e.g. Spanish = "es") under `src/cryptoadvance/specter/translations`. + +In Poedit open the `messages.po` file for your target langage (e.g. Spanish: [src/cryptoadvance/specter/translations/es/LC_MESSAGES/messages.po](../src/cryptoadvance/specter/translations/es/LC_MESSAGES/messages.po)). + +Add or update translations, then save your changes. + + +### Editing Guidelines +* It's okay to leave some lines blank! If you can't provide a proper translation, just skip it and other translators will fill them in later. A blank entry will default to just displaying the original English. + +* Some of the text strings have html or other code-related markup within them: + ``` + Please let us know! Create an issue or ping us on Telegram to fix it. + ``` + + Your translations must preserve all of the html markup. If you are unfamiliar with html markup, feel free to just skip these entries. + +* You'll also see passages with markers for where text will be dynamically inserted: + ``` + "Hello {}, welcome back!" + ``` + In this example case the user's name will be inserted in the curly brackets. Your translation must preserve the curly brackets. + + This is used in a lot of our error reporting: + ``` + "Wallet failed to load. {}" + ``` + The brackets at the end will display an error code, debugging info, etc. + +* Much of the text will include some very technical terms. If you're unfamiliar with the term in English or don't know its equivalent in your target language (e.g. "derivation path" or "hash"), review other occurrences of that word in existing translations in the `messages.po` file or ask in the Telegram group. Obviously we want to try to use the most recognizable, common term in each language, even though there won't necessarily be a standard set. + + And many languages will most likely just keep many of the technical words the same (e.g. "xpub"). + +* The strings are presented out of context and a word may have many possible translations. If you can't figure out the right usage, ask for help in the Telegram group. Each string includes the exact line number where it was found in the code (right-click on it in Poedit and you'll see "Code Occurrences"). Include this info and others can help you get a better sense of how it's being used in that context. You can also directly review that line of code yourself (click on the entry in "Code Occurrences") but that may be bewildering if you are not a developer. + + +### Submitting your changes +The updated `messages.po` file should now show up in Github Desktop as having changes. + + + +_Note: You'll see the app offering to "create a fork". Do not create a fork! We want your local copy of the Specter Desktop code to remain connected to our repo, not a forked version that you'll have to manage._ + +**_The next steps will break from typical `git` procedures in order to keep things simple for our non-programmer translators._** + +In a web browser go to github's latest version of the translation file you were just working on. Remember that the directories are organized by the two-letter language codes. So for Spanish ("es"): +[https://github.com/kdmukai/specter-desktop/tree/babel_integration/src/cryptoadvance/specter/translations/es/LC_MESSAGES/messages.po](https://github.com/kdmukai/specter-desktop/tree/babel_integration/src/cryptoadvance/specter/translations/es/LC_MESSAGES/messages.po) + +Click on the pencil icon to edit the translation file: + + + +You can now directly edit the file. But we want to use the version you just updated in Poedit. + +On your computer, navigate to the `messages.po` file and open it with a simple text editor (macOS: TextEdit; Windows: Notepad). We have to make sure that the text editor doesn't change the file when it opens it (more complex editors might try to reformat the file). Copy the entire contents of the file. + +Back in your browser, delete all the content in the editing window (click into the editing area and CTRL-A to select all, then delete), then paste your latest text into the online editing window. + +If everything went correctly, you should just see your edits when you click the "Preview changes" tab just above the online editing window. + + + +Any changed lines will be highlighted. Red highlights are deletions, green are additions. + +Scroll to the bottom of that web page to the "Commit changes section". If your update addresses a specific issue that was raised in the repo's "Issues" section, reference it by number in the optional extended description box using this format: "Fixes #1234" (using the actual issue number, obv). + +Select the option to "Create a new branch" and then click "Propose changes": + + + +Then on the next screen follow the prompts to create your pull request and submit it to the project. + +A reviewer on the Specter Desktop team will review your changes and (hopefully) accept the changes. Your contributions will be merged into the main Specter Desktop code repository. You will officially be a Specter Desktop open source contributor! + + + +## For Developers: +### "Wrapping" text for translation +All you have to do in your code is wrap each piece of English text with the `ugettext` shorthand `_()`: +* Wrap jinja template text: `

Hello, world!

` becomes `

{{ _('Hello, world!') }}

` +* Wrap python strings: `error="No device was selected."` becomes `error=_("No device was selected.")` +* Use `.format()` to wrap strings with variable injections: + ``` + mystr = f"My dad's name is {dad.name} and my name is {self.name}." + mystr = _("My dad's name is {} and my name is {}").format(dad.name, self.name) + ``` + + If there are a lot of variables to inject, placeholder names can be used: + ``` + mystr = _("My dad's name is {dad_name} and my name is {my_name}").format(dad_name=dad.name, my_name=self.name) + ``` + + +### Rescanning for text that needs translations +Re-generate the `messages.pot` file: +``` +pybabel extract -F babel/babel.cfg -o babel/messages.pot . +``` +This will rescan all wrapped text, picking up new strings as well as updating existings strings that have been edited. + +Then run `update`: +``` +pybabel update -N --no-wrap -i babel/messages.pot -d src/cryptoadvance/specter/translations + +# Or target a specific language code: +pybabel update -N --no-wrap -i babel/messages.pot -d src/cryptoadvance/specter/translations -l es +``` +_note: the `-N` flag prevents babel from trying to use fuzzy matching to re-use existing translations for new strings. The fuzzy matching does not seem to do what we would want so we keep it disabled._ + +Any newly wrapped text strings will be added to each `messages.po` file. Altered strings will be flagged as needing review to see if the existing translations can still be used. + +Once the next round of translations is complete, recompile the results: +``` +pybabel compile -d src/cryptoadvance/specter/translations + +# Or target a specific language code: +pybabel compile -d src/cryptoadvance/specter/translations -l es +``` + + +### Adding support for another language +Assuming you have `extract`ed an updated `messages.pot`, all you have to do is generate the initial version of each new language file: +``` +pybabel init -i babel/messages.pot -d src/cryptoadvance/specter/translations -l es +pybabel init -i babel/messages.pot -d src/cryptoadvance/specter/translations -l fr +pybabel init -i babel/messages.pot -d src/cryptoadvance/specter/translations -l de +``` + +Then `update` and `compile` as above. + +The only other step is to add the new language to the LANGUAGES list in `config.py`; the UI droplist automatically populates from that list. By convention use the native way to present the language: +``` +# wrong: + "he": "Hebrew", + +# right: + "he": "עברית", +``` diff --git a/babel/babel.cfg b/babel/babel.cfg new file mode 100644 index 000000000..de53b622f --- /dev/null +++ b/babel/babel.cfg @@ -0,0 +1,4 @@ +[python: src/**/**.py] +[jinja2: src/**/templates/**.html] +[jinja2: src/**/templates/**.jinja] +extensions=jinja2.ext.autoescape,jinja2.ext.with_ \ No newline at end of file diff --git a/babel/img/add_repo.png b/babel/img/add_repo.png new file mode 100644 index 000000000..349bcf2cf Binary files /dev/null and b/babel/img/add_repo.png differ diff --git a/babel/img/github_desktop_1.png b/babel/img/github_desktop_1.png new file mode 100644 index 000000000..b5e6e38ea Binary files /dev/null and b/babel/img/github_desktop_1.png differ diff --git a/babel/img/github_desktop_setup_01.jpg b/babel/img/github_desktop_setup_01.jpg new file mode 100644 index 000000000..fd439f352 Binary files /dev/null and b/babel/img/github_desktop_setup_01.jpg differ diff --git a/babel/img/github_edit_1.png b/babel/img/github_edit_1.png new file mode 100644 index 000000000..a11861053 Binary files /dev/null and b/babel/img/github_edit_1.png differ diff --git a/babel/img/github_edit_2.png b/babel/img/github_edit_2.png new file mode 100644 index 000000000..e54134896 Binary files /dev/null and b/babel/img/github_edit_2.png differ diff --git a/babel/img/github_edit_3.png b/babel/img/github_edit_3.png new file mode 100644 index 000000000..c482880f2 Binary files /dev/null and b/babel/img/github_edit_3.png differ diff --git a/babel/img/poedit_01.png b/babel/img/poedit_01.png new file mode 100644 index 000000000..8203c90ac Binary files /dev/null and b/babel/img/poedit_01.png differ diff --git a/babel/messages.pot b/babel/messages.pot new file mode 100644 index 000000000..9cbe3635a --- /dev/null +++ b/babel/messages.pot @@ -0,0 +1,4531 @@ +# Translations template for PROJECT. +# Copyright (C) 2021 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2021. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2021-07-05 14:05-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.1\n" + +#: src/cryptoadvance/specter/node.py:316 +msgid "Connection to node failed" +msgstr "" + +#: src/cryptoadvance/specter/node.py:326 +msgid "Core Node might be too old" +msgstr "" + +#: src/cryptoadvance/specter/node.py:343 +msgid "Failed to connect!" +msgstr "" + +#: src/cryptoadvance/specter/node.py:352 +msgid "RPC authentication failed!" +msgstr "" + +#: src/cryptoadvance/specter/node.py:366 +msgid "Failed to connect" +msgstr "" + +#: src/cryptoadvance/specter/managers/device_manager.py:84 +msgid "Could not find Device {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/auth.py:50 +msgid "" +"We could not check your password, maybe Bitcoin Core is not running or " +"not configured?" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/auth.py:85 +msgid "Invalid username or password" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/auth.py:114 +msgid "Please enter a username." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/auth.py:121 +msgid "Please enter a password of a least {} characters." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/auth.py:135 +#: src/cryptoadvance/specter/server_endpoints/settings.py:373 +msgid "Username is already taken, please choose another one" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/auth.py:147 +msgid "" +"You have registered successfully, please login with your new account to " +"start using Specter" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/auth.py:155 +msgid "" +"Invalid registration link, please request a new link from the node " +"operator." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/auth.py:168 +msgid "You were logged out" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/auth.py:174 +msgid "Logged in successfully." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/controller.py:54 +msgid "Wallet not found. Specter reloaded all wallets, please try again." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/controller.py:58 +msgid "Bitcoin Core RpcError: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/controller.py:99 +msgid "" +"Bitcoin Core is not coming up in time. Maybe it's just slow but please " +"check the logs below" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/controller.py:120 +#: src/cryptoadvance/specter/server_endpoints/controller.py:130 +msgid "Session expired. Please refresh and try again." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/controller.py:317 +msgid "" +"You need a mainnet node to retrieve the whitepaper. Check your node " +"configurations." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:64 +#: src/cryptoadvance/specter/server_endpoints/devices.py:290 +#: src/cryptoadvance/specter/server_endpoints/devices.py:308 +#: src/cryptoadvance/specter/server_endpoints/devices.py:434 +msgid "Device name cannot be empty" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:66 +#: src/cryptoadvance/specter/server_endpoints/devices.py:292 +#: src/cryptoadvance/specter/server_endpoints/devices.py:310 +msgid "Device with this name already exists" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:84 +#: src/cryptoadvance/specter/server_endpoints/devices.py:298 +msgid "Failed to parse these xpubs" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:89 +msgid "No paths were specified, please provide at least one." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:102 +#: src/cryptoadvance/specter/server_endpoints/devices.py:147 +msgid "{} keys were added successfully" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:123 +#: src/cryptoadvance/specter/server_endpoints/devices.py:164 +msgid "{} was added successfully!" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:133 +#: src/cryptoadvance/specter/server_endpoints/devices.py:350 +msgid "Failed to setup hot wallet. Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:143 +msgid "xpubs list must not be empty" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:198 +#: src/cryptoadvance/specter/server_endpoints/devices.py:312 +msgid "" +"Invalid mnemonic entered: Must contain either: 12, 15, 18, 21, or 24 " +"words." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:202 +#: src/cryptoadvance/specter/server_endpoints/devices.py:317 +msgid "Invalid mnemonic entered." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:206 +#: src/cryptoadvance/specter/server_endpoints/devices.py:321 +msgid "Invalid address range selected." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:248 +#: src/cryptoadvance/specter/server_endpoints/devices.py:386 +msgid "Device not found" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:257 +msgid "Master blinding key was added successfully" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:295 +msgid "xpubs name cannot be empty" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:397 +msgid "Device could not be removed since it is used in wallets: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:401 +msgid "You must delete those wallets before you can remove this device." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:405 +#: src/cryptoadvance/specter/server_endpoints/devices.py:427 +msgid "You can delete a wallet from its Settings -> Advanced page." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:421 +msgid "Key could not be removed since it is used in wallets: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:425 +msgid "You must delete those wallets before you can remove this key." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/devices.py:438 +msgid "Device already exists" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:47 +#: src/cryptoadvance/specter/server_endpoints/nodes.py:228 +msgid "Node not found" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:66 +#: src/cryptoadvance/specter/server_endpoints/nodes.py:240 +msgid "Only an admin is allowed to access this page" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:101 +msgid "Node name cannot be empty" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:105 +msgid "Node with this name already exists" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:110 +#: src/cryptoadvance/specter/server_endpoints/nodes.py:262 +msgid "Failed to deleted node. Node isn't saved" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:113 +#: src/cryptoadvance/specter/server_endpoints/nodes.py:268 +msgid "Node deleted successfully" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:122 +#: src/cryptoadvance/specter/server_endpoints/nodes.py:277 +msgid "Failed to delete node. Specter must have at least one node configured" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:150 +#: src/cryptoadvance/specter/server_endpoints/nodes.py:154 +msgid "Test failed: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:152 +msgid "Test passed" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:159 +msgid "Node with this name already exists, please choose a different name." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:198 +msgid "Failed connecting to the node" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:253 +msgid "Node name must not be empty" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:286 +msgid "Specter successfully stopped Bitcoin Core" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:290 +msgid "Stopping Bitcoin Core, this might take a few moments." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:294 +msgid "Failed to stop Bitcoin Core {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:297 +msgid "Specter has started Bitcoin Core" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:299 +msgid "Specter failed to start the node" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:309 +msgid "Bitcoin Core successfully uninstalled" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:318 +msgid "Failed to remove Bitcoin Core, error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:327 +msgid "Failed to upgrade Bitcoin Core version, error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/nodes.py:333 +msgid "Bitcoin Core version is already up to date" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:112 +msgid "Failed to import wallet {}, error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:146 +msgid "Failed to perform rescan for wallet: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:152 +msgid "Failed to import wallet {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:154 +msgid "Specter data was successfully loaded from backup" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:157 +msgid "" +"Wallets are rescanning for transactions history.\n" +"This may take a few hours to complete." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:189 +msgid "Only an admin is allowed to access this page." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:260 +msgid "Specter has started Tor" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:262 +msgid "Failed to start Tor, error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:269 +msgid "Specter stopped Tor successfully" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:271 +msgid "Failed to stop Tor, error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:280 +msgid "Tor uninstalled successfully" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:282 +msgid "Failed to uninstall Tor, error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:297 +msgid "Tor requests test completed successfully!" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:300 +msgid "Failed to make test request over Tor. Status-Code: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:316 +msgid "" +"Failed to make test request over Tor.\n" +"Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:390 +#: src/cryptoadvance/specter/server_endpoints/settings.py:415 +msgid "Please enter a password of a least {} characters" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:456 +msgid "(expires in {} hours)" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:458 +msgid "(expires in 1 hour)" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:466 +msgid "New user link generated{}: {}auth/register?otp={}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:473 +msgid "Error: Only the admin account can issue new registration links" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:483 +msgid "User {} was deleted successfully" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:486 +msgid "Error: Only the admin account can delete users" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/settings.py:506 +msgid "HWIBridge URL is updated! Don't forget to whitelist Specter!" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/setup.py:124 +msgid "Tor is already installed" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/setup.py:126 +msgid "Tor installation is still in progress" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/setup.py:127 +msgid "Starting Tor setup!" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/setup.py:144 +msgid "Bitcoin Core is already installed" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/setup.py:146 +#: src/cryptoadvance/specter/server_endpoints/setup.py:208 +msgid "Bitcoin Core installation is still in progress" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/setup.py:147 +#: src/cryptoadvance/specter/server_endpoints/setup.py:209 +msgid "Starting Bitcoin Core setup!" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/setup.py:206 +msgid "Bitcoin Core in not installed but required for this step" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:51 +msgid "SpecterError while {}: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:108 +msgid "Failed to delete wallet: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:120 +msgid "Configure Bitcoin Core to create wallets" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:126 +msgid "" +"


Bitcoin Core is running with wallets disabled.

Please make " +"sure disablewallet is off (set disablewallet=0 in your bitcoin.conf), " +"then restart Bitcoin Core and try again.
See here for more information.

" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:140 +msgid "Unknown wallet type requested" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:167 +msgid "Wallet imported successfully" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:203 +msgid "No device was selected. Please select a device to create the wallet for." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:212 +msgid "Device {} doesn't have keys matching this wallet type" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:240 +#: src/cryptoadvance/specter/server_endpoints/wallets.py:826 +msgid "Wallet already exists" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:275 +msgid "No keys were selected for device, please try adding keys first" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:301 +msgid "Failed to create wallet. Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:491 +msgid "Failed to fetch fee estimations. Please use the manual fee calculation." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:544 +#: src/cryptoadvance/specter/server_endpoints/wallets.py:577 +msgid "Failed to perform RBF. Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:561 +msgid "Failed to cancel transaction with RBF. Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:600 +msgid "Failed to sign PSBT: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:603 +msgid "Device already signed the PSBT" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:619 +msgid "Failed to get RBF coins. Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:673 +msgid "Could not delete Pending PSBT!" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:711 +msgid "Could not import PSBT: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:785 +msgid "Failed to abort rescan. Maybe already complete?" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:822 +msgid "Wallet name cannot be empty" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:858 +msgid "Cannot parse empty data as PSBT" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:882 +msgid "Invalid transaction format" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:898 +msgid "Unknown error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:915 +#: src/cryptoadvance/specter/server_endpoints/wallets.py:972 +msgid "" +"Failed to broadcast transaction: transaction is invalid\n" +"{}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:944 +msgid "Failed to broadcast transaction. Network not supported." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:953 +msgid "Failed to broadcast transaction. Block explorer not supported." +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:967 +msgid "Failed to broadcast transaction with error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1066 +msgid "Exception trying to get address label: Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1274 +msgid "Failed to export addresses list. Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1343 +msgid "Failed to export wallet utxo. Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1378 +msgid "Failed to export wallets overview history. Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1410 +msgid "Failed to export wallets overview utxo. Error: {}" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1436 +msgid "Date" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1437 +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1527 +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1580 +#: src/cryptoadvance/specter/templates/includes/address-data.html:83 +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:142 +#: src/cryptoadvance/specter/templates/includes/tx-table.html:159 +msgid "Label" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1438 +msgid "Category" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1439 +msgid "Amount ({})" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1440 +msgid "Value ({})" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1441 +msgid "Rate (BTC/{})" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1443 +msgid "Rate ({}/SAT)" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1444 +#: src/cryptoadvance/specter/templates/wallet/send/new/components/coin_selection_table.jinja:15 +msgid "TxID" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1445 +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1526 +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1578 +#: src/cryptoadvance/specter/templates/includes/address-data.html:82 +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:140 +#: src/cryptoadvance/specter/templates/wallet/send/new/components/coin_selection_table.jinja:15 +#: src/cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_table.jinja:15 +msgid "Address" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1446 +msgid "Block Height" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1447 +msgid "Timestamp" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1448 +msgid "Raw Transaction" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1451 +msgid "Wallet" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1528 +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1577 +msgid "Index" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1529 +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1581 +#: src/cryptoadvance/specter/templates/includes/address-data.html:87 +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:144 +msgid "Used" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1530 +msgid "Current balance" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1545 +msgid "(external)" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1549 +msgid " (change)" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1554 +msgid "unknown (external address)" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1579 +msgid "Type" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1582 +msgid "UTXO" +msgstr "" + +#: src/cryptoadvance/specter/server_endpoints/wallets.py:1583 +msgid "Amount (BTC)" +msgstr "" + +#: src/cryptoadvance/specter/templates/500.jinja:5 +#: src/cryptoadvance/specter/templates/500_timeout.jinja:5 +#: src/cryptoadvance/specter/templates/base.jinja:5 +msgid "Specter Desktop" +msgstr "" + +#: src/cryptoadvance/specter/templates/500.jinja:18 +msgid "Server error!" +msgstr "" + +#: src/cryptoadvance/specter/templates/500.jinja:19 +#: src/cryptoadvance/specter/templates/500_timeout.jinja:19 +msgid "Exception" +msgstr "" + +#: src/cryptoadvance/specter/templates/500.jinja:21 +#: src/cryptoadvance/specter/templates/500_timeout.jinja:21 +msgid "Back to the main page" +msgstr "" + +#: src/cryptoadvance/specter/templates/500.jinja:23 +msgid "Details" +msgstr "" + +#: src/cryptoadvance/specter/templates/500.jinja:26 +#: src/cryptoadvance/specter/templates/500_timeout.jinja:31 +msgid "" +"Please let us know! Create an issue or ping us on Telegram to " +"fix it." +msgstr "" + +#: src/cryptoadvance/specter/templates/500_timeout.jinja:18 +msgid "Timeout Error!" +msgstr "" + +#: src/cryptoadvance/specter/templates/500_timeout.jinja:23 +msgid "" +"Please have a look in the below log. There are effectively two ways to " +"resolve this:" +msgstr "" + +#: src/cryptoadvance/specter/templates/500_timeout.jinja:25 +msgid "Either the process was just slow and Specter was too impatient" +msgstr "" + +#: src/cryptoadvance/specter/templates/500_timeout.jinja:26 +msgid "" +"The process is in trouble which should be reflected by the content of the" +" logs below" +msgstr "" + +#: src/cryptoadvance/specter/templates/500_timeout.jinja:28 +msgid "Details from the log file" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:63 +msgid "ERROR:" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:69 +msgid "Something went wrong:" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:75 +msgid "Welcome to Specter Desktop" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:78 +msgid "" +"Specter Desktop is a convenient wallet interface to better use your " +"Bitcoin Core node. It’s good for singlesig wallets, but comes with a " +"special focus on multisignature setups for different hardware wallets and" +" air-gapped signing devices." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:85 +msgid "Get started!" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:85 +msgid "Continue setup" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:88 +msgid "Getting Started" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:94 +msgid "Using Specter from a remote machine?" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:96 +msgid "" +"If you run Specter on a remote machine, like Umbrel or a myNode, you need" +" to update settings to connect hardware wallets via USB." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:98 +msgid "Update your settings" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:113 +msgid "Connect Specter with Bitcoin Core node." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:120 +msgid "Connecting Specter to your Bitcoin Core node" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:122 +msgid "I don't have a Bitcoin Core node yet." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:123 +msgid "I have Bitcoin Core on this computer." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:124 +msgid "I have a remote Bitcoin Core node." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:128 +msgid "Installing and Setting Up Bitcoin Core" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:129 +msgid "" +"Check out these video tutorials on downloading and setting up Bitcoin " +"Core with Specter Desktop" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:137 +msgid "Connecting Specter to your local Bitcoin Core node" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:138 +msgid "" +"If you're running a local Bitcoin Core node, Specter should be able to " +"auto-detect it if its data folder is located at the default location." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:139 +msgid "" +"In case it isn't, you might need to specify the Bitcoin Core data folder " +"path in Specter's settings page." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:140 +msgid "" +"Alternatively, you can switch off auto-detect from the settings and " +"provide the Bitcoin Core RPC credentials and host URL manually." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:141 +msgid "" +"Please note:
Your node must be configured with " +"server=1 line in the bitcoin.conf file." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:142 +msgid "If you don't have that, add it and restart Bitcoin Core." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:145 +msgid "" +"In addition, you can check out these video tutorials for setting up " +"Bitcoin Core with Specter Desktop" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:153 +msgid "Connecting Specter to your remote Bitcoin Core node" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:154 +msgid "Connecting to a \"node in a box\"" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:156 +msgid "" +"Specter can be used with a remote Bitcoin Core node running on a machine " +"like RaspiBlitz, myNode, Nodl, Umbrel, and Embassy." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:157 +msgid "" +"RaspiBlitz and myNode currently allow running Specter in the remote " +"machine directly, which means it's possible to use it and skip setting up" +" connection manually." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:158 +msgid "" +"If you use a different node or would still like to connect run Specter " +"locally but connect remotely, you can do so by going to Settings, Bitcoin" +" Core tab, and provide the Bitcoin Core RPC credentials and host URL " +"manually." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:160 +msgid "Connecting over Tor" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:161 +msgid "" +"Connecting over Tor requires that you first configure Tor on your local " +"machine." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:174 +msgid "Add signing devices you wish to use." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:186 +msgid "Create your first wallet!" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:199 +msgid "And when you are all set: Get the whitepaper from the timechain." +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:211 +msgid "" +"Having issues? Try reading the " +"FAQ" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:212 +msgid "Still having issues?" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:213 +msgid "" +"Feel free to open an " +"issue on the GitHub or ask in the Specter Community telegram chat" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:217 +msgid "Help wanted: Do you like Specter?" +msgstr "" + +#: src/cryptoadvance/specter/templates/base.jinja:220 +msgid "Supported and maintained by" +msgstr "" + +#: src/cryptoadvance/specter/templates/hwi_bridge.jinja:11 +msgid "HWI Bridge Settings" +msgstr "" + +#: src/cryptoadvance/specter/templates/hwi_bridge.jinja:15 +msgid "HWI Bridge is also accessible over Tor" +msgstr "" + +#: src/cryptoadvance/specter/templates/hwi_bridge.jinja:16 +msgid "Copied Tor hidden service address" +msgstr "" + +#: src/cryptoadvance/specter/templates/hwi_bridge.jinja:21 +msgid "Whitelisted domains" +msgstr "" + +#: src/cryptoadvance/specter/templates/hwi_bridge.jinja:24 +msgid "" +"To whitelist multiple domains, just list them one after another, each in " +"a new line, for example" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/editable_title.jinja:11 +#: src/cryptoadvance/specter/templates/device/device.jinja:21 +#: src/cryptoadvance/specter/templates/hwi_bridge.jinja:30 +#: src/cryptoadvance/specter/templates/includes/address-label.html:65 +#: src/cryptoadvance/specter/templates/wallet/components/editable_label.jinja:10 +msgid "Update" +msgstr "" + +#: src/cryptoadvance/specter/templates/login.jinja:8 +msgid "Login to Specter" +msgstr "" + +#: src/cryptoadvance/specter/templates/login.jinja:11 +#: src/cryptoadvance/specter/templates/register.jinja:11 +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:41 +msgid "Username" +msgstr "" + +#: src/cryptoadvance/specter/templates/login.jinja:13 +msgid "password" +msgstr "" + +#: src/cryptoadvance/specter/templates/login.jinja:19 +msgid "Login" +msgstr "" + +#: src/cryptoadvance/specter/templates/register.jinja:8 +msgid "Register to the Specter Node" +msgstr "" + +#: src/cryptoadvance/specter/templates/register.jinja:13 +msgid "Password" +msgstr "" + +#: src/cryptoadvance/specter/templates/register.jinja:19 +msgid "Register" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/editable_title.jinja:12 +#: src/cryptoadvance/specter/templates/includes/address-label.html:66 +#: src/cryptoadvance/specter/templates/includes/tx-row.html:241 +#: src/cryptoadvance/specter/templates/wallet/components/editable_label.jinja:11 +msgid "Cancel" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/editable_title.jinja:13 +msgid "Edit Name" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:38 +msgid "Price Settings" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:41 +msgid "" +"Please set custom rate or choose between the automated price provider " +"options." +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:43 +msgid "Manual" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:44 +msgid "Automatic" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:48 +msgid "Price:" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:51 +msgid "Symbol:" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:56 +msgid "Select price provider:" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:61 +msgid "Currency:" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:94 +msgid "Provider:" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:158 +msgid "Weight Unit:" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:172 +msgid "" +"Price will automatically be fetched from the selected provider every 10 " +"minutes." +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:176 +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:67 +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:53 +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:109 +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:102 +msgid "Save" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:179 +msgid "Disable showing price" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:181 +msgid "" +"You can enable showing price feature to see the price
information of " +"your Bitcoin amounts across Specter." +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:183 +msgid "Enable showing price" +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:189 +msgid "Turning on show price mode..." +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:191 +msgid "Turning off show price mode..." +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:212 +msgid "Failed to toggle price mode..." +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:220 +msgid "Updating price data..." +msgstr "" + +#: src/cryptoadvance/specter/templates/components/price_bar.jinja:240 +msgid "" +"Failed to fetch price data from selected provider, please try again or " +"select another provider." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:28 +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:12 +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:122 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:59 +msgid "Network" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:28 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:91 +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:123 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:60 +msgid "Purpose" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:28 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:91 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:183 +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:124 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:61 +msgid "Derivation" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:28 +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:130 +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:154 +#: src/cryptoadvance/specter/templates/includes/tx-table.html:152 +#: src/cryptoadvance/specter/templates/includes/tx-table.html:167 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:17 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:125 +msgid "Export" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:28 +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:125 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:62 +msgid "Key" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:28 +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:126 +#: src/cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_table.jinja:15 +msgid "Actions" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:43 +msgid "Show key QR code" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:58 +#: src/cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_item.jinja:40 +msgid "Delete" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:69 +msgid "Add more keys" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:73 +#: src/cryptoadvance/specter/templates/device/device.jinja:81 +msgid "Sign message on device" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:75 +msgid "Derivation path" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:76 +msgid "Message" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:78 +msgid "Message signature" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:79 +msgid "Copy message signature" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:79 +msgid "Copied message signature" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:86 +msgid "Update master blinding key" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:90 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:25 +msgid "Toggle device passphrase" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:95 +msgid "Forget the device" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:100 +msgid "Wallets Using This Device" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:113 +msgid "New device was added successfully!" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:118 +msgid "Add another device" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:128 +msgid "Create single key wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:136 +msgid "Create multisignature wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device.jinja:176 +msgid "Message was signed successfully!" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device_blinding_key.jinja:9 +msgid "Get the master blinding key" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device_blinding_key.jinja:15 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:102 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:77 +msgid "Get via USB" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device_blinding_key.jinja:20 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:114 +msgid "Scan QR code" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device_blinding_key.jinja:25 +#: src/cryptoadvance/specter/templates/device/device_blinding_key.jinja:28 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:119 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:122 +msgid "Paste xpub" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/device_blinding_key.jinja:31 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:125 +msgid "Add xpub" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:7 +msgid "Adding keys to" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:9 +msgid "Setting up a new device" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:15 +msgid "Name it" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:21 +msgid "Please make sure to choose the device type before continuing" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:23 +msgid "Device Management" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:32 +msgid "Scan, paste or load xpubs" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:35 +msgid "You will be able add more keys later from the device menu." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:38 +msgid "One line per xpub. Ideally with derivation path in the form" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:39 +msgid "Enter your xpubs here" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:43 +#: src/cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja:18 +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:178 +msgid "Scan" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:48 +#: src/cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja:23 +msgid "Using an airgapped device with QR codes" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:49 +msgid "Scan QR codes with extended public keys one by one." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:50 +msgid "" +"We recommend importing Native Segwit and Segwit Multisig " +"keys." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:59 +msgid "Choose files" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:64 +msgid "Using an airgapped ColdCard with MicroSD" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:65 +msgid "Export extended public keys for single-key wallets to the SD card from" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:67 +msgid "To export multisignature pubkeys go to" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:69 +msgid "We recommend using Native Segwit." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:80 +msgid "Specify account number (advanced)" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:82 +msgid "Select the account you wish to import" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:83 +msgid "" +"You can set which account number you wish to import.
Account " +"derivation uses the number choosen here to derive an xpub as specified in" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:85 +msgid "" +"This is an advanced feature.
If you're not familiar with account " +"derivations please leave this as 0." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:86 +msgid "Close" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:89 +msgid "Examples" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:130 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:103 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:96 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:166 +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet.jinja:33 +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:150 +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:152 +msgid "Continue" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:103 +msgid "A note on hot wallets" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:47 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:104 +msgid "" +"This will create a hot " +"wallet on your Bitcoin Core node." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:48 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:105 +msgid "" +"Hot wallets are considered less secure and are not recommended for use " +"with significant amounts. Use with caution and beware the potential " +"risks." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:107 +msgid "Enter you mnemonic here or use the randomly generated one" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:51 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:108 +msgid "Make sure to backup these words!" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:55 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:111 +msgid "Generate" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:56 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:112 +#: src/cryptoadvance/specter/templates/wallet/send/components/send_nav.jinja:14 +msgid "Import" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:50 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:60 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:115 +msgid "Enter your mnemonic here" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:69 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:124 +msgid "Generate New Mnemonic" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:139 +msgid "Encrypt Wallet File" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:85 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:184 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:187 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:142 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:180 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:186 +#: src/cryptoadvance/specter/templates/includes/tx-row.html:250 +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:67 +#: src/cryptoadvance/specter/templates/setup/setup_page.jinja:63 +#: src/cryptoadvance/specter/templates/setup/setup_page.jinja:66 +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:128 +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:173 +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:176 +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:85 +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:502 +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:508 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:18 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:132 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:302 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:305 +msgid "Advanced" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:145 +msgid "BIP39 passphrase (optional)" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:148 +msgid "Derivation paths" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:150 +msgid "" +"Enter each derivation path as a separate line. Start each path with an " +"m. No trailing slash." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:152 +msgid "Specify derivation paths to import for the wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:158 +msgid "Address range to import" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:159 +msgid "From" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:162 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:92 +msgid "to" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:288 +msgid "No devices found" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:523 +#: src/cryptoadvance/specter/templates/device/new_device_manual.jinja:434 +msgid "Unknown key format" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/components/device_type.jinja:2 +msgid "Device Type:" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/components/device_type.jinja:6 +msgid "Select type" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:49 +msgid "Upload Keys" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:51 +msgid "Name your Device: " +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:56 +msgid "" +"Connect your ColdCard to the computer via USB and unlock it or upload a " +"wallet export file from micro SD card." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:59 +msgid "" +"To export the wallet data file from the ColdCard, insert your micro SD " +"card into the device, then:
\n" +" To get the single sig xpubs, go to: Advanced -> " +"MicroSD Card -> Export Wallet -> Generic JSON. When asked for account, " +"select account number (default is 0) and confirm the export.
\n" +" To get the multisig xpubs, go to: Settings -> " +"Multisig Wallets -> Export XPUB and confirm the export." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:66 +msgid "" +"Connect your Specter-DIY to the computer via USB and unlock it or scan " +"the wallet master public key." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:69 +msgid "" +"To get the master public key QR code to scan, click on: Master public " +"keys, then select each key type you'd like to import and scan the " +"displayed QR code for each into Specter." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:74 +msgid "Scan your Cobo Vault master public key or upload a wallet export file." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:77 +msgid "" +"To get the master public keys QR codes to scan:

\n" +" For single sig, click on: Setting -> Watch-Only " +"Wallet -> Generic Wallet, Click the top right 3 dots (...) -> Wallet Info" +" ->Toggle Address Type, then select the wallet address type you would " +"like to use for your wallet.

\n" +" For multisig, click on: Multisig Wallet -> Click the " +"top right 3 dots (...) -> Show/Export XPUB, then select the wallet " +"address type you would like to use for your wallet.
\n" +" Cobo Vault will then display the QR code which you " +"should scan into Specter.

\n" +" To import with SD card, click on \"touch here to " +"export the file with microSD\" on the same screen as the QR code." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:85 +msgid "Connect your hardware device to the computer via USB." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:91 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:278 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:282 +msgid "Edit" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:108 +msgid "Upload from SD Card" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:158 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:213 +msgid "XPUB purpose" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:180 +msgid "#0 Single Sig (Nested)" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:182 +msgid "#0 Single Sig (Segwit)" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:201 +msgid "Account #" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:202 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:227 +msgid "Add account" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:216 +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:37 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:162 +msgid "Add" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:228 +msgid "Add custom derivation" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:279 +#: src/cryptoadvance/specter/templates/setup/end.jinja:7 +msgid "Done" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:311 +msgid "No devices found :(" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja:345 +msgid "Failed to retrive device data. Please try again." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:37 +msgid "Keys" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:37 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:29 +msgid "Device" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:50 +msgid "or use the randomly generated one" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:89 +msgid "Encrypt Wallet File:" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:93 +msgid "BIP39 passphrase (optional):" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:96 +msgid "Addresses range to import:" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:97 +msgid "From:" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja:98 +msgid "to:" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_type.jinja:3 +msgid "Add Device" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_type.jinja:6 +msgid "Select Your Device Type" +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_type.jinja:7 +msgid "Filter devices..." +msgstr "" + +#: src/cryptoadvance/specter/templates/device/new_device/new_device_type.jinja:20 +msgid "Manual configuration" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:18 +msgid "Address details" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:44 +msgid "Loading address" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:44 +msgid "details" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:84 +msgid "From wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:85 +msgid "Address index" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:86 +msgid "Is change address" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:86 +msgid "Yes" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:86 +msgid "No" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:88 +msgid "UTXO count" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:89 +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:148 +#: src/cryptoadvance/specter/templates/includes/tx-table.html:160 +#: src/cryptoadvance/specter/templates/wallet/send/new/components/coin_selection_table.jinja:15 +#: src/cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_table.jinja:15 +msgid "Amount" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:97 +msgid "Verify address on device" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:102 +msgid "Or scan this QR code" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:108 +msgid "Address descriptor" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:111 +msgid "Show raw public keys" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:117 +#: src/cryptoadvance/specter/templates/includes/address-data.html:124 +msgid "Copied address descriptor" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:126 +msgid "Copied address descripto" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-data.html:132 +#: src/cryptoadvance/specter/templates/includes/address-data.html:134 +msgid "Failed to load address details..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-label.html:63 +msgid "Fetching address label..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-label.html:157 +msgid "Failed to update address label. Please refresh the page and try again." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-label.html:198 +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:550 +msgid "Copied address" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-label.html:234 +#: src/cryptoadvance/specter/templates/includes/address-label.html:237 +#: src/cryptoadvance/specter/templates/includes/tx-data.html:68 +msgid "Failed to fetch data. Please refresh the page and retry." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-label.html:236 +msgid "Caught error fetching address label" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-row.html:22 +msgid "Verify on device" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/address-row.html:114 +#: src/cryptoadvance/specter/templates/includes/address-row.html:116 +msgid "Failed to load address data to display..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:98 +msgid "Receive Addresses" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:101 +msgid "Change Addresses" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:107 +#: src/cryptoadvance/specter/templates/includes/tx-table.html:109 +msgid "Page" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:116 +msgid "Export addresses to CSV" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:161 +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:405 +msgid "Fetching addresses..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:409 +msgid "Failed to fetch addresses..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:419 +msgid "Only receive addresses" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:421 +msgid "Only change addresses" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:481 +msgid "No addresses found..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:520 +#: src/cryptoadvance/specter/templates/includes/addresses-table.html:523 +msgid "Failed to fetch addresses list" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/merkletooltip.html:2 +msgid "" +"Specter-Desktop validates BIP 37 Merkle Proofs from your full node " +"guaranteeing that transactions displayed as confirmed " +"have been included in the specified block hash." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/merkletooltip.html:3 +msgid "" +"However, a compromised full node could return a fake block that was never" +" mined into Bitcoin's blockchain!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/merkletooltip.html:4 +msgid "" +"If you find the displayed block hash in other locations (other nodes, " +"block explorers, etc) and you trust specter-desktop isn't lying " +"to you, then you can be sure this transaction exists in their " +"blockchain as well." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/page-limit-select.html:15 +msgid "Page limit" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/page-limit-select.html:22 +msgid "All" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/qr-code.html:207 +msgid "Click to animate" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/qr-scanner.html:128 +msgid "Number of frames in QR code mismatch!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/qr-scanner.html:202 +msgid "" +"Can't get access to the camera. Specter should run on localhost or over " +"https to enable QR code scanning." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/qr-scanner.html:209 +msgid "Can't start the QR scanner!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:16 +msgid "Transaction details" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:39 +msgid "" +"Loading transaction details...\n" +"\n" +"Transaction ID:" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:66 +#: src/cryptoadvance/specter/templates/includes/tx-data.html:255 +msgid "Failed to load transaction details..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:84 +msgid "This transaction (aka \"tx\") could not be found in your node's mempool!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:85 +msgid "" +"If the bitcoin network is very busy, nodes will start purging the pending" +" txs with the lowest fees. Txs older than two weeks are also purged." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:86 +msgid "" +"A purged tx will never complete. Abandoning this tx will clear it from " +"your wallet, making those funds spendable once again." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:87 +msgid "" +"But first verify that other nodes have also purged your tx! Enter the tx " +"id into a public block explorer (warning: slight privacy leak). If the tx" +" cannot be found, it is safe to abandon this tx." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:94 +msgid "Abandon transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:102 +#: src/cryptoadvance/specter/templates/includes/tx-data.html:195 +msgid "Transaction id" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:114 +msgid "Fee" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:115 +msgid "Fee rate" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:120 +msgid "Mined at block" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:121 +msgid "Block hash" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:122 +msgid "Block time" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:126 +msgid "Inputs count" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:127 +msgid "Outputs count" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:178 +#: src/cryptoadvance/specter/templates/includes/tx-data.html:245 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:146 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:173 +msgid "Address:" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:179 +#: src/cryptoadvance/specter/templates/includes/tx-data.html:246 +msgid "Value:" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:185 +#: src/cryptoadvance/specter/templates/includes/tx-data.html:194 +msgid "Input #" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:186 +msgid "Coinbase transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:196 +msgid "Output #" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:202 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:166 +msgid "Outputs" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:244 +msgid "Output #${i}" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-data.html:279 +msgid "Failed to load address data..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:33 +#: src/cryptoadvance/specter/templates/includes/tx-row.html:241 +msgid "Speed up" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:34 +#: src/cryptoadvance/specter/templates/includes/tx-row.html:248 +msgid "Cancel transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:118 +#: src/cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_item.jinja:17 +msgid "Recipients" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:149 +msgid "Confidential" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:159 +#: src/cryptoadvance/specter/templates/includes/tx-table.html:162 +msgid "Confirmations" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:162 +msgid "Unconfirmed" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:164 +msgid "Cancelled (replaced by sender)" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:241 +msgid "the Transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:242 +msgid "You can" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/overlay.html:5 +#: src/cryptoadvance/specter/templates/includes/tx-row.html:242 +msgid "cancel" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:242 +msgid "speed up" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:242 +msgid "the transaction by increasing its fee rate" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:242 +msgid "and sending the funds back to yourself" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:248 +msgid "Speed up!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:252 +msgid "" +"If you would like further customization, you can click here to fully edit" +" the transaction." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:252 +msgid "(advanced, not recommended for new users)" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-row.html:253 +msgid "Edit the transaction (advanced)" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:99 +msgid "History" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:128 +msgid "Freezing a UTXO will make Specter disallow spending it." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:129 +msgid "" +"This is useful especially for dealing with a dust attack, where you don't" +" want to accidentally spend the dust received." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:136 +msgid "Create new transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:140 +msgid "Export transactions to CSV" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:142 +msgid "Fetch historical price data" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:148 +msgid "" +"If enabled, specter will try to fetch historical prices for each " +"transaction date from the configured price provider." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:149 +msgid "This has privacy implications!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:161 +#: src/cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_table.jinja:15 +msgid "Time" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:165 +msgid "Block Hash" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:172 +#: src/cryptoadvance/specter/templates/includes/tx-table.html:484 +msgid "Fetching transactions..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:488 +#: src/cryptoadvance/specter/templates/includes/tx-table.html:521 +msgid "Failed to fetch transactions..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:595 +msgid "No transactions found..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:657 +#: src/cryptoadvance/specter/templates/includes/tx-table.html:660 +msgid "Failed to fetch transactions list." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/tx-table.html:685 +msgid "Copied transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/pin.jinja:16 +#: src/cryptoadvance/specter/templates/includes/hwi/components/pin.jinja:84 +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:53 +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:102 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:14 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:50 +msgid "Processing..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:15 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:50 +msgid "Keep your wallet connected." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:19 +msgid "" +"If your device does not show up, ensure the Specter USB settings are " +"correctly configured." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:21 +msgid "View USB settings" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:28 +msgid "Do you really want to use your Coldcard over USB (no airgap)?" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:30 +msgid "Yes, I am living on the edge!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:33 +msgid "" +"No, I'll use the address explorer on the Coldcard. Get me to the coinkite" +" site for more info." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:85 +msgid "Detecting..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:85 +msgid "Plug in your device" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:100 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:129 +msgid "Pairing Code" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:100 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:129 +msgid "" +"Please confirm the code matches the one displayed on your BitBox02 " +"device.

It could take up to 20 seconds to continue after approving" +" the pairing on the device, please be patient." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:163 +msgid "Extracting public keys..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:164 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:184 +msgid "It may take a while." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/pin.jinja:16 +#: src/cryptoadvance/specter/templates/includes/hwi/components/pin.jinja:84 +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:53 +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:102 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:164 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:184 +msgid "Keep your" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/pin.jinja:16 +#: src/cryptoadvance/specter/templates/includes/hwi/components/pin.jinja:84 +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:53 +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:102 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:164 +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:184 +msgid "connected" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:183 +msgid "Extracting public key..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:203 +msgid "Extracting master blinding key..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:204 +msgid "Please confirm action on your" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/hwi.jinja:204 +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:107 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:112 +msgid "device" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/passphrase.jinja:2 +msgid "Enter Passphrase" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/passphrase.jinja:22 +#: src/cryptoadvance/specter/templates/includes/hwi/components/pin.jinja:62 +msgid "Submit" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/pin.jinja:2 +msgid "Enter PIN" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:2 +msgid "Select USB Wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:78 +msgid "Failed to unlock device! Invalid PIN code?" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:125 +msgid "passphrase toggled successfully" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:140 +#: src/cryptoadvance/specter/templates/includes/hwi/components/wallet.jinja:38 +msgid "Selected device does not have matching signing key." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:143 +msgid "Signing message..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja:143 +#: src/cryptoadvance/specter/templates/includes/hwi/components/wallet.jinja:41 +msgid "Confirm on your" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/wallet.jinja:4 +msgid "Confirm Address" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/wallet.jinja:6 +msgid "" +"Please confirm address matches on your device" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/wallet.jinja:7 +msgid "Expected address" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/wallet.jinja:41 +msgid "Signing transaction..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/wallet.jinja:90 +msgid "" +"Addresses did not match! Be careful! Please contact support and beware of" +" using the displayed address!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/wallet.jinja:93 +msgid "Address displayed successfully! Please check the device screen." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/hwi/components/wallet.jinja:95 +msgid "Address was verified successfully!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/language/language_js.jinja:24 +msgid "Failed to change language" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:2 +msgid "Transaction is Ready to Broadcast" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:4 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:222 +msgid "Send transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:5 +msgid "Send via block explorer" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:6 +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:8 +msgid "Send via blockstream.info" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:7 +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:9 +msgid "Send via mempool.space" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:8 +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:9 +msgid "over Tor hidden service" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:10 +msgid "Back to options" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:11 +msgid "Save as pending" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja:12 +msgid "Copy raw transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/key_export_qr.jinja:17 +msgid "Copied full key" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/key_export_qr.jinja:23 +msgid "Show derivation path" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/key_export_qr.jinja:34 +msgid "Use SLIP-132" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/overlay.html:14 +msgid "Loading... It may take a while..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/qr_code_sign.jinja:4 +msgid "Scan this QR code with your" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/qr_code_sign.jinja:12 +msgid "Scan signed transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/qr_code_sign.jinja:29 +msgid "Scan failed, please try again..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sd_card_sign.jinja:2 +msgid "Sign Transaction with file" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sd_card_sign.jinja:3 +msgid "Save transaction to file" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sd_card_sign.jinja:5 +msgid "Load signed transaction from file" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:12 +msgid "Sign Transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:14 +msgid "Please choose a signing method for your" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:18 +msgid "Sign via USB (HWI)" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:40 +msgid "Sign with SD Card file" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:53 +msgid "Sign with QR codes" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:67 +msgid "Sign with Bitcoin Core" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:70 +msgid "Sign with Elements Core" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:83 +msgid "Enter decryption password" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:85 +msgid "Proceed with signing" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:94 +msgid "Wallet is not encrypted, just click the button." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja:102 +msgid "Sign transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:43 +msgid "Bitcoin Core is still syncing...
(data might be outdated)" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:46 +msgid "" +"Bitcoin Core version is outdated.
Some features might not " +"work...
(minimum required: v20.0.0)." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:76 +msgid "Unavailable. Click to configure." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:129 +msgid "See setup progress" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:132 +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:287 +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:290 +msgid "Wallets" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:135 +msgid "Wallets overview" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:142 +msgid "Updating wallets data..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:145 +msgid "Finished updating your wallets" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:148 +msgid "Click here to refresh" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:162 +msgid "Add new wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:167 +msgid "Failed to load some wallets" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:168 +msgid "Retry loading wallets" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:169 +msgid "Show Details" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:175 +msgid "Wallet Name" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:176 +msgid "Error Details" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:182 +msgid "Download wallet file" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:183 +msgid "Recreate the wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:184 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:252 +msgid "Delete wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:198 +msgid "Wallets are unavailable if Specter is not connected to Bitcoin Core!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:201 +msgid "Configure Node" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:210 +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:279 +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:282 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:26 +msgid "Devices" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:217 +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet.jinja:29 +msgid "Add new device" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:221 +msgid "Specter Version:" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja:223 +msgid "About Specter" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:2 +msgid "Bitcoin Core Node Info" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:5 +msgid "" +"You are using a pruned node.
Pruned nodes may not be able to scan for " +"old balances when importing an existing wallet.
It is recommended to " +"use Specter with an unpruned node." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:8 +msgid "" +"Your node does not have blockfilterindex enabled.
Setting" +" blockfilterindex=1 in your bitcoin.conf file " +"is recommended as it takes just a few GB of storage
and helps to " +"speed-up blockchain rescanning." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:13 +msgid "Bitcoin Core Version" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:14 +msgid "Connections count" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:15 +msgid "Difficulty" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:16 +msgid "Size on disk" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:17 +msgid "Blocks count" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:18 +msgid "Last block hash" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:19 +msgid "Mempool Size" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:20 +msgid "Node uptime" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:20 +msgid "Hours" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:22 +msgid "Automatic pruning" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:23 +msgid "Prune height" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:24 +msgid "Prune target size" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:30 +msgid "Run the numbers!" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:35 +msgid "Calculate the total Bitcoin supply" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:36 +msgid "" +"This will run Bitcoin Core's gettxoutsetinfo command which " +"will calculate the total amount of Bitcoin's UTXO set." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:37 +msgid "This might take a few minutes..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:46 +msgid "Running the numbers... (this might take a few minutes)" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:57 +msgid "Bitcoin Total Supply" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:59 +msgid "Your wallets hold" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:59 +msgid "from the total supply" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/bitcoin_core_info.jinja:72 +msgid "Configure Bitcoin Core RPC Connection" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/node_select_popup.jinja:26 +msgid "Node configuration" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/node_select_popup.jinja:48 +msgid "Node unreachable..." +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/sidebar_device_list_item.jinja:12 +msgid "keys" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/sidebar_wallet_list_item.jinja:14 +msgid "Multisig" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/sidebar_wallet_list_item.jinja:14 +msgid "Single Key" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/sidebar_wallet_list_item.jinja:18 +msgid "Rescanning blockchain" +msgstr "" + +#: src/cryptoadvance/specter/templates/includes/sidebar/components/sidebar_wallet_list_item.jinja:27 +msgid "Loading wallet..." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_logs.jinja:6 +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:10 +#: src/cryptoadvance/specter/templates/wallet/components/wallet_menu.jinja:15 +msgid "Settings" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_logs.jinja:12 +msgid "Return" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_logs.jinja:18 +msgid "" +"If this is an issue, please let us know! Create an issue or ping us on Telegram to fix it." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:9 +msgid "Built-in Bitcoin Node Status:" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:10 +msgid "Bitcoin Core Version:" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:14 +msgid "New Bitcoin version available!" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:15 +msgid "Upgrade Bitcoin Core version to:" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:20 +msgid "Stop Bitcoin Core" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:22 +msgid "Start Bitcoin Core" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:24 +msgid "" +"If this is your first time starting the node, and you haven't used the " +"QuickSync, your node will start with Initial Block Downloading (IBD) to " +"sync with the network." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:25 +msgid "" +"This process of IBD syncing may take several days. If you'd like the " +"QuickSync option, please click on it before starting your node, or if " +"it's running, stop it and the click the QuickSync." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:26 +msgid "(Warning: QuickSync will override any existing data of your Bitcoin Node!)" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:32 +msgid "Debug" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:33 +msgid "See Bitcoind Logs" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:35 +msgid "Danger Zone" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:38 +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:142 +msgid "Forget node" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:40 +msgid "Unistall Bitcoin Core" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/internal_node_settings.jinja:45 +msgid "Delete data folder?" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:12 +msgid "Configure new node" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:13 +msgid "Name your new node:" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:14 +msgid "Name your new node" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:19 +msgid "Bitcoin JSON-RPC configuration" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:31 +msgid "Setting Bitcoin Core Data Directory" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:32 +msgid "" +"When auto-detect is on, Specter will check for Environment-Variables " +"(BTC_RPC_USER, BTC_RPC_PASSWORD, BTC_RPC_HOST, BTC_RPC_PORT) to configure" +" the connection or attempt to automatically locate your Bitcoin data " +"directory and load your node configurations from it." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:33 +msgid "" +"However, if your Bitcoin Core data directory is not located at the " +"default location, you will need to enter its path here so Specter will be" +" able to locate it." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:34 +msgid "" +"If you are connecting to a specific remote node, you can disable the " +"auto-detect feature and enter the node's configurations manually below." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:39 +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:74 +msgid "Bitcoin Core data directory path:" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:45 +msgid "(disable auto-detect to configure manually)" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:56 +msgid "Connect with QR" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:62 +msgid "" +"Default ports: 8332 for mainnet, 18332 for Testnet, " +"18443 for Regtest, 38332 for Signet, 7041 for Liquid" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:66 +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:39 +msgid "Test" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:70 +msgid "Test results:" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:82 +msgid "Connectable" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:85 +msgid "Your Node can't be reached" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:86 +msgid "" +"There are a lot of potential issues preventing the connection. Please " +"double check the Host and the Port. Make sure you can reach the host and " +"make sure that Bitcoin-Core is listening at the port you have specified." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:87 +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:101 +msgid "" +"For more hints, please look at this article." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:98 +msgid "Your Credentials don't work" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:99 +msgid "" +"Please doublecheck the user and the Password. Look at the bitcoin.conf\n" +"\t\t\t\t\t\t\t\tfor the correct values in that field." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:109 +msgid "Version recent enough" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:112 +msgid "Your Core Node might be too old" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:113 +msgid "" +"Specter is working well up from Bitcoin Core version 0.17. The version of" +" your Node is too low, unfortunatley. Please upgrade!" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:124 +msgid "Wallet Support in your Core-Node" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:125 +msgid "" +"The RPC-Interface of your Core-Node is available, but the wallet-api is " +"not. Please make sure to have 'disablewallet=0' in your bitcoin.conf." +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:136 +msgid "Process finished with code " +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:136 +msgid "Output:" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:136 +msgid "Error message:" +msgstr "" + +#: src/cryptoadvance/specter/templates/node/node_settings.jinja:207 +msgid "Failed to read connection data from the QR" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:10 +#: src/cryptoadvance/specter/templates/settings/components/settings_menu.jinja:12 +msgid "Authentication" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:12 +msgid "None" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:13 +msgid "Password Protection" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:14 +msgid "Multiple Users" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:15 +msgid "RPC password as Pin" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:20 +msgid "Rate Limiting (seconds between login/register attempts)" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:23 +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:33 +msgid "Specter Password" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:24 +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:75 +msgid "default" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:29 +msgid "Registration Link Timeout (hours)" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:30 +msgid "Default username is 'admin', password 'admin'." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:32 +msgid "Specter Username" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:43 +msgid "Delete User" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/auth_settings.jinja:58 +msgid "Generate New Registration Link" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:10 +msgid "Language" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:14 +msgid "Backup and Restore" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:19 +msgid "Backing up Your Specter Data" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:20 +msgid "" +"It is recommended that you keep your backup files private, as sharing " +"them will result in privacy leaks." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:21 +msgid "" +"Backups are recommended to ensure that access to funds remain, even in " +"the event that a multisig wallet is lost." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:25 +msgid "Specter Data Backup" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:28 +msgid "Download Specter backup files" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:35 +msgid "Restoring Specter from backup" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:36 +msgid "" +"Here you can restore your wallets and devices from an existing Specter " +"backup." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:37 +msgid "" +"Please make sure to unzip the backup file first, then select the " +"extracted folder for upload." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:38 +msgid "" +"Note: Loading devices/ wallets with names identical to existing ones may " +"overwrite the existing ones." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:42 +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:53 +msgid "Load Specter backup" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:48 +msgid "Choose backup folder" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:56 +msgid "Miscellaneous" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:57 +msgid "Bitcoin unit to use" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:63 +msgid "Block explorer URL" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:67 +msgid "" +"Specter does not use the block explorer to get any data whatsoever. This " +"setting is only to allow opening transactions and addresses in a block " +"explorer directly from Specter. All data Specter uses comes directly from" +" your own connected full node." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:70 +msgid "Fees estimation source" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:73 +msgid "Self hosted mempool.space" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:78 +msgid "Log Level" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:80 +msgid "Specter-Desktop created a Logfile in" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:80 +msgid "" +"The Debug-Level will create a lot of data, so make sure to avoid that if " +"you don't have a reason." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:91 +msgid "Validate Merkle Proofs" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:93 +msgid "Cannot enable when using a pruned bitcoin node" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:100 +msgid "What's this?" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:104 +msgid "" +"Specter-Desktop validates BIP 37 Merkle Proofs from your full node " +"guaranteeing that displayed as confirmed have been " +"included in the specified block hash." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/general_settings.jinja:105 +msgid "" +"However, a compromised full node could return a fake block that was never" +" mined into Bitcoin's blockchain! If you find the displayed block hash in" +" other locations (other nodes, block explorers, etc) and you " +"trust specter-desktop isn't lying to you, then you can be sure " +"this transaction exists in their blockchain as well." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:14 +msgid "Hardware Devices Bridge" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:15 +msgid "Allows Specter to communicate with your hardware devices over USB." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:20 +msgid "Local USB connection" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:22 +msgid "Select this if Specter is installed on this computer" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:28 +msgid "Remote Specter USB connection" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:30 +msgid "Select this if Specter is installed on a different machine" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:38 +msgid "Select this if you would like to configure manually (experts only)" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:75 +msgid "Before changing these settings" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:77 +msgid "" +"If you haven’t done so already, head to \"Preferences\" on your desktop " +"app (found on the top navigation). Select the option to connect remotely." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:83 +msgid "Save Changes" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:86 +msgid "" +"You might also need to allow Specter to communicate with the device " +"bridge." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:88 +msgid "Access the device bridge settings." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:89 +msgid "Add the domain" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:89 +msgid "Copied Specter URL" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:89 +msgid "copy" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:89 +msgid "to the whitelist there." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:89 +msgid "Save the changes and close the window." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:90 +msgid "" +"Connect your hardware wallet to your computer and test if Specter manage " +"to reach it" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:90 +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:80 +msgid "Test connection" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:98 +msgid "Device detected successfully! USB connections configured correctly!" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/hwi_settings.jinja:100 +msgid "Failed to detect devices" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:29 +msgid "Tor configurations" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:31 +msgid "Enable Tor to anonymise your data connections." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:38 +msgid "Stop" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:43 +msgid "Stopped" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:44 +msgid "Uninstall" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:45 +msgid "Start" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:49 +msgid "Set up" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:55 +msgid "Quick and automatic setup." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:61 +msgid "Custom" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:63 +msgid "Use your own Tor configuration." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:66 +msgid "Use Tor proxy running at:" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:70 +msgid "Default for Tor daemon:" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:71 +msgid "Default for Tor Browser:" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:74 +msgid "Tor control port:" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:76 +msgid "Restart Specter for change of the control port to take effect." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:78 +msgid "Set to custom port here, if kept empty the default (9051 and 9151) is used" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:83 +msgid "Additional Options" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:87 +msgid "" +"Running Specter behind a Tor hidden service allows you to acccess Specter" +" over Tor from anywhere via a Tor supporting browser." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:93 +msgid "Enable Tor hidden service" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:95 +msgid "Allows access to Specter from anywhere." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:96 +msgid "Requires authentication to be enabled." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:96 +msgid "Authentication settings" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:100 +msgid "Specter hidden service is running at:" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:101 +msgid "Copied Tor hidden service address:" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:109 +msgid "" +"Some optional Specter functionality, like rescanning UTXO on a pruned " +"node or getting the Bitcoin price, might make calls to external APIs and " +"services." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:110 +msgid "" +"Toggle this on to ensure Specter routes all these external calls over Tor" +" proxy." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:111 +msgid "Note: Some external sources may stop working if they block Tor call." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:117 +msgid "Force external calls over Tor?" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:119 +msgid "Route all external calls over the Tor proxy for improved privacy." +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:122 +msgid "Save changes" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/tor_settings.jinja:142 +msgid "Please set an authentication method before enabling the hidden service" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/components/settings_menu.jinja:11 +msgid "General" +msgstr "" + +#: src/cryptoadvance/specter/templates/settings/components/settings_menu.jinja:13 +msgid "USB Devices" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind.jinja:5 +msgid "Setup Bitcoin Core" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind.jinja:7 +msgid "Start the Setup!" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind.jinja:40 +msgid "Failed to download Bitcoin Core..." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:5 +msgid "Configure your node" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:6 +msgid "QuickSync?" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:11 +msgid "What is QuickSync?" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:12 +msgid "" +"QuickSync will set up your new node from a trusted state of the " +"blockchain." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:13 +msgid "" +"This means all block validation will be skipped until the most recent " +"block in the snapshot." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:14 +msgid "Later blocks will be normally validated like with a regular full node." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:19 +msgid "Select node type:" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:24 +msgid "Archival Node" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:26 +msgid "Requires about 400GB of available storage" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:28 +msgid "Requires about 30GB of available storage" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:30 +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:43 +msgid "Requires a few MB of available storage" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:37 +msgid "Pruned Node" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:39 +msgid "Requires about 10GB of available storage" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:41 +msgid "Requires about 3GB of available storage" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:50 +msgid "" +"Now that you have Bitcoin Core installed, your next step will be to sync " +"with the network." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:51 +msgid "" +"Specter allows you to choose between normal syncing (IBD) - which will " +"download and validate the entire history of the blockchain, or " +"downloading a trusted snapshot of the current state of the network." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:52 +msgid "" +"This snapshot is produced and signed by Specter team - which means you " +"will be trusting it to get the present state of the blockchain, instead " +"of verifying the history yourself." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:53 +msgid "" +"It takes about 5GB to download and will setup a fully synced pruned node " +"for you to use." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:54 +msgid "" +"You can also disable the QuickSync option, and choose between setting up " +"an archival node (which keeps the entire history) or a pruned node." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:55 +msgid "" +"Please note: it is recommended to use a full archival node, or if storage" +" is a constraint, a pruned node synced from scratch. The option for " +"QuickSync is useful for getting started quickly, but is not recommended " +"in the long term or when using Specter with large amounts." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:58 +#: src/cryptoadvance/specter/templates/setup/node_type.jinja:9 +#: src/cryptoadvance/specter/templates/setup/setup_page.jinja:50 +msgid "Unsure? Click here for more info!" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:59 +#: src/cryptoadvance/specter/templates/setup/node_type.jinja:10 +msgid "Still need help?" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:64 +msgid "" +"You have activated to only connect via Tor. This will significantly slow " +"down the download-process and is not recommended." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:71 +msgid "Advanced configurations" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:72 +msgid "Node Network:" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:72 +msgid "(switch)" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:81 +msgid "Start Syncing!" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:84 +msgid "" +"Your Bitcoin Core data folder seems to be already used.
Would you like" +" to override it or select a different folder path?" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:87 +msgid "Edit path" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:88 +msgid "Override existing" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:92 +msgid "Select Network to setup" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:98 +msgid "Mainnet" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:105 +msgid "Testnet" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja:182 +msgid "Failed to start Bitcoin Core..." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/end.jinja:5 +msgid "Setup Completed Successfully!" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/end.jinja:6 +msgid "Your new node is up and running!" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/node_type.jinja:5 +msgid "Would you like to setup a new Bitcoin node or connect to an existing one?" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/node_type.jinja:6 +msgid "" +"If you have an existing Bitcoin Core node you would like to use, either " +"running locally on this computer or somewhere else, like on Umbrel, " +"myNode, or RaspiBlitz, you can just connect and use it." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/node_type.jinja:7 +msgid "" +"Don't have a node? Specter can help you setup a new one! This guide will " +"help you get it up and running!" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/node_type.jinja:14 +msgid "Connect existing node" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/node_type.jinja:15 +msgid "Setup a new node" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/setup_page.jinja:25 +msgid "Cancel process" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/setup_page.jinja:27 +msgid "View Progress" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/setup_page.jinja:83 +msgid "Encountered an error:" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/setup_page.jinja:95 +msgid "Download Progress:" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/setup_page.jinja:107 +msgid "Starting up..." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/start.jinja:4 +msgid "Specter Quickstart!" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/start.jinja:5 +msgid "Get up and running with Specter in just a few clicks!" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/start.jinja:11 +msgid "" +"Here, we'll take you through the process of setting up Specter with your " +"own Bitcoin Core node and Tor." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/start.jinja:12 +msgid "" +"Everything is completely automated, but you make choices to customize " +"your setup to fit your needs." +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/start.jinja:16 +msgid "Get Started!" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/tor.jinja:5 +msgid "Setup Tor daemon" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/tor.jinja:9 +msgid "Skip" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/tor.jinja:11 +msgid "Setup Tor" +msgstr "" + +#: src/cryptoadvance/specter/templates/setup/tor.jinja:44 +msgid "Failed to download Tor daemon..." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/wallets_overview.jinja:18 +msgid "Wallets Overview" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/wallets_overview.jinja:19 +msgid "" +"Here you can see the combined balance and transactions history of all " +"your Specter wallets." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/wallets_overview.jinja:34 +msgid "confirmed" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/wallets_overview.jinja:36 +msgid "pending" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/wallets_overview.jinja:39 +msgid "immature" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:41 +#: src/cryptoadvance/specter/templates/wallet/wallets_overview.jinja:45 +msgid "Assets:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/editable_label.jinja:12 +msgid "Edit Label" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_menu.jinja:11 +msgid "Transactions" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_menu.jinja:12 +msgid "Addresses" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_menu.jinja:13 +msgid "Receive" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_menu.jinja:14 +msgid "Send" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:15 +msgid "Specter Backup File" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:18 +msgid "(keep this information with each of your key backups)" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:30 +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:32 +msgid "multisig" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:37 +msgid "(Native Segwit)" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:39 +msgid "(Nested Segwit)" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:54 +msgid "Scan this QR code with Specter-Desktop" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:56 +msgid "or any other compatible wallet." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:83 +msgid "Device type:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:85 +msgid "Master fingerprint:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:87 +msgid "Derivation path:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:119 +msgid "Advanced Recovery Details" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:123 +msgid "Specter Desktop Raw Data" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:136 +msgid "Bitcoin Core Receive Descriptor" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja:149 +msgid "Bitcoin Core Change Descriptor" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet.jinja:6 +msgid "Pick the devices you want in your multisig quorum" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet.jinja:8 +msgid "Pick the device you want to use" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet.jinja:38 +msgid "We use sorted multisig (BIP-67), so order is NOT important." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet.jinja:40 +msgid "" +"Be aware of multisig security " +"tradeoffs." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:5 +msgid "Name your Wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:10 +msgid "Type of the wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:15 +msgid "Nested Segwit" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:20 +msgid "Segwit" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:26 +msgid "" +"Segwit uses bech32-encoded addresses (bc1), Nested Segwit " +"makes it compatible with legacy software. Don't use legacy." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:32 +msgid "Using" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:34 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:105 +msgid "of" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:42 +msgid "Scan for existing funds?" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:47 +msgid "Importing an existing wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:48 +msgid "" +"Check this option to scan the blockchain for existing wallet balance and " +"history." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:56 +msgid "Rescan type:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:57 +msgid "Full rescan" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:58 +msgid "UTXO only" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:63 +msgid "Choosing Rescan Type" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:64 +msgid "" +"Full rescan is a relativly slow process which looks for and imports the " +"full wallet transaction history and balance." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:65 +msgid "" +"UTXO only is a fast rescan option which only looks for existing balances " +"(UTXO), but will not import the full transaction history." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:77 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:175 +msgid "Rescan blockchain from block:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:80 +msgid "" +"You are using a pruned node.
Wallet history may not fully " +"appear.
Rescan is limited by the pruned height to block:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:83 +msgid "" +"In case you're not sure, it is best to just leave the default " +"number.
481824 was the first Segwit block." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:88 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:218 +msgid "fetch missing data from block explorer" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:89 +msgid "Fetch missing data" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:90 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:220 +msgid "You are using a pruned node. Blocks for some transactions may be missing." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:91 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:221 +msgid "" +"Check this checkbox if you want to fetch missing information from block " +"explorer." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:96 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:227 +msgid "Block explorer URL:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:99 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:230 +msgid "Careful with block explorers!" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:100 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:231 +msgid "This may have privacy implications!" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:101 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:232 +msgid "" +"Information fetched from the block explorer contains a list of unspent " +"transactions of your wallet from old (pruned) blocks." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:102 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:233 +msgid "\"They\" will know what transactions you are interested in." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:115 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:54 +msgid "Signer" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:141 +msgid "Use this key" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:148 +msgid "The device does not have keys matching the wallet type selected." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:151 +msgid "Please choose a different type or add the keys to the device..." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:164 +msgid "Looks like this device doesn't have keys matching this type of wallet." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja:168 +msgid "Create wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:4 +msgid "Select the type of the wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:7 +msgid "Adding a wallet with existing funds?" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:12 +msgid "Importing an existing wallet?" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:13 +msgid "" +"After choosing device(s), click continue, then just select the:
" +"\"Scan for existing funds\" checkbox on the next screen." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:17 +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:47 +msgid "" +"Please Note:
You are using a pruned node. Wallet history may not fully" +" appear." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:28 +msgid "Single key wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:32 +msgid "Multisignature wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:37 +msgid "Import from wallet software" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:42 +msgid "Import From Wallet Software" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:43 +msgid "" +"Click here to import an existing wallet from a wallet software like " +"Electrum, Fully-Noded, Sparrow Wallet, or another Specter instance." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja:57 +msgid "Multisig is better for large-ish amounts." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:40 +msgid "Copied Address:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:41 +msgid "(click to copy)" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:47 +msgid "Get new address" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:54 +msgid "Scan to Verify Address on Your Device" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:57 +msgid "" +"Specter can verify this address if you scan it.
It has an address " +"index included in the QR code." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:60 +msgid "Verify address via QR code" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:71 +msgid "Display address on device" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:73 +msgid "" +"Multsig address on-device display is only available for BitBox02, " +"ColdCard, KeepKey, Specter, and Trezor devices." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:86 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:92 +msgid "Export To Device" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:87 +msgid "" +"Some of your devices require that you first import your multisig wallet " +"data into the device before you can start verifying addresses and sending" +" transactions." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:89 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:94 +msgid "" +"Import this wallet to a device by scanning its QR code or importing its " +"data file." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:99 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:104 +msgid "" +"Import wallet file to your ColdCard: Settings -> Multisig Wallets -> " +"Import from SD" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:102 +msgid "file" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:105 +msgid "Show" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:105 +msgid "QR Code" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:107 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:112 +msgid "Scan this with your" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:110 +msgid "Back" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:117 +msgid "You can always do this later from the wallet Settings tab." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:118 +msgid "Finish" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:121 +msgid "New wallet was created successfully!" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:124 +msgid "Save Backup PDF" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:132 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:44 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:135 +msgid "Use SLIP-132:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:138 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:142 +msgid "To format master keys on the PDF backup document." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:140 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:129 +msgid "" +"It is recommended that you print and save this wallet backup file with " +"each of your devices." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:143 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:144 +msgid "" +"This backup includes all the information you'd need to restore your " +"wallet in Specter Desktop or other compatible wallets including Bitcoin " +"Core itself." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:146 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:147 +msgid "" +"It is recommended that you keep this file private, as it contains all the" +" information needed to track all of the wallet balance and transactions " +"history." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja:148 +msgid "You can always download this file later from the wallet Settings tab." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/components/send_nav.jinja:12 +msgid "New" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/components/send_nav.jinja:13 +msgid "Unsigned" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja:7 +msgid "Import PSBT transaction:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja:8 +msgid "Paste base64-encoded PSBT transaction here to import." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja:13 +msgid "Paste PSBT here" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja:24 +msgid "PSBT should be base64 encoded." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja:32 +msgid "Choose file" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja:37 +msgid "Using a file" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja:38 +msgid "The file should contain either base64 or binary encoded PSBT." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja:44 +msgid "Import transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:29 +msgid "Create Transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:30 +msgid "Available Funds:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:58 +msgid "Funds waiting in unsigned transactions" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:59 +msgid "" +"To make funds available to spend in new transactions, just click on the " +"\"Unsigned\" tab and delete unsigned transaction you have no need for." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:63 +msgid "You have waiting" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:63 +msgid "still in unsigned transactions." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:71 +msgid "Unit:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:75 +msgid "Enter recipient address, amount" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:77 +msgid "Enter each recipient address, amount as a new line:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:78 +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:79 +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:80 +msgid "ADDRESS" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:78 +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:79 +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:80 +msgid "AMOUNT" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:83 +msgid "Remove recipient" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:84 +msgid "Calculate estimated fee" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:88 +msgid "Transaction editor:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:98 +msgid "Add recipient" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:100 +msgid "Select coins" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:100 +msgid "manually" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:107 +msgid "Create  unsigned transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:173 +msgid "Recipient address:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:182 +msgid "Address label (optional):" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:185 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:158 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:161 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:181 +msgid "Amount:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:190 +msgid "send max" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:337 +msgid "Please first enter a valid address" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:385 +msgid "Amount entered is invalid!" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:399 +msgid "You cannot send more than" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:404 +msgid "You need to select more coins to match your amount!" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:409 +msgid "Invalid amount! Wrong unit?" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:445 +msgid "Please enter the amount that you wish to send" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:459 +msgid "Please enter a valid recipient address" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja:585 +msgid "failed to calculate transaction fees" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:5 +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:10 +msgid "Subtract fees from amount" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:11 +msgid "" +"If checked, the transaction fees will be paid off from the transaction " +"amount." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:12 +msgid "" +"Otherwise, the fees will be paid as an added cost in addition to the " +"amount sent." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:17 +msgid "Subtract from recipient number:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:20 +msgid "Fees:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:21 +msgid "dynamic" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:22 +msgid "manual" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:26 +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:39 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:119 +msgid "Fee rate:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:29 +msgid "leave blank to set automatically, 1 sat/vbyte is the minimal fee rate." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:37 +msgid "Estimated speed:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:43 +msgid "RBF Enabled" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:69 +msgid "Very slow" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:71 +msgid "Slow" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:73 +msgid "Medium (1 hour)" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:75 +msgid "Fast (30 minutes)" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:77 +msgid "Very fast (10 minutes)" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/new/components/fee_selection.jinja:79 +msgid "Overpaid! (10 minutes)" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/pending/wallet_sendpending.jinja:6 +msgid "Transactions Awaiting Signing:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/pending/wallet_sendpending.jinja:11 +msgid "" +"Here you can manage PSBTs (Partially Signed Bitcoin Transactions) you " +"have created but did not finish signing or broadcasted to the network." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_item.jinja:34 +msgid "Open" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_table.jinja:15 +msgid "Sigs" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_table.jinja:31 +msgid "No transactions yet." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:80 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:82 +msgid "Sending" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:105 +msgid "Acquired" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:105 +msgid "signatures" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:112 +msgid "transaction details" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:116 +msgid "Transaction Info" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:118 +msgid "Total fee:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:122 +msgid "Estimated size:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:125 +msgid "Size:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:127 +msgid "Inputs count:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:128 +msgid "Outputs count:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:130 +msgid "Inputs" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:140 +msgid "Transaction id:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:142 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:171 +msgid "Output" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:150 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:177 +msgid "Label:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:184 +msgid "Raw PSBT:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:189 +msgid "Save binary" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:194 +msgid "Save base64" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:198 +msgid "Copy Raw PSBT" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:202 +msgid "Show QR code" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:209 +msgid "Sign transaction with your:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:220 +msgid "Transaction is ready to send" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:226 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:229 +msgid "Paste signed transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:230 +msgid "Paste your transaction here" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:232 +msgid "Confirm" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:239 +msgid "Delete Transaction" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:418 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:448 +msgid "Sending transaction..." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:440 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:443 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:473 +#: src/cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja:476 +msgid "Server failed to broadcast transactions!" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:16 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:24 +msgid "Wallet Info" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:41 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:269 +msgid "Show keys details" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:49 +msgid "" +"SLIP-132 extended public keys (xpubs) are a different format for xpubs " +"which usually starts with zpub or ypub." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:82 +msgid "Export Wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:121 +msgid "Export To Wallet Software" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:123 +msgid "" +"Import this wallet to another Specter instance or other supported wallet " +"softwares by scanning the QR code or importing the JSON file." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:127 +msgid "Export PDF backup" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:154 +msgid "Advanced Options" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:156 +msgid "Keypool control" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:159 +msgid "Currently watching" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:159 +msgid "receiving and" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:159 +msgid "change addresses." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:161 +msgid "Watch" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:161 +msgid "more addresses" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:166 +msgid "Blockchain rescan" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:172 +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:196 +msgid "Abort rescan" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:186 +msgid "" +"Note: You are using a pruned node. Rescan is limited by the pruned height" +" to block:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:188 +msgid "was the first Segwit block." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:195 +msgid "UTXO rescan in process:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:200 +msgid "Or rescan only unspent transactions:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:203 +msgid "Rescan UTXO" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:208 +msgid "Rescanning UTXO set" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:209 +msgid "" +"Only unspent transactions will be imported, so you won't see the full " +"history, but your balance will be there." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:210 +msgid "Note:" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:210 +msgid "" +"Make sure you have enough addresses in the keypool, otherwise not all " +"unspent transactions may be found." +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:255 +msgid "Delete Wallet" +msgstr "" + +#: src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja:272 +msgid "Hide keys details" +msgstr "" + diff --git a/requirements.in b/requirements.in index 0fe0f05cf..5d404e1cb 100644 --- a/requirements.in +++ b/requirements.in @@ -3,6 +3,7 @@ chardet==3.0.4 Click==7.1.2 daemonize==2.5.0 Flask==1.1.2 +Flask-Babel==2.0.0 Flask-Cors==3.0.9 Flask-Login==0.5.0 hwi==2.0.1 @@ -19,3 +20,4 @@ pyopenssl==20.0.1 flask_wtf==0.14.3 pgpy==0.5.3 cbor==1.0.0 +mnemonic==0.19 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 0fb4e3530..9424e3bcd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,13 @@ # -# This file is autogenerated by pip-compile +# This file is autogenerated by pip-compile with python 3.8 # To update, run: # # pip-compile --generate-hashes requirements.in # +babel==2.9.1 \ + --hash=sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9 \ + --hash=sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0 + # via flask-babel base58==2.0.1 \ --hash=sha256:365c9561d9babac1b5f18ee797508cd54937a724b6e419a130abad69cec5ca79 \ --hash=sha256:447adc750d6b642987ffc6d397ecd15a799852d5f6a1d308d384500243825058 @@ -103,6 +107,19 @@ ecdsa==0.16.1 \ embit==0.4.2 \ --hash=sha256:d67fc0f7fbdb7588c3eb24441bf8e05770056260bc8e5537399a1b3ce5ccf12a # via -r requirements.in +flask==1.1.2 \ + --hash=sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060 \ + --hash=sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557 + # via + # -r requirements.in + # flask-babel + # flask-cors + # flask-login + # flask-wtf +flask-babel==2.0.0 \ + --hash=sha256:e6820a052a8d344e178cdd36dd4bb8aea09b4bda3d5f9fa9f008df2c7f2f5468 \ + --hash=sha256:f9faf45cdb2e1a32ea2ec14403587d4295108f35017a7821a2b1acb8cfd9257d + # via -r requirements.in flask-cors==3.0.9 \ --hash=sha256:6bcfc100288c5d1bcb1dbb854babd59beee622ffd321e444b05f24d6d58466b8 \ --hash=sha256:cee4480aaee421ed029eaa788f4049e3e26d15b5affb6a880dade6bafad38324 @@ -111,14 +128,6 @@ flask-login==0.5.0 \ --hash=sha256:6d33aef15b5bcead780acc339464aae8a6e28f13c90d8b1cf9de8b549d1c0b4b \ --hash=sha256:7451b5001e17837ba58945aead261ba425fdf7b4f0448777e597ddab39f4fba0 # via -r requirements.in -flask==1.1.2 \ - --hash=sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060 \ - --hash=sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557 - # via - # -r requirements.in - # flask-cors - # flask-login - # flask-wtf flask_wtf==0.14.3 \ --hash=sha256:57b3faf6fe5d6168bda0c36b0df1d05770f8e205e18332d0376ddb954d17aef2 \ --hash=sha256:d417e3a0008b5ba583da1763e4db0f55a1269d9dd91dcc3eb3c026d3c5dbd720 @@ -169,7 +178,9 @@ itsdangerous==1.1.0 \ jinja2==2.11.3 \ --hash=sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419 \ --hash=sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6 - # via flask + # via + # flask + # flask-babel libusb1==1.8 \ --hash=sha256:240f65ac70ba3fab77749ec84a412e4e89624804cb80d6c9d394eef5af8878d6 # via hwi @@ -210,15 +221,15 @@ markupsafe==1.1.1 \ # via # jinja2 # wtforms -mnemonic==0.18 \ - --hash=sha256:02a7306a792370f4a0c106c2cf1ce5a0c84b9dbd7e71c6792fdb9ad88a727f1d - # via hwi +mnemonic==0.19 \ + --hash=sha256:4e37eb02b2cbd56a0079cabe58a6da93e60e3e4d6e757a586d9f23d96abea931 \ + --hash=sha256:a8d78c5100acfa7df9bab6b9db7390831b0e54490934b718ff9efd68f0d731a6 + # via + # -r requirements.in + # hwi noiseprotocol==0.3.1 \ --hash=sha256:2e1a603a38439636cf0ffd8b3e8b12cee27d368a28b41be7dbe568b2abb23111 # via bitbox02 -pbkdf2==1.3 \ - --hash=sha256:ac6397369f128212c43064a2b4878038dab78dab41875364554aaf2a684e6979 - # via mnemonic pgpy==0.5.3 \ --hash=sha256:a49c269cedcaf82ac6999bcae5fd3f543ecb1c759f9d48a15ad8d8fa4ac03987 \ --hash=sha256:cba6fbbb44a896a8a4f5807b3d8d4943a8f7a6607be11587f4a27734c711c1dd @@ -284,6 +295,12 @@ python-dotenv==0.13.0 \ --hash=sha256:25c0ff1a3e12f4bde8d592cc254ab075cfe734fc5dd989036716fd17ee7e5ec7 \ --hash=sha256:3b9909bc96b0edc6b01586e1eed05e71174ef4e04c71da5786370cebea53ad74 # via -r requirements.in +pytz==2021.1 \ + --hash=sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da \ + --hash=sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798 + # via + # babel + # flask-babel requests==2.25.0 \ --hash=sha256:7f1a0b932f4a60a1a65caa4263921bb7d9ee911957e0ae4a23a6dd08185ad5f8 \ --hash=sha256:e786fa28d8c9154e6a4de5d46a1d921b8749f8b74e28bde23768e5e16eece998 diff --git a/src/cryptoadvance/specter/config.py b/src/cryptoadvance/specter/config.py index 04fb262c5..b5a188532 100644 --- a/src/cryptoadvance/specter/config.py +++ b/src/cryptoadvance/specter/config.py @@ -104,6 +104,24 @@ class BaseConfig(object): }, } + # Babel integration. English listed first; other alphabetical by language code + LANGUAGES = { + "en": "English", + "bg": "Български", + "de": "Deutsch", + "el": "Ελληνικά", + "es": "Español", + "fr": "Français", + "he": "עברית", + "hi": "हिंदी", + "nl": "Nederlands", + "pl": "Polski", + "ru": "Русский", + "sv": "Svenska", + "zh_Hans_CN": "简体中文", + "zh_Hant_TW": "繁體中文", + } + class DevelopmentConfig(BaseConfig): # https://stackoverflow.com/questions/22463939/demystify-flask-app-secret-key @@ -112,6 +130,9 @@ class DevelopmentConfig(BaseConfig): os.getenv("SPECTER_DATA_FOLDER", "~/.specter_dev") ) + # Env vars take priority over config settings so ensure that this is set + os.environ["FLASK_ENV"] = "development" + class TestConfig(BaseConfig): SECRET_KEY = "test key" diff --git a/src/cryptoadvance/specter/helpers.py b/src/cryptoadvance/specter/helpers.py index 822743e6d..c71ebf4c1 100644 --- a/src/cryptoadvance/specter/helpers.py +++ b/src/cryptoadvance/specter/helpers.py @@ -265,11 +265,39 @@ def get_startblock_by_chain(specter): # Hot wallet helpers -def generate_mnemonic(strength=256): - # Generate words list - mnemo = Mnemonic("english") - words = mnemo.generate(strength=strength) - return words + +MNEMONIC_LANGUAGES = { + "en": "english", + "es": "spanish", + "fr": "french", + "it": "italian", + # "jp": "japanese", + # "ko": korean", + # "?": chinese_simplified", + # "?": chinese_traditional", +} + + +def initialize_mnemonic(language_code): + if language_code not in MNEMONIC_LANGUAGES: + # Fall back to English if Mnemonic doesn't support the current language + logger.debug( + f"Language code '{language_code}' not supported by python-mnemonic; using English" + ) + language_code = "en" + return Mnemonic(language=MNEMONIC_LANGUAGES[language_code]) + + +def generate_mnemonic(strength=256, language_code="en"): + mnemo = initialize_mnemonic(language_code) + return mnemo.generate(strength=strength) + + +def validate_mnemonic(words): + # We cannot assume the mnemonic will be in the same language currently active + # in the UI (e.g. a Spanish user is likely to have an English mnemonic). + mnemo = initialize_mnemonic(Mnemonic.detect_language(words)) + return mnemo.check(words) def notify_upgrade(app, flash): diff --git a/src/cryptoadvance/specter/managers/device_manager.py b/src/cryptoadvance/specter/managers/device_manager.py index 5e9d06b47..5c6644785 100644 --- a/src/cryptoadvance/specter/managers/device_manager.py +++ b/src/cryptoadvance/specter/managers/device_manager.py @@ -1,6 +1,8 @@ import os import json import logging +from flask_babel import lazy_gettext as _ + from ..helpers import alias, load_jsons from ..rpc import get_default_datadir @@ -79,7 +81,7 @@ class DeviceManager: for device_name in self.devices: if self.devices[device_name].alias == device_alias: return self.devices[device_name] - logger.error("Could not find Device %s" % device_alias) + logger.error(_("Could not find Device {}").format(device_alias)) def remove_device( self, diff --git a/src/cryptoadvance/specter/node.py b/src/cryptoadvance/specter/node.py index 9de1b6ceb..51ba9f417 100644 --- a/src/cryptoadvance/specter/node.py +++ b/src/cryptoadvance/specter/node.py @@ -3,6 +3,7 @@ import logging import os from embit.liquid.networks import get_network +from flask_babel import lazy_gettext as _ from .helpers import is_testnet, is_liquid from .liquid.rpc import LiquidRPC from .persistence import write_node @@ -312,7 +313,7 @@ class Node: """ rpc = self.get_rpc() if rpc is None: - return {"out": "", "err": "Connection to node failed", "code": -1} + return {"out": "", "err": _("Connection to node failed"), "code": -1} r = {} r["tests"] = {"connectable": False} r["err"] = "" @@ -322,7 +323,7 @@ class Node: int(rpc.getnetworkinfo()["version"]) >= 200000 ) if not r["tests"]["recent_version"]: - r["err"] = "Core Node might be too old" + r["err"] = _("Core Node might be too old") r["tests"]["connectable"] = True r["tests"]["credentials"] = True @@ -339,7 +340,7 @@ class Node: logger.error("Caught an ConnectionError while test_rpc: %s", e) r["tests"]["connectable"] = False - r["err"] = "Failed to connect!" + r["err"] = _("Failed to connect!") r["code"] = -1 except RpcError as rpce: logger.error("Caught an RpcError while test_rpc: %s", rpce) @@ -348,7 +349,7 @@ class Node: r["code"] = rpc.r.status_code if rpce.status_code == 401: r["tests"]["credentials"] = False - r["err"] = "RPC authentication failed!" + r["err"] = _("RPC authentication failed!") else: r["err"] = str(rpce.status_code) except Exception as e: @@ -362,7 +363,7 @@ class Node: r["err"] = rpc.r["error"] r["code"] = rpc.r.status_code else: - r["err"] = "Failed to connect" + r["err"] = _("Failed to connect") r["code"] = -1 return r diff --git a/src/cryptoadvance/specter/server.py b/src/cryptoadvance/specter/server.py index dfc1c4f62..fe0cf47a3 100644 --- a/src/cryptoadvance/specter/server.py +++ b/src/cryptoadvance/specter/server.py @@ -5,7 +5,8 @@ import secrets from pathlib import Path from dotenv import load_dotenv -from flask import Flask, redirect, url_for +from flask import Flask, redirect, request, url_for, jsonify, session +from flask_babel import Babel from flask_login import LoginManager, login_user from flask_wtf.csrf import CSRFProtect @@ -26,6 +27,26 @@ load_dotenv(env_path) csrf = CSRFProtect() +class SpecterFlask(Flask): + @property + def supported_languages(self): + return self.config["LANGUAGES"] + + def get_language_code(self): + """ + Helper for Babel and other related language selection tasks. + """ + if "language_code" in session: + # Explicit selection + return session["language_code"] + else: + # autodetect + return request.accept_languages.best_match(self.supported_languages.keys()) + + def set_language_code(self, language_code): + session["language_code"] = language_code + + def calc_module_name(config): """tiny helper to make passing configs more convenient""" if "." in config: @@ -58,11 +79,13 @@ def create_app(config=None): template_folder = os.path.join(sys._MEIPASS, "templates") static_folder = os.path.join(sys._MEIPASS, "static") logger.info("pyinstaller based instance running in {}".format(sys._MEIPASS)) - app = Flask( + app = SpecterFlask( __name__, template_folder=template_folder, static_folder=static_folder ) else: - app = Flask(__name__, template_folder="templates", static_folder="static") + app = SpecterFlask( + __name__, template_folder="templates", static_folder="static" + ) app.jinja_env.autoescape = select_autoescape(default_for_string=True, default=True) logger.info(f"Configuration: {config}") app.config.from_object(config) @@ -71,6 +94,7 @@ def create_app(config=None): ) csrf.init_app(app) app.csrf = csrf + return app @@ -142,6 +166,28 @@ def init_app(app, hwibridge=False, specter=None): return dict(tor_service_id="", tor_enabled=False) return dict(tor_service_id=app.tor_service_id, tor_enabled=app.tor_enabled) + # --------------------- Babel integration --------------------- + babel = Babel(app) + + @babel.localeselector + def get_language_code(): + # Enables Babel to auto-detect current language + return app.get_language_code() + + @app.route("/set_language", methods=["POST"]) + def set_language_code(): + json_data = request.get_json() + if ( + "language_code" in json_data + and json_data["language_code"] in app.supported_languages + ): + app.set_language_code(json_data["language_code"]) + return jsonify(success=True) + else: + return jsonify(success=False) + + # --------------------- Babel integration --------------------- + return app diff --git a/src/cryptoadvance/specter/server_endpoints/auth.py b/src/cryptoadvance/specter/server_endpoints/auth.py index 03fca6c1e..3038e59f6 100644 --- a/src/cryptoadvance/specter/server_endpoints/auth.py +++ b/src/cryptoadvance/specter/server_endpoints/auth.py @@ -9,6 +9,7 @@ from flask import ( jsonify, flash, ) +from flask_babel import lazy_gettext as _ from flask_login import login_required, current_user, logout_user from flask import current_app as app from ..helpers import alias @@ -46,7 +47,9 @@ def login(): ) return redirect_login(request) flash( - "We could not check your password, maybe Bitcoin Core is not running or not configured?", + _( + "We could not check your password, maybe Bitcoin Core is not running or not configured?" + ), "error", ) app.logger.info("AUDIT: Failed to check password") @@ -79,7 +82,7 @@ def login(): app.login(user.id) return redirect_login(request) # Either invalid method or incorrect credentials - flash("Invalid username or password", "error") + flash(_("Invalid username or password"), "error") app.logger.info("AUDIT: Invalid password login attempt") return ( render_template( @@ -108,14 +111,16 @@ def register(): otp = request.form["otp"] if not username: flash( - "Please enter a username.", + _("Please enter a username."), "error", ) return redirect("register?otp={}".format(otp)) min_chars = int(app.specter.config["auth"]["password_min_chars"]) if not password or len(password) < min_chars: flash( - "Please enter a password of a least {} characters.".format(min_chars), + _("Please enter a password of a least {} characters.").format( + min_chars + ), "error", ) return redirect("register?otp={}".format(otp)) @@ -126,7 +131,9 @@ def register(): i += 1 user_id = "{}{}".format(alias(username), i) if app.specter.user_manager.get_user_by_username(username): - flash("Username is already taken, please choose another one", "error") + flash( + _("Username is already taken, please choose another one"), "error" + ) return redirect("register?otp={}".format(otp)) app.specter.otp_manager.remove_new_user_otp(otp) config = { @@ -137,14 +144,18 @@ def register(): user = User(user_id, username, password_hash, config, app.specter) app.specter.user_manager.add_user(user) flash( - "You have registered successfully, \ + _( + "You have registered successfully, \ please login with your new account to start using Specter" + ) ) return redirect(url_for("auth_endpoint.login")) else: flash( - "Invalid registration link, \ -please request a new link from the node operator.", + _( + "Invalid registration link, \ +please request a new link from the node operator." + ), "error", ) return redirect("register?otp={}".format(otp)) @@ -154,13 +165,13 @@ please request a new link from the node operator.", @auth_endpoint.route("/logout", methods=["GET", "POST"]) def logout(): logout_user() - flash("You were logged out", "info") + flash(_("You were logged out"), "info") return redirect(url_for("auth_endpoint.login")) ################### Util ###################### def redirect_login(request): - flash("Logged in successfully.", "info") + flash(_("Logged in successfully."), "info") if request.form.get("next") and request.form.get("next") != "None": response = redirect(request.form["next"]) else: diff --git a/src/cryptoadvance/specter/server_endpoints/controller.py b/src/cryptoadvance/specter/server_endpoints/controller.py index 68fe01877..e9a2cf839 100644 --- a/src/cryptoadvance/specter/server_endpoints/controller.py +++ b/src/cryptoadvance/specter/server_endpoints/controller.py @@ -5,6 +5,7 @@ from flask import make_response from flask_wtf.csrf import CSRFError from werkzeug.exceptions import MethodNotAllowed from flask import render_template, request, redirect, url_for, flash, Markup +from flask_babel import lazy_gettext as _ from flask_login import login_required, current_user from ..helpers import ( generate_mnemonic, @@ -50,10 +51,11 @@ def server_rpc_error(rpce): """Specific SpecterErrors get passed on to the User as flash""" if rpce.error_code == -18: # RPC_WALLET_NOT_FOUND flash( - "Wallet not found. Specter reloaded all Wallets, please try again.", "error" + _("Wallet not found. Specter reloaded all wallets, please try again."), + "error", ) else: - flash(f"BitcoinCore RpcError: {str(rpce)}", "error") + flash(_("Bitcoin Core RpcError: {}").format(str(rpce)), "error") try: app.specter.wallet_manager.update() except SpecterError as se: @@ -94,7 +96,9 @@ def server_error_timeout(e): app.specter.check() app.logger.error("ExternalProcessTimeoutException: %s" % e) flash( - "Bitcoin Core is not coming up in time. Maybe it's just slow but please check the logs below", + _( + "Bitcoin Core is not coming up in time. Maybe it's just slow but please check the logs below" + ), "warn", ) return redirect( @@ -113,7 +117,7 @@ def server_error_csrf(e): app.logger.error("CSRF Exception: %s" % e) trace = traceback.format_exc() app.logger.error(trace) - flash("Session expired. Please refresh and try again.", "error") + flash(_("Session expired. Please refresh and try again."), "error") return redirect(request.url) @@ -123,7 +127,7 @@ def server_error_405(e): app.logger.error("405 MethodNotAllowed Exception: %s" % e) trace = traceback.format_exc() app.logger.error(trace) - flash("Session expired. Please refresh and try again.", "error") + flash(_("Session expired. Please refresh and try again."), "error") return redirect(request.url) @@ -180,7 +184,12 @@ def about(): app.specter.reset_setup("bitcoind") app.specter.reset_setup("torbrowser") - return render_template("base.jinja", specter=app.specter, rand=rand) + return render_template( + "base.jinja", + specter=app.specter, + rand=rand, + supported_languages=app.supported_languages, + ) # TODO: Move all these below to REST API @@ -206,7 +215,12 @@ def wallets_loading(): @app.route("/generatemnemonic/", methods=["GET", "POST"]) @login_required def generatemnemonic(): - return {"mnemonic": generate_mnemonic(strength=int(request.form["strength"]))} + return { + "mnemonic": generate_mnemonic( + strength=int(request.form["strength"]), + language_code=app.get_language_code(), + ) + } ################ RPC data utils #################### @@ -300,5 +314,7 @@ def get_whitepaper(): else: return render_template( "500.jinja", - error="You need a mainnet node to retrieve the whitepaper. Check your node configurations.", + error=_( + "You need a mainnet node to retrieve the whitepaper. Check your node configurations." + ), ) diff --git a/src/cryptoadvance/specter/server_endpoints/devices.py b/src/cryptoadvance/specter/server_endpoints/devices.py index e97ebd1d2..acea38d90 100644 --- a/src/cryptoadvance/specter/server_endpoints/devices.py +++ b/src/cryptoadvance/specter/server_endpoints/devices.py @@ -10,13 +10,14 @@ from flask import ( jsonify, flash, ) -from flask_login import login_required, current_user from flask import current_app as app +from flask_babel import lazy_gettext as _ +from flask_login import login_required, current_user from mnemonic import Mnemonic -from ..helpers import is_testnet, generate_mnemonic +from ..devices.bitcoin_core import BitcoinCore +from ..helpers import is_testnet, generate_mnemonic, validate_mnemonic from ..key import Key from ..managers.device_manager import get_device_class -from ..devices.bitcoin_core import BitcoinCore from ..managers.wallet_manager import purposes from ..specter_error import handle_exception @@ -60,9 +61,9 @@ def new_device_keys(device_type): else: device_name = request.form.get("device_name", "") if not device_name: - err = "Device name must not be empty" + err = _("Device name cannot be empty") elif device_name in app.specter.device_manager.devices_names: - err = "Device with this name already exists" + err = _("Device with this name already exists") xpubs_rows_count = int(request.form["xpubs_rows_count"]) + 1 keys = [] paths = [] @@ -80,12 +81,12 @@ def new_device_keys(device_type): try: keys.append(Key.parse_xpub(xpub, purpose=purpose)) except: - err = "Failed to parse these xpubs:\n" + "\n".join(xpub) + err = _("Failed to parse these xpubs") + ":\n" + "\n".join(xpub) break if not keys and not err: if device_type in ["bitcoincore", "elementscore"]: if not paths: - err = "No paths were specified, please provide at lease one." + err = _("No paths were specified, please provide at least one.") if err is None: if existing_device: device.add_hot_wallet_keys( @@ -98,7 +99,7 @@ def new_device_keys(device_type): keys_range=[range_start, range_end], keys_purposes=keys_purposes, ) - flash("{} keys were added successfully".format(len(paths))) + flash(_("{} keys were added successfully").format(len(paths))) return redirect( url_for( "devices_endpoint.device", device_alias=device.alias @@ -119,7 +120,7 @@ def new_device_keys(device_type): keys_range=[range_start, range_end], keys_purposes=keys_purposes, ) - flash("{} was added successfully!".format(device_name)) + flash(_("{} was added successfully!").format(device_name)) return redirect( url_for( "devices_endpoint.device", device_alias=device.alias @@ -128,7 +129,10 @@ def new_device_keys(device_type): ) except Exception as e: handle_exception(e) - flash(f"Failed to setup hot wallet. Error: {e}", "error") + flash( + _("Failed to setup hot wallet. Error: {}").format(e), + "error", + ) app.specter.device_manager.remove_device( device, app.specter.wallet_manager, @@ -136,11 +140,11 @@ def new_device_keys(device_type): chain=app.specter.chain, ) else: - err = "xpubs list must not be empty" + err = _("xpubs list must not be empty") elif not err: if existing_device: device.add_keys(keys) - flash("{} keys were added successfully".format(len(keys))) + flash(_("{} keys were added successfully").format(len(keys))) return redirect( url_for("devices_endpoint.device", device_alias=device.alias) ) @@ -157,7 +161,7 @@ def new_device_keys(device_type): rand=rand, ) else: - flash("{} was added successfully!".format(device_name)) + flash(_("{} was added successfully!").format(device_name)) return redirect( url_for("devices_endpoint.device", device_alias=device.alias) + "?newdevice=true" @@ -185,18 +189,21 @@ def new_device_keys(device_type): def new_device_mnemonic(device_type): err = None strength = 128 - mnemonic = generate_mnemonic(strength=strength) + mnemonic = generate_mnemonic( + strength=strength, language_code=app.get_language_code() + ) existing_device = None if request.method == "POST": if len(request.form["mnemonic"].split(" ")) not in [12, 15, 18, 21, 24]: - err = "Invalid mnemonic entered: Must contain either: 12, 15, 18, 21, or 24 words." - mnemo = Mnemonic("english") - if not mnemo.check(request.form["mnemonic"]): - err = "Invalid mnemonic entered." + err = _( + "Invalid mnemonic entered: Must contain either: 12, 15, 18, 21, or 24 words." + ) + if not validate_mnemonic(words=request.form["mnemonic"]): + err = _("Invalid mnemonic entered.") range_start = int(request.form["range_start"]) range_end = int(request.form["range_end"]) if range_start > range_end: - err = "Invalid address range selected." + err = _("Invalid address range selected.") mnemonic = request.form["mnemonic"] passphrase = request.form["passphrase"] file_password = request.form["file_password"] @@ -238,7 +245,7 @@ def device_blinding_key(device_alias): device = app.specter.device_manager.get_by_alias(device_alias) except: return render_template( - "base.jinja", error="Device not found", specter=app.specter, rand=rand + "base.jinja", error=_("Device not found"), specter=app.specter, rand=rand ) if not device: return redirect(url_for("index")) @@ -247,7 +254,7 @@ def device_blinding_key(device_alias): blinding_key = request.form.get("blinding_key") device.set_blinding_key(blinding_key) if not new_device: - flash("Master blinding key was added successfully") + flash(_("Master blinding key was added successfully")) return redirect( url_for("devices_endpoint.device", device_alias=device.alias) + ("?newdevice=true" if new_device else "") @@ -271,22 +278,24 @@ def new_device_manual(): device_name = "" xpubs = "" strength = 128 - mnemonic = generate_mnemonic(strength=strength) + mnemonic = generate_mnemonic( + strength=strength, language_code=app.get_language_code() + ) if request.method == "POST": action = request.form["action"] device_type = request.form["device_type"] device_name = request.form["device_name"] if action == "newcolddevice": if not device_name: - err = "Device name must not be empty" + err = _("Device name cannot be empty") elif device_name in app.specter.device_manager.devices_names: - err = "Device with this name already exists" + err = _("Device with this name already exists") xpubs = request.form["xpubs"] if not xpubs: - err = "xpubs name must not be empty" + err = _("xpubs name cannot be empty") keys, failed = Key.parse_xpubs(xpubs) if len(failed) > 0: - err = "Failed to parse these xpubs:\n" + "\n".join(failed) + err = _("Failed to parse these xpubs") + ":\n" + "\n".join(failed) if err is None: device = app.specter.device_manager.add_device( name=device_name, device_type=device_type, keys=keys @@ -296,18 +305,20 @@ def new_device_manual(): ) elif action == "newhotdevice": if not device_name: - err = "Device name must not be empty" + err = _("Device name cannot be empty") elif device_name in app.specter.device_manager.devices_names: - err = "Device with this name already exists" + err = _("Device with this name already exists") if len(request.form["mnemonic"].split(" ")) not in [12, 15, 18, 21, 24]: - err = "Invalid mnemonic entered: Must contain either: 12, 15, 18, 21, or 24 words." - mnemo = Mnemonic("english") - if not mnemo.check(request.form["mnemonic"]): - err = "Invalid mnemonic entered." + err = _( + "Invalid mnemonic entered: Must contain either: 12, 15, 18, 21, or 24 words." + ) + + if not validate_mnemonic(words=request.form["mnemonic"]): + err = _("Invalid mnemonic entered.") range_start = int(request.form["range_start"]) range_end = int(request.form["range_end"]) if range_start > range_end: - err = "Invalid address range selected." + err = _("Invalid address range selected.") if err is None: mnemonic = request.form["mnemonic"] paths = [ @@ -336,7 +347,7 @@ def new_device_manual(): ) except Exception as e: handle_exception(e) - flash(f"Failed to setup hot wallet. Error: {e}", "error") + flash(_("Failed to setup hot wallet. Error: {}").format(e), "error") app.specter.device_manager.remove_device( device, app.specter.wallet_manager, @@ -345,7 +356,9 @@ def new_device_manual(): ) elif action == "generatemnemonic": strength = int(request.form["strength"]) - mnemonic = generate_mnemonic(strength=strength) + mnemonic = generate_mnemonic( + strength=strength, language_code=app.get_language_code() + ) return render_template( "device/new_device_manual.jinja", device_type=device_type, @@ -370,7 +383,7 @@ def device(device_alias): device = app.specter.device_manager.get_by_alias(device_alias) except: return render_template( - "base.jinja", error="Device not found", specter=app.specter, rand=rand + "base.jinja", error=_("Device not found"), specter=app.specter, rand=rand ) if not device: return redirect(url_for("index")) @@ -379,8 +392,17 @@ def device(device_alias): action = request.form["action"] if action == "forget": if len(wallets) != 0: - err = "Device could not be removed since it is used in wallets: {}.
You must delete those wallets before you can remove this device.
You can delete a wallet from its Settings -> Advanced page.".format( - [wallet.name for wallet in wallets] + # TODO: Long message strings like this should be moved into a template. + err = ( + _( + "Device could not be removed since it is used in wallets: {}" + ).format([wallet.name for wallet in wallets]) + + "
" + + _( + "You must delete those wallets before you can remove this device." + ) + + "
" + + _("You can delete a wallet from its Settings -> Advanced page.") ) else: app.specter.device_manager.remove_device( @@ -394,24 +416,33 @@ def device(device_alias): key = Key.from_json({"original": request.form["key"]}) wallets_with_key = [w for w in wallets if key in w.keys] if len(wallets_with_key) != 0: - err = "Key could not be removed since it is used in wallets: {}.
You must delete those wallets before you can remove this key.
You can delete a wallet from its Settings -> Advanced page.".format( - ", ".join([wallet.name for wallet in wallets_with_key]) + # TODO: Long message strings like this should be moved into a template. + err = ( + _( + "Key could not be removed since it is used in wallets: {}" + ).format(", ".join([wallet.name for wallet in wallets_with_key])) + + "
" + + _("You must delete those wallets before you can remove this key.") + + "
" + + _("You can delete a wallet from its Settings -> Advanced page.") ) else: device.remove_key(key) elif action == "rename": device_name = request.form["newtitle"] if not device_name: - flash("Device name must not be empty", "error") + flash(_("Device name cannot be empty"), "error") elif device_name == device.name: pass elif device_name in app.specter.device_manager.devices_names: - flash("Device already exists", "error") + flash(_("Device already exists"), "error") else: device.rename(device_name) elif action == "add_keys": strength = 128 - mnemonic = generate_mnemonic(strength=strength) + mnemonic = generate_mnemonic( + strength=strength, language_code=app.get_language_code() + ) if device.hot_wallet: return render_template( "device/new_device/new_device_mnemonic.jinja", diff --git a/src/cryptoadvance/specter/server_endpoints/nodes.py b/src/cryptoadvance/specter/server_endpoints/nodes.py index 5cdd54637..23cd2cca2 100644 --- a/src/cryptoadvance/specter/server_endpoints/nodes.py +++ b/src/cryptoadvance/specter/server_endpoints/nodes.py @@ -10,6 +10,7 @@ from flask import ( jsonify, flash, ) +from flask_babel import lazy_gettext as _ from flask_login import login_required, current_user from flask import current_app as app from ..rpc import get_default_datadir @@ -43,7 +44,7 @@ def node_settings(node_alias): ) except: return render_template( - "base.jinja", error="Node not found", specter=app.specter, rand=rand + "base.jinja", error=_("Node not found"), specter=app.specter, rand=rand ) else: node = Node.from_json( @@ -62,7 +63,7 @@ def node_settings(node_alias): ) if not current_user.is_admin: - flash("Only an admin is allowed to access this page.", "error") + flash(_("Only an admin is allowed to access this page"), "error") return redirect("") # The node might have been down but is now up again # (and the checker did not realized yet) and the user clicked "Configure Node" @@ -97,19 +98,19 @@ def node_settings(node_alias): if action == "rename": node_name = request.form["newtitle"] if not node_name: - flash("Node name must not be empty", "error") + flash(_("Node name cannot be empty"), "error") elif node_name == node.name: pass elif node_name in app.specter.device_manager.devices_names: - flash("Node with this name already exists", "error") + flash(_("Node with this name already exists"), "error") else: node.rename(node_name) elif action == "forget": if not node_alias: - flash("Failed to deleted node. Node isn't saved", "error") + flash(_("Failed to deleted node. Node isn't saved"), "error") elif len(app.specter.node_manager.nodes) > 1: app.specter.node_manager.delete_node(node, app.specter) - flash("Node deleted successfully") + flash(_("Node deleted successfully")) return redirect( url_for( "nodes_endpoint.node_settings", @@ -118,7 +119,9 @@ def node_settings(node_alias): ) else: flash( - "Failed to deleted node. Specter must have at least one node configured", + _( + "Failed to delete node. Specter must have at least one node configured" + ), "error", ) elif action == "test": @@ -144,16 +147,18 @@ def node_settings(node_alias): if "tests" in test: # If any test has failed, we notify the user that the test has not passed if False in list(test["tests"].values()): - flash(f"Test failed: {test['err']}", "error") + flash(_("Test failed: {}").format(test["err"]), "error") else: - flash("Test passed", "info") + flash(_("Test passed"), "info") elif "err" in test: - flash(f"Test failed: {test['err']}", "error") + flash(_("Test failed: {}").format(test["err"]), "error") elif action == "save": if not node_alias: if node.name in app.specter.node_manager.nodes: flash( - "Node with this name already exits, please choose a different name.", + _( + "Node with this name already exists, please choose a different name." + ), "error", ) return render_template( @@ -190,7 +195,7 @@ def node_settings(node_alias): protocol=protocol, ) if not success: - flash("Failed connecting to the node", "error") + flash(_("Failed connecting to the node"), "error") if app.specter.active_node_alias == node.alias: app.specter.check() @@ -220,7 +225,7 @@ def internal_node_settings(node_alias): ) except: return render_template( - "base.jinja", error="Node not found", specter=app.specter, rand=rand + "base.jinja", error=_("Node not found"), specter=app.specter, rand=rand ) else: # TODO: Allow internal node setup here? @@ -232,7 +237,7 @@ def internal_node_settings(node_alias): ) if not current_user.is_admin: - flash("Only an admin is allowed to access this page.", "error") + flash(_("Only an admin is allowed to access this page"), "error") return redirect("") # The node might have been down but is now up again # (and the checker did not realized yet) and the user clicked "Configure Node" @@ -245,7 +250,7 @@ def internal_node_settings(node_alias): if action == "rename": node_name = request.form["newtitle"] if not node_name: - flash("Node name must not be empty", "error") + flash(_("Node name must not be empty"), "error") elif node_name == node.name: pass elif node_name in app.specter.device_manager.devices_names: @@ -254,13 +259,13 @@ def internal_node_settings(node_alias): node.rename(node_name) elif action == "forget": if not node_alias: - flash("Failed to deleted node. Node isn't saved", "error") + flash(_("Failed to deleted node. Node isn't saved"), "error") elif len(app.specter.node_manager.nodes) > 1: node.stop() app.specter.node_manager.delete_node(node, app.specter) if bool(request.form.get("remove_datadir", False)): shutil.rmtree(os.path.expanduser(node.datadir), ignore_errors=True) - flash("Node deleted successfully") + flash(_("Node deleted successfully")) return redirect( url_for( "nodes_endpoint.node_settings", @@ -269,27 +274,29 @@ def internal_node_settings(node_alias): ) else: flash( - "Failed to deleted node. Specter must have at least one node configured", + _( + "Failed to delete node. Specter must have at least one node configured" + ), "error", ) elif action == "stopbitcoind": try: node.stop() time.sleep(5) - flash("Specter stopped Bitcoin Core successfully") + flash(_("Specter successfully stopped Bitcoin Core")) except Exception as e: try: logger.exception(e) - flash("Stopping Bitcoin Core, this might take a few moments.") + flash(_("Stopping Bitcoin Core, this might take a few moments.")) node.rpc.stop() except Exception as ne: logger.exception(ne) - flash(f"Failed to stop Bitcoin Core {ne}", "error") + flash(_("Failed to stop Bitcoin Core {}").format(ne), "error") elif action == "startbitcoind": if node.start(timeout=120): - flash("Specter has started Bitcoin Core") + flash(_("Specter has started Bitcoin Core")) else: - flash("Specter failed to start the node...", "error") + flash(_("Specter failed to start the node"), "error") elif action == "uninstall_bitcoind": try: node.stop() @@ -299,7 +306,7 @@ def internal_node_settings(node_alias): ) if bool(request.form.get("remove_datadir", False)): shutil.rmtree(os.path.expanduser(node.datadir), ignore_errors=True) - flash(f"Bitcoin Core uninstalled successfully") + flash(_("Bitcoin Core successfully uninstalled")) app.specter.node_manager.delete_node(node, app.specter) return redirect( url_for( @@ -308,7 +315,7 @@ def internal_node_settings(node_alias): ) ) except Exception as e: - flash(f"Failed to remove Bitcoin Core, error: {e}", "error") + flash(_("Failed to remove Bitcoin Core, error: {}").format(e), "error") elif action == "upgrade_bitcoind": if node.version != app.config["INTERNAL_BITCOIND_VERSION"]: try: @@ -317,10 +324,13 @@ def internal_node_settings(node_alias): ) except Exception as e: flash( - f"Failed to upgrade Bitcoin Core version, error: {e}", "error" + _("Failed to upgrade Bitcoin Core version, error: {}").format( + e + ), + "error", ) else: - flash("Bitcoin Core version is already up to date") + flash(_("Bitcoin Core version is already up to date")) return render_template( "node/internal_node_settings.jinja", node=node, diff --git a/src/cryptoadvance/specter/server_endpoints/settings.py b/src/cryptoadvance/specter/server_endpoints/settings.py index 470aec857..e48775a2e 100644 --- a/src/cryptoadvance/specter/server_endpoints/settings.py +++ b/src/cryptoadvance/specter/server_endpoints/settings.py @@ -16,6 +16,7 @@ import requests from flask import Blueprint, Flask from flask import current_app as app from flask import flash, jsonify, redirect, render_template, request, send_file, url_for +from flask_babel import lazy_gettext as _ from flask_login import current_user, login_required from ..helpers import ( @@ -108,7 +109,7 @@ def general(): # continue with the existing one if "already exists" not in str(e): flash( - "Failed to import wallet {}, error: {}".format( + _("Failed to import wallet {}, error: {}").format( wallet["name"], e ), "error", @@ -142,16 +143,21 @@ def general(): ) ) flash( - "Failed to perform rescan for wallet: {}".format(e), "error" + _("Failed to perform rescan for wallet: {}").format(e), + "error", ) wallet_obj.getdata() except Exception: - flash("Failed to import wallet {}".format(wallet["name"]), "error") - flash("Specter data was successfully loaded from backup.", "info") + flash( + _("Failed to import wallet {}").format(wallet["name"]), "error" + ) + flash(_("Specter data was successfully loaded from backup"), "info") if rescanning: flash( - "Wallets are rescanning for transactions history.\n\ -This may take a few hours to complete.", + _( + "Wallets are rescanning for transactions history.\n\ +This may take a few hours to complete." + ), "info", ) @@ -165,6 +171,7 @@ This may take a few hours to complete.", specter=app.specter, current_version=current_version, rand=rand, + supported_languages=app.supported_languages, ) @@ -179,7 +186,7 @@ def tor(): param only_tor "on" or something else ("off") """ if not current_user.is_admin: - flash("Only an admin is allowed to access this page.", "error") + flash(_("Only an admin is allowed to access this page."), "error") return redirect("") app.specter.reset_setup("torbrowser") current_version = notify_upgrade(app, flash) @@ -250,18 +257,18 @@ def tor(): logger.info("Starting Tor...") try: app.specter.tor_daemon.start_tor_daemon() - flash("Specter has started Tor") + flash(_("Specter has started Tor")) except Exception as e: - flash(f"Failed to start Tor, error: {e}", "error") + flash(_("Failed to start Tor, error: {}").format(e), "error") logger.error(f"Failed to start Tor, error: {e}") elif action == "stoptor": logger.info("Stopping Tor...") try: app.specter.tor_daemon.stop_tor_daemon() time.sleep(1) - flash("Specter stopped Tor successfully") + flash(_("Specter stopped Tor successfully")) except Exception as e: - flash(f"Failed to stop Tor, error: {e}", "error") + flash(_("Failed to stop Tor, error: {}").format(e), "error") logger.error(f"Failed to start Tor, error: {e}") elif action == "uninstalltor": logger.info("Uninstalling Tor...") @@ -270,9 +277,9 @@ def tor(): app.specter.tor_daemon.stop_tor_daemon() shutil.rmtree(os.path.join(app.specter.data_folder, "tor-binaries")) os.remove(os.path.join(app.specter.data_folder, "torrc")) - flash(f"Tor uninstalled successfully") + flash(_("Tor uninstalled successfully")) except Exception as e: - flash(f"Failed to uninstall Tor, error: {e}", "error") + flash(_("Failed to uninstall Tor, error: {}").format(e), "error") logger.error(f"Failed to uninstall Tor, error: {e}") elif action == "test_tor": logger.info("Testing the Tor connection...") @@ -287,10 +294,12 @@ def tor(): ) tor_connectable = res.status_code == 200 if tor_connectable: - flash("Tor requests test completed successfully!", "info") + flash(_("Tor requests test completed successfully!"), "info") else: flash( - f"Failed to make test request over Tor. Status-Code: {res.status_code}", + _( + "Failed to make test request over Tor. Status-Code: {}" + ).format(res.status_code), "error", ) logger.error( @@ -303,7 +312,10 @@ def tor(): logger.error(app.specter.tor_daemon.get_logs()) app.specter.tor_daemon.start_tor_daemon() except Exception as e: - flash(f"Failed to make test request over Tor.\nError: {e}", "error") + flash( + _("Failed to make test request over Tor.\nError: {}").format(e), + "error", + ) logger.error(f"Failed to make test request over Tor.\nError: {e}") if tor_type == "builtin": logger.error("Tor-Logs:") @@ -358,7 +370,7 @@ def auth(): if current_user.username != specter_username: if app.specter.user_manager.get_user_by_username(specter_username): flash( - "Username is already taken, please choose another one", + _("Username is already taken, please choose another one"), "error", ) return render_template( @@ -375,9 +387,9 @@ def auth(): if specter_password: if len(specter_password) < min_chars: flash( - "Please enter a password of a least {} characters.".format( - min_chars - ), + _( + "Please enter a password of a least {} characters" + ).format(min_chars), "error", ) return render_template( @@ -400,9 +412,9 @@ def auth(): if new_password: if len(new_password) < min_chars: flash( - "Please enter a password of a least {} characters.".format( - min_chars - ), + _( + "Please enter a password of a least {} characters" + ).format(min_chars), "error", ) return render_template( @@ -441,9 +453,9 @@ def auth(): if timeout > 0: expiry = now + timeout * 60 * 60 if timeout > 1: - expiry_desc = " (expires in {} hours)".format(timeout) + expiry_desc = " " + _("(expires in {} hours)").format(timeout) else: - expiry_desc = " (expires in 1 hour)" + expiry_desc = " " + _("(expires in 1 hour)") else: expiry = 0 expiry_desc = "" @@ -451,14 +463,14 @@ def auth(): {"otp": new_otp, "created_at": now, "expiry": expiry} ) flash( - "New user link generated{}: {}auth/register?otp={}".format( + _("New user link generated{}: {}auth/register?otp={}").format( expiry_desc, request.url_root, new_otp ), "info", ) else: flash( - "Error: Only the admin account can issue new registration links.", + _("Error: Only the admin account can issue new registration links"), "error", ) elif action == "deleteuser": @@ -467,9 +479,11 @@ def auth(): if current_user.is_admin: app.specter.delete_user(user) users.remove(user) - flash("User {} was deleted successfully".format(user.username), "info") + flash( + _("User {} was deleted successfully").format(user.username), "info" + ) else: - flash("Error: Only the admin account can delete users", "error") + flash(_("Error: Only the admin account can delete users"), "error") return render_template( "settings/auth_settings.jinja", method=method, @@ -489,7 +503,7 @@ def hwi(): if request.method == "POST": hwi_bridge_url = request.form["hwi_bridge_url"] app.specter.update_hwi_bridge_url(hwi_bridge_url, current_user) - flash("HWIBridge URL is updated! Don't forget to whitelist Specter!") + flash(_("HWIBridge URL is updated! Don't forget to whitelist Specter!")) return render_template( "settings/hwi_settings.jinja", specter=app.specter, diff --git a/src/cryptoadvance/specter/server_endpoints/setup.py b/src/cryptoadvance/specter/server_endpoints/setup.py index a331766bd..fa4013134 100644 --- a/src/cryptoadvance/specter/server_endpoints/setup.py +++ b/src/cryptoadvance/specter/server_endpoints/setup.py @@ -10,6 +10,7 @@ from flask import ( jsonify, flash, ) +from flask_babel import lazy_gettext as _ from flask_login import login_required, current_user from flask import current_app as app from mnemonic import Mnemonic @@ -120,10 +121,10 @@ def setup_tor(): t = threading.Thread(target=setup_tor_thread, args=(app.specter,)) t.start() elif os.path.isfile(app.specter.torbrowser_path): - return {"error": "Tor is already installed"} + return {"error": _("Tor is already installed")} elif app.specter.setup_status["torbrowser"]["stage_progress"] != -1: - return {"error": "Tor installation is still under progress"} - return {"success": "Starting Tor setup!"} + return {"error": _("Tor installation is still in progress")} + return {"success": _("Starting Tor setup!")} @setup_endpoint.route("/setup_bitcoind", methods=["POST"]) @@ -140,10 +141,10 @@ def setup_bitcoind(): ) t.start() elif os.path.isfile(app.specter.bitcoind_path): - return {"error": "Bitcoin Core is already installed"} + return {"error": _("Bitcoin Core is already installed")} elif app.specter.setup_status["bitcoind"]["stage_progress"] != -1: - return {"error": "Bitcoin Core installation is still under progress"} - return {"success": "Starting Bitcoin Core setup!"} + return {"error": _("Bitcoin Core installation is still in progress")} + return {"success": _("Starting Bitcoin Core setup!")} @setup_endpoint.route("/setup_bitcoind_datadir", methods=["POST"]) @@ -202,10 +203,10 @@ def setup_bitcoind_datadir(): ) t.start() elif not os.path.isfile(app.specter.bitcoind_path): - return {"error": "Bitcoin Core in not installed but required for this step"} + return {"error": _("Bitcoin Core in not installed but required for this step")} elif app.specter.setup_status["bitcoind"]["stage_progress"] != -1: - return {"error": "Bitcoin Core installation is still under progress"} - return {"success": "Starting Bitcoin Core setup!"} + return {"error": _("Bitcoin Core installation is still in progress")} + return {"success": _("Starting Bitcoin Core setup!")} ######################### Setup status (open endpoint) ####################################### diff --git a/src/cryptoadvance/specter/server_endpoints/wallets.py b/src/cryptoadvance/specter/server_endpoints/wallets.py index a2dfa2415..8532eacbb 100644 --- a/src/cryptoadvance/specter/server_endpoints/wallets.py +++ b/src/cryptoadvance/specter/server_endpoints/wallets.py @@ -17,6 +17,7 @@ import requests from flask import Blueprint, Flask from flask import current_app as app from flask import flash, jsonify, redirect, render_template, request, url_for +from flask_babel import lazy_gettext as _ from flask_login import current_user, login_required from werkzeug.wrappers import Response from cryptoadvance.specter.util.psbt_creator import PsbtCreator @@ -47,7 +48,7 @@ wallets_endpoint = Blueprint("wallets_endpoint", __name__) def handle_wallet_error(func_name, error): - flash(f"SpecterError while {func_name}: {error}", "error") + flash(_("SpecterError while {}: {}").format(func_name, error), "error") app.logger.error(f"SpecterError while {func_name}: {error}") app.specter.wallet_manager.update() return redirect(url_for("about")) @@ -56,10 +57,9 @@ def handle_wallet_error(func_name, error): def check_wallet(func): @wraps(func) def wrapper(*args, **kwargs): - """checks the wallet for healthyness A wrapper function""" + """checks the wallet for healthiness A wrapper function""" if kwargs["wallet_alias"]: wallet_alias = kwargs["wallet_alias"] - print("--------------------checking wallet") wallet = app.specter.wallet_manager.get_by_alias(wallet_alias) wallet.get_info() return func(*args, **kwargs) @@ -105,8 +105,7 @@ def failed_wallets(): delete_file(fullpath.replace(".json", "_txs.csv")) app.specter.wallet_manager.update() except Exception as e: - - flash(f"Failed to delete failed wallet: {str(e)}", "error") + flash(_("Failed to delete wallet: {}").format(str(e)), "error") return redirect("/") @@ -118,13 +117,15 @@ def failed_wallets(): def new_wallet_type(): err = None if app.specter.chain is None: - err = "Configure Bitcoin Core to create wallets" + err = _("Configure Bitcoin Core to create wallets") return render_template("base.jinja", error=err, specter=app.specter, rand=rand) try: # Make sure wallet is enabled on Bitcoin Core app.specter.rpc.listwallets() except Exception: - err = '


Configure Bitcoin Core is running with wallets disabled.

Please make sure disablewallet is off (set disablewallet=0 in your bitcoin.conf), then restart Bitcoin Core and try again.
See here for more information.

' + err = _( + '


Bitcoin Core is running with wallets disabled.

Please make sure disablewallet is off (set disablewallet=0 in your bitcoin.conf), then restart Bitcoin Core and try again.
See here for more information.

' + ) return render_template("base.jinja", error=err, specter=app.specter, rand=rand) return render_template( "wallet/new_wallet/new_wallet_type.jinja", specter=app.specter, rand=rand @@ -136,7 +137,7 @@ def new_wallet_type(): def new_wallet(wallet_type): wallet_types = ["simple", "multisig", "import_wallet"] if wallet_type not in wallet_types: - flash("Unknown wallet type requested", "error") + flash(_("Unknown wallet type requested"), "error") return redirect(url_for("wallets_endpoint.new_wallet_type")) err = None @@ -163,7 +164,7 @@ def new_wallet(wallet_type): except SpecterError as se: flash(str(se), "error") return redirect(url_for("wallets_endpoint.new_wallet_type")) - flash("Wallet imported successfully", "info") + flash(_("Wallet imported successfully"), "info") try: wallet_importer.rescan_as_needed(app.specter) except SpecterError as se: @@ -199,17 +200,18 @@ def new_wallet(wallet_type): return render_template( "wallet/new_wallet/new_wallet.jinja", wallet_type=wallet_type, - error="No device was selected. Please select a device to create the wallet for.", + error=_( + "No device was selected. Please select a device to create the wallet for." + ), specter=app.specter, rand=rand, ) devices = get_devices_with_keys_by_type(app, cosigners, wallet_type) for device in devices: if len(device.keys) == 0: - err = ( - "Device %s doesn't have keys matching this wallet type" - % device.name - ) + err = _( + "Device {} doesn't have keys matching this wallet type" + ).format(device.name) break name = wallet_type.title() @@ -235,7 +237,7 @@ def new_wallet(wallet_type): sigs_total = int(request.form.get("sigs_total", 1)) sigs_required = int(request.form.get("sigs_required", 1)) if wallet_name in app.specter.wallet_manager.wallets_names: - err = "Wallet already exists" + err = _("Wallet already exists") if err: devices = [ app.specter.device_manager.get_by_alias( @@ -270,7 +272,9 @@ def new_wallet(wallet_type): except: pass if len(keys) != sigs_total or len(cosigners) != sigs_total: - err = "No keys were selected for device, please try adding keys first" + err = _( + "No keys were selected for device, please try adding keys first" + ) devices = [ app.specter.device_manager.get_by_alias( request.form.get("cosigner{}".format(i)) @@ -294,7 +298,7 @@ def new_wallet(wallet_type): wallet_name, sigs_required, address_type, keys, cosigners ) except Exception as e: - err = f"Failed to create wallet. Error: {e}" + err = _("Failed to create wallet. Error: {}").format(e) return render_template( "wallet/new_wallet/new_wallet_keys.jinja", cosigners=cosigners, @@ -483,7 +487,9 @@ def send_new(wallet_alias): selected_coins = request.form.getlist("coinselect") fee_estimation_data = get_fees(app.specter, app.config) if fee_estimation_data.get("failed", None): - flash("Failed to fetch fee estimations, please use the manual fee calculation") + flash( + _("Failed to fetch fee estimations. Please use the manual fee calculation.") + ) fee_rate = fee_estimation_data["hourFee"] @@ -535,7 +541,7 @@ def send_new(wallet_alias): rand=rand, ) except Exception as e: - flash("Failed to perform RBF. Error: %s" % e, "error") + flash(_("Failed to perform RBF. Error: {}").format(e), "error") elif action == "rbf_cancel": try: rbf_tx_id = request.form["rbf_tx_id"] @@ -551,7 +557,10 @@ def send_new(wallet_alias): rand=rand, ) except Exception as e: - flash("Failed to cancel transaction with RBF. Error: %s" % e, "error") + flash( + _("Failed to cancel transaction with RBF. Error: {}").format(e), + "error", + ) elif action == "rbf_edit": try: decoded_tx = wallet.decode_tx(rbf_tx_id) @@ -565,7 +574,7 @@ def send_new(wallet_alias): fee_options = "manual" rbf = True except Exception as e: - flash("Failed to perform RBF. Error: %s" % e, "error") + flash(_("Failed to perform RBF. Error: {}").format(e), "error") elif action == "signhotwallet": passphrase = request.form["passphrase"] psbt = json.loads(request.form["psbt"]) @@ -588,10 +597,10 @@ def send_new(wallet_alias): signed_psbt = signed_psbt["psbt"] except Exception as e: signed_psbt = None - flash("Failed to sign PSBT: %s" % e, "error") + flash(_("Failed to sign PSBT: {}").format(e), "error") else: signed_psbt = None - flash("Device already signed the PSBT", "error") + flash(_("Device already signed the PSBT"), "error") return render_template( "wallet/send/sign/wallet_send_sign_psbt.jinja", signed_psbt=signed_psbt, @@ -607,7 +616,7 @@ def send_new(wallet_alias): try: rbf_utxo = wallet.get_rbf_utxo(rbf_tx_id) except Exception as e: - flash("Failed to get RBF coins. Error: %s" % e, "error") + flash(_("Failed to get RBF coins. Error: {}").format(e), "error") show_advanced_settings = ( ui_option != "ui" @@ -661,7 +670,7 @@ def send_pending(wallet_alias): ) except Exception as e: app.logger.error("Could not delete Pending PSBT: %s" % e) - flash("Could not delete Pending PSBT!", "error") + flash(_("Could not delete Pending PSBT!"), "error") elif action == "openpsbt": psbt = json.loads(request.form["pending_psbt"]) return render_template( @@ -699,7 +708,7 @@ def import_psbt(wallet_alias): b64psbt = "".join(request.form["rawpsbt"].split()) psbt = wallet.importpsbt(b64psbt) except Exception as e: - flash("Could not import PSBT: %s" % e, "error") + flash(_("Could not import PSBT: {}").format(e), "error") return redirect( url_for("wallets_endpoint.import_psbt", wallet_alias=wallet_alias) ) @@ -773,7 +782,7 @@ def settings(wallet_alias): elif action == "abortrescan": res = wallet.rpc.abortrescan() if not res: - error = "Failed to abort rescan. Maybe already complete?" + error = _("Failed to abort rescan. Maybe already complete?") wallet.getdata() elif action == "rescanutxo": explorer = None @@ -810,11 +819,11 @@ def settings(wallet_alias): elif action == "rename": wallet_name = request.form["newtitle"] if not wallet_name: - flash("Wallet name cannot be empty", "error") + flash(_("Wallet name cannot be empty"), "error") elif wallet_name == wallet.name: pass elif wallet_name in app.specter.wallet_manager.wallets_names: - flash("Wallet already exists", "error") + flash(_("Wallet already exists"), "error") else: app.specter.wallet_manager.rename_wallet(wallet, wallet_name) @@ -846,7 +855,7 @@ def combine(wallet_alias): for i, psbt in enumerate(psbts): if not psbt: - return "Cannot parse empty data as PSBT", 500 + return _("Cannot parse empty data as PSBT"), 500 if "UR:BYTES/" in psbt.upper(): psbt = bcur2base64(psbt).decode() @@ -870,7 +879,7 @@ def combine(wallet_alias): try: bytes.fromhex(psbt) except: - return "Invalid transaction format", 500 + return _("Invalid transaction format"), 500 try: if "hex" in raw: @@ -886,84 +895,84 @@ def combine(wallet_alias): except RpcError as e: return e.error_msg, e.status_code except Exception as e: - return "Unknown error: %r" % e, 500 + return _("Unknown error: {}").format(e), 500 return json.dumps(raw) -@wallets_endpoint.route("/wallet//broadcast/", methods=["GET", "POST"]) +@wallets_endpoint.route("/wallet//broadcast/", methods=["POST"]) @login_required def broadcast(wallet_alias): wallet = app.specter.wallet_manager.get_by_alias(wallet_alias) - if request.method == "POST": - tx = request.form.get("tx") - res = wallet.rpc.testmempoolaccept([tx])[0] - if res["allowed"]: - app.specter.broadcast(tx) - wallet.delete_pending_psbt(get_txid(tx)) - return jsonify(success=True) - else: - return jsonify( - success=False, - error="Failed to broadcast transaction: transaction is invalid\n%s" - % res["reject-reason"], - ) - return jsonify(success=False, error="broadcast tx request must use POST") + tx = request.form.get("tx") + res = wallet.rpc.testmempoolaccept([tx])[0] + if res["allowed"]: + app.specter.broadcast(tx) + wallet.delete_pending_psbt(get_txid(tx)) + return jsonify(success=True) + else: + return jsonify( + success=False, + error=_( + "Failed to broadcast transaction: transaction is invalid\n{}" + ).format(res["reject-reason"]), + ) @wallets_endpoint.route( - "/wallet//broadcast_blockexplorer/", methods=["GET", "POST"] + "/wallet//broadcast_blockexplorer/", methods=["POST"] ) @login_required def broadcast_blockexplorer(wallet_alias): wallet = app.specter.wallet_manager.get_by_alias(wallet_alias) - if request.method == "POST": - tx = request.form.get("tx") - explorer = request.form.get("explorer") - use_tor = request.form.get("use_tor", "true") == "true" - res = wallet.rpc.testmempoolaccept([tx])[0] - if res["allowed"]: - try: - if app.specter.chain == "main": - url_network = "" - elif app.specter.chain == "liquidv1": - url_network = "liquid/" - elif app.specter.chain == "test" or app.specter.chain == "testnet": - url_network = "testnet/" - elif app.specter.chain == "signet": - url_network = "signet/" - else: - return jsonify( - success=False, - error=f"Failed to broadcast transaction. Network not supported.", - ) - if explorer == "mempool": - explorer = f"MEMPOOL_SPACE{'_ONION' if use_tor else ''}" - elif explorer == "blockstream": - explorer = f"BLOCKSTREAM_INFO{'_ONION' if use_tor else ''}" - else: - return jsonify( - success=False, - error=f"Failed to broadcast transaction. Block explorer not supported.", - ) - requests_session = app.specter.requests_session(force_tor=use_tor) - requests_session.post( - f"{app.config['EXPLORERS_LIST'][explorer]['url']}{url_network}api/tx", - data=tx, - ) - wallet.delete_pending_psbt(get_txid(tx)) - return jsonify(success=True) - except Exception as e: + tx = request.form.get("tx") + explorer = request.form.get("explorer") + use_tor = request.form.get("use_tor", "true") == "true" + res = wallet.rpc.testmempoolaccept([tx])[0] + if res["allowed"]: + try: + if app.specter.chain == "main": + url_network = "" + elif app.specter.chain == "liquidv1": + url_network = "liquid/" + elif app.specter.chain == "test" or app.specter.chain == "testnet": + url_network = "testnet/" + elif app.specter.chain == "signet": + url_network = "signet/" + else: return jsonify( success=False, - error=f"Failed to broadcast transaction with error: {e}", + error=_("Failed to broadcast transaction. Network not supported."), ) - else: + if explorer == "mempool": + explorer = f"MEMPOOL_SPACE{'_ONION' if use_tor else ''}" + elif explorer == "blockstream": + explorer = f"BLOCKSTREAM_INFO{'_ONION' if use_tor else ''}" + else: + return jsonify( + success=False, + error=_( + "Failed to broadcast transaction. Block explorer not supported." + ), + ) + requests_session = app.specter.requests_session(force_tor=use_tor) + requests_session.post( + f"{app.config['EXPLORERS_LIST'][explorer]['url']}{url_network}api/tx", + data=tx, + ) + wallet.delete_pending_psbt(get_txid(tx)) + return jsonify(success=True) + except Exception as e: return jsonify( success=False, - error="Failed to broadcast transaction: transaction is invalid\n%s" - % res["reject-reason"], + error=_("Failed to broadcast transaction with error: {}").format(e), ) - return jsonify(success=False, error="broadcast tx request must use POST") + else: + return jsonify( + success=False, + error=_( + "Failed to broadcast transaction: transaction is invalid\n{}" + ).format(res["reject-reason"]), + ) @wallets_endpoint.route("/wallet//decoderawtx/", methods=["GET", "POST"]) @@ -1010,15 +1019,15 @@ def decoderawtx(wallet_alias): if "asset" in v: v["assetlabel"] = app.specter.asset_label(v["asset"]) - return { - "success": True, - "tx": tx, - "rawtx": rawtx, - "walletName": wallet.name, - } + return jsonify( + success=True, + tx=tx, + rawtx=rawtx, + walletName=wallet.name, + ) except Exception as e: app.logger.warning("Failed to fetch transaction data. Exception: {}".format(e)) - return {"success": False} + return jsonify(success=False) @wallets_endpoint.route( @@ -1030,10 +1039,10 @@ def rescan_progress(wallet_alias): try: wallet = app.specter.wallet_manager.get_by_alias(wallet_alias) wallet.get_info() - return { - "active": wallet.rescan_progress is not None, - "progress": wallet.rescan_progress, - } + return jsonify( + active=wallet.rescan_progress is not None, + progress=wallet.rescan_progress, + ) except SpecterError as se: app.logger.error("SpecterError while get wallet rescan_progress: %s" % se) return {} @@ -1046,16 +1055,16 @@ def get_label(wallet_alias): wallet = app.specter.wallet_manager.get_by_alias(wallet_alias) address = request.form.get("address", "") label = wallet.getlabel(address) - return { - "address": address, - "label": label, - } + return jsonify( + address=address, + label=label, + ) except Exception as e: handle_exception(e) - return { - "success": False, - "error": f"Exception trying to get address label: Error: {e}", - } + return jsonify( + success=False, + error=_("Exception trying to get address label: Error: {}").format(e), + ) @wallets_endpoint.route("/wallet//set_label", methods=["POST"]) @@ -1066,7 +1075,7 @@ def set_label(wallet_alias): address = request.form["address"] label = request.form["label"].rstrip() wallet.setlabel(address, label) - return {"success": True} + return jsonify(success=True) @wallets_endpoint.route("/wallet//txlist", methods=["POST"]) @@ -1174,10 +1183,10 @@ def addresses_list(wallet_alias): addresses_list, idx=idx, limit=limit, sortby=sortby, sortdir=sortdir ) - return { - "addressesList": json.dumps(result["addressesList"]), - "pageCount": result["pageCount"], - } + return jsonify( + addressesList=json.dumps(result["addressesList"]), + pageCount=result["pageCount"], + ) @wallets_endpoint.route("/wallet//addressinfo/", methods=["POST"]) @@ -1199,9 +1208,8 @@ def addressinfo(wallet_alias): **address_info, } except Exception as e: - app.logger.warning("Failed to fetch address data. Exception: {}".format(e)) - return {"success": False} + return jsonify(success=False) ################## Wallet CSV export data endpoints ####################### @@ -1263,7 +1271,7 @@ def addresses_list_csv(wallet_alias): return response except Exception as e: app.logger.error("Failed to export addresses list. Error: %s" % e) - flash("Failed to export addresses list. Error: %s" % e, "error") + flash(_("Failed to export addresses list. Error: {}").format(e), "error") return redirect(url_for("index")) @@ -1332,7 +1340,7 @@ def utxo_csv(wallet_alias): return response except Exception as e: logging.exception(e) - return "Failed to export wallet utxo. Error: %s" % e, 500 + return _("Failed to export wallet utxo. Error: {}").format(e), 500 # Export all wallets transaction history combined @@ -1367,7 +1375,7 @@ def wallet_overview_txs_csv(): return response except Exception as e: logging.exception(e) - return "Failed to export wallets overview history. Error: %s" % e, 500 + return _("Failed to export wallets overview history. Error: {}").format(e), 500 # Export all wallets transaction history combined @@ -1399,7 +1407,7 @@ def wallet_overview_utxo_csv(): return response except Exception as e: logging.exception(e) - return "Failed to export wallets overview utxo. Error: %s" % e, 500 + return _("Failed to export wallets overview utxo. Error: {}").format(e), 500 ################## Helpers ####################### @@ -1425,22 +1433,22 @@ def txlist_to_csv(wallet, _txlist, specter, current_user, includePricesHistory=F elif specter.price_provider.endswith("_gbp"): symbol = "GBP" row = ( - "Date", - "Label", - "Category", - "Amount ({})".format(specter.unit.upper()), - "Value ({})".format(symbol), - "Rate (BTC/{})".format(symbol) + _("Date"), + _("Label"), + _("Category"), + _("Amount ({})").format(specter.unit.upper()), + _("Value ({})").format(symbol), + _("Rate (BTC/{})").format(symbol) if specter.unit != "sat" - else "Rate ({}/SAT)".format(symbol), - "TxID", - "Address", - "Block Height", - "Timestamp", - "Raw Transaction", + else _("Rate ({}/SAT)").format(symbol), + _("TxID"), + _("Address"), + _("Block Height"), + _("Timestamp"), + _("Raw Transaction"), ) if not wallet: - row = ("Wallet",) + row + row = (_("Wallet"),) + row w.writerow(row) yield data.getvalue() data.seek(0) @@ -1515,11 +1523,11 @@ def addresses_list_to_csv(wallet): w = csv.writer(data) # write header row = ( - "Address", - "Label", - "Index", - "Used", - "Current balance", + _("Address"), + _("Label"), + _("Index"), + _("Used"), + _("Current balance"), ) w.writerow(row) yield data.getvalue() @@ -1534,15 +1542,16 @@ def addresses_list_to_csv(wallet): row = ( address, address_info.label, - "(external)" + _("(external)") if address_info.is_external else ( - str(address_info.index) + (" (change)" if address_info.change else "") + str(address_info.index) + + (_(" (change)") if address_info.change else "") ), address_info.used, ) if address_info.is_external: - balance_on_address = "unknown (external address)" + balance_on_address = _("unknown (external address)") else: balance_on_address = 0 if address_info.used: @@ -1565,13 +1574,13 @@ def wallet_addresses_list_to_csv(addresses_list): w = csv.writer(data) # write header row = ( - "Index", - "Address", - "Type", - "Label", - "Used", - "UTXO", - "Amount (BTC)", + _("Index"), + _("Address"), + _("Type"), + _("Label"), + _("Used"), + _("UTXO"), + _("Amount (BTC)"), ) w.writerow(row) yield data.getvalue() diff --git a/src/cryptoadvance/specter/templates/500.jinja b/src/cryptoadvance/specter/templates/500.jinja index b7c419c22..e9d376bf4 100644 --- a/src/cryptoadvance/specter/templates/500.jinja +++ b/src/cryptoadvance/specter/templates/500.jinja @@ -2,7 +2,7 @@ - Specter Desktop + {{ _("Specter Desktop") }}
-

Add {% if existing_device %}Keys{% else %}Device{% endif %}


+

{{ _("Add") }} {% if existing_device %}{{ _("Keys") }}{% else %}{{ _("Device") }}{% endif %}


{% if existing_device %} {% endif %} @@ -44,20 +44,20 @@

⚠️ A note on hot wallets:
- This will create a hot wallet on your Bitcoin Core node.
- Hot wallets are considered less secure and are not recommended for use with significant amounts. Use with caution and beware the potential risks. + {{ _('This will create a hot wallet on your Bitcoin Core node.') }}
+ {{ _("Hot wallets are considered less secure and are not recommended for use with significant amounts. Use with caution and beware the potential risks.") }}

-

Enter your mnemonic here{% if not existing_device %} or use the randomly generated one{% endif %}:

- {% if not existing_device %}

Make sure to backup these words!

{% endif %} +

{{ _("Enter your mnemonic here") }}{% if not existing_device %} {{ _("or use the randomly generated one") }}{% endif %}:

+ {% if not existing_device %}

{{ _("Make sure to backup these words!") }}

{% endif %} {% set wordslist = mnemonic.split(' ') %} {% if not existing_device %} {% endif %} - +
@@ -66,7 +66,7 @@
- +

@@ -82,25 +82,25 @@
- Advanced ▶ + {{ _("Advanced") }} ▶

- +

{% endblock %} @@ -181,10 +181,10 @@ let advancedSettings = document.getElementById('advanced-settings'); if (advancedSettings.style.display === 'block') { advancedSettings.style.display = 'none'; - advancedButton.innerHTML = 'Advanced ▶'; + advancedButton.innerHTML = '{{ _("Advanced") }} ▶'; } else { advancedSettings.style.display = 'block'; - advancedButton.innerHTML = 'Advanced ▼'; + advancedButton.innerHTML = '{{ _("Advanced") }} ▼'; } } diff --git a/src/cryptoadvance/specter/templates/device/new_device/new_device_type.jinja b/src/cryptoadvance/specter/templates/device/new_device/new_device_type.jinja index 995b5c068..44ab3a4fd 100644 --- a/src/cryptoadvance/specter/templates/device/new_device/new_device_type.jinja +++ b/src/cryptoadvance/specter/templates/device/new_device/new_device_type.jinja @@ -1,10 +1,10 @@ {% extends "base.jinja" %} {% block main %} -

Add Device


+

{{ _("Add Device") }}


-

Select Your Device Type

- +

{{ _("Select Your Device Type") }}

+
{% for cls in specter.device_manager.supported_devices_for_chain(specter) %} {% if not cls.hot_wallet or specter.rpc %} @@ -17,7 +17,7 @@ {% endif %} {% endfor %}
- Manual configuration + {{ _("Manual configuration") }}
{% endblock %} diff --git a/src/cryptoadvance/specter/templates/device/new_device_manual.jinja b/src/cryptoadvance/specter/templates/device/new_device_manual.jinja index a390d324e..c0e6e72ed 100644 --- a/src/cryptoadvance/specter/templates/device/new_device_manual.jinja +++ b/src/cryptoadvance/specter/templates/device/new_device_manual.jinja @@ -4,50 +4,50 @@ {% include "includes/qr-scanner.html" %} {% if device %} -

Adding keys to {{ device.name }}

+

{{ _("Adding keys to") }} {{ device.name }}

{% else %} -

Setting up a new device

+

{{ _("Setting up a new device") }}

{% endif %}
{% if not device %} - +

{% include "device/components/device_type.jinja" %} - + {% endif %} {% if not device or not device.hot_wallet %}

-

Scan, paste or load xpubs:

+

{{ _("Scan, paste or load xpubs") }}:

{% if not device %} - You will be able add more keys later, from the device menu. + {{ _("You will be able add more keys later from the device menu.") }} {% endif %}
-

One line per xpub. Ideally with derivation path in the form:
[ fingerprint / derivation / path ] xpub.

- +

{{ _("One line per xpub. Ideally with derivation path in the form") }}:
[ fingerprint / derivation / path ] xpub.

+
-

Specify account number (advanced)

+

{{ _("Specify account number (advanced)") }}

- Examples:
+ {{ _("Examples") }}:
 [f79ec910/84'/1'/0']tpubDA5h1hw24fzoBi9...pR1DiM4EBu
 [F79EC910/48h/1h/0h/2h]Vpub5DRk6RvRAjZf9rmZV1Q8...TZSDQL67e5i
 upub5En4f7k8gaG2KDHvBeEYox...rFpJRHpiZ4DE
 			

- +
{% endif %} {% if not device or device.hot_wallet %}
@@ -136,36 +136,34 @@ upub5En4f7k8gaG2KDHvBeEYox...rFpJRHpiZ4DE

- +

- Advanced ▶ + {{ _("Advanced") }} ▶



- +
{% endif %} @@ -179,13 +177,13 @@ m/48h/{{ 0 if specter.info.chain == "main" else 1 }}h/0h/2h let advancedSettings = document.getElementById('advanced_settings'); if (advancedSettings.style.display === 'block') { advancedSettings.style.display = 'none'; - advancedButton.innerHTML = 'Advanced ▶'; + advancedButton.innerHTML = '{{ _("Advanced") }} ▶'; if (isCoinSelectionActive()) { toggleExpand(); } } else { advancedSettings.style.display = 'block'; - advancedButton.innerHTML = 'Advanced ▼'; + advancedButton.innerHTML = '{{ _("Advanced") }} ▼'; } } @@ -287,7 +285,7 @@ m/48h/{{ 0 if specter.info.chain == "main" else 1 }}h/0h/2h } // this shouldn't happen actually if(devices.length == 0){ - showError("No devices found :("); + showError('{{ _("No devices found") }} :('); return; } console.log(devices) @@ -433,7 +431,7 @@ m/48h/{{ 0 if specter.info.chain == "main" else 1 }}h/0h/2h addKeys(str); setDeviceType('cobo'); }else{ - showError("Unknown key format"); + showError('{{ _("Unknown key format") }}'); } }else{ addKeys(result); diff --git a/src/cryptoadvance/specter/templates/hwi_bridge.jinja b/src/cryptoadvance/specter/templates/hwi_bridge.jinja index 912807829..a9d8a1d89 100644 --- a/src/cryptoadvance/specter/templates/hwi_bridge.jinja +++ b/src/cryptoadvance/specter/templates/hwi_bridge.jinja @@ -8,26 +8,26 @@
-

HWI Bridge Settings

+

{{ _("HWI Bridge Settings") }}

{% if tor_service_id %} - HWIBridge is also accessible over Tor:
- + {{ _("HWI Bridge is also accessible over Tor") }}:
+



{% endif %} - +
- To whitelist multiple domains, just list them one after another, each in a new line, for example: + {{ _("To whitelist multiple domains, just list them one after another, each in a new line, for example") }}:
http://127.0.0.1:25440
http://127.0.0.1:25441
http://127.0.0.1:25442


- +
diff --git a/src/cryptoadvance/specter/templates/includes/address-data.html b/src/cryptoadvance/specter/templates/includes/address-data.html index 5c41b9aa0..69756b3ef 100644 --- a/src/cryptoadvance/specter/templates/includes/address-data.html +++ b/src/cryptoadvance/specter/templates/includes/address-data.html @@ -15,7 +15,7 @@ }
-

Address details


+

{{ _("Address details") }}


@@ -41,7 +41,7 @@ this.amountPrice = this.getAttribute('data-amount-price'); this.address = this.getAttribute('data-address'); this.wallet = this.getAttribute('data-address-wallet'); - this.note.innerText = `Loading address: ${this.address} details...`; + this.note.innerText = `{{ _("Loading address") }}: ${this.address} {{ _("details") }}...`; fetchAddressData(this); // Attach the created element to the shadow dom @@ -79,14 +79,14 @@
- - - - - - - - + + + + + + + +
Address:
Label:
From wallet:${walletName}
Address index:${addressIndex}
Is change address:${isChange ? 'Yes' : 'No'}
Used:${self.used ? 'Yes' : 'No'}
UTXO count:${self.utxo}
Amount:${self.amount} ${self.amountPrice}
{{ _("Address") }}:
{{ _("Label") }}:
{{ _("From wallet") }}:${walletName}
{{ _("Address index") }}:${addressIndex}
{{ _("Is change address") }}:${isChange ? '{{ _("Yes") }}' : '{{ _("No") }}'}
{{ _("Used") }}:${self.used ? 'Yes' : 'No'}
{{ _("UTXO count") }}:${self.utxo}
{{ _("Amount") }}:${self.amount} ${self.amountPrice}
` @@ -94,44 +94,44 @@ if (self.isVerifyHwi) { addressInfoHTML += `
- `; + `; } if (self.isVerifyQR) { addressInfoHTML += ` -

Or scan this QR code:

+

{{ _("Or scan this QR code") }}:


`; } addressInfoHTML += `
-

Address descriptor

+

{{ _("Address descriptor") }}


- Show raw public keys  + {{ _("Show raw public keys") }} 

-
${descriptor.descriptor}
+
${descriptor.descriptor}
`; self.info.innerHTML = addressInfoHTML; self.note.innerText = ""; self.info.querySelector('.descriptor-switch').onchange = (e) => { if (e.target.checked) { - self.info.querySelector(".descriptor").innerHTML = `${descriptor.descriptor}`; + self.info.querySelector(".descriptor").innerHTML = `${descriptor.descriptor}`; } else { - self.info.querySelector(".descriptor").innerHTML = `${descriptor.xpubs_descriptor}`; + self.info.querySelector(".descriptor").innerHTML = `${descriptor.xpubs_descriptor}`; } } return; } - self.note.innerText = "Failed to load address details..."; + self.note.innerText = '{{ _("Failed to load address details...") }}'; } catch(e) { - self.note.innerText = "Failed to load address details..."; + self.note.innerText = '{{ _("Failed to load address details...") }}'; console.error(e); } } diff --git a/src/cryptoadvance/specter/templates/includes/address-label.html b/src/cryptoadvance/specter/templates/includes/address-label.html index 8776f5993..c7b63801a 100644 --- a/src/cryptoadvance/specter/templates/includes/address-label.html +++ b/src/cryptoadvance/specter/templates/includes/address-label.html @@ -60,10 +60,10 @@
- Fetching address label... + {{ _("Fetching address label...") }} - - + +
@@ -154,7 +154,7 @@ this.label.innerText = this.address } } else { - showError('Failed to update address label. Please refresh the page and try again.') + showError('{{ _("Failed to update address label. Please refresh the page and try again.") }}') } } @@ -195,7 +195,7 @@ self.explorerLink.onclick = () => {return true;} } else { self.explorerLink.onclick = () => { - copyText(self.address, `Copied address: ${ self.address }`); + copyText(self.address, `{{ _("Copied address") }}: ${ self.address }`); } } } @@ -231,10 +231,10 @@ } return; } - showError('Failed to fetch data. Please refresh the page and retry.'); + showError('{{ _("Failed to fetch data. Please refresh the page and retry.") }}'); } catch(e) { - console.log("Caught error fetching address label: ", e); - showError('Failed to fetch data. Please refresh the page and retry.'); + console.log('{{ _("Caught error fetching address label") }}: ', e); + showError('{{ _("Failed to fetch data. Please refresh the page and retry.") }}'); } } diff --git a/src/cryptoadvance/specter/templates/includes/address-row.html b/src/cryptoadvance/specter/templates/includes/address-row.html index 96fc15cd2..80abde8c6 100644 --- a/src/cryptoadvance/specter/templates/includes/address-row.html +++ b/src/cryptoadvance/specter/templates/includes/address-row.html @@ -19,7 +19,7 @@ - + @@ -111,9 +111,9 @@ displayAddressOnDevice(this.addressData.address, JSON.stringify(descriptor)); return; } - showError("Failed to load address data to display..."); + showError('{{ _("Failed to load address data to display...") }}'); } catch(e) { - showError("Failed to load address data to display..."); + showError('{{ _("Failed to load address data to display...") }}'); showError(e); } } diff --git a/src/cryptoadvance/specter/templates/includes/addresses-table.html b/src/cryptoadvance/specter/templates/includes/addresses-table.html index 826d8f803..de708943a 100644 --- a/src/cryptoadvance/specter/templates/includes/addresses-table.html +++ b/src/cryptoadvance/specter/templates/includes/addresses-table.html @@ -95,16 +95,16 @@
- Page
@@ -113,7 +113,7 @@ {% include "includes/page-limit-select.html" %}
@@ -137,28 +137,28 @@ - - - - {% if supports_hwi != [] and (supports_hwi_multisig_display_address != [] or not wallet.is_multisig) %} {% endif %} - + @@ -402,11 +402,11 @@ async function fetchAddressesItems(self) { self.callId++; // Clean up from existing addresses list - self.emptyRow.children[1].innerText = "Fetching addresses..."; + self.emptyRow.children[1].innerText = '{{ _("Fetching addresses...") }}'; self.emptyRow.classList.remove('hidden'); self.tbody.querySelectorAll('address-row').forEach((row) => { row.remove() }); if (!self.listType) { - self.emptyRow.children[1].innerText = "Failed to fetch addresses..."; + self.emptyRow.children[1].innerText = '{{ _("Failed to fetch addresses...") }}'; return } @@ -416,9 +416,9 @@ self.export.href += `?onlyCurrentType=${self.onlyCurrentTypeSwitch.checked}&addressType=${self.listType}&sortby=${self.sortby}&sortdir=${self.sortdir}`; if (self.listType == "receive") { - self.switchText.innerText = "Only receive addresses: " + self.switchText.innerText = '{{ _("Only receive addresses") }}: ' } else if (self.listType == "change") { - self.switchText.innerText = "Only change addresses: " + self.switchText.innerText = '{{ _("Only change addresses") }}: ' } else { self.switchText.innerText = ""; } @@ -478,7 +478,7 @@ // Show empty row if no addresses found if (self.pageCount == 0 || addressesList.length == 0) { self.emptyRow.classList.remove('hidden'); - self.emptyRow.children[1].innerText = "No addresses found..."; + self.emptyRow.children[1].innerText = '{{ _("No addresses found...") }}'; self.pageCount = 1; } else { self.emptyRow.classList.add('hidden'); @@ -517,10 +517,10 @@ } return; } - showError('Failed to fetch addresses list.') + showError('{{ _("Failed to fetch addresses list") }}') } catch (e) { console.log("Caught error: ", e); - showError(`Failed to fetch addresses list: ${e}`); + showError(`{{ _("Failed to fetch addresses list") }}: ${e}`); } } @@ -547,7 +547,7 @@ `; showPageOverlay('address-popup'); } else { - copyText(address, `Copied address: ${ address }`); + copyText(address, `{{ _("Copied address") }}: ${ address }`); } } diff --git a/src/cryptoadvance/specter/templates/includes/hwi/components/passphrase.jinja b/src/cryptoadvance/specter/templates/includes/hwi/components/passphrase.jinja index 9f13f16e8..62b2fd730 100644 --- a/src/cryptoadvance/specter/templates/includes/hwi/components/passphrase.jinja +++ b/src/cryptoadvance/specter/templates/includes/hwi/components/passphrase.jinja @@ -1,5 +1,5 @@
Address
+
{{ _("Address") }}
Label
+
{{ _("Label") }}
Used
+
{{ _("Used") }}
UTXO
Amount
+
{{ _("Amount") }}
- +
Fetching addresses ...{{ _("Fetching addresses...") }}