From b21bd128bf6594a579e146ff779bd98770a19e25 Mon Sep 17 00:00:00 2001 From: Tony Giorgio Date: Mon, 18 Mar 2024 23:31:37 -0500 Subject: [PATCH 01/40] Add android play build from gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bd506fa9..e11d0c24 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ node_modules dist dist-ssr *.local +android/app/play/* # Editor directories and files .vscode/* @@ -32,4 +33,4 @@ dev-dist /playwright-report/ /playwright/.cache/ -.env \ No newline at end of file +.env From 146f87a960d67ec05d89737b16216d7b9d11fe58 Mon Sep 17 00:00:00 2001 From: Tony Giorgio Date: Mon, 18 Mar 2024 23:36:44 -0500 Subject: [PATCH 02/40] Remove part of the federation warning --- src/i18n/en/translations.ts | 2 +- src/i18n/es/translations.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/en/translations.ts b/src/i18n/en/translations.ts index f93b0fd8..032f5bc2 100644 --- a/src/i18n/en/translations.ts +++ b/src/i18n/en/translations.ts @@ -567,7 +567,7 @@ export default { expires: "Expires", federation_id: "Federation ID", description: - "Mutiny has experimental support for the Fedimint protocol. You'll need a federation invite code to use this feature. These funds are currently not backed up remotely. Store funds in a federation at your own risk!", + "Mutiny has experimental support for the Fedimint protocol. You'll need a federation invite code to use this feature. Store funds in a federation at your own risk!", learn_more: "Learn more about Fedimint." }, gift: { diff --git a/src/i18n/es/translations.ts b/src/i18n/es/translations.ts index 34ab5dfa..83841d33 100644 --- a/src/i18n/es/translations.ts +++ b/src/i18n/es/translations.ts @@ -566,7 +566,7 @@ export default { expires: "Expira", federation_id: "ID federación", description: - "Mutiny tiene soporte experimental para el protocolo Fedimint. Necesitará un código de invitación a la federación para poder usar esta funcionalidad. Estos fondos no están actualmente respaldados remotamente ¡Almacene fondos en una federación bajo su propio riesgo!", + "Mutiny tiene soporte experimental para el protocolo Fedimint. Necesitará un código de invitación a la federación para poder usar esta funcionalidad ¡Almacene fondos en una federación bajo su propio riesgo!", learn_more: "Aprenda más sobre Fedimint." }, gift: { From e1843e6493eacfe94c3dad026a07f7b339264e29 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 7 Mar 2024 15:38:40 -0600 Subject: [PATCH 03/40] refactor translations for easier editing --- .eslintrc.cjs | 10 +- README.md | 33 +- justfile | 4 - package.json | 5 +- pnpm-lock.yaml | 51 +- public/i18n/en.json | 694 +++++++++++++ public/i18n/es.json | 664 ++++++++++++ public/i18n/ko.json | 468 +++++++++ public/i18n/pt.json | 21 + src/i18n/config.ts | 73 +- src/i18n/en/translations.ts | 767 -------------- src/i18n/es/translations.ts | 766 -------------- src/i18n/i18next.d.ts | 9 - src/i18n/ko/translations.ts | 514 ---------- src/i18n/pt/translations.ts | 21 - tools/internal-rules/.eslintrc.js | 19 - tools/internal-rules/lib/index.js | 18 - .../lib/rules/check-i18n-keys.js | 98 -- tools/internal-rules/package.json | 32 - tools/internal-rules/pnpm-lock.yaml | 961 ------------------ 20 files changed, 1909 insertions(+), 3319 deletions(-) create mode 100644 public/i18n/en.json create mode 100644 public/i18n/es.json create mode 100644 public/i18n/ko.json create mode 100644 public/i18n/pt.json delete mode 100644 src/i18n/en/translations.ts delete mode 100644 src/i18n/es/translations.ts delete mode 100644 src/i18n/i18next.d.ts delete mode 100644 src/i18n/ko/translations.ts delete mode 100644 src/i18n/pt/translations.ts delete mode 100644 tools/internal-rules/.eslintrc.js delete mode 100644 tools/internal-rules/lib/index.js delete mode 100644 tools/internal-rules/lib/rules/check-i18n-keys.js delete mode 100644 tools/internal-rules/package.json delete mode 100644 tools/internal-rules/pnpm-lock.yaml diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 6d34b24d..f5d33038 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -20,13 +20,7 @@ module.exports = { rules: { "@typescript-eslint/no-var-requires": "off" // Disable this specific rule for CJS files } - }, - { - files: ['src/i18n/**/translations.ts'], - rules: { - "internal-rules/check-i18n-keys": "off" //Disabled so no warnings are presented everytime pre-commit is run - } - }, + } ], parser: "@typescript-eslint/parser", parserOptions: { @@ -38,7 +32,7 @@ module.exports = { jsx: true } }, - plugins: ["@typescript-eslint", "solid", "import", "internal-rules"], + plugins: ["@typescript-eslint", "solid", "import"], rules: { "@typescript-eslint/no-unused-vars": [ "warn", diff --git a/README.md b/README.md index e5722d71..ea1589a2 100644 --- a/README.md +++ b/README.md @@ -131,20 +131,18 @@ just i18n $lang ### Adding new languages or keys -1. In `src/i18n/` locate your desired language folder or create one if one does not exist +1. In `public/i18n/` locate your desired language .json file or create one if one does not exist - - When creating a new language dir ensure it follows the ISO 639 2-letter standard + - When creating a new language file ensure it follows the ISO 639 2-letter standard -2. In this folder create a file called `translations.ts`, this is where the translation keys for your desired language will be located +2. Populate your translation file with a translation object where all of the keys will be located -3. Populate your translation file with a translation object where all of the keys will be located - -If you want to add Japanese you will create a file `/src/i18n/jp/translations.ts` and populate it with keys like so: +If you want to add Japanese you will create a file `/public/i18n/jp.json` and populate it with keys like so: ``` -export default { - common: { - continue: "続ける", +{ + "common": { + "continue": "続ける", ... } } @@ -152,20 +150,9 @@ export default { (You should compare your translations against the English language as all other languages are not the master and are likely deprecated) -4. Add your new translation file to the `/src/i18n/config.ts` so you can begin to see them in the app - -``` -import fa from "~/i18n/jp/translations.ts" - -export const resources: { - ... - jp: { - translations: jp - } -} -``` +If you're using VS Code there are some nice extensions that can make this easier like i18n-ally and i18n-json-editor -5. Add your language to the `Language` object in `/src/utils/languages.ts`. This will allow you to select the language via the language selector in the UI. If your desired language is set as your primary language in your browser it will be selected automatically +3. Add your language to the `Language` object in `/src/utils/languages.ts`. This will allow you to select the language via the language selector in the UI. If your desired language is set as your primary language in your browser it will be selected automatically ``` export const LANGUAGE_OPTIONS: Language[] = [ @@ -175,4 +162,4 @@ export const LANGUAGE_OPTIONS: Language[] = [ }, ``` -6. That's it! You should now be able to see your translation keys populating the app in your desired language. When youre ready go ahead and open a PR to have you language merged for others! +4. That's it! You should now be able to see your translation keys populating the app in your desired language. When youre ready go ahead and open a PR to have you language merged for others! diff --git a/justfile b/justfile index a91b17ae..70615194 100644 --- a/justfile +++ b/justfile @@ -6,10 +6,6 @@ dev: pre: pnpm run pre-commit -i18n LANG: - #!/usr/bin/env bash - pnpm eslint-path "./src/i18n/{{LANG}}/translations.ts" --rule "{internal-rules/check-i18n-keys: warn}" - local: pnpm install && pnpm link --global "@mutinywallet/mutiny-wasm" diff --git a/package.json b/package.json index 376322c7..7ef5382e 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "check-types": "tsc --noemit", "eslint": "eslint src", "eslint-path": "eslint", - "check-i18n-keys": "eslint src/i18n/**/translations.ts --rule \"{internal-rules/check-i18n-keys: warn}\"", "pre-commit": "pnpm eslint && pnpm run check-types && pnpm run format", "format": "prettier --write \"{.,src/**,e2e/**}/*.{ts,tsx,js,jsx,json,css,scss,md}\"", "check-format": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css,scss,md}\"" @@ -28,7 +27,6 @@ "eslint": "^8.52.0", "eslint-import-resolver-typescript": "2.7.1", "eslint-plugin-import": "2.27.5", - "eslint-plugin-internal-rules": "file:tools/internal-rules", "eslint-plugin-prettier": "4.2.1", "eslint-plugin-solid": "0.13.0", "postcss": "^8.4.31", @@ -43,6 +41,7 @@ "workbox-window": "^7.0.0" }, "dependencies": { + "i18next-http-backend": "^2.5.0", "@capacitor-mlkit/barcode-scanning": "^5.3.0", "@capacitor/android": "^5.5.1", "@capacitor/app": "^5.0.6", @@ -63,7 +62,7 @@ "@solid-primitives/upload": "^0.0.111", "@solidjs/meta": "^0.29.1", "@solidjs/router": "^0.9.0", - "i18next": "^22.5.1", + "i18next": "^23.10.1", "i18next-browser-languagedetector": "^7.1.0", "qr-scanner": "^1.4.2", "solid-js": "^1.8.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 14b7f1fc..54b861dd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -69,11 +69,14 @@ importers: specifier: ^0.9.0 version: 0.9.0(solid-js@1.8.5) i18next: - specifier: ^22.5.1 - version: 22.5.1 + specifier: ^23.10.1 + version: 23.10.1 i18next-browser-languagedetector: specifier: ^7.1.0 version: 7.2.0 + i18next-http-backend: + specifier: ^2.5.0 + version: 2.5.0 qr-scanner: specifier: ^1.4.2 version: 1.4.2 @@ -120,9 +123,6 @@ importers: eslint-plugin-import: specifier: 2.27.5 version: 2.27.5(@typescript-eslint/parser@6.9.1)(eslint-import-resolver-typescript@2.7.1)(eslint@8.52.0) - eslint-plugin-internal-rules: - specifier: file:tools/internal-rules - version: file:tools/internal-rules(eslint@8.52.0) eslint-plugin-prettier: specifier: 4.2.1 version: 4.2.1(eslint@8.52.0)(prettier@3.0.3) @@ -6775,6 +6775,14 @@ packages: - encoding dev: true + /cross-fetch@4.0.0: + resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + dependencies: + node-fetch: 2.6.12 + transitivePeerDependencies: + - encoding + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -9014,8 +9022,16 @@ packages: '@babel/runtime': 7.23.2 dev: false - /i18next@22.5.1: - resolution: {integrity: sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==} + /i18next-http-backend@2.5.0: + resolution: {integrity: sha512-Z/aQsGZk1gSxt2/DztXk92DuDD20J+rNudT7ZCdTrNOiK8uQppfvdjq9+DFQfpAnFPn3VZS+KQIr1S/W1KxhpQ==} + dependencies: + cross-fetch: 4.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /i18next@23.10.1: + resolution: {integrity: sha512-NDiIzFbcs3O9PXpfhkjyf7WdqFn5Vq6mhzhtkXzj51aOcNuPNcTwuYNuXCpHsanZGHlHKL35G7huoFeVic1hng==} dependencies: '@babel/runtime': 7.23.2 dev: false @@ -10336,7 +10352,6 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 - dev: true /node-html-parser@5.4.2: resolution: {integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==} @@ -11568,11 +11583,6 @@ packages: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} dev: true - /requireindex@1.2.0: - resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} - engines: {node: '>=0.10.5'} - dev: true - /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -12781,7 +12791,6 @@ packages: /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true /tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} @@ -13459,7 +13468,6 @@ packages: /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true /webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} @@ -13519,7 +13527,6 @@ packages: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: true /whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} @@ -13942,15 +13949,3 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: true - - file:tools/internal-rules(eslint@8.52.0): - resolution: {directory: tools/internal-rules, type: directory} - id: file:tools/internal-rules - name: eslint-plugin-internal-rules - engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} - peerDependencies: - eslint: '>=7' - dependencies: - eslint: 8.52.0 - requireindex: 1.2.0 - dev: true diff --git a/public/i18n/en.json b/public/i18n/en.json new file mode 100644 index 00000000..7cc74f2e --- /dev/null +++ b/public/i18n/en.json @@ -0,0 +1,694 @@ +{ + "common": { + "title": "Mutiny Wallet", + "mutiny": "Mutiny", + "nice": "Nice", + "home": "Home", + "e_sats": "eSATS", + "e_sat": "eSAT", + "sats": "SATS", + "sat": "SAT", + "scan": "Scan", + "fee": "Fee", + "send": "Send", + "receive": "Receive", + "request": "Request", + "dangit": "Dangit", + "back": "Back", + "coming_soon": "(coming soon)", + "copy": "Copy", + "copied": "Copied", + "continue": "Continue", + "error_unimplemented": "Unimplemented", + "why": "Why?", + "private_tags": "Private tags", + "view_transaction": "View transaction", + "view_payment_details": "View payment details", + "pending": "Pending", + "error_safe_mode": "Mutiny is running in safe mode. Lightning is disabled.", + "self_hosted": "Self-hosted" + }, + "home": { + "receive": "Receive your first sats", + "find": "Find your friends on nostr", + "backup": "Secure your funds!", + "connection": "Create a wallet connection", + "federation": "Join a federation" + }, + "profile": { + "nostr_identity": "Nostr Identity", + "add_lightning_address": "Add Lightning Address", + "edit_profile": "Edit Profile" + }, + "chat": { + "prompt": "This is a new conversation. Try asking for money!", + "placeholder": "Message" + }, + "contacts": { + "new": "new", + "add_contact": "Add Contact", + "new_contact": "New Contact", + "create_contact": "Create contact", + "edit_contact": "Edit contact", + "save_contact": "Save contact", + "delete": "Delete", + "confirm_delete": "Are you sure you want to delete this contact?", + "payment_history": "Payment history", + "no_payments": "No payments yet with", + "edit": "Edit", + "pay": "Pay", + "name": "Name", + "ln_address": "Lightning Address", + "placeholder": "Satoshi", + "lightning_address": "Lightning Address", + "unimplemented": "Unimplemented", + "not_available": "We don't do that yet", + "error_name": "We at least need a name", + "email_error": "That doesn't look like a lightning address", + "npub_error": "That doesn't look like a nostr npub", + "error_ln_address_missing": "New contacts need a lightning address", + "npub": "Nostr Npub", + "link_to_nostr_sync": "Import Nostr Contacts" + }, + "redeem": { + "redeem_bitcoin": "Redeem Bitcoin", + "lnurl_amount_message": "Enter withdrawal amount between {{min}} and {{max}} sats", + "lnurl_redeem_failed": "Withdrawal Failed", + "lnurl_redeem_success": "Payment Received" + }, + "request": { + "request_bitcoin": "Request Bitcoin", + "request": "Request" + }, + "receive": { + "receive_bitcoin": "Receive Bitcoin", + "edit": "Edit", + "checking": "Checking", + "choose_format": "Choose format", + "payment_received": "Payment Received", + "payment_initiated": "Payment Initiated", + "receive_add_the_sender": "Add the sender for your records", + "keep_mutiny_open": "Keep Mutiny open to complete the payment.", + "choose_payment_format": "Choose payment format", + "unified_label": "Unified", + "unified_caption": "Combines a bitcoin address and a lightning invoice. Sender chooses payment method.", + "lightning_label": "Lightning invoice", + "lightning_caption": "Ideal for small transactions. Usually lower fees than on-chain.", + "onchain_label": "Bitcoin address", + "onchain_caption": "On-chain, just like Satoshi did it. Ideal for very large transactions.", + "unified_setup_fee": "A lightning setup fee of {{amount}} SATS will be charged if paid over lightning.", + "lightning_setup_fee": "A lightning setup fee of {{amount}} SATS will be charged for this receive.", + "amount": "Amount", + "fee": "+ Fee", + "total": "Total", + "spendable": "Spendable", + "channel_size": "Channel size", + "channel_reserve": "- Channel reserve", + "error_under_min_lightning": "Defaulting to On-chain. Amount is too small for your initial Lightning receive.", + "error_creating_unified": "Defaulting to On-chain. Something went wrong when creating the unified address", + "error_creating_address": "Something went wrong when creating the on-chain address", + "amount_editable": { + "receive_too_small": "A lightning setup fee might be deducted from the requested amount.", + "setup_fee_lightning": "A lightning setup fee will be charged if paid over lightning.", + "more_than_21m": "There are only 21 million bitcoin.", + "set_amount": "Set amount", + "max": "MAX", + "fix_amounts": { + "ten_k": "10k", + "one_hundred_k": "100k", + "one_million": "1m" + }, + "del": "DEL", + "balance": "Balance" + }, + "integrated_qr": { + "onchain": "On-chain", + "lightning": "Lightning", + "unified": "Unified", + "gift": "Lightning Gift" + }, + "remember_choice": "Remember my choice next time", + "what_for": "What's this for?" + }, + "send": { + "search": { + "placeholder": "Name, address, invoice", + "paste": "Paste", + "contacts": "Contacts", + "global_search": "Global search", + "no_results": "No results found for" + }, + "sending": "Sending...", + "confirm_send": "Confirm Send", + "contact_placeholder": "Add the receiver for your records", + "start_over": "Start Over", + "send_bitcoin": "Send Bitcoin", + "paste": "Paste", + "scan_qr": "Scan QR", + "payment_initiated": "Payment Initiated", + "payment_sent": "Payment Sent", + "destination": "Destination", + "no_payment_info": "No payment info", + "progress_bar": { + "of": "of", + "sats_sent": "sats sent" + }, + "what_for": "What's this for?", + "zap_note": "Zap note", + "error_low_balance": "We do not have enough balance to pay the given amount.", + "error_invoice_match": "Amount requested, {{amount}} SATS, does not equal amount set.", + "error_channel_reserves": "Not enough available funds.", + "error_address": "Invalid Lightning Address", + "error_channel_reserves_explained": "A portion of your channel balance is reserved for fees. Try sending a smaller amount or adding funds.", + "error_clipboard": "Clipboard not supported", + "error_keysend": "Keysend failed", + "error_LNURL": "LNURL Pay failed", + "error_expired": "Invoice is expired", + "payjoin_send": "This is a payjoin! The Mutiny will continue until privacy improves", + "payment_pending": "Payment pending", + "payment_pending_description": "It's taking a while, but it's possible this payment may still go through. Please check 'Activity' for the current status.", + "hodl_invoice_warning": "This is a hodl invoice. Payments to hodl invoices can cause channel force closes, which results in high on-chain fees. Pay at your own risk!", + "private": "Private", + "anonzap": "Anon Zap" + }, + "feedback": { + "header": "Give us feedback!", + "received": "Feedback received!", + "thanks": "Thank you for letting us know what's going on.", + "more": "Got more to say?", + "tracking": "Mutiny doesn't track or spy on your behavior, so your feedback is incredibly helpful.", + "github": "We will not respond to this feedback. If you'd like support please", + "create_issue": "create a GitHub issue.", + "link": "Feedback?", + "feedback_placeholder": "Bugs, feature requests, feedback, etc.", + "info_label": "Include contact info", + "info_caption": "If you need us to follow-up on this issue", + "email": "Email", + "email_caption": "Burners welcome", + "nostr": "Nostr", + "nostr_caption": "Your freshest npub", + "nostr_label": "Nostr npub or NIP-05", + "send_feedback": "Send Feedback", + "invalid_feedback": "Please say something!", + "need_contact": "We need some way to contact you", + "invalid_email": "That doesn't look like an email address to me", + "error": "Error submitting feedback {{error}}", + "try_again": "Please try again later." + }, + "activity": { + "title": "Activity", + "mutiny": "Mutiny", + "wallet": "Wallet", + "nostr": "Nostr", + "view_all": "View all", + "receive_some_sats_to_get_started": "Receive some sats to get started", + "channel_open": "Channel Open", + "channel_close": "Channel Close", + "unknown": "Unknown", + "import_contacts": "Import your contacts from nostr to see who they're zapping.", + "coming_soon": "Coming soon", + "private": "Private", + "anonymous": "Anonymous", + "from": "From:", + "transaction_details": { + "lightning_receive": "Received via Lightning", + "lightning_send": "Sent via Lightning", + "channel_open": "Channel open", + "channel_close": "Channel close", + "onchain_receive": "On-chain receive", + "onchain_send": "On-chain send", + "paid": "Paid", + "unpaid": "Unpaid", + "status": "Status", + "date": "Date", + "tagged_to": "Tagged to", + "description": "Description", + "fee": "Fee", + "onchain_fee": "On-chain Fee", + "invoice": "Invoice", + "payment_hash": "Payment Hash", + "payment_preimage": "Preimage", + "txid": "Txid", + "total": "Amount Requested", + "balance": "Balance", + "reserve": "Reserve", + "peer": "Peer", + "channel_id": "Channel ID", + "reason": "Reason", + "confirmed": "Confirmed", + "unconfirmed": "Unconfirmed", + "sweep_delay": "Funds may take a few days to be swept back into the wallet", + "no_details": "No channel details found, which means this channel has likely been closed.", + "back_home": "back home" + } + }, + "scanner": { + "paste": "Paste Something", + "cancel": "Cancel" + }, + "settings": { + "header": "Settings", + "support": "Learn how to support Mutiny", + "experimental_features": "Experiments", + "debug_tools": "DEBUG TOOLS", + "danger_zone": "Danger zone", + "general": "General", + "version": "Version:", + "admin": { + "title": "Admin Page", + "caption": "Our internal debug tools. Use wisely!", + "header": "Secret Debug Tools", + "warning_one": "If you know what you're doing you're in the right place.", + "warning_two": "These are internal tools we use to debug and test the app. Please be careful!", + "kitchen_sink": { + "disconnect": "Disconnect", + "peers": "Peers", + "no_peers": "No peers", + "refresh_peers": "Refresh Peers", + "connect_peer": "Connect Peer", + "expect_a_value": "Expecting a value...", + "connect": "Connect", + "close_channel": "Close Channel", + "force_close": "Force close Channel", + "abandon_channel": "Abandon Channel", + "confirm_close_channel": "Are you sure you want to close this channel?", + "confirm_force_close": "Are you sure you want to force close this channel? Your funds will take a few days to redeem on chain.", + "confirm_abandon_channel": "Are you sure you want to abandon this channel? Typically only do this if the opening transaction will never confirm. Otherwise, you will lose funds.", + "channels": "Channels", + "no_channels": "No Channels", + "refresh_channels": "Refresh Channels", + "pubkey": "Pubkey", + "amount": "Amount", + "open_channel": "Open Channel", + "nodes": "Nodes", + "no_nodes": "No nodes", + "enable_zaps_to_hodl": "Enable zaps to hodl invoices?", + "zaps_to_hodl_desc": "Zaps to hodl invoices can result in channel force closes, which results in high on-chain fees. Use at your own risk!", + "zaps_to_hodl_enable": "Enable hodl zaps", + "zaps_to_hodl_disable": "Disable hodl zaps" + } + }, + "backup": { + "title": "Backup", + "secure_funds": "Let's get these funds secured.", + "twelve_words_tip": "We'll show you 12 words. You write down the 12 words.", + "warning_one": "If you clear your browser history, or lose your device, these 12 words are the only way you can restore your wallet.", + "warning_two": "Mutiny is self-custodial. It's all up to you...", + "confirm": "I wrote down the words", + "responsibility": "I understand that my funds are my responsibility", + "liar": "I'm not lying just to get this over with", + "seed_words": { + "reveal": "TAP TO REVEAL SEED WORDS", + "hide": "HIDE", + "copy": "Dangerously Copy to Clipboard", + "copied": "Copied!" + } + }, + "channels": { + "title": "Lightning Channels", + "outbound": "Outbound", + "inbound": "Inbound", + "reserve": "Reserve", + "have_channels": "You have", + "have_channels_one": "lightning channel.", + "have_channels_many": "lightning channels.", + "inbound_outbound_tip": "Outbound is the amount of money you can spend on lightning. Inbound is the amount you can receive without incurring a lightning service fee.", + "reserve_tip": "About 1% of your channel balance is reserved on lightning for fees. Additional reserves are required for channels you opened via swap.", + "no_channels": "It looks like you don't have any channels yet. To get started, receive some sats over lightning, or swap some on-chain funds into a channel. Get your hands dirty!", + "close_channel": "Close", + "online_channels": "Online Channels", + "offline_channels": "Offline Channels", + "close_channel_confirm": "Closing this channel will move the balance on-chain and incur an on-chain fee." + }, + "connections": { + "title": "Wallet Connections", + "error_name": "Name cannot be empty", + "error_connection": "Failed to create Wallet Connection", + "error_budget_zero": "Budget must be greater than zero", + "add_connection": "Add Connection", + "manage_connections": "Manage Connections", + "manage_gifts": "Manage Gifts", + "delete_connection": "Delete", + "new_connection": "New Connection", + "edit_connection": "Edit Connection", + "new_connection_label": "Name", + "new_connection_placeholder": "My favorite nostr client...", + "create_connection": "Create Connection", + "save_connection": "Save Changes", + "edit_budget": "Edit Budget", + "open_app": "Open App", + "open_in_nostr_client": "Open in Nostr Client", + "open_in_primal": "Open in Primal", + "nostr_client_not_found": "Nostr client not found", + "client_not_found_description": "Install a nostr client like Primal, Amethyst, or Damus to open this link.", + "relay": "Relay", + "authorize": "Authorize external services to request payments from your wallet. Pairs great with Nostr clients.", + "pending_nwc": { + "title": "Pending Requests", + "approve_all": "Approve All", + "deny_all": "Deny All" + }, + "careful": "Be careful where you share this connection! Requests within budget will paid automatically.", + "spent": "Spent", + "remaining": "Remaining", + "confirm_delete": "Are you sure you want to delete this connection?", + "budget": "Budget", + "resets_every": "Resets every", + "resubscribe_date": "Resubscribe on" + }, + "emergency_kit": { + "title": "Emergency Kit", + "caption": "Diagnose and solve problems with your wallet.", + "emergency_tip": "If your wallet seems broken, here are some tools to try to debug and repair it.", + "questions": "If you have any questions on what these buttons do, please", + "link": "reach out to us for support.", + "import_export": { + "title": "Export wallet state", + "error_password": "Password is required", + "error_read_file": "File read error", + "error_no_text": "No text found in file", + "tip": "You can export your entire Mutiny Wallet state to a file and import it into a new browser. It usually works!", + "caveat_header": "Important caveats:", + "caveat": "after exporting don't do any operations in the original browser. If you do, you'll need to export again. After a successful import, a best practice is to clear the state of the original browser just to make sure you don't create conflicts.", + "save_state": "Save State As File", + "import_state": "Import State From File", + "confirm_replace": "Do you want to replace your state with", + "password": "Enter your password to decrypt", + "decrypt_wallet": "Decrypt Wallet" + }, + "logs": { + "title": "Download debug logs", + "something_screwy": "Something screwy going on? Check out the logs!", + "download_logs": "Download Logs", + "password": "Enter your password to decrypt", + "confirm_password_label": "Confirm Password" + }, + "delete_everything": { + "delete": "Delete Everything", + "confirm": "This will delete your node's state. This can't be undone!", + "deleted": "Deleted", + "deleted_description": "Deleted all data" + } + }, + "encrypt": { + "title": "Change Password", + "caption": "Backup first to unlock encryption", + "header": "Encrypt your seed words", + "hot_wallet_warning": "Mutiny is a \"hot wallet\" so it needs your seed word to operate, but you can optionally encrypt those words with a password.", + "password_tip": "That way, if someone gets access to your browser, they still won't have access to your funds.", + "optional": "(optional)", + "existing_password": "Existing password", + "existing_password_caption": "Leave blank if you haven't set a password yet.", + "new_password_label": "Password", + "new_password_placeholder": "Enter a password", + "new_password_caption": "This password will be used to encrypt your seed words. If you forget it, you will need to re-enter your seed words to access your funds. You did write down your seed words, right?", + "confirm_password_label": "Confirm Password", + "confirm_password_placeholder": "Enter the same password", + "encrypt": "Encrypt", + "skip": "Skip", + "error_match": "Passwords do not match", + "error_same_as_existingpassword": "New password must not match existing password" + }, + "decrypt": { + "title": "Enter your password", + "decrypt_wallet": "Decrypt Wallet", + "forgot_password_link": "Forgot Password?", + "error_wrong_password": "Invalid Password" + }, + "currency": { + "title": "Currency", + "caption": "Choose your preferred currency pair", + "select_currency": "Select Currency", + "select_currency_label": "Currency Pair", + "select_currency_caption": "Choosing a new currency will resync the wallet to fetch a price update", + "request_currency_support_link": "Request support for more currencies", + "error_unsupported_currency": "Please Select a supported currency." + }, + "language": { + "title": "Language", + "caption": "Choose your preferred language", + "select_language": "Select Language", + "select_language_label": "Language", + "select_language_caption": "Choosing a new currency will change the wallet language, ignoring current browser language", + "request_language_support_link": "Request support for more languages", + "error_unsupported_language": "Please Select a supported language." + }, + "lnurl_auth": { + "title": "LNURL Auth", + "auth": "Auth", + "expected": "Expecting something like LNURL..." + }, + "plus": { + "title": "Mutiny+", + "join": "Join", + "sats_per_month": "for {{amount}} sats a month.", + "lightning_balance": "You'll need at least {{amount}} sats in your lightning balance to get started. Try before you buy!", + "restore": "Restore Subscription", + "ready_to_join": "Ready to join", + "click_confirm": "Click confirm to pay for your first month.", + "open_source": "Mutiny is open source and self-hostable.", + "optional_pay": "But also you can pay for it.", + "paying_for": "Paying for", + "supports_dev": "helps support ongoing development and unlocks early access to new features and premium functionality:", + "thanks": "You're part of the mutiny! Enjoy the following perks:", + "renewal_time": "You'll get a renewal payment request around", + "cancel": "To cancel your subscription just don't pay. You can also disable the Mutiny+", + "wallet_connection": "Wallet Connection.", + "subscribe": "Subscribe", + "error_no_plan": "No plans found", + "error_failure": "Couldn't subscribe", + "error_no_subscription": "No existing subscription found", + "error_expired_subscription": "Your subscription has expired, click join to renew", + "satisfaction": "Smug satisfaction", + "gifting": "Gifting", + "multi_device": "Multi-device access", + "ios_testflight": "iOS TestFlight access", + "more": "... and more to come", + "cta_description": "Enjoy early access to new features and premium functionality.", + "cta_but_already_plus": "Thank you for your support!" + }, + "restore": { + "title": "Restore", + "all_twelve": "You need to enter all 12 words", + "wrong_word": "Wrong word", + "paste": "Dangerously Paste from Clipboard", + "confirm_text": "Are you sure you want to restore to this wallet? Your existing wallet will be deleted!", + "restore_tip": "You can restore an existing Mutiny Wallet from your 12 word seed phrase. This will replace your existing wallet, so make sure you know what you're doing!", + "multi_browser_warning": "Do not use on multiple browsers at the same time.", + "error_clipboard": "Clipboard not supported", + "error_word_number": "Wrong number of words", + "error_invalid_seed": "Invalid seed phrase" + }, + "servers": { + "title": "Servers", + "caption": "Don't trust us! Use your own servers to back Mutiny.", + "link": "Learn more about self-hosting", + "proxy_label": "Websockets Proxy", + "proxy_caption": "How your lightning node communicates with the rest of the network.", + "error_proxy": "Should be a url starting with wss://", + "esplora_label": "Esplora", + "esplora_caption": "Block data for on-chain information.", + "error_esplora": "That doesn't look like a URL", + "rgs_label": "RGS", + "rgs_caption": "Rapid Gossip Sync. Network data about the lightning network used for routing.", + "error_rgs": "That doesn't look like a URL", + "lsp_label": "LSP", + "lsp_caption": "Lightning Service Provider. Automatically opens channels to you for inbound liquidity. Also wraps invoices for privacy.", + "lsps_connection_string_label": "LSPS Connection String", + "lsps_connection_string_caption": "Lightning Service Provider. Automatically opens channels to you for inbound liquidity. Using LSP specification.", + "error_lsps_connection_string": "That doesn't look like node connection string", + "lsps_token_label": "LSPS Token", + "lsps_token_caption": "LSPS Token. Used to identify what wallet is connecting to the LSP", + "lsps_valid_error": "You can either have just an LSP set or LSPS Connection String and LSPS Token set, not both.", + "error_lsps_token": "That doesn't look like a valid token", + "storage_label": "Storage", + "storage_caption": "Encrypted VSS backup service.", + "error_lsp": "That doesn't look like a URL", + "save": "Save" + }, + "nostr_contacts": { + "title": "Sync Nostr Contacts", + "npub_label": "Nostr npub", + "npub_required": "Npub can't be blank", + "sync": "Sync", + "resync": "Resync", + "remove": "Remove" + }, + "manage_federations": { + "title": "Manage Federations", + "federation_code_label": "Federation code", + "federation_code_required": "Federation code can't be blank", + "federation_added_success": "Federation added successfully", + "federation_remove_confirm": "Are you sure you want to remove this federation? Make sure any funds you have are transferred to your lightning balance or another wallet first.", + "add": "Add", + "remove": "Remove", + "expires": "Expires", + "federation_id": "Federation ID", + "description": "Mutiny has experimental support for the Fedimint protocol. You'll need a federation invite code to use this feature. Store funds in a federation at your own risk!", + "learn_more": "Learn more about Fedimint." + }, + "gift": { + "give_sats_link": "Give sats as a gift", + "something_went_wrong": "Something went wrong", + "title": "Gifting", + "no_plus_caption": "Upgrade to Mutiny+ to enable gifting", + "receive_too_small": "Your first receive needs to be {{amount}} SATS or greater.", + "setup_fee_lightning": "A lightning setup fee will be charged to receive this gift.", + "already_claimed": "This gift has already been claimed", + "sender_is_poor": "The sender doesn't have enough balance to pay this gift.", + "sender_timed_out": "Gift payment timed out. The sender may be offline, or this gift has already been claimed.", + "sender_generic_error": "Sender sent error: {{error}}", + "receive_header": "You've been gifted some sats!", + "receive_description": "You must be pretty special. To claim your money just hit the big button. Funds will be added to this wallet the next time your gifter is online.", + "receive_claimed": "Gift claimed! You should see the gift hit your balance shortly.", + "receive_cta": "Claim Gift", + "receive_try_again": "Try Again", + "send_header": "Create Gift", + "send_explainer": "Give the gift of sats. Create a Mutiny gift URL that can be claimed by anyone with a web browser.", + "send_name_required": "This is for your records", + "send_name_label": "Recipient Name", + "send_header_claimed": "Gift Received!", + "send_claimed": "Your gift has been claimed. Thanks for sharing.", + "send_sharable_header": "Sharable URL", + "send_instructions": "Copy this gift URL to your recipient, or ask them to scan this QR code with their wallet.", + "send_another": "Create Another", + "send_small_warning": "A brand new Mutiny user won't be able to redeem fewer than 100k sats.", + "send_cta": "Create a gift", + "send_delete_button": "Delete Gift", + "send_delete_confirm": "Are you sure you want to delete this gift? Is this your rugpull moment?", + "send_tip": "Your copy of Mutiny Wallet needs to be open for the gift to be redeemed.", + "need_plus": "Upgrade to Mutiny+ to enable gifting. Gifting allows you to create a Mutiny gift URL that can be claimed by anyone with a web browser." + } + }, + "swap": { + "peer_not_found": "Peer not found", + "channel_too_small": "It's just silly to make a channel smaller than {{amount}} sats", + "insufficient_funds": "You don't have enough funds to make this channel", + "header": "Swap to Lightning", + "initiated": "Swap Initiated", + "sats_added": "+{{amount}} sats will be added to your Lightning balance", + "use_existing": "Use existing peer", + "choose_peer": "Choose a peer", + "peer_connect_label": "Connect to new peer", + "peer_connect_placeholder": "Peer connect string", + "connect": "Connect", + "connecting": "Connecting...", + "confirm_swap": "Confirm Swap" + }, + "swap_lightning": { + "insufficient_funds": "You don't have enough funds to swap to lightning", + "header": "Swap to Lightning", + "header_preview": "Preview Swap", + "completed": "Swap Completed", + "too_small": "Invalid amount entered. You need to swap at least 100k sats.", + "sats_added": "+{{amount}} sats have been added to your Lightning balance", + "sats_fee": "+{{amount}} sats fee", + "confirm_swap": "Confirm Swap", + "preview_swap": "Preview Swap Fee" + }, + "reload": { + "mutiny_update": "Mutiny Update", + "new_version_description": "New version of Mutiny has been cached, reload to start using it.", + "reload": "Reload" + }, + "error": { + "title": "Error", + "emergency_link": "emergency kit.", + "reload": "Reload", + "restart": { + "title": "Something *extra* screwy going on? Stop the nodes!", + "start": "Start", + "stop": "Stop" + }, + "general": { + "oh_no": "Oh no!", + "never_should_happen": "This never should've happened", + "try_reloading": "Try reloading this page or clicking the \"Dangit\" button. If you keep having problems,", + "support_link": "reach out to us for support.", + "getting_desperate": "Getting desperate? Try the" + }, + "load_time": { + "stuck": "Stuck on this screen? Try reloading. If that doesn't work, check out the" + }, + "not_found": { + "title": "Not Found", + "wtf_paul": "This is probably Paul's fault." + }, + "reset_router": { + "payments_failing": "Failing to make payments? Try resetting the lightning router.", + "reset_router": "Reset Router" + }, + "resync": { + "incorrect_balance": "On-chain balance seems incorrect? Try re-syncing the on-chain wallet.", + "resync_wallet": "Resync wallet" + }, + "on_boot": { + "existing_tab": { + "title": "Multiple tabs detected", + "description": "Mutiny can only be used in one tab at a time. It looks like you have another tab open with Mutiny running. Please close that tab and refresh this page, or close this tab and refresh the other one." + }, + "already_running": { + "title": "Mutiny may be running on another device", + "description": "Mutiny can only be used in one place at a time. It looks like you have another device or browser using this wallet. If you've recently closed Mutiny on another device, please wait a few minutes and try again.", + "retry_again_in": "Retry again in", + "seconds": "seconds" + }, + "incompatible_browser": { + "title": "Incompatible browser", + "header": "Incompatible browser detected", + "description": "Mutiny requires a modern browser that supports WebAssembly, LocalStorage, and IndexedDB. Some browsers disable these features in private mode.", + "try_different_browser": "Please make sure your browser supports all these features, or consider trying another browser. You might also try disabling certain extensions or \"shields\" that block these features.", + "browser_storage": "(We'd love to support more private browsers, but we have to save your wallet data to browser storage or else you will lose funds.)", + "browsers_link": "Supported Browsers" + }, + "loading_failed": { + "title": "Failed to load", + "header": "Failed to load Mutiny", + "description": "Something went wrong while booting up Mutiny Wallet.", + "repair_options": "If your wallet seems broken, here are some tools to try to debug and repair it.", + "questions": "If you have any questions on what these buttons do, please", + "support_link": "reach out to us for support.", + "services_down": "It looks like one of Mutiny's services is down. Please try again later.", + "in_the_meantime": "In the meantime if you want to access your on-chain funds you can load Mutiny in", + "safe_mode": "Safe Mode" + } + } + }, + "modals": { + "share": "Share", + "details": "Details", + "loading": { + "loading": "Loading: {{stage}}", + "default": "Just getting started", + "double_checking": "Double checking something", + "existing_wallet": "Checking for existing wallet", + "downloading": "Downloading", + "setup": "Setup", + "done": "Done" + }, + "onboarding": { + "welcome": "Welcome!", + "restore_from_backup": "If you've used Mutiny before you can restore from a backup. Otherwise you can skip this and enjoy your new wallet!", + "not_available": "We don't do that yet", + "secure_your_funds": "Secure your funds" + }, + "more_info": { + "whats_with_the_fees": "What's with the fees?", + "self_custodial": "Mutiny is a self-custodial wallet. To initiate a lightning payment we must open a lightning channel, which requires a minimum amount and a setup fee.", + "future_payments": "Future payments, both send and receive, will only incur normal network fees and a nominal service fee unless your channel runs out of inbound capacity.", + "liquidity": "Learn more about liquidity" + }, + "confirm_dialog": { + "are_you_sure": "Are you sure?", + "cancel": "Cancel", + "confirm": "Confirm" + }, + "lnurl_auth": { + "auth_request": "Authentication Request", + "login": "Login", + "decline": "Decline", + "error": "That didn't work for some reason.", + "authenticated": "Authenticated!" + } + } +} \ No newline at end of file diff --git a/public/i18n/es.json b/public/i18n/es.json new file mode 100644 index 00000000..a868a535 --- /dev/null +++ b/public/i18n/es.json @@ -0,0 +1,664 @@ +{ + "common": { + "title": "Billetera Mutiny", + "mutiny": "Mutiny", + "nice": "Bien", + "home": "Inicio", + "e_sats": "eSATS", + "e_sat": "eSAT", + "sats": "SATS", + "sat": "SAT", + "fee": "Comisión", + "send": "Enviar", + "receive": "Recibir", + "dangit": "¡Qué pena!", + "back": "Atrás", + "coming_soon": "(muy pronto)", + "copy": "Copiar", + "copied": "Copiado", + "continue": "Continuar", + "error_unimplemented": "Sin implementar", + "why": "¿Por qué?", + "private_tags": "Etiquetas privadas", + "view_transaction": "Ver transacción", + "view_payment_details": "Ver detalles del pago", + "pending": "Pendiente", + "error_safe_mode": "Mutiny se está ejecutando en modo seguro. Lightning esta deshabilitado.", + "self_hosted": "Auto-hospedado" + }, + "contacts": { + "new": "nuevo", + "add_contact": "Añadir Contacto", + "new_contact": "Nuevo Contacto", + "create_contact": "Crear contacto", + "edit_contact": "Editar contacto", + "save_contact": "Guardar contacto", + "delete": "Elminar", + "confirm_delete": "¿Está seguro de querer eliminar este contacto?", + "payment_history": "Historial de pagos", + "no_payments": "Todavía no hay pagos con", + "edit": "Editar", + "pay": "Pagar", + "name": "Nombre", + "ln_address": "Dirección Lightning", + "placeholder": "Satoshi", + "lightning_address": "Dirección Lightning", + "unimplemented": "Sin implementar", + "not_available": "No hacemos eso todavía", + "error_name": "Necesitamos por lo menos un nombre", + "email_error": "Eso no parece una dirección lightning", + "npub_error": "Eso no parece un npub de nostr", + "error_ln_address_missing": "Los contactos nuevos necesitan una dirección lightning", + "npub": "Npub Nostr", + "link_to_nostr_sync": "Importar Contactos de Nostr" + }, + "receive": { + "receive_bitcoin": "Recibir Bitcoin", + "edit": "Editar", + "checking": "Verificando", + "choose_format": "Escoja formato", + "payment_received": "Pago Recibido", + "payment_initiated": "Pago Iniciado", + "receive_add_the_sender": "Agregue el remitente para sus registros", + "keep_mutiny_open": "Deje Mutiny abierto para completar el pago.", + "choose_payment_format": "Escoja el formato de pago", + "unified_label": "Unificado", + "unified_caption": "Combina una dirección de bitcoin y una factura lightning. El remitente escoge el método de pago.", + "lightning_label": "Factura Lightning", + "lightning_caption": "Ideal para transacciones pequeñas. Usualmente comisiones más bajas que en-cadena.", + "onchain_label": "Dirección bitcoin", + "onchain_caption": "En-cadena, tal como lo hizo Satoshi. Ideal para transacciones muy grandes.", + "unified_setup_fee": "Una comisión de instalación de lightning por {{amount}} SATS se cobrará si pagado a través de lightning.", + "lightning_setup_fee": "Una comisión de instalación de lightning por {{amount}} SATS se cobrará para esta recepción.", + "amount": "Monto", + "fee": "+ Comisión", + "total": "Total", + "spendable": "Gastable", + "channel_size": "Tamaño canal", + "channel_reserve": "- Reserva canal", + "error_under_min_lightning": "En-cadena por defecto. El monto es demasiado pequeño para su recepción en Lightning.", + "error_creating_unified": "En-cadena por defecto. Also salió mal al crear la dirección unificada", + "error_creating_address": "Also salió mal al crear la dirección en-cadena", + "amount_editable": { + "receive_too_small": "Una comisión de instalación de lightning puede ser deducida del monto solicitado.", + "setup_fee_lightning": "Se cargará una comisión de instalación de lightning si se paga por lightning.", + "more_than_21m": "Hay solo 21 millones bitcoins.", + "set_amount": "Establecer monto", + "max": "MAX", + "fix_amounts": { + "ten_k": "10k", + "one_hundred_k": "100k", + "one_million": "1m" + }, + "del": "BORR", + "balance": "Balance" + }, + "integrated_qr": { + "onchain": "En-cadena", + "lightning": "Lightning", + "unified": "Unificado", + "gift": "Regalo Lightning" + }, + "remember_choice": "Recordar my selección para la próxima vez", + "what_for": "¿Para qué es esto?" + }, + "send": { + "search": { + "placeholder": "Nombre, dirección, factura", + "paste": "Pegar", + "contacts": "Contactos", + "global_search": "Búsqueda global", + "no_results": "No hay resultados para" + }, + "sending": "Enviando...", + "confirm_send": "Confirmar Envío", + "contact_placeholder": "Aggregar el recipiente para su registro", + "start_over": "Comenzar de Nuevo", + "send_bitcoin": "Enviar Bitcoin", + "paste": "Pegar", + "scan_qr": "Escanear QR", + "payment_initiated": "Pago Iniciado", + "payment_sent": "Pago Enviado", + "destination": "Destino", + "no_payment_info": "No hay información de pago", + "progress_bar": { + "of": "de", + "sats_sent": "sats enviados" + }, + "what_for": "¿Para qué es esto?", + "zap_note": "Zapear nota", + "error_low_balance": "No tenemos saldo suficiente para pagar el monto indicada.", + "error_invoice_match": "Monto solicitado, {{amount}} SATS, no es igual al monto establecido.", + "error_channel_reserves": "No hay suficientes fondos disponibles.", + "error_address": "Dirección Lightning Inválida", + "error_channel_reserves_explained": "Una porción del balance de su canal es reservada para comisiones. Intente enviar un monto más pequeño o agregue fondos.", + "error_clipboard": "Portapapeles no soportado", + "error_keysend": "Keysend falló", + "error_LNURL": "Pago LNURL falló", + "error_expired": "La factura está expirada", + "payjoin_send": "Esto es un payjoin! El Mutiny continuará hasta que la privacidad mejore", + "payment_pending": "Pago pendiente", + "payment_pending_description": "Se esta tomando un tiempo, pero es posible que este pago todavía se realice. Por favor verifique 'Actividad' para el estado actual.", + "hodl_invoice_warning": "Esta es una factura hodl. Los pagos a facturas hodl pueden causar cierres forzosos del canal, lo que resulta en comisiones altas en-cadena ¡Pague bajo su propio riesgo!", + "private": "Privado", + "anonzap": "Zap Anon" + }, + "feedback": { + "header": "¡Denos retroalimentación!", + "received": "¡Retroalimentacion recibida!", + "thanks": "Gracias por decirnos lo que está sucediendo.", + "more": "¿Tiene algo más que decir?", + "tracking": "Mutiny no rastrea n espía su comportamiento, por lo que su retroalimentación es increíblemente útil.", + "github": "No responderemos a esta retroalimentación. Si desea soporte por favor", + "create_issue": "cree una issue en GitHub.", + "link": "¿Retroalimentación?", + "feedback_placeholder": "Bugs, solicitud de funcionalidad, retroalimentación, etc.", + "info_label": "Incluir información de contacto", + "info_caption": "Si necesita que le demos seguimiento a este problema", + "email": "Correo electrónico", + "email_caption": "Direcciones desechables son bienvenidas", + "nostr": "Nostr", + "nostr_caption": "Su npub más fresco", + "nostr_label": "npub de Nostr o NIP-05", + "send_feedback": "Enviar Retroalimentación", + "invalid_feedback": "¡Por favor diga algo!", + "need_contact": "Necesitamos alguna forma de contactarlo", + "invalid_email": "Eso no me parece una dirección de correo electrónico", + "error": "Error enviando retroalimentación {{error}}", + "try_again": "Por favor intente de nuevo más tarde." + }, + "activity": { + "title": "Actividad", + "mutiny": "Mutiny", + "wallet": "Billetera", + "nostr": "Nostr", + "view_all": "Ver todo", + "receive_some_sats_to_get_started": "Reciba algunos sats para comenzar", + "channel_open": "Canal Abierto", + "channel_close": "Canal Cerrado", + "unknown": "Desconocido", + "import_contacts": "Importe sus contactos desde nostr para ver a quién están zapeando.", + "coming_soon": "Muy pronto", + "private": "Privado", + "anonymous": "Anónimo", + "from": "De:", + "transaction_details": { + "lightning_receive": "Recibido via Lightning", + "lightning_send": "Enviado via Lightning", + "channel_open": "Canal abierto", + "channel_close": "Canal cerrado", + "onchain_receive": "Recibido en-cadena", + "onchain_send": "Enviado en-cadena", + "paid": "Pagado", + "unpaid": "Sin pagar", + "status": "Estado", + "date": "Fecha", + "tagged_to": "Etiquetado a", + "description": "Descripción", + "fee": "Comisión", + "onchain_fee": "Comisión En-cadena", + "invoice": "Factura", + "payment_hash": "Hash de Pago", + "payment_preimage": "Preimagen", + "txid": "Txid", + "total": "Monto Solicitado", + "balance": "Balance", + "reserve": "Reserva", + "peer": "Par", + "channel_id": "ID Canal", + "reason": "Razón", + "confirmed": "Confirmado", + "unconfirmed": "Sin Confirmar", + "sweep_delay": "Los fondos pueden tomar algunos días en regresar a la billetera", + "no_details": "No se encontraron detalles del canal, lo que significa que probablemente el canal ha sido cerrado.", + "back_home": "regresar a inicio" + } + }, + "scanner": { + "paste": "Pegar Algo", + "cancel": "Cancelar" + }, + "settings": { + "header": "Ajustes", + "support": "Entérese como apoyar a Mutiny", + "experimental_features": "Experimentos", + "debug_tools": "HERRAMIENTAS DE DEPURACIÓN", + "danger_zone": "Zona de peligro", + "general": "General", + "version": "Versión:", + "admin": { + "title": "Página de Administración", + "caption": "Nuestras herramientas internas de depuración ¡Úselas sabiamente!", + "header": "Herramientas Secretas de Depuración", + "warning_one": "Si sabe lo que está haciendo está en el lugar adecuado.", + "warning_two": "Estas son herramientas internas que usamos para depurar y probar la aplicación ¡Por favor tenga cuidado!", + "kitchen_sink": { + "disconnect": "Desconectar", + "peers": "Pares", + "no_peers": "No hay pares", + "refresh_peers": "Refrescar Pares", + "connect_peer": "Conectar a Par", + "expect_a_value": "Esperando un valor...", + "connect": "Conectar", + "close_channel": "Cerrar Canal", + "force_close": "Forzar cierre de canal", + "abandon_channel": "Abandonar Canal", + "confirm_close_channel": "¿Está seguro de querer cerrar este canal?", + "confirm_force_close": "¿Está seguro de querer forzar el cierre de este canal? Sus fondos tardarán unos días en ser redimidos en la cadena.", + "confirm_abandon_channel": "¿Está seguro de querer abandonar este canal? Típicamente haga esto solo si la transacción de apertura no se confirma nunca. De lo contrario, perderá fondos.", + "channels": "Canales", + "no_channels": "No hay Canales", + "refresh_channels": "Refrescar Canales", + "pubkey": "Pubkey", + "amount": "Monto", + "open_channel": "Abrir Canal", + "nodes": "Nodos", + "no_nodes": "No hay nodos", + "enable_zaps_to_hodl": "¿Habilitar zaps a facturas hodl?", + "zaps_to_hodl_desc": "Zaps a facturas hodl pueden resultar en el cierre forzoso de canales, lo que resulta en altas comisiones en-cadena ¡Use bajo su propio riesgo!", + "zaps_to_hodl_enable": "Habilitar zaps hodl", + "zaps_to_hodl_disable": "Deshabilitar zaps hodl" + } + }, + "backup": { + "title": "Respaldo", + "secure_funds": "Aseguremos estos fondos.", + "twelve_words_tip": "Le mostraremos 12 palabras. Usted escribe esas 12 palabras.", + "warning_one": "Si limpia el historial de su navegador, o pierde su dispositivo, estas 12 palabras son la única manera de restaurar su billetera.", + "warning_two": "Mutiny es auto-custodial. Todo depende de usted...", + "confirm": "Escribí las palabras", + "responsibility": "Entiendo que mis fondos son mi responsabilidad", + "liar": "No estoy mintiendo solo para terminar con esto", + "seed_words": { + "reveal": "TOQUE PARA REVELAR LAS PALABRAS SEMILLA", + "hide": "ESCONDER", + "copy": "Peligrosamente Copiar al Portapapeles", + "copied": "Copiado!" + } + }, + "channels": { + "title": "Canales Lightning", + "outbound": "Saliente", + "inbound": "Entrante", + "reserve": "Reserva", + "have_channels": "Tiene", + "have_channels_one": "canal lightning.", + "have_channels_many": "canales lightning.", + "inbound_outbound_tip": "Saliente es el monto de dinero que puede gastar en lightning. Entrante es el monto que puede recibir sin incurrir en una comisión de servicio de lightning.", + "reserve_tip": "Alrededor del 1% del balance de su canal está reservado en lightning para comisiones. Reservas adicionales son requeridas para canales que abrió usando swap.", + "no_channels": "Parece que todavía no tiene ningún canal. Para empezar, reciba algunos sats port lightning, o haga un swap para mover fondos en-cadena hacia un canal ¡Manos a la obra!", + "close_channel": "Cerrar", + "online_channels": "Canales en Línea", + "offline_channels": "Canales Fuera de Línea", + "close_channel_confirm": "Cerrar este canal moverá el saldo en-cadena e incurrirá en una comisión en-cadena." + }, + "connections": { + "title": "Conexiones Billetera", + "error_name": "El nombre no puede estar vacío", + "error_connection": "Fallo al crear Conexión Billetera", + "error_budget_zero": "El presupuesto debe ser mayor a cero", + "add_connection": "Agregar Conexión", + "manage_connections": "Manejar Conexiones", + "manage_gifts": "Manejar Regalos", + "delete_connection": "Eliminar", + "new_connection": "Nueva Conexión", + "edit_connection": "Editar Conexión", + "new_connection_label": "Nombre", + "new_connection_placeholder": "Mi cliente nostr favorito...", + "create_connection": "Crear Conexión", + "save_connection": "Guardar Cambios", + "edit_budget": "Editar Presupuesto", + "open_app": "Abrir Aplicación", + "open_in_nostr_client": "Abrir en Cliente Nostr", + "open_in_primal": "Abrir en Primal", + "nostr_client_not_found": "Cliente nostr no encontrado", + "client_not_found_description": "Instale un cliente nostr como Primal, Amethyst, o Damus para abrir este enlace.", + "relay": "Relé", + "authorize": "Autoriza servicios externos para solicitar pagos desde su billetera. Combina muy bien con clientes Nostr.", + "pending_nwc": { + "title": "Solicitudes Pendientes", + "approve_all": "Aprovar Todo", + "deny_all": "Denegar Todo" + }, + "careful": "¡Tenga cuidado dónde comparte esta conexión! Solicitudes dentro del presupuesto serán pagadas automáticamente.", + "spent": "Gastado", + "remaining": "Restante", + "confirm_delete": "¿Está seguro de querer eliminar esta conexión?", + "budget": "Presupuesto", + "resets_every": "Se restablece cada", + "resubscribe_date": "Suscribirse de nuevo en" + }, + "emergency_kit": { + "title": "Kit de Emergencia", + "caption": "Diagnostique y resuelva problemas con su billetera.", + "emergency_tip": "Si su billetera parece dañada, aquí hay algunas herramientas para tratar depurarla y repararla.", + "questions": "Si tiene preguntas acerca de qué hacen estos botones, por favor", + "link": "contáctenos para recibir soporte.", + "import_export": { + "title": "Exportar estado de la billetera", + "error_password": "Contraseña requerida", + "error_read_file": "Error al leer archivo", + "error_no_text": "No se encontró texto en el archivo", + "tip": "Puede exportar todo el estado de su Billetera Mutiny a un archivo e importarlo a otro navegador ¡Usualmente funciona!", + "caveat_header": "Advertencias importantes:", + "caveat": "después de exportar no realice ninguna operación en el navegador original. Si lo hace, tendrá que exportar de nuevo. Después de una importación exitosa, una buena práctica es borrar el estado del navegador original solo para asegurarse de no crear conflictos.", + "save_state": "Guardar Estado a Archivo", + "import_state": "Importar Estado desde Archivo", + "confirm_replace": "¿Desea reemplazar su estado con", + "password": "Ingrese su contraseña para descifrar", + "decrypt_wallet": "Descifrar Billetera" + }, + "logs": { + "title": "Descargar logs de depuración", + "something_screwy": "Algo raro está sucediendo? ¡Verifique los logs!", + "download_logs": "Descargar logs", + "password": "Ingrese su contraseña para cifrar", + "confirm_password_label": "Confirme la Contraseña" + }, + "delete_everything": { + "delete": "Eliminar Todo", + "confirm": "Esto eliminará el estado de su nodo ¡Esto no puede ser deshecho!", + "deleted": "Eliminado", + "deleted_description": "Eliminados todos los datos" + } + }, + "encrypt": { + "title": "Cambiar Contraseña", + "caption": "Haga un respaldo primero para desbloquear el cifrado", + "header": "Cifre sus palabras semilla", + "hot_wallet_warning": "Mutiny es una \"billetera caliente\" por lo que necesita sus palabras semilla para operar, pero usted puede opcionalmente cifrar esas palabras con una contraseña.", + "password_tip": "De esa manera, si alguien consigue acceder a su navegador, de todas maneras no tendrá acceso a sus fondos.", + "optional": "(opcional)", + "existing_password": "Constraseña existente", + "existing_password_caption": "Deje vacío si no ha establecido una contraseña todavía.", + "new_password_label": "Contraseña", + "new_password_placeholder": "Ingrese una contraseña", + "new_password_caption": "Esta contraseña será usada para cifrar sus palabras semilla. Si se le olvida, necesitará reingresar sus palabras semilla para acceder a sus fondos. Usted si escribió sus palabras semilla ¿correcto?", + "confirm_password_label": "Confirme Contraseña", + "confirm_password_placeholder": "Ingrese la misma contraseña", + "encrypt": "Cifrar", + "skip": "Saltar", + "error_match": "Las contraseñas no coinciden", + "error_same_as_existingpassword": "La nueva contraseña no debe coincidir con la contraseña existente" + }, + "decrypt": { + "title": "Ingrese su contraseña", + "decrypt_wallet": "Descifrar Billetera", + "forgot_password_link": "¿Olvidó la Contraseña?", + "error_wrong_password": "Contraseña Inválida" + }, + "currency": { + "title": "Moneda", + "caption": "Escoja su par de monedas preferida", + "select_currency": "Seleccione Moneda", + "select_currency_label": "Par de Moneda", + "select_currency_caption": "Al escoger una nueva moneda se resincronizará la billetera para obtener una actualización del precio", + "request_currency_support_link": "Solicite soporte para más monedas", + "error_unsupported_currency": "Por favor seleccione una moneda soportada." + }, + "language": { + "title": "Idioma", + "caption": "Escoja su idioma preferido", + "select_language": "Seleccione Idioma", + "select_language_label": "Idioma", + "select_language_caption": "Al escoger un nuevo idioma se cambiará el lenguaje de la billetera, ignorando el idioma actual del navegador", + "request_language_support_link": "Solicite soporte para más idiomas", + "error_unsupported_language": "Por favor seleccione un idioma soportado." + }, + "lnurl_auth": { + "title": "LNURL Auth", + "auth": "Auth", + "expected": "Esperando algo como LNURL..." + }, + "plus": { + "title": "Mutiny+", + "join": "Unirse", + "sats_per_month": "por {{amount}} sats por mes.", + "lightning_balance": "Necesitará por lo menos {{amount}} sats en su saldo lightning para empezar ¡Intente antes de comprar!", + "restore": "Restaurar Suscripción", + "ready_to_join": "Listo para unirse", + "click_confirm": "Haga clic en confirmar para pagar su primer mes.", + "open_source": "Mutiny es código abierto y auto-hospedable.", + "optional_pay": "Pero también puede pagar por él.", + "paying_for": "Pagando por", + "supports_dev": "ayuda a soportar el desarrollo continuo y desbloquea el acceso temprano a nuevas características y funcionalidad premium:", + "thanks": "¡Usted hace parte del motín! Disfrute de las siguientes ventajas:", + "renewal_time": "Recibirá una solicitud de renovación de pago hacia", + "cancel": "Para cancelar su suscripción simplemente no pague. También puede deshabilitar el Mutiny+", + "wallet_connection": "Conexión Billetera.", + "subscribe": "Suscribirse", + "error_no_plan": "No se encontraron planes", + "error_failure": "No se pudo suscribir", + "error_no_subscription": "No se encontró ninguna suscripción", + "error_expired_subscription": "Su suscripción ha expirado, haga clic en unirse para renovar", + "satisfaction": "Satisfacción engreída", + "gifting": "Regalos", + "multi_device": "Acceso multi-dispositivo", + "ios_testflight": "Acceso a iOS TestFlight", + "more": "... y más por venir", + "cta_description": "Disfrute acceso temprano a nuevas características y funcionalidad premium.", + "cta_but_already_plus": "¡Gracias por su apoyo!" + }, + "restore": { + "title": "Restaurar", + "all_twelve": "Necesita ingresar todas las 12 palabras", + "wrong_word": "Palabra equivocada", + "paste": "Peligrosamente Pegar del Portapapeles", + "confirm_text": "¿Está seguro de querer restaurar a esta billetera? ¡Su billetera existente será eliminada!", + "restore_tip": "Podrá restaurar una Billetera Mutiny existente desde su frase de 12 palabras semilla. Esto reemplazará su billetera existente, ¡por lo tanto esté seguro de saber lo que está haciendo!", + "multi_browser_warning": "No use múltiples navegadores al mismo tiempo.", + "error_clipboard": "Portapapeles no soportado", + "error_word_number": "Número equivocado de palabras", + "error_invalid_seed": "Frase semilla inválida" + }, + "servers": { + "title": "Servidores", + "caption": "¡No confíe en nosotros! Use sus propios servidores para respaldar Mutiny.", + "link": "Aprenda más acerca de auto-hospedaje", + "proxy_label": "Proxy de Websockets", + "proxy_caption": "Cómo su nodo de lightning se comunica con el resto de la red.", + "error_proxy": "Debe ser una url comenzando con wss://", + "esplora_label": "Esplora", + "esplora_caption": "Datos de bloques para información en-cadena.", + "error_esplora": "Eso no parece una URL", + "rgs_label": "RGS", + "rgs_caption": "Rapid Gossip Sync. Datos de red sobre la red de lightning usados para enrutamiento.", + "error_rgs": "Eso no parece una URL", + "lsp_label": "LSP", + "lsp_caption": "Lightning Service Provider. Automáticamente abre canales hacia usted para liquidez entrante. También envuelve facturas para privacidad.", + "lsps_connection_string_label": "Cadena de Caracteres de Conexión LSPS", + "lsps_connection_string_caption": "Lightning Service Provider. Automáticamente abre canales hacia usted para liquidez entrante. Usando la especificación LSP.", + "error_lsps_connection_string": "Eso no parece una cadena de caracteres de conexión", + "lsps_token_label": "Token LSPS", + "lsps_token_caption": "Token LSPS. Usado para identificar qué billetera está conectando al LSP", + "lsps_valid_error": "Puede tener tan solo un LSP establecido o una Cadena de Caracteres de Conexión LSPS y Token LSPS establecidos, no ambos.", + "error_lsps_token": "Eso no parece un token válido", + "storage_label": "Almacenamiento", + "storage_caption": "Servicio de respaldo VSS cifrado.", + "error_lsp": "Eso no parece un URL", + "save": "Guardar" + }, + "nostr_contacts": { + "title": "Sincronizar Contactos Nostr", + "npub_label": "npub nostr", + "npub_required": "Npub no puede estar vacío", + "sync": "Sincronizar", + "resync": "Resincronizar", + "remove": "Eliminar" + }, + "manage_federations": { + "title": "Manejar Federaciones", + "federation_code_label": "Código federación", + "federation_code_required": "Código federación no puede estar vacío", + "federation_added_success": "Federación agregada exitosamente", + "federation_remove_confirm": "¿Esta seguro de querer eliminar esta federación? Asegúrese primero de que sus fondos sean transferidos a su balance lightning u otra billetera.", + "add": "Agregar", + "remove": "Eliminar", + "expires": "Expira", + "federation_id": "ID federación", + "description": "Mutiny tiene soporte experimental para el protocolo Fedimint. Necesitará un código de invitación a la federación para poder usar esta funcionalidad ¡Almacene fondos en una federación bajo su propio riesgo!", + "learn_more": "Aprenda más sobre Fedimint." + }, + "gift": { + "give_sats_link": "Dar sats de regalo", + "title": "Regalo", + "no_plus_caption": "Actualice a Mutiny+ para habilitar regalos", + "receive_too_small": "Su primera recepción debe ser de {{amount}} SATS o más.", + "setup_fee_lightning": "Una comisión de instalación de lightning será cargada para recibir este regalo.", + "already_claimed": "Este regalo ya ha sido reclamado", + "sender_is_poor": "El remitente no tiene suficiente saldo para pagar este regalo.", + "sender_timed_out": "Se agotó el tiempo para el pago del regalo. El remitente puede estar desconectado, o este regalo ya ha sido reclamado.", + "sender_generic_error": "Remitente envió error: {{error}}", + "receive_header": "¡Le han regalado algunos sats!", + "receive_description": "Usted debe ser bastante especial. Para reclamar su dinero simplemente presione el botón grande. Los fondos serán agregados a esta billetera la próxima vez que el remitente se conecte.", + "receive_claimed": "¡Regalo reclamado! Deberá ver el regalo reflejado en el balance en breve.", + "receive_cta": "Reclamar Regalo", + "receive_try_again": "Intente de Nuevo", + "send_header": "Crear Regalo", + "send_explainer": "Regale sats. Cree una URL de regalo de Mutiny que pueda ser reclamado por cualquiera con un navegador.", + "send_name_required": "Esto es para sus registros", + "send_name_label": "Nombre del Recipiente", + "send_header_claimed": "¡Regalo Recibido!", + "send_claimed": "Su regalo ha sido reclamado. Gracias por compartir.", + "send_sharable_header": "URL compartible", + "send_instructions": "Copie este URL de regalo a su recipiente, o pídale que escanee este código QR con su billetera.", + "send_another": "Crear Otro", + "send_small_warning": "Un usuario nuevo de Mutiny no podrá redimir menos de 100k sats.", + "send_cta": "Crear un regalo", + "send_delete_button": "Eliminar Regalo", + "send_delete_confirm": "¿Está seguro de querer eliminar este regalo? ¿Es este su momento de tirar de la alfombra?", + "send_tip": "Su copia de la Billetera Mutiny necesita estar abierta para que el regalo sea reclamado.", + "need_plus": "Actualice a Mutiny+ para habilitar regalos. La funcionalidad de regalos le permite crear una URL de regalo de Mutiny que puede ser reclamado por cualquiera con un navegador." + } + }, + "swap": { + "peer_not_found": "Par no encontrado", + "channel_too_small": "Es simplemente tonto crear un canal más pequeño que {{amount}} sats", + "insufficient_funds": "No tiene suficientes fondos para crear este canal", + "header": "Hacer un Swap a Lightning", + "initiated": "Swap Iniciado", + "sats_added": "+{{amount}} sats serán agregados a su balance lightning", + "use_existing": "Usar par existente", + "choose_peer": "Escoja un par", + "peer_connect_label": "Conectar a un par nuevo", + "peer_connect_placeholder": "Cadena de caracteres de conexión a par", + "connect": "Conectar", + "connecting": "Conectando...", + "confirm_swap": "Confirmar Swap" + }, + "swap_lightning": { + "insufficient_funds": "No tiene fondos suficientes para hacer swap a lightning", + "header": "Hacer Swap a Lightning", + "header_preview": "Previsualizar Swap", + "completed": "Swap Completado", + "too_small": "Monto invalido ingresado. Tiene que hacer un swap de por lo menos 100k sats.", + "sats_added": "+{{amount}} sats han sido agregados a su balance de Lightning", + "sats_fee": "+{{amount}} sats de comisión", + "confirm_swap": "Confirmar Swap", + "preview_swap": "Previsualizar Comisión de Swap" + }, + "reload": { + "mutiny_update": "Actualización de Mutiny", + "new_version_description": "Una nueva versión de Mutiny ha sido almacenada en el caché, recargue para empezar a usarla.", + "reload": "Recargar" + }, + "error": { + "title": "Error", + "emergency_link": "kit de emergencia.", + "reload": "Recargar", + "restart": { + "title": "¿Algo *extra* absurdo sucediendo? ¡Detenga los nodos!", + "start": "Iniciar", + "stop": "Parar" + }, + "general": { + "oh_no": "¡Oh no!", + "never_should_happen": "Esto nunca debió suceder", + "try_reloading": "Intente recargar esta página o haga clic en el botón \"Qué Pena\". Si continua teniendo problemas,", + "support_link": "contáctenos para recibir soporte.", + "getting_desperate": "¿Desesperado? Intente" + }, + "load_time": { + "stuck": "¿Atascado en esta pantalla? Intente recargar. Si eso no funciona, intente" + }, + "not_found": { + "title": "No Encontrado", + "wtf_paul": "Esto es probablemente culpa de Paul." + }, + "reset_router": { + "payments_failing": "¿No puede hacer pagos? Intente reiniciar el enrutador de lightning.", + "reset_router": "Reiniciar Enrutador" + }, + "resync": { + "incorrect_balance": "¿El balance en-cadena parece incorrecto? Intente resincronizar la billetera en-cadena.", + "resync_wallet": "Resincronizar billetera" + }, + "on_boot": { + "existing_tab": { + "title": "Múltiples pestañas detectadas", + "description": "Mutiny solo puede ser usado en una pestaña a la vez. Parece que tiene otra pestaña abierta con Mutiny ejecutándose. Por favor cierre esa pestaña y refresque esta página, o cierre esta pestaña y refresque la otra." + }, + "already_running": { + "title": "Mutiny puede estar ejecutándose en otro dispositivo", + "description": "Mutiny solo puede ser usado en un lugar a la vez. Parece que tiene otro dispositivo o navegador usando esta billetera. Si ha cerrado Mutiny recientemente en otro dispositivo, por favor espere unos minutos e intente de nuevo.", + "retry_again_in": "Intente de nuevo en", + "seconds": "segundos" + }, + "incompatible_browser": { + "title": "Navegador incompatible", + "header": "Navegador incompatible detectado", + "description": "Mutiny requiere un navegador moderno que soporte WebAssembly, LocalStorage, e IndexedDB. Algunos navegadores deshabilitan estas funcionalidades en modo privado.", + "try_different_browser": "Por favor asegúrese de que su navegador soporte todas estas funcionalidades, o considere intentar con otro navegador. También puede intentar deshabilitar ciertas extensiones o \"escudos\" que puedan bloquear estas funcionalidades.", + "browser_storage": "(Nos encantaría soportar más navegadores privados, pero tenemos que guardar los datos de su billetera en el almacenamiento del navegador o de lo contrario perdería esos fondos.)", + "browsers_link": "Navegadores Soportados" + }, + "loading_failed": { + "title": "Fallo al cargar", + "header": "Fallo al cargar Mutiny", + "description": "Algo no funcionó al iniciar la Billetera Mutiny.", + "repair_options": "Si su billetera parece dañada, aquí hay algunas herramientas para tratar depurarla y repararla.", + "questions": "Si tiene alguna pregunta acerca de qué hacen estos botones, por favor", + "support_link": "contáctenos para recibir soporte.", + "services_down": "Parece que uno de los servicios de Mutiny está abajo. Por favor intente de nuevo más tarde.", + "in_the_meantime": "Mientras tanto si desea acceder a sus fondos en-cadena puede cargar Mutiny en", + "safe_mode": "Modo Seguro" + } + } + }, + "modals": { + "share": "Compartir", + "details": "Detalles", + "loading": { + "loading": "Cargando: {{stage}}", + "default": "Apenas empezando", + "double_checking": "Verificando de nuevo algo", + "downloading": "Descargando", + "setup": "Configuración", + "done": "Hecho" + }, + "onboarding": { + "welcome": "¡Bienvenido!", + "restore_from_backup": "Si ha usado Mutiny antes puede restaurar desde un respaldo ¡De lo contrario puede saltarse esto y disfrutar su nueva billetera!", + "not_available": "Todavía no hacemos eso", + "secure_your_funds": "Asegure sus fondos" + }, + "more_info": { + "whats_with_the_fees": "¿Cuál es el asunto con las comisiones?", + "self_custodial": "Mutiny es una billetera auto-custodial. Para iniciar un pago lightning debemos abrir un canal lightning, lo que requiere un monto mínimo y una comisión de instalación.", + "future_payments": "Pagos futuros, tanto envíos como recepciones, solamente incurrirán en comisiones de red y una comisión nominal de servicio a menos de que su canal se quede sin capacidad entrante.", + "liquidity": "Aprenda más sobre liquidez" + }, + "confirm_dialog": { + "are_you_sure": "¿Está seguro?", + "cancel": "Cancelar", + "confirm": "Confirmar" + }, + "lnurl_auth": { + "auth_request": "Solicitud de autenticación", + "login": "Acceder", + "decline": "Declinar", + "error": "Eso no funcionó por alguna razón.", + "authenticated": "¡Autenticado!" + } + } +} \ No newline at end of file diff --git a/public/i18n/ko.json b/public/i18n/ko.json new file mode 100644 index 00000000..798be9e4 --- /dev/null +++ b/public/i18n/ko.json @@ -0,0 +1,468 @@ +{ + "common": { + "title": "Mutiny 지갑", + "nice": "멋지다", + "home": "홈", + "sats": "SATS", + "sat": "SAT", + "usd": "USD", + "fee": "수수료", + "send": "보내기", + "receive": "받기", + "dangit": "땡글", + "back": "뒤로", + "coming_soon": "(곧 출시 예정)", + "copy": "복사", + "copied": "복사됨", + "continue": "계속", + "error_unimplemented": "미구현", + "why": "왜?", + "view_transaction": "거래 보기", + "private_tags": "비공개 태그", + "pending": "대기 중" + }, + "contacts": { + "new": "새로 만들기", + "add_contact": "연락처 추가", + "new_contact": "새 연락처", + "create_contact": "연락처 생성", + "edit_contact": "연락처 수정", + "save_contact": "연락처 저장", + "payment_history": "결제 기록", + "no_payments": "아직 결제 기록이 없습니다.", + "edit": "수정", + "pay": "지불", + "name": "이름", + "placeholder": "사토시", + "unimplemented": "미구현", + "not_available": "아직 제공되지 않습니다.", + "error_name": "이름은 필수입니다." + }, + "receive": { + "receive_bitcoin": "비트코인 받기", + "edit": "수정", + "checking": "확인 중", + "choose_format": "포맷 선택", + "payment_received": "결제 완료", + "payment_initiated": "결제 시작됨", + "receive_add_the_sender": "송신자를 기록에 추가하세요.", + "choose_payment_format": "결제 포맷 선택", + "unified_label": "통합", + "unified_caption": "비트코인 주소와 라이트닝 인보이스를 결합합니다. 송신자가 결제 방법을 선택합니다.", + "lightning_label": "라이트닝 인보이스", + "lightning_caption": "작은 거래에 적합합니다. 보통 온체인 수수료보다 낮습니다.", + "onchain_label": "비트코인 주소", + "onchain_caption": "온체인, 사토시가 한 것처럼. 아주 큰 거래에 적합합니다.", + "unified_setup_fee": "라이트닝으로 지불하는 경우 {{amount}} SATS의 라이트닝 설치 비용이 부과됩니다.", + "lightning_setup_fee": "이 받기에는 {{amount}} SATS의 라이트닝 설치 비용이 부과됩니다.", + "amount": "금액", + "fee": "+ 수수료", + "total": "합계", + "spendable": "사용 가능", + "channel_size": "채널 크기", + "channel_reserve": "- 채널 예비금", + "amount_editable": { + "receive_too_small": "첫 라이트닝 받기는 {{amount}} SATS 이상이어야 합니다. 요청한 금액에서 설정 비용이 차감됩니다.", + "setup_fee_lightning": "라이트닝으로 지불하는 경우 라이트닝 설치 비용이 부과됩니다.", + "more_than_21m": "비트코인은 총 2,100만 개밖에 없습니다.", + "set_amount": "금액 설정", + "max": "최대", + "fix_amounts": { + "ten_k": "1만", + "one_hundred_k": "10만", + "one_million": "100만" + }, + "del": "삭제" + }, + "integrated_qr": { + "onchain": "온체인", + "lightning": "라이트닝", + "unified": "통합" + } + }, + "send": { + "sending": "보내는 중...", + "confirm_send": "보내기 확인", + "contact_placeholder": "기록을 위해 수신자 추가", + "start_over": "다시 시작", + "paste": "붙여넣기", + "scan_qr": "QR 스캔", + "payment_initiated": "결제 시작됨", + "payment_sent": "결제 완료", + "destination": "수신처", + "progress_bar": { + "of": "/", + "sats_sent": "SATS 보냄" + }, + "error_low_balance": "지불할 금액보다 충분한 잔액이 없습니다.", + "error_clipboard": "클립보드를 지원하지 않습니다.", + "error_keysend": "KeySend 실패", + "error_LNURL": "LNURL Pay 실패" + }, + "feedback": { + "header": "피드백 주세요!", + "received": "피드백이 수신되었습니다!", + "thanks": "문제가 발생했음을 알려주셔서 감사합니다.", + "more": "더 하실 말씀이 있으신가요?", + "tracking": "Mutiny는 사용자 행동을 추적하거나 감시하지 않기 때문에 피드백이 매우 유용합니다.", + "github_one": "GitHub에 익숙하시다면", + "github_two": "를 사용하여", + "create_issue": "이슈를 생성하세요", + "link": "피드백?", + "feedback_placeholder": "버그, 기능 요청, 피드백 등", + "info_label": "연락처 정보 포함", + "info_caption": "문제에 대한 후속 조치를 필요로 하는 경우", + "email": "이메일", + "email_caption": "일회용 이메일 사용 가능", + "nostr": "Nostr", + "nostr_caption": "신선한 npub", + "nostr_label": "Nostr npub 또는 NIP-05", + "send_feedback": "피드백 보내기", + "invalid_feedback": "피드백을 입력하세요.", + "need_contact": "연락처 정보가 필요합니다.", + "invalid_email": "올바른 이메일 주소가 아닙니다.", + "error": "피드백 전송 오류", + "try_again": "나중에 다시 시도하세요." + }, + "activity": { + "title": "활동", + "mutiny": "Mutiny", + "nostr": "Nostr", + "view_all": "전체 보기", + "receive_some_sats_to_get_started": "시작하려면 일부 SATS를 받으세요", + "channel_open": "채널 오픈", + "channel_close": "채널 닫기", + "unknown": "알 수 없음", + "import_contacts": "Nostr에서 연락처를 가져와 누가 체널을 열고 있는지 확인하세요.", + "coming_soon": "곧 출시 예정", + "transaction_details": { + "lightning_receive": "라이트닝 입금", + "lightning_send": "라이트닝 송금", + "channel_open": "채널 개설", + "channel_close": "채널 종료", + "onchain_receive": "체인상 입금", + "onchain_send": "체인상 송금", + "paid": "지불 완료", + "unpaid": "미지불", + "status": "상태", + "when": "시간", + "description": "설명", + "fee": "수수료", + "fees": "수수료", + "bolt11": "Bolt11", + "payment_hash": "지불 해시", + "preimage": "사전 이미지", + "txid": "거래 ID", + "balance": "잔고", + "reserve": "리저브", + "peer": "피어", + "channel_id": "채널 ID", + "reason": "이유", + "confirmed": "확인됨", + "unconfirmed": "확인 대기", + "no_details": "채널 상세정보를 찾을 수 없습니다. 이는 해당 채널이 종료된 것으로 보입니다." + } + }, + "scanner": { + "paste": "붙여넣기", + "cancel": "취소" + }, + "settings": { + "header": "설정", + "support": "Mutiny 지원 방법 알아보기", + "general": "일반", + "experimental_features": "실험", + "debug_tools": "디버그 도구", + "danger_zone": "위험 지역", + "admin": { + "title": "관리자 페이지", + "caption": "내부 디버그 도구입니다. 신중하게 사용하세요!", + "header": "비밀 디버그 도구", + "warning_one": "잘 알고 있는 경우 올바른 위치입니다.", + "warning_two": "디버그 및 테스트에 사용하는 내부 도구입니다. 주의하세요!", + "kitchen_sink": { + "disconnect": "연결 끊기", + "peers": "피어", + "no_peers": "피어 없음", + "refresh_peers": "피어 새로고침", + "connect_peer": "피어 연결", + "expect_a_value": "값을 입력하세요...", + "connect": "연결", + "close_channel": "채널 종료", + "force_close": "강제 종료", + "abandon_channel": "채널 포기", + "confirm_close_channel": "이 채널을 종료하시겠습니까?", + "confirm_force_close": "이 채널을 강제로 종료하시겠습니까? 자금은 몇 일 이후에 체인상에서 사용 가능해집니다.", + "confirm_abandon_channel": "이 채널을 포기하시겠습니까? 대개 개방 트랜잭션이 확인되지 않는다면 이렇게 하십시오. 그렇지 않으면 자금을 잃게 될 수 있습니다.", + "channels": "채널", + "no_channels": "채널 없음", + "refresh_channels": "채널 새로고침", + "pubkey": "퍼블릭 키", + "amount": "금액", + "open_channel": "채널 개설", + "nodes": "노드", + "no_nodes": "노드 없음" + } + }, + "backup": { + "title": "백업", + "secure_funds": "자금을 안전하게 보호하세요.", + "twelve_words_tip": "12개의 단어를 보여드립니다. 12개의 단어를 기록하세요.", + "warning_one": "브라우저 기록을 지우거나 기기를 분실하면 이 12개의 단어만으로 지갑을 복원할 수 있습니다.", + "warning_two": "Mutiny는 사용자의 자산을 사용자 스스로 관리해야 합니다...", + "confirm": "12개의 단어를 기록했습니다.", + "responsibility": "자금이 사용자 스스로의 책임임을 이해합니다.", + "liar": "속이려는 것이 아닙니다.", + "seed_words": { + "reveal": "씨드 단어 공개", + "hide": "숨기기", + "copy": "클립보드에 복사", + "copied": "복사됨!" + } + }, + "channels": { + "title": "라이트닝 채널", + "outbound": "송신", + "inbound": "수신", + "have_channels": "라이트닝 채널이", + "have_channels_one": "개 있습니다.", + "have_channels_many": "개 있습니다.", + "inbound_outbound_tip": "송신은 라이트닝으로 지출할 수 있는 금액을 나타냅니다. 수신은 수수료 없이 받을 수 있는 금액을 나타냅니다.", + "no_channels": "아직 채널이 없는 것 같습니다. 먼저 라이트닝으로 몇 sats를 받거나 체인상 자금을 채널로 바꾸세요. 시작해보세요!" + }, + "connections": { + "title": "지갑 연결", + "error_name": "이름을 입력하세요.", + "error_connection": "지갑 연결 생성에 실패했습니다.", + "add_connection": "연결 추가", + "manage_connections": "연결 관리", + "disable_connection": "비활성화", + "enable_connection": "활성화", + "new_connection": "새로운 연결", + "new_connection_label": "이름", + "new_connection_placeholder": "내가 좋아하는 nostr 클라이언트...", + "create_connection": "연결 생성", + "open_app": "앱 열기", + "open_in_nostr_client": "Nostr 클라이언트에서 열기", + "open_in_primal": "Primal에서 열기", + "authorize": "외부 서비스가 지갑에서 결제를 요청할 수 있도록 인증합니다. nostr 클라이언트와 잘 맞습니다.", + "pending_nwc": { + "title": "대기 중인 요청", + "configure_link": "설정" + } + }, + "emergency_kit": { + "title": "비상 키트", + "caption": "지갑 문제를 진단하고 해결하는 도구입니다.", + "emergency_tip": "지갑이 망가지는 것 같다면 이 도구를 사용하여 문제를 진단하고 해결하세요.", + "questions": "이 버튼들이 무엇을 하는지 궁금하다면, 지원을 받으시려면", + "link": "연락처를 통해 문의해주세요.", + "import_export": { + "title": "지갑 상태 내보내기", + "error_password": "비밀번호가 필요합니다.", + "error_read_file": "파일 읽기 오류", + "error_no_text": "파일에서 텍스트를 찾을 수 없습니다.", + "tip": "Mutiny 지갑 상태 전체를 파일로 내보내서 새 브라우저에 가져와서 복원할 수 있습니다. 보통 동작합니다!", + "caveat_header": "주의 사항:", + "caveat": "내보낸 후에는 원래 브라우저에서 아무 동작도 수행하지 마세요. 그렇게 하면 다시 내보내야 합니다. 성공적인 가져오기 후에는 원래 브라우저의 상태를 초기화하는 것이 좋습니다.", + "save_state": "상태를 파일로 저장", + "import_state": "파일에서 상태 가져오기", + "confirm_replace": "상태를 다음으로 대체하시겠습니까?", + "password": "복호화를 위해 비밀번호 입력", + "decrypt_wallet": "지갑 복호화" + }, + "logs": { + "title": "디버그 로그 다운로드", + "something_screwy": "문제가 발생했나요? 로그를 확인하세요!", + "download_logs": "로그 다운로드" + }, + "delete_everything": { + "delete": "모두 삭제", + "confirm": "노드 상태가 모두 삭제됩니다. 복구할 수 없습니다!", + "deleted": "삭제됨", + "deleted_description": "모든 데이터 삭제됨" + } + }, + "encrypt": { + "header": "시드 단어 암호화", + "hot_wallet_warning": "Mutiny는 ”핫 월렛”이므로 시드 단어를 사용하여 작동하지만 선택적으로 비밀번호로 암호화할 수 있습니다.", + "password_tip": "이렇게 하면 다른 사람이 브라우저에 접근하더라도 자금에 접근할 수 없습니다.", + "optional": "(선택 사항)", + "existing_password": "기존 비밀번호", + "existing_password_caption": "비밀번호를 설정하지 않았다면 비워 두세요.", + "new_password_label": "비밀번호", + "new_password_placeholder": "비밀번호를 입력하세요", + "new_password_caption": "이 비밀번호는 시드 단어를 암호화하는 데 사용됩니다. 이를 잊어버리면 자금에 접근하려면 시드 단어를 다시 입력해야 합니다. 시드 단어를 기록해 두었나요?", + "confirm_password_label": "비밀번호 확인", + "confirm_password_placeholder": "동일한 비밀번호를 입력하세요", + "encrypt": "암호화", + "skip": "건너뛰기", + "error_match": "비밀번호가 일치하지 않습니다." + }, + "decrypt": { + "title": "비밀번호를 입력하세요", + "decrypt_wallet": "지갑 복호화", + "forgot_password_link": "비밀번호를 잊으셨나요?", + "error_wrong_password": "유효하지 않은 비밀번호" + }, + "lnurl_auth": { + "title": "LNURL 인증", + "auth": "인증", + "expected": "LNURL과 같은 형식으로 입력해주세요." + }, + "plus": { + "title": "Mutiny+", + "join": "가입", + "for": "에 대해", + "sats_per_month": "sats 월별 비용입니다.", + "you_need": "적어도 다음 금액이 필요합니다.", + "lightning_balance": "라이트닝 잔액에서 sats를 지불하세요. 먼저 시험해보세요!", + "restore": "구독 복원", + "ready_to_join": "가입할 준비가 되었습니다.", + "click_confirm": "첫 달 비용을 지불하려면 확인을 클릭하세요.", + "open_source": "Mutiny는 오픈 소스이며 스스로 호스팅할 수 있습니다.", + "optional_pay": "또한 지불할 수도 있습니다.", + "paying_for": "지불 대상:", + "supports_dev": "는 지속적인 개발을 지원하고 새 기능과 프리미엄 기능의 조기 액세스를 제공합니다.", + "thanks": "Mutiny의 일원이 되셨습니다! 다음 혜택을 즐기세요:", + "renewal_time": "다음 시기에 갱신 요청이 도착합니다.", + "cancel": "구독을 취소하려면 결제하지 않으세요. 또는 Mutiny+ 기능을 비활성화할 수도 있습니다.", + "wallet_connection": "지갑 연결 기능.", + "subscribe": "구독하기", + "error_no_plan": "", + "error_failure": "", + "error_no_subscription": "기존 구독이 없습니다.", + "satisfaction": "만족함", + "gifting": "선물하기", + "multi_device": "다중 장치 접속", + "more": "... 그리고 더 많은 기능이 추가될 예정입니다." + }, + "restore": { + "title": "복원", + "all_twelve": "12개 단어를 모두 입력해야 합니다.", + "wrong_word": "잘못된 단어", + "paste": "클립보드에서 붙여넣기 (위험)", + "confirm_text": "이 지갑으로 복원하시겠습니까? 기존 지갑이 삭제됩니다!", + "restore_tip": "기존 Mutiny 지갑을 12개의 씨드 단어로 복원할 수 있습니다. 기존 지갑이 대체됩니다. 신중하게 사용하세요!", + "multi_browser_warning": "여러 브라우저에서 동시에 사용하지 마세요.", + "error_clipboard": "클립보드를 지원하지 않습니다.", + "error_word_number": "잘못된 단어 개수", + "error_invalid_seed": "잘못된 씨드 단어입니다." + }, + "servers": { + "title": "서버", + "caption": "우리를 믿지 마세요! Mutiny를 백업하기 위해 자체 서버를 사용하세요.", + "link": "자체 호스팅에 대해 자세히 알아보기", + "proxy_label": "웹소켓 프록시", + "proxy_caption": "라이트닝 노드가 네트워크와 통신하는 방법입니다.", + "error_proxy": "wss://로 시작하는 URL이어야 합니다.", + "esplora_label": "Esplora", + "esplora_caption": "온체인 정보를 위한 블록 데이터입니다.", + "error_esplora": "URL처럼 보이지 않습니다.", + "rgs_label": "RGS", + "rgs_caption": "Rapid Gossip Sync. 라우팅을 위해 사용되는 라이트닝 네트워크에 대한 네트워크 데이터입니다.", + "error_rgs": "URL처럼 보이지 않습니다.", + "lsp_label": "LSP", + "lsp_caption": "라이트닝 서비스 공급자. 인바운드 유동성을 위해 자동으로 채널을 열고, 개인 정보 보호를 위해 인보이스를 래핑합니다.", + "error_lsp": "URL처럼 보이지 않습니다.", + "save": "저장" + } + }, + "swap": { + "peer_not_found": "피어를 찾을 수 없음", + "channel_too_small": "{{amount}} sats보다 작은 채널을 만드는 것은 그저 어리석은 짓입니다.", + "insufficient_funds": "이 채널을 만들기에 충분한 자금이 없습니다.", + "header": "라이트닝으로 스왑", + "initiated": "스왑 시작됨", + "sats_added": "sats가 라이트닝 잔액에 추가됩니다.", + "use_existing": "기존 피어 사용", + "choose_peer": "피어 선택", + "peer_connect_label": "새 피어 연결", + "peer_connect_placeholder": "피어 연결 문자열", + "connect": "연결", + "connecting": "연결 중...", + "confirm_swap": "스왑 확인" + }, + "error": { + "title": "오류", + "emergency_link": "긴급 킷.", + "restart": "문제가 *더* 발생했나요? 노드를 중지하세요!", + "general": { + "oh_no": "앗!", + "never_should_happen": "이런 일은 일어나면 안 됩니다.", + "try_reloading": "이 페이지를 새로 고치거나 ”얘들아” 버튼을 눌러보세요. 계속해서 문제가 발생하면", + "support_link": "지원을 요청하세요.", + "getting_desperate": "좀 답답하신가요? 다음을 시도해보세요." + }, + "load_time": { + "stuck": "이 화면에 멈춰있나요? 다시 로드해보세요. 그래도 동작하지 않으면 다음을 확인하세요." + }, + "not_found": { + "title": "찾을 수 없음", + "wtf_paul": "이건 아마 폴의 잘못입니다." + }, + "reset_router": { + "payments_failing": "결제 실패하고 있나요? 라이트닝 라우터를 초기화해보세요.", + "reset_router": "라우터 초기화" + }, + "resync": { + "incorrect_balance": "온체인 잔액이 잘못된 것 같나요? 온체인 월렛을 다시 동기화해보세요.", + "resync_wallet": "월렛 다시 동기화" + }, + "on_boot": { + "existing_tab": { + "title": "여러 탭 감지됨", + "description": "현재 Mutiny Wallet을 한 번에 한 탭에서만 사용할 수 있습니다. Mutiny가 실행 중인 다른 탭이 열려 있습니다. 해당 탭을 닫고 이 페이지를 새로 고치거나, 이 탭을 닫고 다른 탭을 새로 고치세요." + }, + "incompatible_browser": { + "title": "호환되지 않는 브라우저", + "header": "호환되지 않는 브라우저가 감지되었습니다.", + "description": "Mutiny Wallet은 WebAssembly, LocalStorage 및 IndexedDB를 지원하는 현대적인 브라우저를 필요로 합니다. 일부 브라우저는 이러한 기능을 비활성화하는 경우도 있습니다.", + "try_different_browser": "이러한 모든 기능을 지원하는 브라우저를 사용하는지 확인하거나 다른 브라우저를 시도하세요. 또는 이러한 기능을 차단하는 특정 확장 기능이나 ”보호 기능”을 비활성화해보세요.", + "browser_storage": "(더 많은 프라이버시 브라우저를 지원하고 싶지만, 월렛 데이터를 브라우저 저장소에 저장해야 하므로 그렇게 할 수 없습니다. )", + "browsers_link": "지원되는 브라우저" + }, + "loading_failed": { + "title": "로드 실패", + "header": "Mutiny 로드 실패", + "description": "Mutiny Wallet을 부팅하는 동안 문제가 발생했습니다.", + "repair_options": "월렛이 손상된 것 같다면, 디버그 및 복구를 시도하기 위한 몇 가지 도구입니다.", + "questions": "이러한 버튼이 무엇을 하는지 궁금하다면,", + "support_link": "지원을 요청하세요." + } + } + }, + "modals": { + "share": "공유", + "details": "상세정보", + "loading": { + "loading": "로딩 중:", + "default": "시작 중", + "double_checking": "검증 중", + "downloading": "다운로드 중", + "setup": "설정 중", + "done": "완료" + }, + "onboarding": { + "welcome": "환영합니다!", + "restore_from_backup": "이미 Mutiny를 사용한 적이 있으시다면 백업에서 복원할 수 있습니다. 그렇지 않다면 이 단계를 건너뛰고 새로운 지갑을 즐기실 수 있습니다!", + "not_available": "아직 이 기능은 지원하지 않습니다", + "secure_your_funds": "자금을 안전하게 보호하세요" + }, + "more_info": { + "whats_with_the_fees": "수수료는 어떻게 되나요?", + "self_custodial": "Mutiny는 자체 보관 월렛입니다. 라이트닝 지불을 시작하려면 라이트닝 채널을 개설해야 하며, 이는 최소 금액과 설정 비용이 필요합니다.", + "future_payments": "앞으로의 송금 및 입금은 일반 네트워크 수수료와 노말 서비스 수수료만 부과되며, 채널에 인바운드 용량이 부족한 경우에만 추가 수수료가 발생합니다.", + "liquidity": "유동성에 대해 자세히 알아보기" + }, + "confirm_dialog": { + "are_you_sure": "확실합니까?", + "cancel": "취소", + "confirm": "확인" + } + }, + "create_an_issue": "이슈 생성", + "send_bitcoin": "비트코인 전송", + "continue": "계속하기", + "keep_mutiny_open": "결제를 완료하기 위해 Mutiny를 열어두세요." +} \ No newline at end of file diff --git a/public/i18n/pt.json b/public/i18n/pt.json new file mode 100644 index 00000000..8dc05fd9 --- /dev/null +++ b/public/i18n/pt.json @@ -0,0 +1,21 @@ +{ + "create_an_issue": "Crie uma issue", + "view_all": "Ver todas", + "receive_some_sats_to_get_started": "Receba alguns satoshis para começar", + "send_bitcoin": "Enviar Bitcoin", + "view_transaction": "Ver transação", + "amount_editable_first_payment_10k_or_greater": "Seu primeiro recebimento na lightning precisa ser de pelo menos 10.000 sats. Uma taxa de configuração será deduzida da quantidade requisitada.", + "why?": "Por que?", + "more_info_modal_p1": "Mutiny é uma carteira de auto custódia. Para iniciar um pagamento na lightning, nós precisamos abrir um canal que requer uma quantidade mínima e uma taxa de configuração.", + "more_info_modal_p2": "Transaçoēs futuras, como envios e recebimentos, terão somente taxas normais da rede e uma taxa de serviço nominal a não ser que seu canal fique sem capacidade de entrada.", + "learn_more_about_liquidity": "Aprenda mais sobre liquidez", + "set_amount": "Definir quantidade", + "whats_with_the_fees": "O que há com as taxas?", + "private_tags": "Tags privadas", + "receive_add_the_sender": "Marque quem o enviou para registro próprio", + "continue": "Continuar", + "receive_bitcoin": "Receber Bitcoin", + "settings": { + "header": "" + } +} diff --git a/src/i18n/config.ts b/src/i18n/config.ts index 6a8352a5..dd3017da 100644 --- a/src/i18n/config.ts +++ b/src/i18n/config.ts @@ -1,55 +1,32 @@ import { use } from "i18next"; -// FIXME: this doesn't work when deployed -// import HttpApi from 'i18next-http-backend'; import LanguageDetector from "i18next-browser-languagedetector"; - -import en from "~/i18n/en/translations"; -import es from "~/i18n/es/translations"; -import ko from "~/i18n/ko/translations"; -import pt from "~/i18n/pt/translations"; - -export const resources = { - en: { - translations: en - }, - es: { - translations: es - }, - pt: { - translations: pt - }, - ko: { - translations: ko - } -}; +import HttpApi from "i18next-http-backend"; export const defaultNS = "translations"; -const i18n = use(LanguageDetector).init( - { - returnNull: false, - fallbackLng: "en", - preload: ["en"], - load: "languageOnly", - ns: ["translations"], - defaultNS: defaultNS, - fallbackNS: false, - debug: true, - detection: { - order: ["localStorage", "querystring", "navigator", "htmlTag"], - lookupQuerystring: "lang", - lookupLocalStorage: "i18nextLng", - caches: ["localStorage"] +const i18n = use(HttpApi) + .use(LanguageDetector) + .init( + { + returnNull: false, + fallbackLng: "en", + preload: ["en"], + load: "languageOnly", + fallbackNS: false, + debug: true, + detection: { + order: ["localStorage", "querystring", "navigator", "htmlTag"], + lookupQuerystring: "lang", + lookupLocalStorage: "i18nextLng", + caches: ["localStorage"] + }, + backend: { + loadPath: "/i18n/{{lng}}.json" + } }, - resources: resources - // FIXME: this doesn't work when deployed - // backend: { - // loadPath: 'src/i18n/{{lng}}/{{ns}}.json', - // } - }, - (err, _t) => { - // Do we actually wanna log something in case of an unsupported language? - if (err) return console.error(err); - } -); + (err, _t) => { + // Do we actually wanna log something in case of an unsupported language? + if (err) return console.error(err); + } + ); export default i18n; diff --git a/src/i18n/en/translations.ts b/src/i18n/en/translations.ts deleted file mode 100644 index 032f5bc2..00000000 --- a/src/i18n/en/translations.ts +++ /dev/null @@ -1,767 +0,0 @@ -export default { - common: { - title: "Mutiny Wallet", - mutiny: "Mutiny", - nice: "Nice", - home: "Home", - e_sats: "eSATS", - e_sat: "eSAT", - sats: "SATS", - sat: "SAT", - fee: "Fee", - send: "Send", - receive: "Receive", - dangit: "Dangit", - back: "Back", - coming_soon: "(coming soon)", - copy: "Copy", - copied: "Copied", - continue: "Continue", - error_unimplemented: "Unimplemented", - why: "Why?", - private_tags: "Private tags", - view_transaction: "View transaction", - view_payment_details: "View payment details", - pending: "Pending", - error_safe_mode: - "Mutiny is running in safe mode. Lightning is disabled.", - self_hosted: "Self-hosted" - }, - contacts: { - new: "new", - add_contact: "Add Contact", - new_contact: "New Contact", - create_contact: "Create contact", - edit_contact: "Edit contact", - save_contact: "Save contact", - delete: "Delete", - confirm_delete: "Are you sure you want to delete this contact?", - payment_history: "Payment history", - no_payments: "No payments yet with", - edit: "Edit", - pay: "Pay", - name: "Name", - ln_address: "Lightning Address", - placeholder: "Satoshi", - lightning_address: "Lightning Address", - unimplemented: "Unimplemented", - not_available: "We don't do that yet", - error_name: "We at least need a name", - email_error: "That doesn't look like a lightning address", - npub_error: "That doesn't look like a nostr npub", - error_ln_address_missing: "New contacts need a lightning address", - npub: "Nostr Npub", - link_to_nostr_sync: "Import Nostr Contacts" - }, - redeem: { - redeem_bitcoin: "Redeem Bitcoin", - lnurl_amount_message: - "Enter withdrawal amount between {{min}} and {{max}} sats", - lnurl_redeem_failed: "Withdrawal Failed", - lnurl_redeem_success: "Payment Received" - }, - receive: { - receive_bitcoin: "Receive Bitcoin", - edit: "Edit", - checking: "Checking", - choose_format: "Choose format", - payment_received: "Payment Received", - payment_initiated: "Payment Initiated", - receive_add_the_sender: "Add the sender for your records", - keep_mutiny_open: "Keep Mutiny open to complete the payment.", - choose_payment_format: "Choose payment format", - unified_label: "Unified", - unified_caption: - "Combines a bitcoin address and a lightning invoice. Sender chooses payment method.", - lightning_label: "Lightning invoice", - lightning_caption: - "Ideal for small transactions. Usually lower fees than on-chain.", - onchain_label: "Bitcoin address", - onchain_caption: - "On-chain, just like Satoshi did it. Ideal for very large transactions.", - unified_setup_fee: - "A lightning setup fee of {{amount}} SATS will be charged if paid over lightning.", - lightning_setup_fee: - "A lightning setup fee of {{amount}} SATS will be charged for this receive.", - amount: "Amount", - fee: "+ Fee", - total: "Total", - spendable: "Spendable", - channel_size: "Channel size", - channel_reserve: "- Channel reserve", - error_under_min_lightning: - "Defaulting to On-chain. Amount is too small for your initial Lightning receive.", - error_creating_unified: - "Defaulting to On-chain. Something went wrong when creating the unified address", - error_creating_address: - "Something went wrong when creating the on-chain address", - amount_editable: { - receive_too_small: - "A lightning setup fee might be deducted from the requested amount.", - setup_fee_lightning: - "A lightning setup fee will be charged if paid over lightning.", - more_than_21m: "There are only 21 million bitcoin.", - set_amount: "Set amount", - max: "MAX", - fix_amounts: { - ten_k: "10k", - one_hundred_k: "100k", - one_million: "1m" - }, - del: "DEL", - balance: "Balance" - }, - integrated_qr: { - onchain: "On-chain", - lightning: "Lightning", - unified: "Unified", - gift: "Lightning Gift" - }, - remember_choice: "Remember my choice next time", - what_for: "What's this for?" - }, - send: { - search: { - placeholder: "Name, address, invoice", - paste: "Paste", - contacts: "Contacts", - global_search: "Global search", - no_results: "No results found for" - }, - sending: "Sending...", - confirm_send: "Confirm Send", - contact_placeholder: "Add the receiver for your records", - start_over: "Start Over", - send_bitcoin: "Send Bitcoin", - paste: "Paste", - scan_qr: "Scan QR", - payment_initiated: "Payment Initiated", - payment_sent: "Payment Sent", - destination: "Destination", - no_payment_info: "No payment info", - progress_bar: { - of: "of", - sats_sent: "sats sent" - }, - what_for: "What's this for?", - zap_note: "Zap note", - error_low_balance: - "We do not have enough balance to pay the given amount.", - error_invoice_match: - "Amount requested, {{amount}} SATS, does not equal amount set.", - error_channel_reserves: "Not enough available funds.", - error_address: "Invalid Lightning Address", - error_channel_reserves_explained: - "A portion of your channel balance is reserved for fees. Try sending a smaller amount or adding funds.", - error_clipboard: "Clipboard not supported", - error_keysend: "Keysend failed", - error_LNURL: "LNURL Pay failed", - error_expired: "Invoice is expired", - payjoin_send: - "This is a payjoin! The Mutiny will continue until privacy improves", - payment_pending: "Payment pending", - payment_pending_description: - "It's taking a while, but it's possible this payment may still go through. Please check 'Activity' for the current status.", - hodl_invoice_warning: - "This is a hodl invoice. Payments to hodl invoices can cause channel force closes, which results in high on-chain fees. Pay at your own risk!", - private: "Private", - anonzap: "Anon Zap" - }, - feedback: { - header: "Give us feedback!", - received: "Feedback received!", - thanks: "Thank you for letting us know what's going on.", - more: "Got more to say?", - tracking: - "Mutiny doesn't track or spy on your behavior, so your feedback is incredibly helpful.", - github: "We will not respond to this feedback. If you'd like support please", - create_issue: "create a GitHub issue.", - link: "Feedback?", - feedback_placeholder: "Bugs, feature requests, feedback, etc.", - info_label: "Include contact info", - info_caption: "If you need us to follow-up on this issue", - email: "Email", - email_caption: "Burners welcome", - nostr: "Nostr", - nostr_caption: "Your freshest npub", - nostr_label: "Nostr npub or NIP-05", - send_feedback: "Send Feedback", - invalid_feedback: "Please say something!", - need_contact: "We need some way to contact you", - invalid_email: "That doesn't look like an email address to me", - error: "Error submitting feedback {{error}}", - try_again: "Please try again later." - }, - activity: { - title: "Activity", - mutiny: "Mutiny", - wallet: "Wallet", - nostr: "Nostr", - view_all: "View all", - receive_some_sats_to_get_started: "Receive some sats to get started", - channel_open: "Channel Open", - channel_close: "Channel Close", - unknown: "Unknown", - import_contacts: - "Import your contacts from nostr to see who they're zapping.", - coming_soon: "Coming soon", - private: "Private", - anonymous: "Anonymous", - from: "From:", - transaction_details: { - lightning_receive: "Received via Lightning", - lightning_send: "Sent via Lightning", - channel_open: "Channel open", - channel_close: "Channel close", - onchain_receive: "On-chain receive", - onchain_send: "On-chain send", - paid: "Paid", - unpaid: "Unpaid", - status: "Status", - date: "Date", - tagged_to: "Tagged to", - description: "Description", - fee: "Fee", - onchain_fee: "On-chain Fee", - invoice: "Invoice", - payment_hash: "Payment Hash", - payment_preimage: "Preimage", - txid: "Txid", - total: "Amount Requested", - balance: "Balance", - reserve: "Reserve", - peer: "Peer", - channel_id: "Channel ID", - reason: "Reason", - confirmed: "Confirmed", - unconfirmed: "Unconfirmed", - sweep_delay: - "Funds may take a few days to be swept back into the wallet", - no_details: - "No channel details found, which means this channel has likely been closed.", - back_home: "back home" - } - }, - scanner: { - paste: "Paste Something", - cancel: "Cancel" - }, - settings: { - header: "Settings", - support: "Learn how to support Mutiny", - experimental_features: "Experiments", - debug_tools: "DEBUG TOOLS", - danger_zone: "Danger zone", - general: "General", - version: "Version:", - admin: { - title: "Admin Page", - caption: "Our internal debug tools. Use wisely!", - header: "Secret Debug Tools", - warning_one: - "If you know what you're doing you're in the right place.", - warning_two: - "These are internal tools we use to debug and test the app. Please be careful!", - kitchen_sink: { - disconnect: "Disconnect", - peers: "Peers", - no_peers: "No peers", - refresh_peers: "Refresh Peers", - connect_peer: "Connect Peer", - expect_a_value: "Expecting a value...", - connect: "Connect", - close_channel: "Close Channel", - force_close: "Force close Channel", - abandon_channel: "Abandon Channel", - confirm_close_channel: - "Are you sure you want to close this channel?", - confirm_force_close: - "Are you sure you want to force close this channel? Your funds will take a few days to redeem on chain.", - confirm_abandon_channel: - "Are you sure you want to abandon this channel? Typically only do this if the opening transaction will never confirm. Otherwise, you will lose funds.", - channels: "Channels", - no_channels: "No Channels", - refresh_channels: "Refresh Channels", - pubkey: "Pubkey", - amount: "Amount", - open_channel: "Open Channel", - nodes: "Nodes", - no_nodes: "No nodes", - enable_zaps_to_hodl: "Enable zaps to hodl invoices?", - zaps_to_hodl_desc: - "Zaps to hodl invoices can result in channel force closes, which results in high on-chain fees. Use at your own risk!", - zaps_to_hodl_enable: "Enable hodl zaps", - zaps_to_hodl_disable: "Disable hodl zaps" - } - }, - backup: { - title: "Backup", - secure_funds: "Let's get these funds secured.", - twelve_words_tip: - "We'll show you 12 words. You write down the 12 words.", - warning_one: - "If you clear your browser history, or lose your device, these 12 words are the only way you can restore your wallet.", - warning_two: "Mutiny is self-custodial. It's all up to you...", - confirm: "I wrote down the words", - responsibility: "I understand that my funds are my responsibility", - liar: "I'm not lying just to get this over with", - seed_words: { - reveal: "TAP TO REVEAL SEED WORDS", - hide: "HIDE", - copy: "Dangerously Copy to Clipboard", - copied: "Copied!" - } - }, - channels: { - title: "Lightning Channels", - outbound: "Outbound", - inbound: "Inbound", - reserve: "Reserve", - have_channels: "You have", - have_channels_one: "lightning channel.", - have_channels_many: "lightning channels.", - inbound_outbound_tip: - "Outbound is the amount of money you can spend on lightning. Inbound is the amount you can receive without incurring a lightning service fee.", - reserve_tip: - "About 1% of your channel balance is reserved on lightning for fees. Additional reserves are required for channels you opened via swap.", - no_channels: - "It looks like you don't have any channels yet. To get started, receive some sats over lightning, or swap some on-chain funds into a channel. Get your hands dirty!", - close_channel: "Close", - online_channels: "Online Channels", - offline_channels: "Offline Channels", - close_channel_confirm: - "Closing this channel will move the balance on-chain and incur an on-chain fee." - }, - connections: { - title: "Wallet Connections", - error_name: "Name cannot be empty", - error_connection: "Failed to create Wallet Connection", - error_budget_zero: "Budget must be greater than zero", - add_connection: "Add Connection", - manage_connections: "Manage Connections", - manage_gifts: "Manage Gifts", - delete_connection: "Delete", - new_connection: "New Connection", - edit_connection: "Edit Connection", - new_connection_label: "Name", - new_connection_placeholder: "My favorite nostr client...", - create_connection: "Create Connection", - save_connection: "Save Changes", - edit_budget: "Edit Budget", - open_app: "Open App", - open_in_nostr_client: "Open in Nostr Client", - open_in_primal: "Open in Primal", - nostr_client_not_found: "Nostr client not found", - client_not_found_description: - "Install a nostr client like Primal, Amethyst, or Damus to open this link.", - relay: "Relay", - authorize: - "Authorize external services to request payments from your wallet. Pairs great with Nostr clients.", - pending_nwc: { - title: "Pending Requests", - approve_all: "Approve All", - deny_all: "Deny All" - }, - careful: - "Be careful where you share this connection! Requests within budget will paid automatically.", - spent: "Spent", - remaining: "Remaining", - confirm_delete: "Are you sure you want to delete this connection?", - budget: "Budget", - resets_every: "Resets every", - resubscribe_date: "Resubscribe on" - }, - emergency_kit: { - title: "Emergency Kit", - caption: "Diagnose and solve problems with your wallet.", - emergency_tip: - "If your wallet seems broken, here are some tools to try to debug and repair it.", - questions: - "If you have any questions on what these buttons do, please", - link: "reach out to us for support.", - import_export: { - title: "Export wallet state", - error_password: "Password is required", - error_read_file: "File read error", - error_no_text: "No text found in file", - tip: "You can export your entire Mutiny Wallet state to a file and import it into a new browser. It usually works!", - caveat_header: "Important caveats:", - caveat: "after exporting don't do any operations in the original browser. If you do, you'll need to export again. After a successful import, a best practice is to clear the state of the original browser just to make sure you don't create conflicts.", - save_state: "Save State As File", - import_state: "Import State From File", - confirm_replace: "Do you want to replace your state with", - password: "Enter your password to decrypt", - decrypt_wallet: "Decrypt Wallet" - }, - logs: { - title: "Download debug logs", - something_screwy: - "Something screwy going on? Check out the logs!", - download_logs: "Download Logs", - password: "Enter your password to decrypt", - confirm_password_label: "Confirm Password" - }, - delete_everything: { - delete: "Delete Everything", - confirm: - "This will delete your node's state. This can't be undone!", - deleted: "Deleted", - deleted_description: "Deleted all data" - } - }, - encrypt: { - title: "Change Password", - caption: "Backup first to unlock encryption", - header: "Encrypt your seed words", - hot_wallet_warning: - 'Mutiny is a "hot wallet" so it needs your seed word to operate, but you can optionally encrypt those words with a password.', - password_tip: - "That way, if someone gets access to your browser, they still won't have access to your funds.", - optional: "(optional)", - existing_password: "Existing password", - existing_password_caption: - "Leave blank if you haven't set a password yet.", - new_password_label: "Password", - new_password_placeholder: "Enter a password", - new_password_caption: - "This password will be used to encrypt your seed words. If you forget it, you will need to re-enter your seed words to access your funds. You did write down your seed words, right?", - confirm_password_label: "Confirm Password", - confirm_password_placeholder: "Enter the same password", - encrypt: "Encrypt", - skip: "Skip", - error_match: "Passwords do not match", - error_same_as_existingpassword: - "New password must not match existing password" - }, - decrypt: { - title: "Enter your password", - decrypt_wallet: "Decrypt Wallet", - forgot_password_link: "Forgot Password?", - error_wrong_password: "Invalid Password" - }, - currency: { - title: "Currency", - caption: "Choose your preferred currency pair", - select_currency: "Select Currency", - select_currency_label: "Currency Pair", - select_currency_caption: - "Choosing a new currency will resync the wallet to fetch a price update", - request_currency_support_link: - "Request support for more currencies", - error_unsupported_currency: "Please Select a supported currency." - }, - language: { - title: "Language", - caption: "Choose your preferred language", - select_language: "Select Language", - select_language_label: "Language", - select_language_caption: - "Choosing a new currency will change the wallet language, ignoring current browser language", - request_language_support_link: "Request support for more languages", - error_unsupported_language: "Please Select a supported language." - }, - lnurl_auth: { - title: "LNURL Auth", - auth: "Auth", - expected: "Expecting something like LNURL..." - }, - plus: { - title: "Mutiny+", - join: "Join", - sats_per_month: "for {{amount}} sats a month.", - lightning_balance: - "You'll need at least {{amount}} sats in your lightning balance to get started. Try before you buy!", - restore: "Restore Subscription", - ready_to_join: "Ready to join", - click_confirm: "Click confirm to pay for your first month.", - open_source: "Mutiny is open source and self-hostable.", - optional_pay: "But also you can pay for it.", - paying_for: "Paying for", - supports_dev: - "helps support ongoing development and unlocks early access to new features and premium functionality:", - thanks: "You're part of the mutiny! Enjoy the following perks:", - renewal_time: "You'll get a renewal payment request around", - cancel: "To cancel your subscription just don't pay. You can also disable the Mutiny+", - wallet_connection: "Wallet Connection.", - subscribe: "Subscribe", - error_no_plan: "No plans found", - error_failure: "Couldn't subscribe", - error_no_subscription: "No existing subscription found", - error_expired_subscription: - "Your subscription has expired, click join to renew", - satisfaction: "Smug satisfaction", - gifting: "Gifting", - multi_device: "Multi-device access", - ios_testflight: "iOS TestFlight access", - more: "... and more to come", - cta_description: - "Enjoy early access to new features and premium functionality.", - cta_but_already_plus: "Thank you for your support!" - }, - restore: { - title: "Restore", - all_twelve: "You need to enter all 12 words", - wrong_word: "Wrong word", - paste: "Dangerously Paste from Clipboard", - confirm_text: - "Are you sure you want to restore to this wallet? Your existing wallet will be deleted!", - restore_tip: - "You can restore an existing Mutiny Wallet from your 12 word seed phrase. This will replace your existing wallet, so make sure you know what you're doing!", - multi_browser_warning: - "Do not use on multiple browsers at the same time.", - error_clipboard: "Clipboard not supported", - error_word_number: "Wrong number of words", - error_invalid_seed: "Invalid seed phrase" - }, - servers: { - title: "Servers", - caption: "Don't trust us! Use your own servers to back Mutiny.", - link: "Learn more about self-hosting", - proxy_label: "Websockets Proxy", - proxy_caption: - "How your lightning node communicates with the rest of the network.", - error_proxy: "Should be a url starting with wss://", - esplora_label: "Esplora", - esplora_caption: "Block data for on-chain information.", - error_esplora: "That doesn't look like a URL", - rgs_label: "RGS", - rgs_caption: - "Rapid Gossip Sync. Network data about the lightning network used for routing.", - error_rgs: "That doesn't look like a URL", - lsp_label: "LSP", - lsp_caption: - "Lightning Service Provider. Automatically opens channels to you for inbound liquidity. Also wraps invoices for privacy.", - lsps_connection_string_label: "LSPS Connection String", - lsps_connection_string_caption: - "Lightning Service Provider. Automatically opens channels to you for inbound liquidity. Using LSP specification.", - error_lsps_connection_string: - "That doesn't look like node connection string", - lsps_token_label: "LSPS Token", - lsps_token_caption: - "LSPS Token. Used to identify what wallet is connecting to the LSP", - lsps_valid_error: - "You can either have just an LSP set or LSPS Connection String and LSPS Token set, not both.", - error_lsps_token: "That doesn't look like a valid token", - storage_label: "Storage", - storage_caption: "Encrypted VSS backup service.", - error_lsp: "That doesn't look like a URL", - save: "Save" - }, - nostr_contacts: { - title: "Sync Nostr Contacts", - npub_label: "Nostr npub", - npub_required: "Npub can't be blank", - sync: "Sync", - resync: "Resync", - remove: "Remove" - }, - manage_federations: { - title: "Manage Federations", - federation_code_label: "Federation code", - federation_code_required: "Federation code can't be blank", - federation_added_success: "Federation added successfully", - federation_remove_confirm: - "Are you sure you want to remove this federation? Make sure any funds you have are transferred to your lightning balance or another wallet first.", - add: "Add", - remove: "Remove", - expires: "Expires", - federation_id: "Federation ID", - description: - "Mutiny has experimental support for the Fedimint protocol. You'll need a federation invite code to use this feature. Store funds in a federation at your own risk!", - learn_more: "Learn more about Fedimint." - }, - gift: { - give_sats_link: "Give sats as a gift", - title: "Gifting", - no_plus_caption: "Upgrade to Mutiny+ to enable gifting", - receive_too_small: - "Your first receive needs to be {{amount}} SATS or greater.", - setup_fee_lightning: - "A lightning setup fee will be charged to receive this gift.", - already_claimed: "This gift has already been claimed", - sender_is_poor: - "The sender doesn't have enough balance to pay this gift.", - sender_timed_out: - "Gift payment timed out. The sender may be offline, or this gift has already been claimed.", - sender_generic_error: "Sender sent error: {{error}}", - receive_header: "You've been gifted some sats!", - receive_description: - "You must be pretty special. To claim your money just hit the big button. Funds will be added to this wallet the next time your gifter is online.", - receive_claimed: - "Gift claimed! You should see the gift hit your balance shortly.", - receive_cta: "Claim Gift", - receive_try_again: "Try Again", - send_header: "Create Gift", - send_explainer: - "Give the gift of sats. Create a Mutiny gift URL that can be claimed by anyone with a web browser.", - send_name_required: "This is for your records", - send_name_label: "Recipient Name", - send_header_claimed: "Gift Received!", - send_claimed: "Your gift has been claimed. Thanks for sharing.", - send_sharable_header: "Sharable URL", - send_instructions: - "Copy this gift URL to your recipient, or ask them to scan this QR code with their wallet.", - send_another: "Create Another", - send_small_warning: - "A brand new Mutiny user won't be able to redeem fewer than 100k sats.", - send_cta: "Create a gift", - send_delete_button: "Delete Gift", - send_delete_confirm: - "Are you sure you want to delete this gift? Is this your rugpull moment?", - send_tip: - "Your copy of Mutiny Wallet needs to be open for the gift to be redeemed.", - need_plus: - "Upgrade to Mutiny+ to enable gifting. Gifting allows you to create a Mutiny gift URL that can be claimed by anyone with a web browser." - } - }, - swap: { - peer_not_found: "Peer not found", - channel_too_small: - "It's just silly to make a channel smaller than {{amount}} sats", - insufficient_funds: "You don't have enough funds to make this channel", - header: "Swap to Lightning", - initiated: "Swap Initiated", - sats_added: "+{{amount}} sats will be added to your Lightning balance", - use_existing: "Use existing peer", - choose_peer: "Choose a peer", - peer_connect_label: "Connect to new peer", - peer_connect_placeholder: "Peer connect string", - connect: "Connect", - connecting: "Connecting...", - confirm_swap: "Confirm Swap" - }, - swap_lightning: { - insufficient_funds: "You don't have enough funds to swap to lightning", - header: "Swap to Lightning", - header_preview: "Preview Swap", - completed: "Swap Completed", - too_small: - "Invalid amount entered. You need to swap at least 100k sats.", - sats_added: - "+{{amount}} sats have been added to your Lightning balance", - sats_fee: "+{{amount}} sats fee", - confirm_swap: "Confirm Swap", - preview_swap: "Preview Swap Fee" - }, - reload: { - mutiny_update: "Mutiny Update", - new_version_description: - "New version of Mutiny has been cached, reload to start using it.", - reload: "Reload" - }, - error: { - title: "Error", - emergency_link: "emergency kit.", - reload: "Reload", - restart: { - title: "Something *extra* screwy going on? Stop the nodes!", - start: "Start", - stop: "Stop" - }, - general: { - oh_no: "Oh no!", - never_should_happen: "This never should've happened", - try_reloading: - 'Try reloading this page or clicking the "Dangit" button. If you keep having problems,', - support_link: "reach out to us for support.", - getting_desperate: "Getting desperate? Try the" - }, - load_time: { - stuck: "Stuck on this screen? Try reloading. If that doesn't work, check out the" - }, - not_found: { - title: "Not Found", - wtf_paul: "This is probably Paul's fault." - }, - reset_router: { - payments_failing: - "Failing to make payments? Try resetting the lightning router.", - reset_router: "Reset Router" - }, - resync: { - incorrect_balance: - "On-chain balance seems incorrect? Try re-syncing the on-chain wallet.", - resync_wallet: "Resync wallet" - }, - on_boot: { - existing_tab: { - title: "Multiple tabs detected", - description: - "Mutiny can only be used in one tab at a time. It looks like you have another tab open with Mutiny running. Please close that tab and refresh this page, or close this tab and refresh the other one." - }, - already_running: { - title: "Mutiny may be running on another device", - description: - "Mutiny can only be used in one place at a time. It looks like you have another device or browser using this wallet. If you've recently closed Mutiny on another device, please wait a few minutes and try again.", - retry_again_in: "Retry again in", - seconds: "seconds" - }, - incompatible_browser: { - title: "Incompatible browser", - header: "Incompatible browser detected", - description: - "Mutiny requires a modern browser that supports WebAssembly, LocalStorage, and IndexedDB. Some browsers disable these features in private mode.", - try_different_browser: - 'Please make sure your browser supports all these features, or consider trying another browser. You might also try disabling certain extensions or "shields" that block these features.', - browser_storage: - "(We'd love to support more private browsers, but we have to save your wallet data to browser storage or else you will lose funds.)", - browsers_link: "Supported Browsers" - }, - loading_failed: { - title: "Failed to load", - header: "Failed to load Mutiny", - description: - "Something went wrong while booting up Mutiny Wallet.", - repair_options: - "If your wallet seems broken, here are some tools to try to debug and repair it.", - questions: - "If you have any questions on what these buttons do, please", - support_link: "reach out to us for support.", - services_down: - "It looks like one of Mutiny's services is down. Please try again later.", - in_the_meantime: - "In the meantime if you want to access your on-chain funds you can load Mutiny in", - safe_mode: "Safe Mode" - } - } - }, - modals: { - share: "Share", - details: "Details", - loading: { - loading: "Loading: {{stage}}", - default: "Just getting started", - double_checking: "Double checking something", - downloading: "Downloading", - setup: "Setup", - done: "Done" - }, - onboarding: { - welcome: "Welcome!", - restore_from_backup: - "If you've used Mutiny before you can restore from a backup. Otherwise you can skip this and enjoy your new wallet!", - not_available: "We don't do that yet", - secure_your_funds: "Secure your funds" - }, - more_info: { - whats_with_the_fees: "What's with the fees?", - self_custodial: - "Mutiny is a self-custodial wallet. To initiate a lightning payment we must open a lightning channel, which requires a minimum amount and a setup fee.", - future_payments: - "Future payments, both send and receive, will only incur normal network fees and a nominal service fee unless your channel runs out of inbound capacity.", - liquidity: "Learn more about liquidity" - }, - confirm_dialog: { - are_you_sure: "Are you sure?", - cancel: "Cancel", - confirm: "Confirm" - }, - lnurl_auth: { - auth_request: "Authentication Request", - login: "Login", - decline: "Decline", - error: "That didn't work for some reason.", - authenticated: "Authenticated!" - } - } -}; diff --git a/src/i18n/es/translations.ts b/src/i18n/es/translations.ts deleted file mode 100644 index 83841d33..00000000 --- a/src/i18n/es/translations.ts +++ /dev/null @@ -1,766 +0,0 @@ -export default { - common: { - title: "Billetera Mutiny", - mutiny: "Mutiny", - nice: "Bien", - home: "Inicio", - e_sats: "eSATS", - e_sat: "eSAT", - sats: "SATS", - sat: "SAT", - fee: "Comisión", - send: "Enviar", - receive: "Recibir", - dangit: "¡Qué pena!", - back: "Atrás", - coming_soon: "(muy pronto)", - copy: "Copiar", - copied: "Copiado", - continue: "Continuar", - error_unimplemented: "Sin implementar", - why: "¿Por qué?", - private_tags: "Etiquetas privadas", - view_transaction: "Ver transacción", - view_payment_details: "Ver detalles del pago", - pending: "Pendiente", - error_safe_mode: - "Mutiny se está ejecutando en modo seguro. Lightning esta deshabilitado.", - self_hosted: "Auto-hospedado" - }, - contacts: { - new: "nuevo", - add_contact: "Añadir Contacto", - new_contact: "Nuevo Contacto", - create_contact: "Crear contacto", - edit_contact: "Editar contacto", - save_contact: "Guardar contacto", - delete: "Elminar", - confirm_delete: "¿Está seguro de querer eliminar este contacto?", - payment_history: "Historial de pagos", - no_payments: "Todavía no hay pagos con", - edit: "Editar", - pay: "Pagar", - name: "Nombre", - ln_address: "Dirección Lightning", - placeholder: "Satoshi", - lightning_address: "Dirección Lightning", - unimplemented: "Sin implementar", - not_available: "No hacemos eso todavía", - error_name: "Necesitamos por lo menos un nombre", - email_error: "Eso no parece una dirección lightning", - npub_error: "Eso no parece un npub de nostr", - error_ln_address_missing: - "Los contactos nuevos necesitan una dirección lightning", - npub: "Npub Nostr", - link_to_nostr_sync: "Importar Contactos de Nostr" - }, - receive: { - receive_bitcoin: "Recibir Bitcoin", - edit: "Editar", - checking: "Verificando", - choose_format: "Escoja formato", - payment_received: "Pago Recibido", - payment_initiated: "Pago Iniciado", - receive_add_the_sender: "Agregue el remitente para sus registros", - keep_mutiny_open: "Deje Mutiny abierto para completar el pago.", - choose_payment_format: "Escoja el formato de pago", - unified_label: "Unificado", - unified_caption: - "Combina una dirección de bitcoin y una factura lightning. El remitente escoge el método de pago.", - lightning_label: "Factura Lightning", - lightning_caption: - "Ideal para transacciones pequeñas. Usualmente comisiones más bajas que en-cadena.", - onchain_label: "Dirección bitcoin", - onchain_caption: - "En-cadena, tal como lo hizo Satoshi. Ideal para transacciones muy grandes.", - unified_setup_fee: - "Una comisión de instalación de lightning por {{amount}} SATS se cobrará si pagado a través de lightning.", - lightning_setup_fee: - "Una comisión de instalación de lightning por {{amount}} SATS se cobrará para esta recepción.", - amount: "Monto", - fee: "+ Comisión", - total: "Total", - spendable: "Gastable", - channel_size: "Tamaño canal", - channel_reserve: "- Reserva canal", - error_under_min_lightning: - "En-cadena por defecto. El monto es demasiado pequeño para su recepción en Lightning.", - error_creating_unified: - "En-cadena por defecto. Also salió mal al crear la dirección unificada", - error_creating_address: - "Also salió mal al crear la dirección en-cadena", - amount_editable: { - receive_too_small: - "Una comisión de instalación de lightning puede ser deducida del monto solicitado.", - setup_fee_lightning: - "Se cargará una comisión de instalación de lightning si se paga por lightning.", - more_than_21m: "Hay solo 21 millones bitcoins.", - set_amount: "Establecer monto", - max: "MAX", - fix_amounts: { - ten_k: "10k", - one_hundred_k: "100k", - one_million: "1m" - }, - del: "BORR", - balance: "Balance" - }, - integrated_qr: { - onchain: "En-cadena", - lightning: "Lightning", - unified: "Unificado", - gift: "Regalo Lightning" - }, - remember_choice: "Recordar my selección para la próxima vez", - what_for: "¿Para qué es esto?" - }, - send: { - search: { - placeholder: "Nombre, dirección, factura", - paste: "Pegar", - contacts: "Contactos", - global_search: "Búsqueda global", - no_results: "No hay resultados para" - }, - sending: "Enviando...", - confirm_send: "Confirmar Envío", - contact_placeholder: "Aggregar el recipiente para su registro", - start_over: "Comenzar de Nuevo", - send_bitcoin: "Enviar Bitcoin", - paste: "Pegar", - scan_qr: "Escanear QR", - payment_initiated: "Pago Iniciado", - payment_sent: "Pago Enviado", - destination: "Destino", - no_payment_info: "No hay información de pago", - progress_bar: { - of: "de", - sats_sent: "sats enviados" - }, - what_for: "¿Para qué es esto?", - zap_note: "Zapear nota", - error_low_balance: - "No tenemos saldo suficiente para pagar el monto indicada.", - error_invoice_match: - "Monto solicitado, {{amount}} SATS, no es igual al monto establecido.", - error_channel_reserves: "No hay suficientes fondos disponibles.", - error_address: "Dirección Lightning Inválida", - error_channel_reserves_explained: - "Una porción del balance de su canal es reservada para comisiones. Intente enviar un monto más pequeño o agregue fondos.", - error_clipboard: "Portapapeles no soportado", - error_keysend: "Keysend falló", - error_LNURL: "Pago LNURL falló", - error_expired: "La factura está expirada", - payjoin_send: - "Esto es un payjoin! El Mutiny continuará hasta que la privacidad mejore", - payment_pending: "Pago pendiente", - payment_pending_description: - "Se esta tomando un tiempo, pero es posible que este pago todavía se realice. Por favor verifique 'Actividad' para el estado actual.", - hodl_invoice_warning: - "Esta es una factura hodl. Los pagos a facturas hodl pueden causar cierres forzosos del canal, lo que resulta en comisiones altas en-cadena ¡Pague bajo su propio riesgo!", - private: "Privado", - anonzap: "Zap Anon" - }, - feedback: { - header: "¡Denos retroalimentación!", - received: "¡Retroalimentacion recibida!", - thanks: "Gracias por decirnos lo que está sucediendo.", - more: "¿Tiene algo más que decir?", - tracking: - "Mutiny no rastrea n espía su comportamiento, por lo que su retroalimentación es increíblemente útil.", - github: "No responderemos a esta retroalimentación. Si desea soporte por favor", - create_issue: "cree una issue en GitHub.", - link: "¿Retroalimentación?", - feedback_placeholder: - "Bugs, solicitud de funcionalidad, retroalimentación, etc.", - info_label: "Incluir información de contacto", - info_caption: "Si necesita que le demos seguimiento a este problema", - email: "Correo electrónico", - email_caption: "Direcciones desechables son bienvenidas", - nostr: "Nostr", - nostr_caption: "Su npub más fresco", - nostr_label: "npub de Nostr o NIP-05", - send_feedback: "Enviar Retroalimentación", - invalid_feedback: "¡Por favor diga algo!", - need_contact: "Necesitamos alguna forma de contactarlo", - invalid_email: "Eso no me parece una dirección de correo electrónico", - error: "Error enviando retroalimentación {{error}}", - try_again: "Por favor intente de nuevo más tarde." - }, - activity: { - title: "Actividad", - mutiny: "Mutiny", - wallet: "Billetera", - nostr: "Nostr", - view_all: "Ver todo", - receive_some_sats_to_get_started: "Reciba algunos sats para comenzar", - channel_open: "Canal Abierto", - channel_close: "Canal Cerrado", - unknown: "Desconocido", - import_contacts: - "Importe sus contactos desde nostr para ver a quién están zapeando.", - coming_soon: "Muy pronto", - private: "Privado", - anonymous: "Anónimo", - from: "De:", - transaction_details: { - lightning_receive: "Recibido via Lightning", - lightning_send: "Enviado via Lightning", - channel_open: "Canal abierto", - channel_close: "Canal cerrado", - onchain_receive: "Recibido en-cadena", - onchain_send: "Enviado en-cadena", - paid: "Pagado", - unpaid: "Sin pagar", - status: "Estado", - date: "Fecha", - tagged_to: "Etiquetado a", - description: "Descripción", - fee: "Comisión", - onchain_fee: "Comisión En-cadena", - invoice: "Factura", - payment_hash: "Hash de Pago", - payment_preimage: "Preimagen", - txid: "Txid", - total: "Monto Solicitado", - balance: "Balance", - reserve: "Reserva", - peer: "Par", - channel_id: "ID Canal", - reason: "Razón", - confirmed: "Confirmado", - unconfirmed: "Sin Confirmar", - sweep_delay: - "Los fondos pueden tomar algunos días en regresar a la billetera", - no_details: - "No se encontraron detalles del canal, lo que significa que probablemente el canal ha sido cerrado.", - back_home: "regresar a inicio" - } - }, - scanner: { - paste: "Pegar Algo", - cancel: "Cancelar" - }, - settings: { - header: "Ajustes", - support: "Entérese como apoyar a Mutiny", - experimental_features: "Experimentos", - debug_tools: "HERRAMIENTAS DE DEPURACIÓN", - danger_zone: "Zona de peligro", - general: "General", - version: "Versión:", - admin: { - title: "Página de Administración", - caption: - "Nuestras herramientas internas de depuración ¡Úselas sabiamente!", - header: "Herramientas Secretas de Depuración", - warning_one: - "Si sabe lo que está haciendo está en el lugar adecuado.", - warning_two: - "Estas son herramientas internas que usamos para depurar y probar la aplicación ¡Por favor tenga cuidado!", - kitchen_sink: { - disconnect: "Desconectar", - peers: "Pares", - no_peers: "No hay pares", - refresh_peers: "Refrescar Pares", - connect_peer: "Conectar a Par", - expect_a_value: "Esperando un valor...", - connect: "Conectar", - close_channel: "Cerrar Canal", - force_close: "Forzar cierre de canal", - abandon_channel: "Abandonar Canal", - confirm_close_channel: - "¿Está seguro de querer cerrar este canal?", - confirm_force_close: - "¿Está seguro de querer forzar el cierre de este canal? Sus fondos tardarán unos días en ser redimidos en la cadena.", - confirm_abandon_channel: - "¿Está seguro de querer abandonar este canal? Típicamente haga esto solo si la transacción de apertura no se confirma nunca. De lo contrario, perderá fondos.", - channels: "Canales", - no_channels: "No hay Canales", - refresh_channels: "Refrescar Canales", - pubkey: "Pubkey", - amount: "Monto", - open_channel: "Abrir Canal", - nodes: "Nodos", - no_nodes: "No hay nodos", - enable_zaps_to_hodl: "¿Habilitar zaps a facturas hodl?", - zaps_to_hodl_desc: - "Zaps a facturas hodl pueden resultar en el cierre forzoso de canales, lo que resulta en altas comisiones en-cadena ¡Use bajo su propio riesgo!", - zaps_to_hodl_enable: "Habilitar zaps hodl", - zaps_to_hodl_disable: "Deshabilitar zaps hodl" - } - }, - backup: { - title: "Respaldo", - secure_funds: "Aseguremos estos fondos.", - twelve_words_tip: - "Le mostraremos 12 palabras. Usted escribe esas 12 palabras.", - warning_one: - "Si limpia el historial de su navegador, o pierde su dispositivo, estas 12 palabras son la única manera de restaurar su billetera.", - warning_two: "Mutiny es auto-custodial. Todo depende de usted...", - confirm: "Escribí las palabras", - responsibility: "Entiendo que mis fondos son mi responsabilidad", - liar: "No estoy mintiendo solo para terminar con esto", - seed_words: { - reveal: "TOQUE PARA REVELAR LAS PALABRAS SEMILLA", - hide: "ESCONDER", - copy: "Peligrosamente Copiar al Portapapeles", - copied: "Copiado!" - } - }, - channels: { - title: "Canales Lightning", - outbound: "Saliente", - inbound: "Entrante", - reserve: "Reserva", - have_channels: "Tiene", - have_channels_one: "canal lightning.", - have_channels_many: "canales lightning.", - inbound_outbound_tip: - "Saliente es el monto de dinero que puede gastar en lightning. Entrante es el monto que puede recibir sin incurrir en una comisión de servicio de lightning.", - reserve_tip: - "Alrededor del 1% del balance de su canal está reservado en lightning para comisiones. Reservas adicionales son requeridas para canales que abrió usando swap.", - no_channels: - "Parece que todavía no tiene ningún canal. Para empezar, reciba algunos sats port lightning, o haga un swap para mover fondos en-cadena hacia un canal ¡Manos a la obra!", - close_channel: "Cerrar", - online_channels: "Canales en Línea", - offline_channels: "Canales Fuera de Línea", - close_channel_confirm: - "Cerrar este canal moverá el saldo en-cadena e incurrirá en una comisión en-cadena." - }, - connections: { - title: "Conexiones Billetera", - error_name: "El nombre no puede estar vacío", - error_connection: "Fallo al crear Conexión Billetera", - error_budget_zero: "El presupuesto debe ser mayor a cero", - add_connection: "Agregar Conexión", - manage_connections: "Manejar Conexiones", - manage_gifts: "Manejar Regalos", - delete_connection: "Eliminar", - new_connection: "Nueva Conexión", - edit_connection: "Editar Conexión", - new_connection_label: "Nombre", - new_connection_placeholder: "Mi cliente nostr favorito...", - create_connection: "Crear Conexión", - save_connection: "Guardar Cambios", - edit_budget: "Editar Presupuesto", - open_app: "Abrir Aplicación", - open_in_nostr_client: "Abrir en Cliente Nostr", - open_in_primal: "Abrir en Primal", - nostr_client_not_found: "Cliente nostr no encontrado", - client_not_found_description: - "Instale un cliente nostr como Primal, Amethyst, o Damus para abrir este enlace.", - relay: "Relé", - authorize: - "Autoriza servicios externos para solicitar pagos desde su billetera. Combina muy bien con clientes Nostr.", - pending_nwc: { - title: "Solicitudes Pendientes", - approve_all: "Aprovar Todo", - deny_all: "Denegar Todo" - }, - careful: - "¡Tenga cuidado dónde comparte esta conexión! Solicitudes dentro del presupuesto serán pagadas automáticamente.", - spent: "Gastado", - remaining: "Restante", - confirm_delete: "¿Está seguro de querer eliminar esta conexión?", - budget: "Presupuesto", - resets_every: "Se restablece cada", - resubscribe_date: "Suscribirse de nuevo en" - }, - emergency_kit: { - title: "Kit de Emergencia", - caption: "Diagnostique y resuelva problemas con su billetera.", - emergency_tip: - "Si su billetera parece dañada, aquí hay algunas herramientas para tratar depurarla y repararla.", - questions: - "Si tiene preguntas acerca de qué hacen estos botones, por favor", - link: "contáctenos para recibir soporte.", - import_export: { - title: "Exportar estado de la billetera", - error_password: "Contraseña requerida", - error_read_file: "Error al leer archivo", - error_no_text: "No se encontró texto en el archivo", - tip: "Puede exportar todo el estado de su Billetera Mutiny a un archivo e importarlo a otro navegador ¡Usualmente funciona!", - caveat_header: "Advertencias importantes:", - caveat: "después de exportar no realice ninguna operación en el navegador original. Si lo hace, tendrá que exportar de nuevo. Después de una importación exitosa, una buena práctica es borrar el estado del navegador original solo para asegurarse de no crear conflictos.", - save_state: "Guardar Estado a Archivo", - import_state: "Importar Estado desde Archivo", - confirm_replace: "¿Desea reemplazar su estado con", - password: "Ingrese su contraseña para descifrar", - decrypt_wallet: "Descifrar Billetera" - }, - logs: { - title: "Descargar logs de depuración", - something_screwy: - "Algo raro está sucediendo? ¡Verifique los logs!", - download_logs: "Descargar logs", - password: "Ingrese su contraseña para cifrar", - confirm_password_label: "Confirme la Contraseña" - }, - delete_everything: { - delete: "Eliminar Todo", - confirm: - "Esto eliminará el estado de su nodo ¡Esto no puede ser deshecho!", - deleted: "Eliminado", - deleted_description: "Eliminados todos los datos" - } - }, - encrypt: { - title: "Cambiar Contraseña", - caption: "Haga un respaldo primero para desbloquear el cifrado", - header: "Cifre sus palabras semilla", - hot_wallet_warning: - 'Mutiny es una "billetera caliente" por lo que necesita sus palabras semilla para operar, pero usted puede opcionalmente cifrar esas palabras con una contraseña.', - password_tip: - "De esa manera, si alguien consigue acceder a su navegador, de todas maneras no tendrá acceso a sus fondos.", - optional: "(opcional)", - existing_password: "Constraseña existente", - existing_password_caption: - "Deje vacío si no ha establecido una contraseña todavía.", - new_password_label: "Contraseña", - new_password_placeholder: "Ingrese una contraseña", - new_password_caption: - "Esta contraseña será usada para cifrar sus palabras semilla. Si se le olvida, necesitará reingresar sus palabras semilla para acceder a sus fondos. Usted si escribió sus palabras semilla ¿correcto?", - confirm_password_label: "Confirme Contraseña", - confirm_password_placeholder: "Ingrese la misma contraseña", - encrypt: "Cifrar", - skip: "Saltar", - error_match: "Las contraseñas no coinciden", - error_same_as_existingpassword: - "La nueva contraseña no debe coincidir con la contraseña existente" - }, - decrypt: { - title: "Ingrese su contraseña", - decrypt_wallet: "Descifrar Billetera", - forgot_password_link: "¿Olvidó la Contraseña?", - error_wrong_password: "Contraseña Inválida" - }, - currency: { - title: "Moneda", - caption: "Escoja su par de monedas preferida", - select_currency: "Seleccione Moneda", - select_currency_label: "Par de Moneda", - select_currency_caption: - "Al escoger una nueva moneda se resincronizará la billetera para obtener una actualización del precio", - request_currency_support_link: "Solicite soporte para más monedas", - error_unsupported_currency: - "Por favor seleccione una moneda soportada." - }, - language: { - title: "Idioma", - caption: "Escoja su idioma preferido", - select_language: "Seleccione Idioma", - select_language_label: "Idioma", - select_language_caption: - "Al escoger un nuevo idioma se cambiará el lenguaje de la billetera, ignorando el idioma actual del navegador", - request_language_support_link: "Solicite soporte para más idiomas", - error_unsupported_language: - "Por favor seleccione un idioma soportado." - }, - lnurl_auth: { - title: "LNURL Auth", - auth: "Auth", - expected: "Esperando algo como LNURL..." - }, - plus: { - title: "Mutiny+", - join: "Unirse", - sats_per_month: "por {{amount}} sats por mes.", - lightning_balance: - "Necesitará por lo menos {{amount}} sats en su saldo lightning para empezar ¡Intente antes de comprar!", - restore: "Restaurar Suscripción", - ready_to_join: "Listo para unirse", - click_confirm: "Haga clic en confirmar para pagar su primer mes.", - open_source: "Mutiny es código abierto y auto-hospedable.", - optional_pay: "Pero también puede pagar por él.", - paying_for: "Pagando por", - supports_dev: - "ayuda a soportar el desarrollo continuo y desbloquea el acceso temprano a nuevas características y funcionalidad premium:", - thanks: "¡Usted hace parte del motín! Disfrute de las siguientes ventajas:", - renewal_time: "Recibirá una solicitud de renovación de pago hacia", - cancel: "Para cancelar su suscripción simplemente no pague. También puede deshabilitar el Mutiny+", - wallet_connection: "Conexión Billetera.", - subscribe: "Suscribirse", - error_no_plan: "No se encontraron planes", - error_failure: "No se pudo suscribir", - error_no_subscription: "No se encontró ninguna suscripción", - error_expired_subscription: - "Su suscripción ha expirado, haga clic en unirse para renovar", - satisfaction: "Satisfacción engreída", - gifting: "Regalos", - multi_device: "Acceso multi-dispositivo", - ios_testflight: "Acceso a iOS TestFlight", - more: "... y más por venir", - cta_description: - "Disfrute acceso temprano a nuevas características y funcionalidad premium.", - cta_but_already_plus: "¡Gracias por su apoyo!" - }, - restore: { - title: "Restaurar", - all_twelve: "Necesita ingresar todas las 12 palabras", - wrong_word: "Palabra equivocada", - paste: "Peligrosamente Pegar del Portapapeles", - confirm_text: - "¿Está seguro de querer restaurar a esta billetera? ¡Su billetera existente será eliminada!", - restore_tip: - "Podrá restaurar una Billetera Mutiny existente desde su frase de 12 palabras semilla. Esto reemplazará su billetera existente, ¡por lo tanto esté seguro de saber lo que está haciendo!", - multi_browser_warning: - "No use múltiples navegadores al mismo tiempo.", - error_clipboard: "Portapapeles no soportado", - error_word_number: "Número equivocado de palabras", - error_invalid_seed: "Frase semilla inválida" - }, - servers: { - title: "Servidores", - caption: - "¡No confíe en nosotros! Use sus propios servidores para respaldar Mutiny.", - link: "Aprenda más acerca de auto-hospedaje", - proxy_label: "Proxy de Websockets", - proxy_caption: - "Cómo su nodo de lightning se comunica con el resto de la red.", - error_proxy: "Debe ser una url comenzando con wss://", - esplora_label: "Esplora", - esplora_caption: "Datos de bloques para información en-cadena.", - error_esplora: "Eso no parece una URL", - rgs_label: "RGS", - rgs_caption: - "Rapid Gossip Sync. Datos de red sobre la red de lightning usados para enrutamiento.", - error_rgs: "Eso no parece una URL", - lsp_label: "LSP", - lsp_caption: - "Lightning Service Provider. Automáticamente abre canales hacia usted para liquidez entrante. También envuelve facturas para privacidad.", - lsps_connection_string_label: - "Cadena de Caracteres de Conexión LSPS", - lsps_connection_string_caption: - "Lightning Service Provider. Automáticamente abre canales hacia usted para liquidez entrante. Usando la especificación LSP.", - error_lsps_connection_string: - "Eso no parece una cadena de caracteres de conexión", - lsps_token_label: "Token LSPS", - lsps_token_caption: - "Token LSPS. Usado para identificar qué billetera está conectando al LSP", - lsps_valid_error: - "Puede tener tan solo un LSP establecido o una Cadena de Caracteres de Conexión LSPS y Token LSPS establecidos, no ambos.", - error_lsps_token: "Eso no parece un token válido", - storage_label: "Almacenamiento", - storage_caption: "Servicio de respaldo VSS cifrado.", - error_lsp: "Eso no parece un URL", - save: "Guardar" - }, - nostr_contacts: { - title: "Sincronizar Contactos Nostr", - npub_label: "npub nostr", - npub_required: "Npub no puede estar vacío", - sync: "Sincronizar", - resync: "Resincronizar", - remove: "Eliminar" - }, - manage_federations: { - title: "Manejar Federaciones", - federation_code_label: "Código federación", - federation_code_required: "Código federación no puede estar vacío", - federation_added_success: "Federación agregada exitosamente", - federation_remove_confirm: - "¿Esta seguro de querer eliminar esta federación? Asegúrese primero de que sus fondos sean transferidos a su balance lightning u otra billetera.", - add: "Agregar", - remove: "Eliminar", - expires: "Expira", - federation_id: "ID federación", - description: - "Mutiny tiene soporte experimental para el protocolo Fedimint. Necesitará un código de invitación a la federación para poder usar esta funcionalidad ¡Almacene fondos en una federación bajo su propio riesgo!", - learn_more: "Aprenda más sobre Fedimint." - }, - gift: { - give_sats_link: "Dar sats de regalo", - title: "Regalo", - no_plus_caption: "Actualice a Mutiny+ para habilitar regalos", - receive_too_small: - "Su primera recepción debe ser de {{amount}} SATS o más.", - setup_fee_lightning: - "Una comisión de instalación de lightning será cargada para recibir este regalo.", - already_claimed: "Este regalo ya ha sido reclamado", - sender_is_poor: - "El remitente no tiene suficiente saldo para pagar este regalo.", - sender_timed_out: - "Se agotó el tiempo para el pago del regalo. El remitente puede estar desconectado, o este regalo ya ha sido reclamado.", - sender_generic_error: "Remitente envió error: {{error}}", - receive_header: "¡Le han regalado algunos sats!", - receive_description: - "Usted debe ser bastante especial. Para reclamar su dinero simplemente presione el botón grande. Los fondos serán agregados a esta billetera la próxima vez que el remitente se conecte.", - receive_claimed: - "¡Regalo reclamado! Deberá ver el regalo reflejado en el balance en breve.", - receive_cta: "Reclamar Regalo", - receive_try_again: "Intente de Nuevo", - send_header: "Crear Regalo", - send_explainer: - "Regale sats. Cree una URL de regalo de Mutiny que pueda ser reclamado por cualquiera con un navegador.", - send_name_required: "Esto es para sus registros", - send_name_label: "Nombre del Recipiente", - send_header_claimed: "¡Regalo Recibido!", - send_claimed: "Su regalo ha sido reclamado. Gracias por compartir.", - send_sharable_header: "URL compartible", - send_instructions: - "Copie este URL de regalo a su recipiente, o pídale que escanee este código QR con su billetera.", - send_another: "Crear Otro", - send_small_warning: - "Un usuario nuevo de Mutiny no podrá redimir menos de 100k sats.", - send_cta: "Crear un regalo", - send_delete_button: "Eliminar Regalo", - send_delete_confirm: - "¿Está seguro de querer eliminar este regalo? ¿Es este su momento de tirar de la alfombra?", - send_tip: - "Su copia de la Billetera Mutiny necesita estar abierta para que el regalo sea reclamado.", - need_plus: - "Actualice a Mutiny+ para habilitar regalos. La funcionalidad de regalos le permite crear una URL de regalo de Mutiny que puede ser reclamado por cualquiera con un navegador." - } - }, - swap: { - peer_not_found: "Par no encontrado", - channel_too_small: - "Es simplemente tonto crear un canal más pequeño que {{amount}} sats", - insufficient_funds: "No tiene suficientes fondos para crear este canal", - header: "Hacer un Swap a Lightning", - initiated: "Swap Iniciado", - sats_added: "+{{amount}} sats serán agregados a su balance lightning", - use_existing: "Usar par existente", - choose_peer: "Escoja un par", - peer_connect_label: "Conectar a un par nuevo", - peer_connect_placeholder: "Cadena de caracteres de conexión a par", - connect: "Conectar", - connecting: "Conectando...", - confirm_swap: "Confirmar Swap" - }, - swap_lightning: { - insufficient_funds: - "No tiene fondos suficientes para hacer swap a lightning", - header: "Hacer Swap a Lightning", - header_preview: "Previsualizar Swap", - completed: "Swap Completado", - too_small: - "Monto invalido ingresado. Tiene que hacer un swap de por lo menos 100k sats.", - sats_added: - "+{{amount}} sats han sido agregados a su balance de Lightning", - sats_fee: "+{{amount}} sats de comisión", - confirm_swap: "Confirmar Swap", - preview_swap: "Previsualizar Comisión de Swap" - }, - reload: { - mutiny_update: "Actualización de Mutiny", - new_version_description: - "Una nueva versión de Mutiny ha sido almacenada en el caché, recargue para empezar a usarla.", - reload: "Recargar" - }, - error: { - title: "Error", - emergency_link: "kit de emergencia.", - reload: "Recargar", - restart: { - title: "¿Algo *extra* absurdo sucediendo? ¡Detenga los nodos!", - start: "Iniciar", - stop: "Parar" - }, - general: { - oh_no: "¡Oh no!", - never_should_happen: "Esto nunca debió suceder", - try_reloading: - 'Intente recargar esta página o haga clic en el botón "Qué Pena". Si continua teniendo problemas,', - support_link: "contáctenos para recibir soporte.", - getting_desperate: "¿Desesperado? Intente" - }, - load_time: { - stuck: "¿Atascado en esta pantalla? Intente recargar. Si eso no funciona, intente" - }, - not_found: { - title: "No Encontrado", - wtf_paul: "Esto es probablemente culpa de Paul." - }, - reset_router: { - payments_failing: - "¿No puede hacer pagos? Intente reiniciar el enrutador de lightning.", - reset_router: "Reiniciar Enrutador" - }, - resync: { - incorrect_balance: - "¿El balance en-cadena parece incorrecto? Intente resincronizar la billetera en-cadena.", - resync_wallet: "Resincronizar billetera" - }, - on_boot: { - existing_tab: { - title: "Múltiples pestañas detectadas", - description: - "Mutiny solo puede ser usado en una pestaña a la vez. Parece que tiene otra pestaña abierta con Mutiny ejecutándose. Por favor cierre esa pestaña y refresque esta página, o cierre esta pestaña y refresque la otra." - }, - already_running: { - title: "Mutiny puede estar ejecutándose en otro dispositivo", - description: - "Mutiny solo puede ser usado en un lugar a la vez. Parece que tiene otro dispositivo o navegador usando esta billetera. Si ha cerrado Mutiny recientemente en otro dispositivo, por favor espere unos minutos e intente de nuevo.", - retry_again_in: "Intente de nuevo en", - seconds: "segundos" - }, - incompatible_browser: { - title: "Navegador incompatible", - header: "Navegador incompatible detectado", - description: - "Mutiny requiere un navegador moderno que soporte WebAssembly, LocalStorage, e IndexedDB. Algunos navegadores deshabilitan estas funcionalidades en modo privado.", - try_different_browser: - 'Por favor asegúrese de que su navegador soporte todas estas funcionalidades, o considere intentar con otro navegador. También puede intentar deshabilitar ciertas extensiones o "escudos" que puedan bloquear estas funcionalidades.', - browser_storage: - "(Nos encantaría soportar más navegadores privados, pero tenemos que guardar los datos de su billetera en el almacenamiento del navegador o de lo contrario perdería esos fondos.)", - browsers_link: "Navegadores Soportados" - }, - loading_failed: { - title: "Fallo al cargar", - header: "Fallo al cargar Mutiny", - description: "Algo no funcionó al iniciar la Billetera Mutiny.", - repair_options: - "Si su billetera parece dañada, aquí hay algunas herramientas para tratar depurarla y repararla.", - questions: - "Si tiene alguna pregunta acerca de qué hacen estos botones, por favor", - support_link: "contáctenos para recibir soporte.", - services_down: - "Parece que uno de los servicios de Mutiny está abajo. Por favor intente de nuevo más tarde.", - in_the_meantime: - "Mientras tanto si desea acceder a sus fondos en-cadena puede cargar Mutiny en", - safe_mode: "Modo Seguro" - } - } - }, - modals: { - share: "Compartir", - details: "Detalles", - loading: { - loading: "Cargando: {{stage}}", - default: "Apenas empezando", - double_checking: "Verificando de nuevo algo", - downloading: "Descargando", - setup: "Configuración", - done: "Hecho" - }, - onboarding: { - welcome: "¡Bienvenido!", - restore_from_backup: - "Si ha usado Mutiny antes puede restaurar desde un respaldo ¡De lo contrario puede saltarse esto y disfrutar su nueva billetera!", - not_available: "Todavía no hacemos eso", - secure_your_funds: "Asegure sus fondos" - }, - more_info: { - whats_with_the_fees: "¿Cuál es el asunto con las comisiones?", - self_custodial: - "Mutiny es una billetera auto-custodial. Para iniciar un pago lightning debemos abrir un canal lightning, lo que requiere un monto mínimo y una comisión de instalación.", - future_payments: - "Pagos futuros, tanto envíos como recepciones, solamente incurrirán en comisiones de red y una comisión nominal de servicio a menos de que su canal se quede sin capacidad entrante.", - liquidity: "Aprenda más sobre liquidez" - }, - confirm_dialog: { - are_you_sure: "¿Está seguro?", - cancel: "Cancelar", - confirm: "Confirmar" - }, - lnurl_auth: { - auth_request: "Solicitud de autenticación", - login: "Acceder", - decline: "Declinar", - error: "Eso no funcionó por alguna razón.", - authenticated: "¡Autenticado!" - } - } -}; diff --git a/src/i18n/i18next.d.ts b/src/i18n/i18next.d.ts deleted file mode 100644 index c7db5d40..00000000 --- a/src/i18n/i18next.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { defaultNS, resources } from "~/i18n/config"; - -declare module "i18next" { - interface CustomTypeOptions { - defaultNS: typeof defaultNS; - resources: (typeof resources)["en"]; - returnNull: false; - } -} diff --git a/src/i18n/ko/translations.ts b/src/i18n/ko/translations.ts deleted file mode 100644 index 0082b3f9..00000000 --- a/src/i18n/ko/translations.ts +++ /dev/null @@ -1,514 +0,0 @@ -export default { - common: { - title: "Mutiny 지갑", - nice: "멋지다", - home: "홈", - sats: "SATS", - sat: "SAT", - usd: "USD", - fee: "수수료", - send: "보내기", - receive: "받기", - dangit: "땡글", - back: "뒤로", - coming_soon: "(곧 출시 예정)", - copy: "복사", - copied: "복사됨", - continue: "계속", - error_unimplemented: "미구현", - why: "왜?", - view_transaction: "거래 보기", - private_tags: "비공개 태그", - pending: "대기 중" - }, - contacts: { - new: "새로 만들기", - add_contact: "연락처 추가", - new_contact: "새 연락처", - create_contact: "연락처 생성", - edit_contact: "연락처 수정", - save_contact: "연락처 저장", - payment_history: "결제 기록", - no_payments: "아직 결제 기록이 없습니다.", - edit: "수정", - pay: "지불", - name: "이름", - placeholder: "사토시", - unimplemented: "미구현", - not_available: "아직 제공되지 않습니다.", - error_name: "이름은 필수입니다." - }, - receive: { - receive_bitcoin: "비트코인 받기", - edit: "수정", - checking: "확인 중", - choose_format: "포맷 선택", - payment_received: "결제 완료", - payment_initiated: "결제 시작됨", - receive_add_the_sender: "송신자를 기록에 추가하세요.", - choose_payment_format: "결제 포맷 선택", - unified_label: "통합", - unified_caption: - "비트코인 주소와 라이트닝 인보이스를 결합합니다. 송신자가 결제 방법을 선택합니다.", - lightning_label: "라이트닝 인보이스", - lightning_caption: - "작은 거래에 적합합니다. 보통 온체인 수수료보다 낮습니다.", - onchain_label: "비트코인 주소", - onchain_caption: - "온체인, 사토시가 한 것처럼. 아주 큰 거래에 적합합니다.", - unified_setup_fee: - "라이트닝으로 지불하는 경우 {{amount}} SATS의 라이트닝 설치 비용이 부과됩니다.", - lightning_setup_fee: - "이 받기에는 {{amount}} SATS의 라이트닝 설치 비용이 부과됩니다.", - amount: "금액", - fee: "+ 수수료", - total: "합계", - spendable: "사용 가능", - channel_size: "채널 크기", - channel_reserve: "- 채널 예비금", - amount_editable: { - receive_too_small: - "첫 라이트닝 받기는 {{amount}} SATS 이상이어야 합니다. 요청한 금액에서 설정 비용이 차감됩니다.", - setup_fee_lightning: - "라이트닝으로 지불하는 경우 라이트닝 설치 비용이 부과됩니다.", - more_than_21m: "비트코인은 총 2,100만 개밖에 없습니다.", - set_amount: "금액 설정", - max: "최대", - fix_amounts: { - ten_k: "1만", - one_hundred_k: "10만", - one_million: "100만" - }, - del: "삭제" - }, - integrated_qr: { - onchain: "온체인", - lightning: "라이트닝", - unified: "통합" - } - }, - send: { - sending: "보내는 중...", - confirm_send: "보내기 확인", - contact_placeholder: "기록을 위해 수신자 추가", - start_over: "다시 시작", - paste: "붙여넣기", - scan_qr: "QR 스캔", - payment_initiated: "결제 시작됨", - payment_sent: "결제 완료", - destination: "수신처", - progress_bar: { - of: "/", - sats_sent: "SATS 보냄" - }, - error_low_balance: "지불할 금액보다 충분한 잔액이 없습니다.", - error_clipboard: "클립보드를 지원하지 않습니다.", - error_keysend: "KeySend 실패", - error_LNURL: "LNURL Pay 실패" - }, - feedback: { - header: "피드백 주세요!", - received: "피드백이 수신되었습니다!", - thanks: "문제가 발생했음을 알려주셔서 감사합니다.", - more: "더 하실 말씀이 있으신가요?", - tracking: - "Mutiny는 사용자 행동을 추적하거나 감시하지 않기 때문에 피드백이 매우 유용합니다.", - github_one: "GitHub에 익숙하시다면", - github_two: "를 사용하여", - create_issue: "이슈를 생성하세요", - link: "피드백?", - feedback_placeholder: "버그, 기능 요청, 피드백 등", - info_label: "연락처 정보 포함", - info_caption: "문제에 대한 후속 조치를 필요로 하는 경우", - email: "이메일", - email_caption: "일회용 이메일 사용 가능", - nostr: "Nostr", - nostr_caption: "신선한 npub", - nostr_label: "Nostr npub 또는 NIP-05", - send_feedback: "피드백 보내기", - invalid_feedback: "피드백을 입력하세요.", - need_contact: "연락처 정보가 필요합니다.", - invalid_email: "올바른 이메일 주소가 아닙니다.", - error: "피드백 전송 오류", - try_again: "나중에 다시 시도하세요." - }, - activity: { - title: "활동", - mutiny: "Mutiny", - nostr: "Nostr", - view_all: "전체 보기", - receive_some_sats_to_get_started: "시작하려면 일부 SATS를 받으세요", - channel_open: "채널 오픈", - channel_close: "채널 닫기", - unknown: "알 수 없음", - import_contacts: - "Nostr에서 연락처를 가져와 누가 체널을 열고 있는지 확인하세요.", - coming_soon: "곧 출시 예정", - transaction_details: { - lightning_receive: "라이트닝 입금", - lightning_send: "라이트닝 송금", - channel_open: "채널 개설", - channel_close: "채널 종료", - onchain_receive: "체인상 입금", - onchain_send: "체인상 송금", - paid: "지불 완료", - unpaid: "미지불", - status: "상태", - when: "시간", - description: "설명", - fee: "수수료", - fees: "수수료", - bolt11: "Bolt11", - payment_hash: "지불 해시", - preimage: "사전 이미지", - txid: "거래 ID", - balance: "잔고", - reserve: "리저브", - peer: "피어", - channel_id: "채널 ID", - reason: "이유", - confirmed: "확인됨", - unconfirmed: "확인 대기", - no_details: - "채널 상세정보를 찾을 수 없습니다. 이는 해당 채널이 종료된 것으로 보입니다." - } - }, - scanner: { - paste: "붙여넣기", - cancel: "취소" - }, - settings: { - header: "설정", - support: "Mutiny 지원 방법 알아보기", - general: "일반", - experimental_features: "실험", - debug_tools: "디버그 도구", - danger_zone: "위험 지역", - admin: { - title: "관리자 페이지", - caption: "내부 디버그 도구입니다. 신중하게 사용하세요!", - header: "비밀 디버그 도구", - warning_one: "잘 알고 있는 경우 올바른 위치입니다.", - warning_two: - "디버그 및 테스트에 사용하는 내부 도구입니다. 주의하세요!", - kitchen_sink: { - disconnect: "연결 끊기", - peers: "피어", - no_peers: "피어 없음", - refresh_peers: "피어 새로고침", - connect_peer: "피어 연결", - expect_a_value: "값을 입력하세요...", - connect: "연결", - close_channel: "채널 종료", - force_close: "강제 종료", - abandon_channel: "채널 포기", - confirm_close_channel: "이 채널을 종료하시겠습니까?", - confirm_force_close: - "이 채널을 강제로 종료하시겠습니까? 자금은 몇 일 이후에 체인상에서 사용 가능해집니다.", - confirm_abandon_channel: - "이 채널을 포기하시겠습니까? 대개 개방 트랜잭션이 확인되지 않는다면 이렇게 하십시오. 그렇지 않으면 자금을 잃게 될 수 있습니다.", - channels: "채널", - no_channels: "채널 없음", - refresh_channels: "채널 새로고침", - pubkey: "퍼블릭 키", - amount: "금액", - open_channel: "채널 개설", - nodes: "노드", - no_nodes: "노드 없음" - } - }, - backup: { - title: "백업", - secure_funds: "자금을 안전하게 보호하세요.", - twelve_words_tip: - "12개의 단어를 보여드립니다. 12개의 단어를 기록하세요.", - warning_one: - "브라우저 기록을 지우거나 기기를 분실하면 이 12개의 단어만으로 지갑을 복원할 수 있습니다.", - warning_two: - "Mutiny는 사용자의 자산을 사용자 스스로 관리해야 합니다...", - confirm: "12개의 단어를 기록했습니다.", - responsibility: "자금이 사용자 스스로의 책임임을 이해합니다.", - liar: "속이려는 것이 아닙니다.", - seed_words: { - reveal: "씨드 단어 공개", - hide: "숨기기", - copy: "클립보드에 복사", - copied: "복사됨!" - } - }, - channels: { - title: "라이트닝 채널", - outbound: "송신", - inbound: "수신", - have_channels: "라이트닝 채널이", - have_channels_one: "개 있습니다.", - have_channels_many: "개 있습니다.", - inbound_outbound_tip: - "송신은 라이트닝으로 지출할 수 있는 금액을 나타냅니다. 수신은 수수료 없이 받을 수 있는 금액을 나타냅니다.", - no_channels: - "아직 채널이 없는 것 같습니다. 먼저 라이트닝으로 몇 sats를 받거나 체인상 자금을 채널로 바꾸세요. 시작해보세요!" - }, - connections: { - title: "지갑 연결", - error_name: "이름을 입력하세요.", - error_connection: "지갑 연결 생성에 실패했습니다.", - add_connection: "연결 추가", - manage_connections: "연결 관리", - disable_connection: "비활성화", - enable_connection: "활성화", - new_connection: "새로운 연결", - new_connection_label: "이름", - new_connection_placeholder: "내가 좋아하는 nostr 클라이언트...", - create_connection: "연결 생성", - open_app: "앱 열기", - open_in_nostr_client: "Nostr 클라이언트에서 열기", - open_in_primal: "Primal에서 열기", - authorize: - "외부 서비스가 지갑에서 결제를 요청할 수 있도록 인증합니다. nostr 클라이언트와 잘 맞습니다.", - pending_nwc: { - title: "대기 중인 요청", - configure_link: "설정" - } - }, - emergency_kit: { - title: "비상 키트", - caption: "지갑 문제를 진단하고 해결하는 도구입니다.", - emergency_tip: - "지갑이 망가지는 것 같다면 이 도구를 사용하여 문제를 진단하고 해결하세요.", - questions: - "이 버튼들이 무엇을 하는지 궁금하다면, 지원을 받으시려면", - link: "연락처를 통해 문의해주세요.", - import_export: { - title: "지갑 상태 내보내기", - error_password: "비밀번호가 필요합니다.", - error_read_file: "파일 읽기 오류", - error_no_text: "파일에서 텍스트를 찾을 수 없습니다.", - tip: "Mutiny 지갑 상태 전체를 파일로 내보내서 새 브라우저에 가져와서 복원할 수 있습니다. 보통 동작합니다!", - caveat_header: "주의 사항:", - caveat: "내보낸 후에는 원래 브라우저에서 아무 동작도 수행하지 마세요. 그렇게 하면 다시 내보내야 합니다. 성공적인 가져오기 후에는 원래 브라우저의 상태를 초기화하는 것이 좋습니다.", - save_state: "상태를 파일로 저장", - import_state: "파일에서 상태 가져오기", - confirm_replace: "상태를 다음으로 대체하시겠습니까?", - password: "복호화를 위해 비밀번호 입력", - decrypt_wallet: "지갑 복호화" - }, - logs: { - title: "디버그 로그 다운로드", - something_screwy: "문제가 발생했나요? 로그를 확인하세요!", - download_logs: "로그 다운로드" - }, - delete_everything: { - delete: "모두 삭제", - confirm: "노드 상태가 모두 삭제됩니다. 복구할 수 없습니다!", - deleted: "삭제됨", - deleted_description: "모든 데이터 삭제됨" - } - }, - encrypt: { - header: "시드 단어 암호화", - hot_wallet_warning: - "Mutiny는 ”핫 월렛”이므로 시드 단어를 사용하여 작동하지만 선택적으로 비밀번호로 암호화할 수 있습니다.", - password_tip: - "이렇게 하면 다른 사람이 브라우저에 접근하더라도 자금에 접근할 수 없습니다.", - optional: "(선택 사항)", - existing_password: "기존 비밀번호", - existing_password_caption: - "비밀번호를 설정하지 않았다면 비워 두세요.", - new_password_label: "비밀번호", - new_password_placeholder: "비밀번호를 입력하세요", - new_password_caption: - "이 비밀번호는 시드 단어를 암호화하는 데 사용됩니다. 이를 잊어버리면 자금에 접근하려면 시드 단어를 다시 입력해야 합니다. 시드 단어를 기록해 두었나요?", - confirm_password_label: "비밀번호 확인", - confirm_password_placeholder: "동일한 비밀번호를 입력하세요", - encrypt: "암호화", - skip: "건너뛰기", - error_match: "비밀번호가 일치하지 않습니다." - }, - - decrypt: { - title: "비밀번호를 입력하세요", - decrypt_wallet: "지갑 복호화", - forgot_password_link: "비밀번호를 잊으셨나요?", - error_wrong_password: "유효하지 않은 비밀번호" - }, - lnurl_auth: { - title: "LNURL 인증", - auth: "인증", - expected: "LNURL과 같은 형식으로 입력해주세요." - }, - plus: { - title: "Mutiny+", - join: "가입", - for: "에 대해", - sats_per_month: "sats 월별 비용입니다.", - you_need: "적어도 다음 금액이 필요합니다.", - lightning_balance: - "라이트닝 잔액에서 sats를 지불하세요. 먼저 시험해보세요!", - restore: "구독 복원", - ready_to_join: "가입할 준비가 되었습니다.", - click_confirm: "첫 달 비용을 지불하려면 확인을 클릭하세요.", - open_source: "Mutiny는 오픈 소스이며 스스로 호스팅할 수 있습니다.", - optional_pay: "또한 지불할 수도 있습니다.", - paying_for: "지불 대상:", - supports_dev: - "는 지속적인 개발을 지원하고 새 기능과 프리미엄 기능의 조기 액세스를 제공합니다.", - thanks: "Mutiny의 일원이 되셨습니다! 다음 혜택을 즐기세요:", - renewal_time: "다음 시기에 갱신 요청이 도착합니다.", - cancel: "구독을 취소하려면 결제하지 않으세요. 또는 Mutiny+ 기능을 비활성화할 수도 있습니다.", - wallet_connection: "지갑 연결 기능.", - subscribe: "구독하기", - error_no_plan: "", - error_failure: "", - error_no_subscription: "기존 구독이 없습니다.", - satisfaction: "만족함", - gifting: "선물하기", - multi_device: "다중 장치 접속", - more: "... 그리고 더 많은 기능이 추가될 예정입니다." - }, - restore: { - title: "복원", - all_twelve: "12개 단어를 모두 입력해야 합니다.", - wrong_word: "잘못된 단어", - paste: "클립보드에서 붙여넣기 (위험)", - confirm_text: - "이 지갑으로 복원하시겠습니까? 기존 지갑이 삭제됩니다!", - restore_tip: - "기존 Mutiny 지갑을 12개의 씨드 단어로 복원할 수 있습니다. 기존 지갑이 대체됩니다. 신중하게 사용하세요!", - multi_browser_warning: "여러 브라우저에서 동시에 사용하지 마세요.", - error_clipboard: "클립보드를 지원하지 않습니다.", - error_word_number: "잘못된 단어 개수", - error_invalid_seed: "잘못된 씨드 단어입니다." - }, - servers: { - title: "서버", - caption: - "우리를 믿지 마세요! Mutiny를 백업하기 위해 자체 서버를 사용하세요.", - link: "자체 호스팅에 대해 자세히 알아보기", - proxy_label: "웹소켓 프록시", - proxy_caption: "라이트닝 노드가 네트워크와 통신하는 방법입니다.", - error_proxy: "wss://로 시작하는 URL이어야 합니다.", - esplora_label: "Esplora", - esplora_caption: "온체인 정보를 위한 블록 데이터입니다.", - error_esplora: "URL처럼 보이지 않습니다.", - rgs_label: "RGS", - rgs_caption: - "Rapid Gossip Sync. 라우팅을 위해 사용되는 라이트닝 네트워크에 대한 네트워크 데이터입니다.", - error_rgs: "URL처럼 보이지 않습니다.", - lsp_label: "LSP", - lsp_caption: - "라이트닝 서비스 공급자. 인바운드 유동성을 위해 자동으로 채널을 열고, 개인 정보 보호를 위해 인보이스를 래핑합니다.", - error_lsp: "URL처럼 보이지 않습니다.", - save: "저장" - } - }, - swap: { - peer_not_found: "피어를 찾을 수 없음", - channel_too_small: - "{{amount}} sats보다 작은 채널을 만드는 것은 그저 어리석은 짓입니다.", - insufficient_funds: "이 채널을 만들기에 충분한 자금이 없습니다.", - header: "라이트닝으로 스왑", - initiated: "스왑 시작됨", - sats_added: "sats가 라이트닝 잔액에 추가됩니다.", - use_existing: "기존 피어 사용", - choose_peer: "피어 선택", - peer_connect_label: "새 피어 연결", - peer_connect_placeholder: "피어 연결 문자열", - connect: "연결", - connecting: "연결 중...", - confirm_swap: "스왑 확인" - }, - error: { - title: "오류", - emergency_link: "긴급 킷.", - restart: "문제가 *더* 발생했나요? 노드를 중지하세요!", - general: { - oh_no: "앗!", - never_should_happen: "이런 일은 일어나면 안 됩니다.", - try_reloading: - "이 페이지를 새로 고치거나 ”얘들아” 버튼을 눌러보세요. 계속해서 문제가 발생하면", - support_link: "지원을 요청하세요.", - getting_desperate: "좀 답답하신가요? 다음을 시도해보세요." - }, - load_time: { - stuck: "이 화면에 멈춰있나요? 다시 로드해보세요. 그래도 동작하지 않으면 다음을 확인하세요." - }, - not_found: { - title: "찾을 수 없음", - wtf_paul: "이건 아마 폴의 잘못입니다." - }, - reset_router: { - payments_failing: - "결제 실패하고 있나요? 라이트닝 라우터를 초기화해보세요.", - reset_router: "라우터 초기화" - }, - resync: { - incorrect_balance: - "온체인 잔액이 잘못된 것 같나요? 온체인 월렛을 다시 동기화해보세요.", - resync_wallet: "월렛 다시 동기화" - }, - on_boot: { - existing_tab: { - title: "여러 탭 감지됨", - description: - "현재 Mutiny Wallet을 한 번에 한 탭에서만 사용할 수 있습니다. Mutiny가 실행 중인 다른 탭이 열려 있습니다. 해당 탭을 닫고 이 페이지를 새로 고치거나, 이 탭을 닫고 다른 탭을 새로 고치세요." - }, - incompatible_browser: { - title: "호환되지 않는 브라우저", - header: "호환되지 않는 브라우저가 감지되었습니다.", - description: - "Mutiny Wallet은 WebAssembly, LocalStorage 및 IndexedDB를 지원하는 현대적인 브라우저를 필요로 합니다. 일부 브라우저는 이러한 기능을 비활성화하는 경우도 있습니다.", - try_different_browser: - "이러한 모든 기능을 지원하는 브라우저를 사용하는지 확인하거나 다른 브라우저를 시도하세요. 또는 이러한 기능을 차단하는 특정 확장 기능이나 ”보호 기능”을 비활성화해보세요.", - browser_storage: - "(더 많은 프라이버시 브라우저를 지원하고 싶지만, 월렛 데이터를 브라우저 저장소에 저장해야 하므로 그렇게 할 수 없습니다. )", - browsers_link: "지원되는 브라우저" - }, - loading_failed: { - title: "로드 실패", - header: "Mutiny 로드 실패", - description: - "Mutiny Wallet을 부팅하는 동안 문제가 발생했습니다.", - repair_options: - "월렛이 손상된 것 같다면, 디버그 및 복구를 시도하기 위한 몇 가지 도구입니다.", - questions: "이러한 버튼이 무엇을 하는지 궁금하다면,", - support_link: "지원을 요청하세요." - } - } - }, - modals: { - share: "공유", - details: "상세정보", - loading: { - loading: "로딩 중:", - default: "시작 중", - double_checking: "검증 중", - downloading: "다운로드 중", - setup: "설정 중", - done: "완료" - }, - onboarding: { - welcome: "환영합니다!", - restore_from_backup: - "이미 Mutiny를 사용한 적이 있으시다면 백업에서 복원할 수 있습니다. 그렇지 않다면 이 단계를 건너뛰고 새로운 지갑을 즐기실 수 있습니다!", - not_available: "아직 이 기능은 지원하지 않습니다", - secure_your_funds: "자금을 안전하게 보호하세요" - }, - more_info: { - whats_with_the_fees: "수수료는 어떻게 되나요?", - self_custodial: - "Mutiny는 자체 보관 월렛입니다. 라이트닝 지불을 시작하려면 라이트닝 채널을 개설해야 하며, 이는 최소 금액과 설정 비용이 필요합니다.", - future_payments: - "앞으로의 송금 및 입금은 일반 네트워크 수수료와 노말 서비스 수수료만 부과되며, 채널에 인바운드 용량이 부족한 경우에만 추가 수수료가 발생합니다.", - liquidity: "유동성에 대해 자세히 알아보기" - }, - confirm_dialog: { - are_you_sure: "확실합니까?", - cancel: "취소", - confirm: "확인" - } - }, - create_an_issue: "이슈 생성", - send_bitcoin: "비트코인 전송", - continue: "계속하기", - keep_mutiny_open: "결제를 완료하기 위해 Mutiny를 열어두세요." -}; diff --git a/src/i18n/pt/translations.ts b/src/i18n/pt/translations.ts deleted file mode 100644 index ed99d695..00000000 --- a/src/i18n/pt/translations.ts +++ /dev/null @@ -1,21 +0,0 @@ -export default { - create_an_issue: "Crie uma issue", - view_all: "Ver todas", - receive_some_sats_to_get_started: "Receba alguns satoshis para começar", - send_bitcoin: "Enviar Bitcoin", - view_transaction: "Ver transação", - amount_editable_first_payment_10k_or_greater: - "Seu primeiro recebimento na lightning precisa ser de pelo menos 10.000 sats. Uma taxa de configuração será deduzida da quantidade requisitada.", - "why?": "Por que?", - more_info_modal_p1: - "Mutiny é uma carteira de auto custódia. Para iniciar um pagamento na lightning, nós precisamos abrir um canal que requer uma quantidade mínima e uma taxa de configuração.", - more_info_modal_p2: - "Transaçoēs futuras, como envios e recebimentos, terão somente taxas normais da rede e uma taxa de serviço nominal a não ser que seu canal fique sem capacidade de entrada.", - learn_more_about_liquidity: "Aprenda mais sobre liquidez", - set_amount: "Definir quantidade", - whats_with_the_fees: "O que há com as taxas?", - private_tags: "Tags privadas", - receive_add_the_sender: "Marque quem o enviou para registro próprio", - continue: "Continuar", - receive_bitcoin: "Receber Bitcoin" -}; diff --git a/tools/internal-rules/.eslintrc.js b/tools/internal-rules/.eslintrc.js deleted file mode 100644 index 769d038b..00000000 --- a/tools/internal-rules/.eslintrc.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; - -module.exports = { - root: true, - extends: [ - "eslint:recommended", - "plugin:eslint-plugin/recommended", - "plugin:node/recommended" - ], - env: { - node: true - }, - overrides: [ - { - files: ["tests/**/*.js"], - env: { mocha: true } - } - ] -}; diff --git a/tools/internal-rules/lib/index.js b/tools/internal-rules/lib/index.js deleted file mode 100644 index 3bd8fc7c..00000000 --- a/tools/internal-rules/lib/index.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @fileoverview internal eslint rules - * @author - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const requireIndex = require("requireindex"); - -//------------------------------------------------------------------------------ -// Plugin Definition -//------------------------------------------------------------------------------ - -// import all rules in lib/rules -module.exports.rules = requireIndex(__dirname + "/rules"); diff --git a/tools/internal-rules/lib/rules/check-i18n-keys.js b/tools/internal-rules/lib/rules/check-i18n-keys.js deleted file mode 100644 index 7b61d877..00000000 --- a/tools/internal-rules/lib/rules/check-i18n-keys.js +++ /dev/null @@ -1,98 +0,0 @@ -"use strict"; - -const fs = require("fs"); -const path = require("path"); -const { parse } = require("@babel/parser"); - -module.exports = { - meta: { - name: "check-i18n-keys", - type: "suggestion", - docs: { - description: - "Ensure translation keys in other language files match the keys in the English translation file.", - category: "Best Practices", - recommended: true - }, - fixable: null, - schema: [] - }, - create: function (context) { - function extractKeys(node, parentKey = "") { - const keys = []; - let properties = node.properties; - - if (typeof node === "string") { - const fileContent = fs.readFileSync(node, "utf8"); - const ast = parse(fileContent, { - sourceType: "module", - plugins: ["typescript", "jsx"] - }); - properties = - !!ast && ast.program.body[0].declaration.properties; - } - - function traverseProperties(properties, parentKey) { - properties.forEach((property) => { - if ( - (property.type === "ObjectProperty" || - property.type === "Property") && - property.key.type === "Identifier" - ) { - const currentKey = parentKey - ? `${parentKey}.${property.key.name}` - : property.key.name; - keys.push(currentKey); - if (property.value.type === "ObjectExpression") { - traverseProperties( - property.value.properties, - currentKey - ); - } - } - }); - } - - traverseProperties(properties, parentKey); - - return keys; - } - - return { - Program(node) { - for (const statement of node.body) { - const fallbackFilePath = path - .relative(process.cwd(), context.getFilename()) - .replace( - /\/i18n\/\w+\/translations\.ts$/, - "/i18n/en/translations.ts" - ); - - const keys = extractKeys(statement.declaration); - - const enKeys = extractKeys(fallbackFilePath); - - // Report missing keys - enKeys.forEach((enKey) => { - if (!keys.includes(enKey)) { - context.report({ - node: node, - message: `missing key '${enKey}'` - }); - } - }); - - // Report extra keys - keys.forEach((key) => { - if (!enKeys.includes(key)) { - context.report({ - node: node, - message: `extra key '${key}'` - }); - } - }); - } - } - }; - } -}; diff --git a/tools/internal-rules/package.json b/tools/internal-rules/package.json deleted file mode 100644 index b19f160d..00000000 --- a/tools/internal-rules/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "eslint-plugin-internal-rules", - "version": "0.0.0", - "description": "internal eslint rules", - "keywords": [ - "eslint", - "eslintplugin", - "eslint-plugin" - ], - "author": "", - "main": "./lib/index.js", - "exports": "./lib/index.js", - "scripts": { - "lint": "npm-run-all \"lint:*\"", - "lint:js": "eslint ." - }, - "dependencies": { - "requireindex": "^1.2.0" - }, - "devDependencies": { - "eslint": "^8.19.0", - "eslint-plugin-eslint-plugin": "^5.0.0", - "eslint-plugin-node": "^11.1.0" - }, - "engines": { - "node": "^14.17.0 || ^16.0.0 || >= 18.0.0" - }, - "peerDependencies": { - "eslint": ">=7" - }, - "license": "ISC" -} diff --git a/tools/internal-rules/pnpm-lock.yaml b/tools/internal-rules/pnpm-lock.yaml deleted file mode 100644 index d72865c5..00000000 --- a/tools/internal-rules/pnpm-lock.yaml +++ /dev/null @@ -1,961 +0,0 @@ -lockfileVersion: "6.0" - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -dependencies: - requireindex: - specifier: ^1.2.0 - version: 1.2.0 - -devDependencies: - eslint: - specifier: ^8.19.0 - version: 8.19.0 - eslint-plugin-eslint-plugin: - specifier: ^5.0.0 - version: 5.0.0(eslint@8.19.0) - eslint-plugin-node: - specifier: ^11.1.0 - version: 11.1.0(eslint@8.19.0) - -packages: - /@aashutoshrathi/word-wrap@1.2.6: - resolution: - { - integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - } - engines: { node: ">=0.10.0" } - dev: true - - /@eslint/eslintrc@1.4.1: - resolution: - { - integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/config-array@0.9.5: - resolution: - { - integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== - } - engines: { node: ">=10.10.0" } - dependencies: - "@humanwhocodes/object-schema": 1.2.1 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/object-schema@1.2.1: - resolution: - { - integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - } - dev: true - - /acorn-jsx@5.3.2(acorn@8.11.3): - resolution: - { - integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - } - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.3 - dev: true - - /acorn@8.11.3: - resolution: - { - integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - } - engines: { node: ">=0.4.0" } - hasBin: true - dev: true - - /ajv@6.12.6: - resolution: - { - integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - } - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ansi-regex@5.0.1: - resolution: - { - integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - } - engines: { node: ">=8" } - dev: true - - /ansi-styles@4.3.0: - resolution: - { - integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - } - engines: { node: ">=8" } - dependencies: - color-convert: 2.0.1 - dev: true - - /argparse@2.0.1: - resolution: - { - integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - } - dev: true - - /balanced-match@1.0.2: - resolution: - { - integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - } - dev: true - - /brace-expansion@1.1.11: - resolution: - { - integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - } - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /callsites@3.1.0: - resolution: - { - integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - } - engines: { node: ">=6" } - dev: true - - /chalk@4.1.2: - resolution: - { - integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - } - engines: { node: ">=10" } - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /color-convert@2.0.1: - resolution: - { - integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - } - engines: { node: ">=7.0.0" } - dependencies: - color-name: 1.1.4 - dev: true - - /color-name@1.1.4: - resolution: - { - integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - } - dev: true - - /concat-map@0.0.1: - resolution: - { - integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - } - dev: true - - /cross-spawn@7.0.3: - resolution: - { - integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - } - engines: { node: ">= 8" } - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /debug@4.3.4: - resolution: - { - integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - } - engines: { node: ">=6.0" } - peerDependencies: - supports-color: "*" - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /deep-is@0.1.4: - resolution: - { - integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - } - dev: true - - /doctrine@3.0.0: - resolution: - { - integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - } - engines: { node: ">=6.0.0" } - dependencies: - esutils: 2.0.3 - dev: true - - /escape-string-regexp@4.0.0: - resolution: - { - integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - } - engines: { node: ">=10" } - dev: true - - /eslint-plugin-es@3.0.1(eslint@8.19.0): - resolution: - { - integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== - } - engines: { node: ">=8.10.0" } - peerDependencies: - eslint: ">=4.19.1" - dependencies: - eslint: 8.19.0 - eslint-utils: 2.1.0 - regexpp: 3.2.0 - dev: true - - /eslint-plugin-eslint-plugin@5.0.0(eslint@8.19.0): - resolution: - { - integrity: sha512-4j1sOUmZEd6RsdRKjUbEwYLAcihOVlPLzX3jpLpp7d3lHM+nSlAXVAwCT8o2OfJ501LICr1v6OZo7b6tPzQkUQ== - } - engines: { node: ^14.17.0 || ^16.0.0 || >= 18.0.0 } - peerDependencies: - eslint: ">=7.0.0" - dependencies: - eslint: 8.19.0 - eslint-utils: 3.0.0(eslint@8.19.0) - estraverse: 5.3.0 - dev: true - - /eslint-plugin-node@11.1.0(eslint@8.19.0): - resolution: - { - integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== - } - engines: { node: ">=8.10.0" } - peerDependencies: - eslint: ">=5.16.0" - dependencies: - eslint: 8.19.0 - eslint-plugin-es: 3.0.1(eslint@8.19.0) - eslint-utils: 2.1.0 - ignore: 5.3.1 - minimatch: 3.1.2 - resolve: 1.22.8 - semver: 6.3.1 - dev: true - - /eslint-scope@7.2.2: - resolution: - { - integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-utils@2.1.0: - resolution: - { - integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - } - engines: { node: ">=6" } - dependencies: - eslint-visitor-keys: 1.3.0 - dev: true - - /eslint-utils@3.0.0(eslint@8.19.0): - resolution: - { - integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - } - engines: { node: ^10.0.0 || ^12.0.0 || >= 14.0.0 } - peerDependencies: - eslint: ">=5" - dependencies: - eslint: 8.19.0 - eslint-visitor-keys: 2.1.0 - dev: true - - /eslint-visitor-keys@1.3.0: - resolution: - { - integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - } - engines: { node: ">=4" } - dev: true - - /eslint-visitor-keys@2.1.0: - resolution: - { - integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - } - engines: { node: ">=10" } - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: - { - integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - dev: true - - /eslint@8.19.0: - resolution: - { - integrity: sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw== - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - hasBin: true - dependencies: - "@eslint/eslintrc": 1.4.1 - "@humanwhocodes/config-array": 0.9.5 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-utils: 3.0.0(eslint@8.19.0) - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - functional-red-black-tree: 1.0.1 - glob-parent: 6.0.2 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - regexpp: 3.2.0 - strip-ansi: 6.0.1 - strip-json-comments: 3.1.1 - text-table: 0.2.0 - v8-compile-cache: 2.4.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@9.6.1: - resolution: - { - integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - dev: true - - /esquery@1.5.0: - resolution: - { - integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - } - engines: { node: ">=0.10" } - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: - { - integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - } - engines: { node: ">=4.0" } - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@5.3.0: - resolution: - { - integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - } - engines: { node: ">=4.0" } - dev: true - - /esutils@2.0.3: - resolution: - { - integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - } - engines: { node: ">=0.10.0" } - dev: true - - /fast-deep-equal@3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - } - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: - { - integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - } - dev: true - - /fast-levenshtein@2.0.6: - resolution: - { - integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - } - dev: true - - /file-entry-cache@6.0.1: - resolution: - { - integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - } - engines: { node: ^10.12.0 || >=12.0.0 } - dependencies: - flat-cache: 3.2.0 - dev: true - - /flat-cache@3.2.0: - resolution: - { - integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - } - engines: { node: ^10.12.0 || >=12.0.0 } - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - dev: true - - /flatted@3.3.1: - resolution: - { - integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== - } - dev: true - - /fs.realpath@1.0.0: - resolution: - { - integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - } - dev: true - - /function-bind@1.1.2: - resolution: - { - integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - } - dev: true - - /functional-red-black-tree@1.0.1: - resolution: - { - integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== - } - dev: true - - /glob-parent@6.0.2: - resolution: - { - integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - } - engines: { node: ">=10.13.0" } - dependencies: - is-glob: 4.0.3 - dev: true - - /glob@7.2.3: - resolution: - { - integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - } - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /globals@13.24.0: - resolution: - { - integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - } - engines: { node: ">=8" } - dependencies: - type-fest: 0.20.2 - dev: true - - /has-flag@4.0.0: - resolution: - { - integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - } - engines: { node: ">=8" } - dev: true - - /hasown@2.0.1: - resolution: - { - integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA== - } - engines: { node: ">= 0.4" } - dependencies: - function-bind: 1.1.2 - dev: true - - /ignore@5.3.1: - resolution: - { - integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== - } - engines: { node: ">= 4" } - dev: true - - /import-fresh@3.3.0: - resolution: - { - integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - } - engines: { node: ">=6" } - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /imurmurhash@0.1.4: - resolution: - { - integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - } - engines: { node: ">=0.8.19" } - dev: true - - /inflight@1.0.6: - resolution: - { - integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - } - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: - { - integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - } - dev: true - - /is-core-module@2.13.1: - resolution: - { - integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - } - dependencies: - hasown: 2.0.1 - dev: true - - /is-extglob@2.1.1: - resolution: - { - integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - } - engines: { node: ">=0.10.0" } - dev: true - - /is-glob@4.0.3: - resolution: - { - integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - } - engines: { node: ">=0.10.0" } - dependencies: - is-extglob: 2.1.1 - dev: true - - /isexe@2.0.0: - resolution: - { - integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - } - dev: true - - /js-yaml@4.1.0: - resolution: - { - integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - } - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /json-buffer@3.0.1: - resolution: - { - integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - } - dev: true - - /json-schema-traverse@0.4.1: - resolution: - { - integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - } - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: - { - integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - } - dev: true - - /keyv@4.5.4: - resolution: - { - integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - } - dependencies: - json-buffer: 3.0.1 - dev: true - - /levn@0.4.1: - resolution: - { - integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - } - engines: { node: ">= 0.8.0" } - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lodash.merge@4.6.2: - resolution: - { - integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - } - dev: true - - /minimatch@3.1.2: - resolution: - { - integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - } - dependencies: - brace-expansion: 1.1.11 - dev: true - - /ms@2.1.2: - resolution: - { - integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - } - dev: true - - /natural-compare@1.4.0: - resolution: - { - integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - } - dev: true - - /once@1.4.0: - resolution: - { - integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - } - dependencies: - wrappy: 1.0.2 - dev: true - - /optionator@0.9.3: - resolution: - { - integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== - } - engines: { node: ">= 0.8.0" } - dependencies: - "@aashutoshrathi/word-wrap": 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /parent-module@1.0.1: - resolution: - { - integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - } - engines: { node: ">=6" } - dependencies: - callsites: 3.1.0 - dev: true - - /path-is-absolute@1.0.1: - resolution: - { - integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - } - engines: { node: ">=0.10.0" } - dev: true - - /path-key@3.1.1: - resolution: - { - integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - } - engines: { node: ">=8" } - dev: true - - /path-parse@1.0.7: - resolution: - { - integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - } - dev: true - - /prelude-ls@1.2.1: - resolution: - { - integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - } - engines: { node: ">= 0.8.0" } - dev: true - - /punycode@2.3.1: - resolution: - { - integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - } - engines: { node: ">=6" } - dev: true - - /regexpp@3.2.0: - resolution: - { - integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - } - engines: { node: ">=8" } - dev: true - - /requireindex@1.2.0: - resolution: - { - integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww== - } - engines: { node: ">=0.10.5" } - dev: false - - /resolve-from@4.0.0: - resolution: - { - integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - } - engines: { node: ">=4" } - dev: true - - /resolve@1.22.8: - resolution: - { - integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - } - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /rimraf@3.0.2: - resolution: - { - integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - } - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /semver@6.3.1: - resolution: - { - integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - } - hasBin: true - dev: true - - /shebang-command@2.0.0: - resolution: - { - integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - } - engines: { node: ">=8" } - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: - { - integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - } - engines: { node: ">=8" } - dev: true - - /strip-ansi@6.0.1: - resolution: - { - integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - } - engines: { node: ">=8" } - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-json-comments@3.1.1: - resolution: - { - integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - } - engines: { node: ">=8" } - dev: true - - /supports-color@7.2.0: - resolution: - { - integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - } - engines: { node: ">=8" } - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: - { - integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - } - engines: { node: ">= 0.4" } - dev: true - - /text-table@0.2.0: - resolution: - { - integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - } - dev: true - - /type-check@0.4.0: - resolution: - { - integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - } - engines: { node: ">= 0.8.0" } - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-fest@0.20.2: - resolution: - { - integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - } - engines: { node: ">=10" } - dev: true - - /uri-js@4.4.1: - resolution: - { - integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - } - dependencies: - punycode: 2.3.1 - dev: true - - /v8-compile-cache@2.4.0: - resolution: - { - integrity: sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== - } - dev: true - - /which@2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - } - engines: { node: ">= 8" } - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /wrappy@1.0.2: - resolution: - { - integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - } - dev: true From ee32e59eb7f50cfdd51e25705e0ccb12d1d23bc7 Mon Sep 17 00:00:00 2001 From: benthecarman Date: Thu, 21 Mar 2024 12:34:44 -0500 Subject: [PATCH 04/40] Add error message for tor urls --- public/i18n/en.json | 1 + src/routes/settings/Servers.tsx | 62 +++++++++++++++++++++++++++++---- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/public/i18n/en.json b/public/i18n/en.json index 7cc74f2e..6a1b66fb 100644 --- a/public/i18n/en.json +++ b/public/i18n/en.json @@ -504,6 +504,7 @@ "storage_label": "Storage", "storage_caption": "Encrypted VSS backup service.", "error_lsp": "That doesn't look like a URL", + "error_tor": "Tor URLs are not currently supported", "save": "Save" }, "nostr_contacts": { diff --git a/src/routes/settings/Servers.tsx b/src/routes/settings/Servers.tsx index caf15673..13fc82b7 100644 --- a/src/routes/settings/Servers.tsx +++ b/src/routes/settings/Servers.tsx @@ -1,4 +1,4 @@ -import { createForm, url } from "@modular-forms/solid"; +import { createForm, custom, url } from "@modular-forms/solid"; import { createResource, Match, Suspense, Switch } from "solid-js"; import { @@ -24,6 +24,26 @@ import { } from "~/logic/mutinyWalletSetup"; import { eify } from "~/utils"; +const validateNotTorUrl = async (value?: string) => { + if (!value) { + return false; + } + + // if it is one of the default URLs, it's safe + // need this handling for self-hosting deployments + if ( + value === import.meta.env.VITE_PROXY || + value === import.meta.env.VITE_ESPLORA || + value === import.meta.env.VITE_RGS || + value === import.meta.env.VITE_LSP || + value === import.meta.env.VITE_STORAGE + ) { + return true; + } + + return !value.includes(".onion"); +}; + function SettingsStringsEditor(props: { initialSettings: MutinyWalletSettingStrings; }) { @@ -54,7 +74,13 @@ function SettingsStringsEditor(props: {
{(field, props) => ( {(field, props) => ( {(field, props) => ( {(field, props) => ( {(field, props) => ( Date: Sat, 13 Jan 2024 12:45:58 +0000 Subject: [PATCH 05/40] new home --- android/app/capacitor.build.gradle | 2 + android/capacitor.settings.gradle | 6 + e2e/encrypt.spec.ts | 43 +- e2e/fedimint.spec.ts | 71 +- e2e/load.spec.ts | 19 +- e2e/restore.spec.ts | 60 +- e2e/roundtrip.spec.ts | 16 +- e2e/routes.spec.ts | 57 +- e2e/utils.ts | 27 + index.html | 11 +- ios/App/Podfile | 2 + ios/App/Podfile.lock | 20 +- package.json | 50 +- pnpm-lock.yaml | 10326 ++++-------------- postcss.config.cjs | 7 + public/i18n/en.json | 14 +- public/mutiny-pixel-m-white.png | Bin 0 -> 267 bytes public/mutiny-pixel-m.png | Bin 0 -> 281 bytes src/App.tsx | 36 - src/assets/generic-avatar.jpg | Bin 0 -> 2376 bytes src/assets/icons/airplane.svg | 3 - src/assets/icons/back.svg | 3 - src/assets/icons/big-receive.svg | 3 - src/assets/icons/black-close.svg | 3 - src/assets/icons/bolt-black.svg | 3 - src/assets/icons/bolt.svg | 3 - src/assets/icons/chain-black.svg | 4 - src/assets/icons/chain.svg | 4 - src/assets/icons/check.svg | 3 - src/assets/icons/close.svg | 3 - src/assets/icons/coin.svg | 18 - src/assets/icons/community.svg | 4 - src/assets/icons/copy-black.svg | 3 - src/assets/icons/copy.svg | 3 - src/assets/icons/currency-swap.svg | 3 - src/assets/icons/down.svg | 5 - src/assets/icons/download-channel.svg | 3 - src/assets/icons/eye.svg | 3 - src/assets/icons/feedback.svg | 3 - src/assets/icons/forward.svg | 5 - src/assets/icons/gift.svg | 3 - src/assets/icons/green-check.svg | 3 - src/assets/icons/help.svg | 5 - src/assets/icons/info.svg | 3 - src/assets/icons/m.svg | 3 - src/assets/icons/paste.svg | 5 - src/assets/icons/pencil.svg | 3 - src/assets/icons/private-eye.svg | 3 - src/assets/icons/receive.svg | 3 - src/assets/icons/red-close.svg | 3 - src/assets/icons/refresh.svg | 3 - src/assets/icons/right-arrow.svg | 3 - src/assets/icons/rs.svg | 16 - src/assets/icons/save.svg | 3 - src/assets/icons/scan.svg | 3 - src/assets/icons/send.svg | 3 - src/assets/icons/settings.svg | 3 - src/assets/icons/share-black.svg | 3 - src/assets/icons/share.svg | 3 - src/assets/icons/shuffle-black.svg | 3 - src/assets/icons/shuffle.svg | 3 - src/assets/icons/side-to-side.svg | 5 - src/assets/icons/tinyArrow.svg | 3 - src/assets/icons/up-down.svg | 3 - src/assets/icons/upload-channel.svg | 3 - src/assets/icons/upload.svg | 3 - src/assets/icons/user-clock.svg | 10 - src/assets/icons/user.svg | 3 - src/assets/svg/Back.tsx | 18 - src/assets/svg/Paste.tsx | 24 - src/assets/svg/Scan.tsx | 18 - src/components/Activity.tsx | 278 +- src/components/ActivityDetailsModal.tsx | 74 +- src/components/ActivityItem.tsx | 172 - src/components/Amount.tsx | 10 +- src/components/BalanceBox.tsx | 91 +- src/components/BigMoney.tsx | 12 +- src/components/ContactButton.tsx | 28 + src/components/ContactViewer.tsx | 32 +- src/components/DeleteEverything.tsx | 3 + src/components/EditProfileForm.tsx | 88 + src/components/ErrorDisplay.tsx | 58 +- src/components/Fab.tsx | 171 + src/components/Fee.tsx | 2 +- src/components/GenericItem.tsx | 193 + src/components/GiftLink.tsx | 4 +- src/components/HomeBalance.tsx | 54 + src/components/HomeSubnav.tsx | 128 + src/components/IOSbanner.tsx | 4 +- src/components/InfoBox.tsx | 5 +- src/components/IntegratedQR.tsx | 93 +- src/components/LabelCircle.tsx | 59 +- src/components/LoadingIndicator.tsx | 12 +- src/components/MoreInfoModal.tsx | 11 +- src/components/MutinyPlusCta.tsx | 4 +- src/components/NavBar.tsx | 54 +- src/components/NostrActivity.tsx | 213 +- src/components/OnboardWarning.tsx | 37 - src/components/PendingNwc.tsx | 175 +- src/components/Reader.tsx | 2 +- src/components/ReceiveWarnings.tsx | 4 +- src/components/Reload.tsx | 7 +- src/components/SeedWords.tsx | 8 +- src/components/SetupErrorDisplay.tsx | 286 +- src/components/ShareCard.tsx | 12 +- src/components/SharpButton.tsx | 4 +- src/components/SimpleInput.tsx | 2 +- src/components/SocialActionRow.tsx | 52 + src/components/Toaster.tsx | 8 +- src/components/index.ts | 8 +- src/components/layout/BackButton.tsx | 20 - src/components/layout/BackLink.tsx | 24 +- src/components/layout/BackPop.tsx | 43 +- src/components/layout/Button.tsx | 17 +- src/components/layout/LoadingSpinner.tsx | 9 +- src/components/layout/Misc.tsx | 97 +- src/components/layout/index.ts | 1 - src/components/successfail/SuccessModal.tsx | 1 - src/index.tsx | 18 +- src/logic/mutinyWalletSetup.ts | 30 +- src/logic/waila.ts | 6 +- src/root.css | 51 +- src/router.tsx | 158 +- src/routes/Activity.tsx | 196 - src/routes/Chat.tsx | 605 + src/routes/EditProfile.tsx | 86 + src/routes/Feedback.tsx | 79 +- src/routes/Gift.tsx | 229 +- src/routes/ImportProfile.tsx | 85 + src/routes/Main.tsx | 179 +- src/routes/NewProfile.tsx | 71 + src/routes/Profile.tsx | 94 + src/routes/Receive.tsx | 6 +- src/routes/Request.tsx | 140 + src/routes/Scanner.tsx | 4 +- src/routes/Search.tsx | 222 +- src/routes/Send.tsx | 76 +- src/routes/Setup.tsx | 79 + src/routes/[...404].tsx | 20 +- src/routes/index.ts | 8 +- src/routes/settings/Admin.tsx | 38 +- src/routes/settings/Backup.tsx | 62 +- src/routes/settings/Channels.tsx | 24 +- src/routes/settings/Connections.tsx | 47 +- src/routes/settings/Currency.tsx | 28 +- src/routes/settings/EmergencyKit.tsx | 37 +- src/routes/settings/Encrypt.tsx | 186 +- src/routes/settings/Gift.tsx | 217 +- src/routes/settings/Language.tsx | 28 +- src/routes/settings/ManageFederations.tsx | 105 +- src/routes/settings/Plus.tsx | 114 +- src/routes/settings/Restore.tsx | 35 +- src/routes/settings/Root.tsx | 217 +- src/routes/settings/Servers.tsx | 17 +- src/routes/settings/SyncNostrContacts.tsx | 110 +- src/state/megaStore.tsx | 135 +- src/styles/dialogs.ts | 5 +- src/utils/blobToBase64.ts | 20 + src/utils/fetchZaps.ts | 92 +- src/utils/index.ts | 1 + src/utils/nostr.ts | 9 + src/utils/prettyPrintTime.ts | 27 + tailwind.config.cjs | 25 +- tsconfig.json | 4 +- vite.config.ts | 13 +- 165 files changed, 6736 insertions(+), 10991 deletions(-) create mode 100644 e2e/utils.ts create mode 100644 postcss.config.cjs create mode 100644 public/mutiny-pixel-m-white.png create mode 100644 public/mutiny-pixel-m.png delete mode 100644 src/App.tsx create mode 100644 src/assets/generic-avatar.jpg delete mode 100644 src/assets/icons/airplane.svg delete mode 100644 src/assets/icons/back.svg delete mode 100644 src/assets/icons/big-receive.svg delete mode 100644 src/assets/icons/black-close.svg delete mode 100644 src/assets/icons/bolt-black.svg delete mode 100644 src/assets/icons/bolt.svg delete mode 100644 src/assets/icons/chain-black.svg delete mode 100644 src/assets/icons/chain.svg delete mode 100644 src/assets/icons/check.svg delete mode 100644 src/assets/icons/close.svg delete mode 100644 src/assets/icons/coin.svg delete mode 100644 src/assets/icons/community.svg delete mode 100644 src/assets/icons/copy-black.svg delete mode 100644 src/assets/icons/copy.svg delete mode 100644 src/assets/icons/currency-swap.svg delete mode 100644 src/assets/icons/down.svg delete mode 100644 src/assets/icons/download-channel.svg delete mode 100644 src/assets/icons/eye.svg delete mode 100644 src/assets/icons/feedback.svg delete mode 100644 src/assets/icons/forward.svg delete mode 100644 src/assets/icons/gift.svg delete mode 100644 src/assets/icons/green-check.svg delete mode 100644 src/assets/icons/help.svg delete mode 100644 src/assets/icons/info.svg delete mode 100644 src/assets/icons/m.svg delete mode 100644 src/assets/icons/paste.svg delete mode 100644 src/assets/icons/pencil.svg delete mode 100644 src/assets/icons/private-eye.svg delete mode 100644 src/assets/icons/receive.svg delete mode 100644 src/assets/icons/red-close.svg delete mode 100644 src/assets/icons/refresh.svg delete mode 100644 src/assets/icons/right-arrow.svg delete mode 100644 src/assets/icons/rs.svg delete mode 100644 src/assets/icons/save.svg delete mode 100644 src/assets/icons/scan.svg delete mode 100644 src/assets/icons/send.svg delete mode 100644 src/assets/icons/settings.svg delete mode 100644 src/assets/icons/share-black.svg delete mode 100644 src/assets/icons/share.svg delete mode 100644 src/assets/icons/shuffle-black.svg delete mode 100644 src/assets/icons/shuffle.svg delete mode 100644 src/assets/icons/side-to-side.svg delete mode 100644 src/assets/icons/tinyArrow.svg delete mode 100644 src/assets/icons/up-down.svg delete mode 100644 src/assets/icons/upload-channel.svg delete mode 100644 src/assets/icons/upload.svg delete mode 100644 src/assets/icons/user-clock.svg delete mode 100644 src/assets/icons/user.svg delete mode 100644 src/assets/svg/Back.tsx delete mode 100644 src/assets/svg/Paste.tsx delete mode 100644 src/assets/svg/Scan.tsx delete mode 100644 src/components/ActivityItem.tsx create mode 100644 src/components/ContactButton.tsx create mode 100644 src/components/EditProfileForm.tsx create mode 100644 src/components/Fab.tsx create mode 100644 src/components/GenericItem.tsx create mode 100644 src/components/HomeBalance.tsx create mode 100644 src/components/HomeSubnav.tsx delete mode 100644 src/components/OnboardWarning.tsx create mode 100644 src/components/SocialActionRow.tsx delete mode 100644 src/components/layout/BackButton.tsx delete mode 100644 src/routes/Activity.tsx create mode 100644 src/routes/Chat.tsx create mode 100644 src/routes/EditProfile.tsx create mode 100644 src/routes/ImportProfile.tsx create mode 100644 src/routes/NewProfile.tsx create mode 100644 src/routes/Profile.tsx create mode 100644 src/routes/Request.tsx create mode 100644 src/routes/Setup.tsx create mode 100644 src/utils/blobToBase64.ts diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index c909025a..5b5832d4 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -12,12 +12,14 @@ dependencies { implementation project(':capacitor-mlkit-barcode-scanning') implementation project(':capacitor-app') implementation project(':capacitor-app-launcher') + implementation project(':capacitor-camera') implementation project(':capacitor-clipboard') implementation project(':capacitor-filesystem') implementation project(':capacitor-haptics') implementation project(':capacitor-share') implementation project(':capacitor-status-bar') implementation project(':capacitor-toast') + implementation project(':capacitor-secure-storage-plugin') } diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle index 8a2fdb13..ba78cf2e 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -11,6 +11,9 @@ project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacito include ':capacitor-app-launcher' project(':capacitor-app-launcher').projectDir = new File('../node_modules/.pnpm/@capacitor+app-launcher@5.0.6_@capacitor+core@5.5.1/node_modules/@capacitor/app-launcher/android') +include ':capacitor-camera' +project(':capacitor-camera').projectDir = new File('../node_modules/.pnpm/@capacitor+camera@5.0.9_@capacitor+core@5.5.1/node_modules/@capacitor/camera/android') + include ':capacitor-clipboard' project(':capacitor-clipboard').projectDir = new File('../node_modules/.pnpm/@capacitor+clipboard@5.0.6_@capacitor+core@5.5.1/node_modules/@capacitor/clipboard/android') @@ -28,3 +31,6 @@ project(':capacitor-status-bar').projectDir = new File('../node_modules/.pnpm/@c include ':capacitor-toast' project(':capacitor-toast').projectDir = new File('../node_modules/.pnpm/@capacitor+toast@5.0.6_@capacitor+core@5.5.1/node_modules/@capacitor/toast/android') + +include ':capacitor-secure-storage-plugin' +project(':capacitor-secure-storage-plugin').projectDir = new File('../node_modules/.pnpm/capacitor-secure-storage-plugin@0.9.0_@capacitor+core@5.5.1/node_modules/capacitor-secure-storage-plugin/android') diff --git a/e2e/encrypt.spec.ts b/e2e/encrypt.spec.ts index f0e897aa..81f6f61c 100644 --- a/e2e/encrypt.spec.ts +++ b/e2e/encrypt.spec.ts @@ -1,28 +1,14 @@ import { expect, test } from "@playwright/test"; +import { loadHome, visitSettings } from "./utils"; + test.beforeEach(async ({ page }) => { await page.goto("http://localhost:3420/"); }); test("test local encrypt", async ({ page }) => { - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Mutiny Wallet/); - - // Wait for an element matching the selector to appear in DOM. - await page.waitForSelector("text=0 SATS"); - - console.log("Page loaded."); - - // Wait for a while just to make sure we can load everything - await page.waitForTimeout(1000); - - // Navigate to settings - const settingsLink = await page.getByRole("link", { name: "Settings" }); - - settingsLink.click(); - - // Wait for settings to load - await page.waitForSelector("text=Settings"); + await loadHome(page); + await visitSettings(page); // Click the "Backup" link await page.click("text=Backup"); @@ -48,6 +34,13 @@ test("test local encrypt", async ({ page }) => { // Click the "I wrote down the words" button await wroteDownButton.click(); + // Make sure the balance box ready light is on + await page.locator("title=READY"); + + // Go back to settings / change password + await visitSettings(page); + await page.click("text=Change Password"); + // The header should now say "Encrypt your seed words" await expect(page.locator("h1")).toContainText(["Encrypt your seed words"]); @@ -56,7 +49,7 @@ test("test local encrypt", async ({ page }) => { const passwordInput = await page.locator(`input[name='password']`); // 2. Type the password into the input field - await passwordInput.type("test"); + await passwordInput.fill("test"); // 3. Find the input field with the name "confirmPassword" const confirmPasswordInput = await page.locator( @@ -64,15 +57,21 @@ test("test local encrypt", async ({ page }) => { ); // 4. Type the password into the input field - await confirmPasswordInput.type("test"); + await confirmPasswordInput.fill("test"); // The "Encrypt" button should not be disabled const encryptButton = await page.locator("button", { hasText: "Encrypt" }); await expect(encryptButton).not.toBeDisabled(); + // wait 5 seconds for no reason (SADLY THIS IS IMPORTANT FOR THE TEST TO PASS) + await page.waitForTimeout(5000); + // Click the "Encrypt" button await encryptButton.click(); + // wait for a while just to see what happens + // await page.waitForTimeout(10000); + // Wait for a modal with the text "Enter your password" await page.waitForSelector("text=Enter your password"); @@ -80,11 +79,11 @@ test("test local encrypt", async ({ page }) => { const passwordInput2 = await page.locator(`input[name='password']`); // Type the password into the input field - await passwordInput2.type("test"); + await passwordInput2.fill("test"); // Click the "Decrypt Wallet" button await page.click("text=Decrypt Wallet"); // Wait for an element matching the selector to appear in DOM. - await page.waitForSelector("text=0 SATS"); + await page.locator(`text=0 sats`).first(); }); diff --git a/e2e/fedimint.spec.ts b/e2e/fedimint.spec.ts index 6ba9d244..933326ff 100644 --- a/e2e/fedimint.spec.ts +++ b/e2e/fedimint.spec.ts @@ -1,5 +1,7 @@ import { expect, test } from "@playwright/test"; +import { loadHome, visitSettings } from "./utils"; + const SIGNET_INVITE_CODE = "fed11qgqzc2nhwden5te0vejkg6tdd9h8gepwvejkg6tdd9h8garhduhx6at5d9h8jmn9wshxxmmd9uqqzgxg6s3evnr6m9zdxr6hxkdkukexpcs3mn7mj3g5pc5dfh63l4tj6g9zk4er"; @@ -8,24 +10,8 @@ test.beforeEach(async ({ page }) => { }); test("fedmint join, receive, send", async ({ page }) => { - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Mutiny Wallet/); - - // Wait for an element matching the selector to appear in DOM. - await page.waitForSelector("text=0 SATS"); - - console.log("Page loaded."); - - // Wait for a while just to make sure we can load everything - await page.waitForTimeout(1000); - - // Navigate to settings - const settingsLink = await page.getByRole("link", { name: "Settings" }); - - settingsLink.click(); - - // Wait for settings to load - await page.waitForSelector("text=Settings"); + await loadHome(page); + await visitSettings(page); // Click "Manage Federations" link await page.click("text=Manage Federations"); @@ -45,11 +31,20 @@ test("fedmint join, receive, send", async ({ page }) => { await page.goBack(); await page.goBack(); - // Make sure there's a fedimint icon - await expect(page.getByRole("img", { name: "community" })).toBeVisible(); + // Click the top left button (it's the profile button), a child of header + // TODO: better ARIA stuff + await page.locator(`header button`).first().click(); - // Click the receive button - await page.click("text=Receive"); + // Make sure there's text that says "fedimint" + await page.locator("text=fedimint").first(); + + // Navigate back home + await page.goBack(); + + // Click the fab button + await page.locator("#fab").click(); + // Click the receive button in the fab + await page.locator("text=Receive").last().click(); // Expect the url to conain receive await expect(page).toHaveURL(/.*receive/); @@ -57,9 +52,6 @@ test("fedmint join, receive, send", async ({ page }) => { // At least one h1 should show "0 sats" await expect(page.locator("h1")).toContainText(["0 SATS"]); - // At least one h2 should show "0 USD" - await expect(page.locator("h2")).toContainText(["$0 USD"]); - // Type 100 into the input await page.locator("#sats-input").pressSequentially("100"); @@ -72,11 +64,7 @@ test("fedmint join, receive, send", async ({ page }) => { }); await expect(continueButton).not.toBeDisabled(); - // Wait one second - // TODO: figure out how to not get an error without waiting - await page.waitForTimeout(1000); - - continueButton.click(); + await continueButton.click(); await expect( page.getByText("Keep Mutiny open to complete the payment.") @@ -109,21 +97,17 @@ test("fedmint join, receive, send", async ({ page }) => { ); // Wait for an h1 to appear in the dom that says "Payment Received" - await page.waitForSelector("text=Payment Received", { timeout: 30000 }); + await page.waitForSelector("text=Payment Received"); // Click the "Nice" button await page.click("text=Nice"); - // Make sure we have 100 sats in the fedimint balance - await expect( - page - .locator("div") - .filter({ hasText: /^100 eSATS$/ }) - .nth(1) - ).toBeVisible(); + // Make sure we have 100 sats in the top balance + await page.waitForSelector("text=100 SATS"); // Now we send - await page.click("text=Send"); + await page.locator("#fab").click(); + await page.locator("text=Send").last().click(); // type refund@lnurl-staging.mutinywallet.com const sendInput = await page.locator("input"); @@ -131,9 +115,8 @@ test("fedmint join, receive, send", async ({ page }) => { await page.click("text=Continue"); - // Wait two seconds (the destination doesn't show up immediately) - // TODO: figure out how to not get an error without waiting - await page.waitForTimeout(2000); + // Wait for the destination to show up + await page.waitForSelector("text=LIGHTNING"); // Type 90 into the input await page.locator("#sats-input").fill("90"); @@ -147,8 +130,8 @@ test("fedmint join, receive, send", async ({ page }) => { }); await expect(confirmButton).not.toBeDisabled(); - confirmButton.click(); + await confirmButton.click(); // Wait for an h1 to appear in the dom that says "Payment Sent" - await page.waitForSelector("text=Payment Sent", { timeout: 30000 }); + await page.waitForSelector("text=Payment Sent"); }); diff --git a/e2e/load.spec.ts b/e2e/load.spec.ts index d41af63c..4774a688 100644 --- a/e2e/load.spec.ts +++ b/e2e/load.spec.ts @@ -1,22 +1,11 @@ -import { expect, test } from "@playwright/test"; +import { test } from "@playwright/test"; + +import { loadHome } from "./utils"; test.beforeEach(async ({ page }) => { await page.goto("http://localhost:3420/"); }); test("initial load", async ({ page }) => { - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Mutiny Wallet/); - - await expect(page.locator("header")).toContainText(["Activity"], { - timeout: 30000 - }); - - // Wait up to 30 seconds for an image element matching the selector to be visible - await page.waitForSelector("img[alt='lightning']", { timeout: 30000 }); - - // Wait for an element matching the selector to appear in DOM. - await page.waitForSelector("text=0 SATS"); - - console.log("Page loaded."); + await loadHome(page); }); diff --git a/e2e/restore.spec.ts b/e2e/restore.spec.ts index 651e6f2e..d054d046 100644 --- a/e2e/restore.spec.ts +++ b/e2e/restore.spec.ts @@ -1,49 +1,37 @@ import { expect, test } from "@playwright/test"; +import { visitSettings } from "./utils"; + test.beforeEach(async ({ page }) => { await page.goto("http://localhost:3420/"); }); test("restore from seed @slow", async ({ page }) => { - // should have 100k sats on-chain - const TEST_SEED_WORDS = - "rival hood review write spoon tide orange ill opera enrich clip acoustic"; - - // Expect a title "to contain" a substring. + // Start on the home page await expect(page).toHaveTitle(/Mutiny Wallet/); + await page.waitForSelector("text=Welcome to the Mutiny!"); - // Wait for an element matching the selector to appear in DOM. - await page.waitForSelector("text=0 SATS"); - - console.log("Page loaded."); - - // Wait for a while just to make sure we can load everything - await page.waitForTimeout(1000); - - // Navigate to settings - const settingsLink = await page.getByRole("link", { name: "Settings" }); - - settingsLink.click(); + console.log("Waiting for new wallet to be created..."); - // Wait for settings to load - await page.waitForSelector("text=Settings"); + await page.locator(`button:has-text('Import Existing')`).click(); - // Click the "Restore" link - page.click("text=Restore"); + // should have 100k sats on-chain + const TEST_SEED_WORDS = + "rival hood review write spoon tide orange ill opera enrich clip acoustic"; // There should be some warning text: "This will replace your existing wallet" await expect(page.locator("p")).toContainText([ "This will replace your existing wallet" ]); - let seedWords = TEST_SEED_WORDS.split(" "); + const seedWords = TEST_SEED_WORDS.split(" "); // Find the input field with the name "words.0" for (let i = 0; i < 12; i++) { const wordInput = await page.locator(`input[name='words.${i}']`); // Type the seed words into the input field - await wordInput.type(seedWords[i]); + await wordInput.fill(seedWords[i]); } // There should be a button with the text "Restore" and it should not be disabled @@ -54,33 +42,29 @@ test("restore from seed @slow", async ({ page }) => { // A modal should pop up, click the "Confirm" button const confirmButton = await page.locator("button", { hasText: "Confirm" }); - confirmButton.click(); - - // Wait for the wallet to load - await page.waitForSelector("img[alt='lightning']"); + await confirmButton.click(); // Eventually we should have a balance of 100k sats - await page.waitForSelector("text=100,000 SATS"); + await page.locator("text=100,000 SATS"); // Now we should clean up after ourselves and delete the wallet - settingsLink.click(); - - // Wait for settings to load - await page.waitForSelector("text=Settings"); + await visitSettings(page); // Click the "Restore" link - page.click("text=Admin Page"); + await page.click("text=Admin Page"); // Clicke the Delete Everything button - page.click("text=Delete Everything"); + await page.click("text=Delete Everything"); // A modal should pop up, click the "Confirm" button const confirmDeleteButton = await page.locator("button", { hasText: "Confirm" }); - confirmDeleteButton.click(); - // Wait for the wallet to load - // Wait for the wallet to load - await page.waitForSelector("img[alt='lightning']"); + // wait 5 seconds for no reason + await page.waitForTimeout(5000); + + await confirmDeleteButton.click(); + + await page.locator("text=Welcome to the Mutiny!"); }); diff --git a/e2e/roundtrip.spec.ts b/e2e/roundtrip.spec.ts index 0acefd5b..2450d334 100644 --- a/e2e/roundtrip.spec.ts +++ b/e2e/roundtrip.spec.ts @@ -1,21 +1,26 @@ import { expect, test } from "@playwright/test"; +import { loadHome } from "./utils"; + test.beforeEach(async ({ page }) => { await page.goto("http://localhost:3420/"); }); test("rountrip receive and send", async ({ page }) => { - // Click the receive button - await page.click("text=Receive"); + await loadHome(page); + + await page.locator("#fab").click(); + await page.locator("text=Receive").last().click(); - // Expect the url to conain receive + // Expect the url to contain receive await expect(page).toHaveURL(/.*receive/); // At least one h1 should show "0 sats" await expect(page.locator("h1")).toContainText(["0 SATS"]); // At least one h2 should show "0 USD" - await expect(page.locator("h2")).toContainText(["$0 USD"]); + // await expect(page.locator("h2")).toContainText(["$0 USD"]); + await page.waitForSelector("text=$0 USD"); // Type 100000 into the input await page.locator("#sats-input").pressSequentially("100000"); @@ -72,7 +77,8 @@ test("rountrip receive and send", async ({ page }) => { await page.click("text=Nice"); // Now we send - await page.click("text=Send"); + await page.locator("#fab").click(); + await page.locator("text=Send").click(); // In the textarea with the placeholder "bitcoin:..." type refund@lnurl-staging.mutinywallet.com const sendInput = await page.locator("input"); diff --git a/e2e/routes.spec.ts b/e2e/routes.spec.ts index 97234753..a99293b3 100644 --- a/e2e/routes.spec.ts +++ b/e2e/routes.spec.ts @@ -1,12 +1,14 @@ import { expect, Page, test } from "@playwright/test"; +import { loadHome, visitSettings } from "./utils"; + const routes = [ "/", - "/activity", "/feedback", "/gift", "/receive", "/scanner", + "/search", "/send", "/swap", "/settings" @@ -57,25 +59,13 @@ test.beforeEach(async ({ page }) => { }); test("visit each route", async ({ page }) => { - // Start on the home page - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Mutiny Wallet/); - - // Wait for an element matching the selector to appear in DOM. - await page.waitForSelector("text=0 SATS"); - - console.log("Page loaded."); - - // Wait for a while just to make sure we can load everything - await page.waitForTimeout(1000); + await loadHome(page); checklist.set("/", true); - await checkRoute(page, "/activity", "Activity", checklist); - await page.goBack(); + await visitSettings(page); - // Navigate to settings - await checkRoute(page, "/settings", "Settings", checklist); + checklist.set("/settings", true); // Mutiny+ await checkRoute(page, "/settings/plus", "Mutiny+", checklist); @@ -146,22 +136,43 @@ test("visit each route", async ({ page }) => { await checkRoute(page, "/settings/admin", "Secret Debug Tools", checklist); await page.goBack(); - // Go back home - await page.goBack(); - // Feedback await checkRoute(page, "/feedback", "Give us feedback!", checklist); await page.goBack(); - // Receive is covered in another test - checklist.set("/receive", true); + // Go back home + await page.goBack(); + + // Try the fab button + await page.locator("#fab").click(); + await page.locator("text=Send").click(); + await expect(page.locator("input").first()).toBeFocused(); // Send is covered in another test checklist.set("/send", true); + await page.goBack(); + + // Try the fab button again + await page.locator("#fab").click(); + // (There are actually two buttons with the "Receive text on first run) + await page.locator("text=Receive").last().click(); + + await expect(page.locator("h1").first()).toHaveText("Receive Bitcoin"); + + // Actual receive is covered in another test + checklist.set("/receive", true); + + await page.goBack(); + + // Try the fab button again + await page.locator("#fab").click(); + await page.locator("text=Scan").click(); + // Scanner - await page.locator(`a[href='/scanner']`).first().click(); - await expect(page.locator("button").first()).toHaveText("Paste Something"); + await expect( + page.locator("button:has-text('Paste Something')") + ).toBeVisible(); checklist.set("/scanner", true); // Now we have to check routes that aren't linked to directly for whatever reason diff --git a/e2e/utils.ts b/e2e/utils.ts new file mode 100644 index 00000000..d4cafd33 --- /dev/null +++ b/e2e/utils.ts @@ -0,0 +1,27 @@ +import { expect, Page } from "@playwright/test"; + +export async function loadHome(page: Page) { + // Start on the home page + await expect(page).toHaveTitle(/Mutiny Wallet/); + await page.waitForSelector("text=Welcome to the Mutiny!"); + + console.log("Waiting for new wallet to be created..."); + + await page.locator(`button:has-text('New Wallet')`).click(); + + await page.locator("text=Create your profile").first(); + + await page.locator("button:has-text('Skip for now')").click(); + + // Should have a balance up top now + await page.locator(`text=0 sats`).first(); + // Status light should be ready + await page.locator(`title="READY"`).first(); +} + +export async function visitSettings(page: Page) { + // Find an image with an alt text of "mutiny" and click it + // TODO: probably should have better ARIA stuff for this + await page.locator("img[alt='mutiny']").first().click(); + await expect(page.locator("h1").first()).toHaveText("Settings"); +} diff --git a/index.html b/index.html index 3c0d91be..5be48c9f 100644 --- a/index.html +++ b/index.html @@ -47,6 +47,9 @@ #no-script { margin: 1rem; } + body { + background-color: hsla(0, 0%, 5%, 1); + } @@ -63,8 +66,10 @@ Please update or enable WebAssembly to run this app.

- If you're running iOS in lockdown mode you'll need to add an - exception for Mutiny Wallet. + If you're running iOS in lockdown mode you'll need to + add an exception for Mutiny Wallet.

-
+