From 0257f5cf76a33cf068ae2fc251b6e07a8283f4ae Mon Sep 17 00:00:00 2001 From: malik1004x Date: Tue, 4 Aug 2026 14:08:48 +0200 Subject: [PATCH 01/10] cw-1584-ironwood-migration-modal (#3481) * ironwood migration modal * auto-show when migration begins * remove restricted import * new condition * string fix * only activate if ironwood is active * reaction safeguards * migration* --- cw_zcash/lib/src/zcash_wallet.dart | 17 ++ lib/entities/preferences_key.dart | 1 + lib/new-ui/pages/home_page.dart | 22 +++ .../unconfirmed_balance_widget.dart | 26 ++- .../coins_page/zcash_migration_modal.dart | 152 ++++++++++++++++++ lib/store/settings_store.dart | 9 ++ .../dashboard/dashboard_view_model.dart | 24 +++ lib/zcash/cw_zcash.dart | 5 + res/pictures/ironwood_migration.svg | 3 + res/values/strings_en.arb | 8 +- tool/configure.dart | 1 + 11 files changed, 260 insertions(+), 8 deletions(-) create mode 100644 lib/new-ui/widgets/coins_page/zcash_migration_modal.dart create mode 100644 res/pictures/ironwood_migration.svg diff --git a/cw_zcash/lib/src/zcash_wallet.dart b/cw_zcash/lib/src/zcash_wallet.dart index 6a09724fa..98d4a92b1 100644 --- a/cw_zcash/lib/src/zcash_wallet.dart +++ b/cw_zcash/lib/src/zcash_wallet.dart @@ -1214,6 +1214,23 @@ abstract class ZcashWalletBase return migratable; } + Future hasOrchardMigratableBalance() async { + + final (active, migratableOrchard) = await runWithCoin( + accountId: accountId, + func: (final coin) async => ( + await zkool_network.isIronwoodActive(c: coin), + await _migratableOrchardTotal(coin), + ), + ); + + if(!active) { + return false; + } + + return migratableOrchard > BigInt.zero; + } + Future _$autoShield() async { if (syncStatus is! SyncedSyncStatus) { return; diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index b12c58265..63c94bdb7 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -145,4 +145,5 @@ class PreferencesKey { static const backgroundImage = 'background_image'; static const mwebAdDismissed = "mweb_ad_dismissed"; static const balanceHideCounter = "balance_hide_counter"; + static const zcashMigrationModalViewed = "zcash_migration_modal_viewed"; } diff --git a/lib/new-ui/pages/home_page.dart b/lib/new-ui/pages/home_page.dart index 8fd2e3e23..f62440952 100644 --- a/lib/new-ui/pages/home_page.dart +++ b/lib/new-ui/pages/home_page.dart @@ -13,10 +13,14 @@ import 'package:cake_wallet/new-ui/widgets/coins_page/mweb_ad.dart'; import 'package:cake_wallet/new-ui/widgets/coins_page/top_bar_widget/top_bar.dart'; import 'package:cake_wallet/new-ui/widgets/coins_page/unconfirmed_balance_widget.dart'; import 'package:cake_wallet/new-ui/widgets/coins_page/wallet_info.dart'; +import "package:cake_wallet/new-ui/widgets/coins_page/zcash_migration_modal.dart"; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/monero_account_list_view_model.dart'; +import "package:cw_core/amount/money.dart"; +import "package:cw_core/crypto_currency.dart"; +import "package:cw_core/transaction_direction.dart"; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -48,6 +52,24 @@ class _NewHomePageState extends State { _lightningMode = false; }); }); + + reaction((_) => widget.dashboardViewModel.isMigratingToIronwood, (val) { + if (val && !widget.dashboardViewModel.settingsStore.zcashMigrationModalViewed) { + if(!context.mounted) { + return; + } + widget.dashboardViewModel.settingsStore.zcashMigrationModalViewed = true; + showMaterialModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + builder: (context) => ZcashMigrationModal( + hasContinue: true, + balance: widget.dashboardViewModel.wallet.balance.values.first.unavailable + .toStringWithSymbol(), + ), + ); + } + }); } void _setAccountViewModel() { diff --git a/lib/new-ui/widgets/coins_page/unconfirmed_balance_widget.dart b/lib/new-ui/widgets/coins_page/unconfirmed_balance_widget.dart index 461b8167a..912a592dd 100644 --- a/lib/new-ui/widgets/coins_page/unconfirmed_balance_widget.dart +++ b/lib/new-ui/widgets/coins_page/unconfirmed_balance_widget.dart @@ -1,8 +1,10 @@ import 'package:cake_wallet/generated/i18n.dart'; +import "package:cake_wallet/new-ui/widgets/coins_page/zcash_migration_modal.dart"; import 'package:cake_wallet/new-ui/widgets/new_primary_button.dart'; import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import "package:flutter/cupertino.dart"; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; @@ -21,6 +23,7 @@ class UnconfirmedBalanceWidget extends StatelessWidget { return Observer(builder: (_) { final show = dashboardViewModel.balanceViewModel .hasAdditionalBalance(dashboardViewModel.wallet.currency); + final isIronwoodMigration = dashboardViewModel.isMigratingToIronwood; return AnimatedSize( duration: const Duration(milliseconds: 300), @@ -44,13 +47,17 @@ class UnconfirmedBalanceWidget extends StatelessWidget { color: Colors.transparent, child: InkWell( onTap: () { + final modal = isIronwoodMigration + ? ZcashMigrationModal( + hasContinue: false, balance: "${balance} ${currency.symbol}") + : UnconfirmedBalanceModal( + balance: balance.toStringWithSymbol(), + currencyIconPath: currency.iconPath ?? "", + ); showMaterialModalBottomSheet( backgroundColor: Colors.transparent, context: context, - builder: (context) => UnconfirmedBalanceModal( - balance: balance.toStringWithSymbol(), - currencyIconPath: currency.iconPath ?? "", - )); + builder: (context) => modal); }, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12.0), @@ -63,8 +70,12 @@ class UnconfirmedBalanceWidget extends StatelessWidget { SizedBox( height: 20, width: 20, - child: CircularProgressIndicator( - strokeWidth: 2, + child: isIronwoodMigration + ? CupertinoActivityIndicator( + color: Theme.of(context).colorScheme.primary, + ) + : CircularProgressIndicator( + strokeWidth: 2, backgroundColor: Theme.of(context).colorScheme.primary.withAlpha(50), color: Theme.of(context).colorScheme.primary, @@ -80,7 +91,7 @@ class UnconfirmedBalanceWidget extends StatelessWidget { color: Theme.of(context).colorScheme.primary, ), ), - Text(S.of(context).confirming), + Text(isIronwoodMigration ? S.of(context).migrating_to_ironwood : S.of(context).confirming), ], ) ], @@ -172,3 +183,4 @@ class UnconfirmedBalanceModal extends StatelessWidget { ); } } + diff --git a/lib/new-ui/widgets/coins_page/zcash_migration_modal.dart b/lib/new-ui/widgets/coins_page/zcash_migration_modal.dart new file mode 100644 index 000000000..e1f66b1fb --- /dev/null +++ b/lib/new-ui/widgets/coins_page/zcash_migration_modal.dart @@ -0,0 +1,152 @@ +import "package:cake_wallet/generated/i18n.dart"; +import "package:cake_wallet/new-ui/widgets/new_primary_button.dart"; +import "package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart"; +import "package:cake_wallet/src/widgets/cake_image_widget.dart"; +import "package:flutter/material.dart"; +import "package:url_launcher/url_launcher.dart"; + +class ZcashMigrationModal extends StatelessWidget { + const ZcashMigrationModal({required this.hasContinue, required this.balance, super.key}); + + final String balance; + final bool hasContinue; + + @override + Widget build(BuildContext context) => SafeArea( + bottom: false, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),), + child: SafeArea( + top: false, + child: Column( + children: [ + ModalTopBar( + title: S.of(context).zcash_network_upgrade, + trailingIcon: const Icon(Icons.close), + onTrailingPressed: Navigator.of(context).pop, + trailingSemanticLabel: S.of(context).close, + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + children: [ + Expanded( + child: Column( + spacing: 40, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: 146, + height: 79, + child: Stack( + children: [ + const Positioned( + left: 67, + top: 0, + bottom: 0, + child: CakeImageWidget( + imageUrl: "assets/new-ui/ironwood_migration.svg", + width: 75, + height: 75, + ), + ), + Positioned( + left: 0, + child: Container( + width: 79, + height: 79, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(99999999), + border: Border.all( + color: Theme.of(context).colorScheme.surface, + width: 4,),), + child: const CakeImageWidget( + imageUrl: "assets/new-ui/crypto_full_icons/zcash.svg", + height: 75, + width: 75, + ), + ), + ), + ], + ), + ), + Container( + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Theme.of(context).colorScheme.surfaceContainer,), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 4, + children: [ + Text( + balance, + style: TextStyle( + color: Theme.of(context).colorScheme.primary,), + ), + Text(S.of(context).is_currently_being_migrated), + ], + ), + ),), + RichText( + textAlign: TextAlign.center, + text: TextSpan( + children: [ + TextSpan( + text: "${S.of(context).zcash_network_upgrade_desc_1}\n\n", + style: Theme.of(context).textTheme.bodyMedium,), + TextSpan( + text: "${S.of(context).zcash_network_upgrade_desc_2}\n\n", + style: Theme.of(context).textTheme.bodyMedium,), + TextSpan( + text: "${S.of(context).zcash_network_upgrade_desc_3}\n\n", + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: const Color(0xFFF9C03C), + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(12), + child: Column( + spacing: 12, + children: [ + NewPrimaryButton( + onPressed: _launchDocs, + text: S.of(context).learn_more, + color: Theme.of(context).colorScheme.surfaceContainer, + textColor: Theme.of(context).colorScheme.primary,), + if (hasContinue) + NewPrimaryButton( + onPressed: Navigator.of(context).pop, + text: S.of(context).continue_text, + color: Theme.of(context).colorScheme.primary, + textColor: Theme.of(context).colorScheme.onPrimary,), + ], + ), + ), + ], + ), + ), + ), + ); + + void _launchDocs() { + try { + launchUrl(Uri.parse("https://docs.cakewallet.com/cryptos/zcash/ironwood-migration")); + } catch (_) {} + } +} diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index d67c1f045..95ab5d52c 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -151,6 +151,7 @@ abstract class SettingsStoreBase with Store { required this.mwebNodeUri, required this.mwebAdDismissed, required this.balanceHideCounter, + required this.zcashMigrationModalViewed, required bool initialEnableAutomaticNodeSwitching, required String initialBackgroundImage, TransactionPriority? initialBitcoinTransactionPriority, @@ -766,6 +767,9 @@ abstract class SettingsStoreBase with Store { (int balanceHideCounter) => _sharedPreferences.setInt(PreferencesKey.balanceHideCounter, balanceHideCounter)); + reaction((_) => zcashMigrationModalViewed, + (val) => _sharedPreferences.setBool(PreferencesKey.zcashMigrationModalViewed, val)); + this.nodes.observe((change) { if (change.newValue != null && change.key != null) { _saveCurrentNode(change.newValue!, change.key!); @@ -1075,6 +1079,9 @@ abstract class SettingsStoreBase with Store { @observable bool mwebAdDismissed; + @observable + bool zcashMigrationModalViewed; + final SecureStorage _secureStorage; final SharedPreferences _sharedPreferences; @@ -1350,6 +1357,7 @@ abstract class SettingsStoreBase with Store { final enableAutomaticNodeSwitching = sharedPreferences.getBool(PreferencesKey.enableAutomaticNodeSwitching) ?? true; final backgroundImage = sharedPreferences.getString(PreferencesKey.backgroundImage) ?? ''; + final zcashMigrationModalViewed = sharedPreferences.getBool(PreferencesKey.zcashMigrationModalViewed) ?? false; // If no value if (pinLength == null || pinLength == 0) { @@ -1762,6 +1770,7 @@ abstract class SettingsStoreBase with Store { initialBuiltinTor: builtinTor, mwebAdDismissed: mwebAdDismissed, balanceHideCounter: balanceHideCounter, + zcashMigrationModalViewed: zcashMigrationModalViewed ); } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index e16b0af3a..fb2d53b74 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -96,6 +96,7 @@ abstract class DashboardViewModelBase with Store { isShowFirstYatIntroduction = false, isShowSecondYatIntroduction = false, isShowThirdYatIntroduction = false, + isMigratingToIronwood = false, filterItems = [], exchangeFilterItems = [], subname = '', @@ -250,6 +251,8 @@ abstract class DashboardViewModelBase with Store { reaction((_) => tradesStore.trades, (_) => tradeMonitor.monitorActiveTrades(wallet.id)); + addZcashMigrationReaction(); + tradeMonitor.monitorActiveTrades(wallet.id); } @@ -374,6 +377,22 @@ abstract class DashboardViewModelBase with Store { ); } + @observable + ReactionDisposer? zcashMigrationReactionDisposer; + + @action + void addZcashMigrationReaction() { + zcashMigrationReactionDisposer?.reaction.dispose(); + zcashMigrationReactionDisposer = null; + + if (wallet.type == WalletType.zcash) { + zcashMigrationReactionDisposer = reaction((_) => wallet.balance.values.first, (_) async { + isMigratingToIronwood = + wallet.type == WalletType.zcash && await zcash!.hasOrchardMigratableBalance(wallet); + }); + } + } + @computed bool get isSyncHeavy { if ([ @@ -1270,6 +1289,8 @@ abstract class DashboardViewModelBase with Store { name = wallet.name; loadFilterItems(); + addZcashMigrationReaction(); + if (wallet.type == WalletType.monero) { subname = monero!.getCurrentAccount(wallet).label; @@ -1551,6 +1572,9 @@ abstract class DashboardViewModelBase with Store { } } + @observable + bool isMigratingToIronwood; + String getTransactionType(TransactionInfo tx) { if (wallet.type == WalletType.bitcoin) { if (tx.isReplaced == true) return ' (replaced)'; diff --git a/lib/zcash/cw_zcash.dart b/lib/zcash/cw_zcash.dart index 76ecb5ca6..51c9dc53e 100644 --- a/lib/zcash/cw_zcash.dart +++ b/lib/zcash/cw_zcash.dart @@ -213,6 +213,11 @@ class CWZcash extends Zcash { bool ironwoodActive(WalletAddresses walletAddresses) { return (walletAddresses as ZcashWalletAddresses).ironwoodActive; } + + @override + Future hasOrchardMigratableBalance(WalletBase wallet) { + return (wallet as ZcashWallet).hasOrchardMigratableBalance(); + } } const wordList = [ diff --git a/res/pictures/ironwood_migration.svg b/res/pictures/ironwood_migration.svg new file mode 100644 index 000000000..114e7cc1c --- /dev/null +++ b/res/pictures/ironwood_migration.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 9376a6332..648568f30 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -571,6 +571,7 @@ "invalid_input": "Invalid input", "invalid_password": "Invalid password", "invoice_details": "Invoice details", + "is_currently_being_migrated": "is currently being migrated", "is_percentage": "is", "keys": "Keys", "label": "Label", @@ -646,6 +647,7 @@ "messages": "Messages", "method": "Method", "methods": "Methods", + "migrating_to_ironwood": "migrating to Ironwood", "min_amount": "Min: ${value}", "min_value": "Min: ${value} ${currency}", "mining": "Mining", @@ -1476,5 +1478,9 @@ "zcash_card_enable_later": "You can always enable this card later in settings", "zcash_card_missing_funds": "Missing funds?", "zcash_card_scan": "Scan", - "zcash_card_warning": "Do not close the app until the procedure completes, if you do so this process will need to restart from scratch." + "zcash_card_warning": "Do not close the app until the procedure completes, if you do so this process will need to restart from scratch.", + "zcash_network_upgrade": "Zcash Network Upgrade", + "zcash_network_upgrade_desc_1": "Zcash has undergone a network upgrade called Ironwood that requires migration of funds before they can be spent. This migration is automatic, privacy-preserving, and starts as soon as you open your Zcash wallet.", + "zcash_network_upgrade_desc_2": "When the migration finishes, your Available Balance will return to normal, and you can continue to send and receive Zcash as usual.", + "zcash_network_upgrade_desc_3": "Please allow your Zcash wallet to finishing syncing, and then leave the app open until migration finishes which can take a few minutes depending on the balance." } diff --git a/tool/configure.dart b/tool/configure.dart index 6621fc21a..66c302799 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -1770,6 +1770,7 @@ abstract class Zcash { bool showMissingFundsCard(WalletBase wallet); Future rescanInternalChange(WalletBase wallet); bool ironwoodActive(WalletAddresses walletAddresses); + Future hasOrchardMigratableBalance(WalletBase wallet); } """; From 0b93bafe0b20e2443d383e286815da2338ac70c9 Mon Sep 17 00:00:00 2001 From: malik1004x Date: Tue, 4 Aug 2026 14:09:04 +0200 Subject: [PATCH 02/10] replace asserts for semantic labels with lints (#3483) --- cw_custom_lints/lib/main.dart | 4 ++ .../modal_top_bar_semantics_rule.dart | 69 +++++++++++++++++++ .../modern_button_semantics_rule.dart | 56 +++++++++++++++ .../lib/no_bare_catch/no_bare_catch_rule.dart | 51 ++++++++++++++ .../lib/utils/widget_arguments.dart | 39 +++++++++++ lib/new-ui/widgets/modern_button.dart | 8 +-- .../widgets/receive_page/receive_top_bar.dart | 7 +- 7 files changed, 222 insertions(+), 12 deletions(-) create mode 100644 cw_custom_lints/lib/modal_top_bar_semantics/modal_top_bar_semantics_rule.dart create mode 100644 cw_custom_lints/lib/modern_button_semantics/modern_button_semantics_rule.dart create mode 100644 cw_custom_lints/lib/no_bare_catch/no_bare_catch_rule.dart create mode 100644 cw_custom_lints/lib/utils/widget_arguments.dart diff --git a/cw_custom_lints/lib/main.dart b/cw_custom_lints/lib/main.dart index 39e07ba30..e57e22525 100644 --- a/cw_custom_lints/lib/main.dart +++ b/cw_custom_lints/lib/main.dart @@ -1,6 +1,8 @@ import "package:analysis_server_plugin/plugin.dart"; import "package:analysis_server_plugin/registry.dart"; import "package:cw_custom_lints/http_force_proxy/http_force_proxy_rule.dart"; +import "package:cw_custom_lints/modal_top_bar_semantics/modal_top_bar_semantics_rule.dart"; +import "package:cw_custom_lints/modern_button_semantics/modern_button_semantics_rule.dart"; import "package:cw_custom_lints/print_verbose/print_verbose_fix.dart"; import "package:cw_custom_lints/print_verbose/print_verbose_rule.dart"; import "package:cw_custom_lints/restricted_imports/restricted_imports_rule.dart"; @@ -16,6 +18,8 @@ class CwCustomLintsPlugin extends Plugin { registry.registerWarningRule(PrintVerboseRule()); registry.registerWarningRule(RestrictedImportsRule()); registry.registerWarningRule(HttpForceProxyRule()); + registry.registerWarningRule(ModernButtonSemanticsRule()); + registry.registerWarningRule(ModalTopBarSemanticsRule()); registry.registerFixForRule(PrintVerboseRule.code, ReplaceWithPrintV.new); } diff --git a/cw_custom_lints/lib/modal_top_bar_semantics/modal_top_bar_semantics_rule.dart b/cw_custom_lints/lib/modal_top_bar_semantics/modal_top_bar_semantics_rule.dart new file mode 100644 index 000000000..69eccaffe --- /dev/null +++ b/cw_custom_lints/lib/modal_top_bar_semantics/modal_top_bar_semantics_rule.dart @@ -0,0 +1,69 @@ +import "package:analyzer/analysis_rule/analysis_rule.dart"; +import "package:analyzer/analysis_rule/rule_context.dart"; +import "package:analyzer/analysis_rule/rule_visitor_registry.dart"; +import "package:analyzer/dart/ast/ast.dart"; +import "package:analyzer/dart/ast/visitor.dart"; +import "package:analyzer/error/error.dart"; +import "package:cw_custom_lints/utils/widget_arguments.dart"; + +class ModalTopBarSemanticsRule extends AnalysisRule { + ModalTopBarSemanticsRule() + : super( + name: "require_modal_top_bar_semantics", + description: + "ModalTopBar icons need a semantic label, because the icon alone does not say whether it closes the modal, goes back or does something else.", + ); + + static const LintCode code = LintCode( + "require_modal_top_bar_semantics", + "ModalTopBar was given a {0} without a {1}, so screen readers have nothing to announce.", + correctionMessage: "Pass a localized {1} next to the {0}.", + severity: DiagnosticSeverity.WARNING, + ); + + static const _iconSemanticLabels = { + "leadingIcon": "leadingSemanticLabel", + "trailingIcon": "trailingSemanticLabel", + }; + + @override + LintCode get diagnosticCode => code; + + @override + void registerNodeProcessors(RuleVisitorRegistry registry, RuleContext context) => + registry.addInstanceCreationExpression(this, _Visitor(this)); +} + +class _Visitor extends SimpleAstVisitor { + _Visitor(this.rule); + + final AnalysisRule rule; + + @override + void visitInstanceCreationExpression(InstanceCreationExpression node) { + if (!isCakeWalletWidget(node.constructorName, "ModalTopBar")) { + return; + } + + for (final slot in ModalTopBarSemanticsRule._iconSemanticLabels.entries) { + _checkSlot(node.argumentList, iconName: slot.key, semanticLabelName: slot.value); + } + } + + void _checkSlot( + ArgumentList argumentList, { + required String iconName, + required String semanticLabelName, + }) { + final icon = namedArgument(argumentList, iconName); + if (icon == null || icon.argumentExpression is NullLiteral) { + return; + } + + if (!isMissingOrEmptyText(namedArgumentExpression(argumentList, semanticLabelName))) { + return; + } + + rule.reportAtToken(icon.name, arguments: [iconName, semanticLabelName]); + } +} diff --git a/cw_custom_lints/lib/modern_button_semantics/modern_button_semantics_rule.dart b/cw_custom_lints/lib/modern_button_semantics/modern_button_semantics_rule.dart new file mode 100644 index 000000000..7824fced4 --- /dev/null +++ b/cw_custom_lints/lib/modern_button_semantics/modern_button_semantics_rule.dart @@ -0,0 +1,56 @@ +import "package:analyzer/analysis_rule/analysis_rule.dart"; +import "package:analyzer/analysis_rule/rule_context.dart"; +import "package:analyzer/analysis_rule/rule_visitor_registry.dart"; +import "package:analyzer/dart/ast/ast.dart"; +import "package:analyzer/dart/ast/visitor.dart"; +import "package:analyzer/error/error.dart"; +import "package:cw_custom_lints/utils/widget_arguments.dart"; + +class ModernButtonSemanticsRule extends AnalysisRule { + ModernButtonSemanticsRule() + : super( + name: "require_modern_button_semantics", + description: + "ModernButton needs a semanticLabel when it has no visible label, otherwise screen readers announce an unnamed button.", + ); + + static const LintCode code = LintCode( + "require_modern_button_semantics", + "ModernButton has no visible label, so screen readers have nothing to announce.", + correctionMessage: "Pass a localized semanticLabel, or a non-empty label.", + severity: DiagnosticSeverity.WARNING, + ); + + @override + LintCode get diagnosticCode => code; + + @override + void registerNodeProcessors(RuleVisitorRegistry registry, RuleContext context) => + registry.addInstanceCreationExpression(this, _Visitor(this)); +} + +class _Visitor extends SimpleAstVisitor { + _Visitor(this.rule); + + final AnalysisRule rule; + + @override + void visitInstanceCreationExpression(InstanceCreationExpression node) { + final constructorName = node.constructorName; + if (!isCakeWalletWidget(constructorName, "ModernButton")) { + return; + } + + final argumentList = node.argumentList; + final hasLabel = !isMissingOrEmptyText(namedArgumentExpression(argumentList, "label")); + final hasSemanticLabel = !isMissingOrEmptyText( + namedArgumentExpression(argumentList, "semanticLabel"), + ); + + if (hasLabel || hasSemanticLabel) { + return; + } + + rule.reportAtNode(constructorName); + } +} diff --git a/cw_custom_lints/lib/no_bare_catch/no_bare_catch_rule.dart b/cw_custom_lints/lib/no_bare_catch/no_bare_catch_rule.dart new file mode 100644 index 000000000..611ca6bfe --- /dev/null +++ b/cw_custom_lints/lib/no_bare_catch/no_bare_catch_rule.dart @@ -0,0 +1,51 @@ +import "package:analyzer/analysis_rule/analysis_rule.dart"; +import "package:analyzer/analysis_rule/rule_context.dart"; +import "package:analyzer/analysis_rule/rule_visitor_registry.dart"; +import "package:analyzer/dart/ast/ast.dart"; +import "package:analyzer/dart/ast/visitor.dart"; +import "package:analyzer/error/error.dart"; + +class NoBareCatchRule extends AnalysisRule { + NoBareCatchRule() + : super( + name: "no_bare_catch", + description: "please specify the exception class to catch (on SomeException catch (e))", + ); + + static const LintCode code = LintCode( + "no_bare_catch", + "please specify the exception class to catch (on SomeException catch (e))", + severity: DiagnosticSeverity.WARNING, + ); + + @override + LintCode get diagnosticCode => code; + + @override + void registerNodeProcessors(RuleVisitorRegistry registry, RuleContext context) { + registry.addCatchClause(this, _Visitor(this)); + } +} + +class _Visitor extends SimpleAstVisitor { + _Visitor(this.rule); + + final AnalysisRule rule; + + @override + void visitCatchClause(CatchClause node) { + if (node.exceptionType != null) { + return; + } + + final tryStatement = node.parent; + if (tryStatement is TryStatement) { + final precedingClauses = tryStatement.catchClauses.takeWhile((clause) => clause != node); + if (precedingClauses.any((clause) => clause.exceptionType != null)) { + return; + } + } + + rule.reportAtNode(node); + } +} diff --git a/cw_custom_lints/lib/utils/widget_arguments.dart b/cw_custom_lints/lib/utils/widget_arguments.dart new file mode 100644 index 000000000..cd6bb22d3 --- /dev/null +++ b/cw_custom_lints/lib/utils/widget_arguments.dart @@ -0,0 +1,39 @@ +import "package:analyzer/dart/ast/ast.dart"; + +bool isCakeWalletWidget(ConstructorName constructorName, String className) { + final element = constructorName.type.element; + if (element == null || element.name != className) { + return false; + } + + final libraryUri = element.library?.uri; + if (libraryUri == null || libraryUri.scheme != "package") { + return false; + } + + final segments = libraryUri.pathSegments; + return segments.isNotEmpty && segments.first == "cake_wallet"; +} + +NamedArgument? namedArgument(ArgumentList argumentList, String name) { + for (final argument in argumentList.arguments) { + if (argument is NamedArgument && argument.name.lexeme == name) { + return argument; + } + } + + return null; +} + +Expression? namedArgumentExpression(ArgumentList argumentList, String name) => + namedArgument(argumentList, name)?.argumentExpression; + +// passed null or "" +// does NOT work if a runtime expression evaluates to an empty string or null +bool isMissingOrEmptyText(Expression? expression) { + if (expression == null || expression is NullLiteral) { + return true; + } + + return expression is StringLiteral && (expression.stringValue?.isEmpty ?? false); +} diff --git a/lib/new-ui/widgets/modern_button.dart b/lib/new-ui/widgets/modern_button.dart index bba456d35..748aea817 100644 --- a/lib/new-ui/widgets/modern_button.dart +++ b/lib/new-ui/widgets/modern_button.dart @@ -28,9 +28,7 @@ class ModernButton extends StatelessWidget { this.backgroundColor, this.label, this.semanticLabel}) - : svgPath = null, - assert(semanticLabel != null || (label != null && label != ""), - "ModernButton needs a semanticLabel when it has no visible label"); + : svgPath = null; const ModernButton.svg( {super.key, @@ -42,9 +40,7 @@ class ModernButton extends StatelessWidget { this.backgroundColor, this.label, this.semanticLabel}) - : icon = null, - assert(semanticLabel != null || (label != null && label != ""), - "ModernButton needs a semanticLabel when it has no visible label"); + : icon = null; @override Widget build(BuildContext context) { diff --git a/lib/new-ui/widgets/receive_page/receive_top_bar.dart b/lib/new-ui/widgets/receive_page/receive_top_bar.dart index 374c58d07..4d49b4dd9 100644 --- a/lib/new-ui/widgets/receive_page/receive_top_bar.dart +++ b/lib/new-ui/widgets/receive_page/receive_top_bar.dart @@ -16,12 +16,7 @@ class ModalTopBar extends StatelessWidget { this.leadingWidget, this.trailingWidget, this.leadingSemanticLabel, - this.trailingSemanticLabel}) - : assert(leadingIcon == null || (leadingSemanticLabel != null && leadingSemanticLabel != ""), - "leadingIcon requires a non-empty leadingSemanticLabel"), - assert( - trailingIcon == null || (trailingSemanticLabel != null && trailingSemanticLabel != ""), - "trailingIcon requires a non-empty trailingSemanticLabel") { + this.trailingSemanticLabel}) { if (leadingIcon != null && leadingWidget != null) { throw Exception("Cannot have both leadingIcon and leadingWidget"); } From 0e42f162be83dd7757399560721214b93eb71bbc Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 08:42:50 +0200 Subject: [PATCH 03/10] Wrap long passphrase value on the wallet seed/keys screen (#3480) --- .../screens/wallet_keys/wallet_keys_page.dart | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/src/screens/wallet_keys/wallet_keys_page.dart b/lib/src/screens/wallet_keys/wallet_keys_page.dart index ebd4e7496..e5cb40c16 100644 --- a/lib/src/screens/wallet_keys/wallet_keys_page.dart +++ b/lib/src/screens/wallet_keys/wallet_keys_page.dart @@ -300,6 +300,7 @@ class _WalletKeysPageBodyState extends State color: Theme.of(context).colorScheme.surfaceContainer, ), child: Row( + crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( @@ -313,21 +314,25 @@ class _WalletKeysPageBodyState extends State const SizedBox(width: 6), Expanded( child: Row( + crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Observer( - builder: (BuildContext context) { - return Text( - (widget.walletKeysViewModel.obscurePassphrase) - ? "*****" - : widget.walletKeysViewModel.passphrase, - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ); - }, + Expanded( + child: Observer( + builder: (BuildContext context) { + return Text( + (widget.walletKeysViewModel.obscurePassphrase) + ? "*****" + : widget.walletKeysViewModel.passphrase, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ); + }, + ), ), + const SizedBox(width: 6), Observer( builder: (BuildContext context) { return GestureDetector( From 061f36a6b8669141247b454c71bbf488123697a3 Mon Sep 17 00:00:00 2001 From: Serhii <17529954+serhii-bor@users.noreply.github.com> Date: Wed, 5 Aug 2026 09:49:54 +0300 Subject: [PATCH 04/10] fix:quick actions cold start (#3476) * fix:quick actions cold start * route receive links to new receive page --- lib/reactions/on_authentication_state_change.dart | 4 +++- lib/router.dart | 11 +++++++++++ lib/routes.dart | 1 + lib/view_model/link_view_model.dart | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/reactions/on_authentication_state_change.dart b/lib/reactions/on_authentication_state_change.dart index 02ddd5639..d63c54781 100644 --- a/lib/reactions/on_authentication_state_change.dart +++ b/lib/reactions/on_authentication_state_change.dart @@ -146,7 +146,9 @@ void startAuthenticationStateChange( ), ); } else { - await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false); + unawaited( + navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false), + ); } WidgetsBinding.instance.addPostFrameCallback((_) { final linkViewModel = getIt.get(); diff --git a/lib/router.dart b/lib/router.dart index a130b2667..837eab8c8 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -11,6 +11,7 @@ import 'package:cake_wallet/new-ui/pages/bridge/bridge_receiving_wallet_page.dar import 'package:cake_wallet/new-ui/pages/coin_control_page.dart'; import 'package:cake_wallet/new-ui/pages/addresses_page.dart'; import 'package:cake_wallet/new-ui/pages/lightning_username_page.dart'; +import "package:cake_wallet/new-ui/pages/receive_page.dart"; import 'package:cake_wallet/new-ui/pages/send_page.dart'; import 'package:cake_wallet/order/order.dart'; import 'package:cake_wallet/core/new_wallet_type_arguments.dart'; @@ -469,6 +470,16 @@ Route createRoute(RouteSettings settings) { return handleRouteWithPlatformAwareness((context) => getIt.get(), settings: settings); + case Routes.newReceivePage: + if (FeatureFlag.hasNewUi) { + return handleRouteWithPlatformAwareness( + (context) => Material(child: getIt.get(param1: false, param2: null)), + settings: settings, + ); + } + return handleRouteWithPlatformAwareness((context) => getIt.get(), + settings: settings); + case Routes.transactionDetails: return CupertinoPageRoute( fullscreenDialog: true, diff --git a/lib/routes.dart b/lib/routes.dart index 96ac8264d..236196bf7 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -71,6 +71,7 @@ class Routes { static const unspentCoinsList = '/unspent_coins_list'; static const unspentCoinsDetails = '/unspent_coins_details'; static const addressPage = '/address_page'; + static const newReceivePage = '/new_receive_page'; static const fullscreenQR = '/fullscreen_qr'; static const cakePayWelcomePage = '/cake_pay_welcome_page'; static const cakePayLoginPage = '/cake_pay_login_page'; diff --git a/lib/view_model/link_view_model.dart b/lib/view_model/link_view_model.dart index a9e742733..f14718ec5 100644 --- a/lib/view_model/link_view_model.dart +++ b/lib/view_model/link_view_model.dart @@ -47,7 +47,7 @@ class LinkViewModel { case 'send': return Routes.send; case 'receive': - return Routes.addressPage; + return Routes.newReceivePage; default: return null; } From 930397cbe66c48f083431ec6afbeeb27cb0737ed Mon Sep 17 00:00:00 2001 From: Seth For Privacy <40500387+sethforprivacy@users.noreply.github.com> Date: Wed, 5 Aug 2026 03:16:58 -0400 Subject: [PATCH 05/10] a11y: receive flow semantics (copy control, pickers, selection state) (#3467) * Add strings for receive-flow accessibility labels New English keys: info, long_press_to_copy, standard, token. They replace hard-coded English in the receive amount modal, the payjoin copy modal and the addresses long-press menu, and name the copy hint. * Collapse copy-to-clipboard controls to one accessible button CopyWrapper gains an optional controlBuilder that hands the copy callback to the control it builds instead of stacking its own gesture layer on top, and it now announces the copy through SemanticsService so screen-reader users get the same feedback the copied state gives sighted users. When there is nothing to copy it no longer leaves a gesture detector behind that reads as actionable but does nothing. Its own tap/long-press wrapper is exposed as one merged button node with a copy hint and a Copy custom action, so tap-to-copy stays reachable on rows that also navigate. The receive copy button used an outer gesture detector for the real work while the visible ModernButton had a no-op onPressed behind two IgnorePointers. It is now a single ModernButton whose onPressed copies, or opens the payjoin copy modal when there is no direct URI to copy; the AnimatedSwitcher copied state is unchanged. The payjoin modal announces the copy and no longer hard-codes "Standard". * Add screen-reader semantics to receive flow and address pickers Every control touched here becomes exactly one merged semantics node with a localized name, the right role and, where it exists, its selection state: - receive page: the label chip is a button hinted with set_label and is kept out of the semantics tree while it is collapsed to zero height. - amount modal: token picker and currency picker are buttons named by select_token / select_fiat_currency_title, the amount field carries the amount label instead of relying on its placeholder, and the visible captions are excluded so they are not announced twice. - amount display: amount, symbol and fiat equivalent are announced together. - info box: Dismiss is a real button, the info icon and the illustrative currency stack are decorative (the message text carries their meaning). - address type: the row and its chevron triggered the same picker; only the row is exposed now, named by address_type. - address type selector: More Options exposes its expanded state, each option row reports selected + inMutuallyExclusiveGroup (its checkbox is excluded so the state is announced once), and the collapsed options are unreachable. - label modal quick-label chips are buttons. - addresses page: rows are buttons reporting selection, with the long-press actions (set label, hide/unhide, info) also exposed as custom semantics actions; the checkmark is decorative; the search field keeps a name once it has text; show-hidden-addresses is a button. - currency picker: search field, clear button, currency rows, chain chips and network rows get names, roles and selection state; icons and chevrons are decorative. No visual or pointer behaviour changes. * Drop single-use locals to keep the diff minimal * Address review: replace deprecated copy announcements with semantic state --- lib/new-ui/pages/addresses_page.dart | 315 ++++++++++-------- lib/new-ui/pages/receive_page.dart | 22 +- lib/new-ui/widgets/copy_wrapper.dart | 65 +++- .../currency_picker/chain_chip_strip.dart | 43 ++- .../currency_picker/currency_picker_row.dart | 102 +++--- .../currency_picker_search_field.dart | 48 ++- .../currency_picker/select_network_page.dart | 74 ++-- .../receive_page/payjoin_copy_modal.dart | 16 +- .../receive_page/receive_address_type.dart | 100 +++--- .../receive_address_type_selector.dart | 262 ++++++++------- .../receive_page/receive_amount_display.dart | 82 ++--- .../receive_page/receive_amount_modal.dart | 229 +++++++------ .../receive_page/receive_bottom_buttons.dart | 45 ++- .../receive_page/receive_info_box.dart | 153 +++++---- .../receive_page/receive_label_modal.dart | 47 +-- .../receive_page/receive_label_widget.dart | 18 +- .../swap_page/swap_send_external_modal.dart | 4 + res/values/strings_en.arb | 4 + 18 files changed, 938 insertions(+), 691 deletions(-) diff --git a/lib/new-ui/pages/addresses_page.dart b/lib/new-ui/pages/addresses_page.dart index e75dc16fe..ee02aa88f 100644 --- a/lib/new-ui/pages/addresses_page.dart +++ b/lib/new-ui/pages/addresses_page.dart @@ -20,6 +20,7 @@ import 'package:cake_wallet/wownero/wownero.dart'; import 'package:cw_core/card_design.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/semantics.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/utils/list_item.dart'; @@ -213,24 +214,31 @@ class AddressSearchBox extends StatelessWidget { border: Border.all( color: Theme.of(context).colorScheme.surfaceContainerHighest, width: 1), borderRadius: BorderRadius.circular(99999)), - child: TextField( - controller: controller, - decoration: InputDecoration( - hintText: S.of(context).search, - hintStyle: TextStyle( - fontWeight: FontWeight.w600, + // The hint names the field only while it is empty, so the label is + // supplied once there is text to keep exactly one announcement. + child: MergeSemantics( + child: Semantics( + label: controller.text.isEmpty ? null : S.of(context).search, + child: TextField( + controller: controller, + decoration: InputDecoration( + hintText: S.of(context).search, + hintStyle: TextStyle( + fontWeight: FontWeight.w600, + ), + prefixIcon: ExcludeSemantics(child: Icon(Icons.search)), + filled: false, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(99999), + borderSide: BorderSide.none, + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(99999), + borderSide: BorderSide.none, + ), + contentPadding: EdgeInsets.symmetric(vertical: 8), + ), ), - prefixIcon: Icon(Icons.search), - filled: false, - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(99999), - borderSide: BorderSide.none, - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(99999), - borderSide: BorderSide.none, - ), - contentPadding: EdgeInsets.symmetric(vertical: 8), ), ), ), @@ -334,116 +342,139 @@ class AddressRow extends StatelessWidget { @override Widget build(BuildContext context) { final hasLabel = item.name != null && item.name!.isNotEmpty; + final hideLabel = item.isHidden ? S.of(context).unhide_address : S.of(context).hide_address; - return GestureDetector( - onTap: onSelect, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: LongPressPopupBuilder( - popup: LongPressMenu( - items: [ - LongPressMenuItem( - label: S.of(context).set_label, - iconPath: "assets/new-ui/address_set_label.svg", - onSelected: () async { - Navigator.of(context, rootNavigator: true).pop(); - final res = await showPopUp( - context: context, - builder: (context) => getIt.get(param1: item)); + Future editLabel() async { + final res = await showPopUp( + context: context, builder: (context) => getIt.get(param1: item)); - if (res != null) { - onLabelChanged(); - } - }), - LongPressMenuItem( - label: item.isHidden ? S.of(context).unhide_address : S.of(context).hide_address, - iconPath: "assets/new-ui/address_hide.svg", - onSelected: () { - Navigator.of(context, rootNavigator: true).pop(); - onAddressHidden(); - }, - color: Theme.of(context).colorScheme.error), - LongPressMenuItem( - label: 'Info', - iconPath: "assets/images/info_icon.svg", - onSelected: () async { - Navigator.of(context, rootNavigator: true).pop(); - await showPopUp( - context: context, - builder: (context) => getIt.get(param1: item)); - }), - ], - ), - child: AnimatedContainer( - duration: Duration(milliseconds: 150), - decoration: BoxDecoration( - color: selected - ? Theme.of(context).colorScheme.surfaceContainerHigh - : Theme.of(context).colorScheme.surfaceContainer, - borderRadius: BorderRadius.vertical( - top: Radius.circular(first ? 16 : 0), - bottom: Radius.circular(last ? 16 : 0), + if (res != null) { + onLabelChanged(); + } + } + + Future showInfo() async { + await showPopUp( + context: context, builder: (context) => getIt.get(param1: item)); + } + + // The row is a single control: selection on tap, and the actions that are + // otherwise reachable only by long press exposed as custom actions. + return MergeSemantics( + child: Semantics( + button: true, + selected: selected, + customSemanticsActions: { + CustomSemanticsAction(label: S.of(context).set_label): editLabel, + CustomSemanticsAction(label: hideLabel): onAddressHidden, + CustomSemanticsAction(label: S.of(context).info): showInfo, + }, + child: GestureDetector( + onTap: onSelect, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: LongPressPopupBuilder( + popup: LongPressMenu( + items: [ + LongPressMenuItem( + label: S.of(context).set_label, + iconPath: "assets/new-ui/address_set_label.svg", + onSelected: () { + Navigator.of(context, rootNavigator: true).pop(); + editLabel(); + }), + LongPressMenuItem( + label: hideLabel, + iconPath: "assets/new-ui/address_hide.svg", + onSelected: () { + Navigator.of(context, rootNavigator: true).pop(); + onAddressHidden(); + }, + color: Theme.of(context).colorScheme.error), + LongPressMenuItem( + label: S.of(context).info, + iconPath: "assets/images/info_icon.svg", + onSelected: () { + Navigator.of(context, rootNavigator: true).pop(); + showInfo(); + }), + ], ), - ), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Row( - spacing: 8, - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - children: [ - Row( - spacing: 4, + child: AnimatedContainer( + duration: Duration(milliseconds: 150), + decoration: BoxDecoration( + color: selected + ? Theme.of(context).colorScheme.surfaceContainerHigh + : Theme.of(context).colorScheme.surfaceContainer, + borderRadius: BorderRadius.vertical( + top: Radius.circular(first ? 16 : 0), + bottom: Radius.circular(last ? 16 : 0), + ), + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + spacing: 8, + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( children: [ - if (hasLabel) - Text( - item.name!, - style: TextStyle( - fontSize: 12, - color: Theme.of(context).colorScheme.onSurface, - fontWeight: FontWeight.w500), - ), - Expanded( - child: AddressFormatter.buildSegmentedAddress( - address: item.address, - walletType: walletType, - textAlign: TextAlign.left, - evenTextStyle: Theme.of(context).textTheme.bodyMedium!.copyWith( + Row( + spacing: 4, + children: [ + if (hasLabel) + Text( + item.name!, + style: TextStyle( fontSize: 12, - fontWeight: FontWeight.w400, - color: hasLabel - ? Theme.of(context).colorScheme.onSurfaceVariant - : Theme.of(context).colorScheme.onSurface, - ), - shouldTruncate: (hasLabel)), + color: Theme.of(context).colorScheme.onSurface, + fontWeight: FontWeight.w500), + ), + Expanded( + child: AddressFormatter.buildSegmentedAddress( + address: item.address, + walletType: walletType, + textAlign: TextAlign.left, + evenTextStyle: Theme.of(context).textTheme.bodyMedium!.copyWith( + fontSize: 12, + fontWeight: FontWeight.w400, + color: hasLabel + ? Theme.of(context).colorScheme.onSurfaceVariant + : Theme.of(context).colorScheme.onSurface, + ), + shouldTruncate: (hasLabel)), + ), + ], ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "${S.of(context).transactions}: ${item.txCount}", + style: TextStyle( + fontSize: 12, + color: Theme.of(context).colorScheme.onSurfaceVariant), + ), + Text( + "${hasReceived ? S.of(context).received : S.of(context).balance}: ${item.balance}", + style: TextStyle( + fontSize: 12, + color: Theme.of(context).colorScheme.onSurfaceVariant)), + ], + ) ], ), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "${S.of(context).transactions}: ${item.txCount}", - style: TextStyle( - fontSize: 12, - color: Theme.of(context).colorScheme.onSurfaceVariant), - ), - Text( - "${hasReceived ? S.of(context).received : S.of(context).balance}: ${item.balance}", - style: TextStyle( - fontSize: 12, - color: Theme.of(context).colorScheme.onSurfaceVariant)), - ], - ) - ], - ), + ), + // The row's selected state carries this information. + if (selected) + ExcludeSemantics( + child: CakeImageWidget(imageUrl: "assets/new-ui/checkmark.svg")) + ], ), - if (selected) CakeImageWidget(imageUrl: "assets/new-ui/checkmark.svg") - ], + ), ), ), ), @@ -463,26 +494,34 @@ class ShowHiddenButton extends StatelessWidget { child: Column( children: [ Material( - child: InkWell( - onTap: () { - Navigator.of(context).pushNamed(Routes.receiveAddresses, arguments: true); - }, - child: Container( - height: 48, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainer, - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(S.of(context).show_hidden_addresses), - RotatedBox( - quarterTurns: 1, - child: CakeImageWidget(imageUrl: "assets/new-ui/dropdown_arrow.svg")) - ], + child: MergeSemantics( + child: Semantics( + button: true, + child: InkWell( + onTap: () { + Navigator.of(context).pushNamed(Routes.receiveAddresses, arguments: true); + }, + child: Container( + height: 48, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainer, + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(S.of(context).show_hidden_addresses), + ExcludeSemantics( + child: RotatedBox( + quarterTurns: 1, + child: + CakeImageWidget(imageUrl: "assets/new-ui/dropdown_arrow.svg")), + ) + ], + ), + ), ), ), ), diff --git a/lib/new-ui/pages/receive_page.dart b/lib/new-ui/pages/receive_page.dart index e68a09305..b5656e9de 100644 --- a/lib/new-ui/pages/receive_page.dart +++ b/lib/new-ui/pages/receive_page.dart @@ -275,11 +275,23 @@ class _NewReceivePageState extends State { ReceiveAddressWidget( addressListViewModel: widget.addressListViewModel, ), - GestureDetector( - onTap: _showLabelModal, - child: ReceiveLabelWidget( - name: _addressItemWithLabel?.name ?? "", - largeQrMode: _largeQrMode, + // The label chip animates to zero height when there is no + // label (or in large QR mode); keep it out of the semantics + // tree entirely while it is collapsed. + ExcludeSemantics( + excluding: _largeQrMode || !hasLabel, + child: MergeSemantics( + child: Semantics( + button: true, + hint: S.of(context).set_label, + child: GestureDetector( + onTap: _showLabelModal, + child: ReceiveLabelWidget( + name: _addressItemWithLabel?.name ?? "", + largeQrMode: _largeQrMode, + ), + ), + ), ), ), Observer( diff --git a/lib/new-ui/widgets/copy_wrapper.dart b/lib/new-ui/widgets/copy_wrapper.dart index 0f3255c48..3f9011ab4 100644 --- a/lib/new-ui/widgets/copy_wrapper.dart +++ b/lib/new-ui/widgets/copy_wrapper.dart @@ -1,8 +1,10 @@ import 'dart:io'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/utils/clipboard_util.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/semantics.dart'; import 'package:flutter/services.dart'; class CopyWrapper extends StatefulWidget { @@ -11,13 +13,25 @@ class CopyWrapper extends StatefulWidget { this.data, this.requireLongPress = false, this.isSensitive = false, - required this.builder, - this.duration = const Duration(milliseconds: 1200)}); + this.builder, + this.controlBuilder, + this.duration = const Duration(milliseconds: 1200)}) + : assert((builder == null) != (controlBuilder == null), + "Provide exactly one of builder or controlBuilder"); final ClipboardData? data; final bool isSensitive; final bool requireLongPress; - final Widget Function(BuildContext, bool) builder; + + /// Builds content that this widget makes copyable with its own gesture + /// detector. Receives the transient "copied" state. + final Widget Function(BuildContext, bool)? builder; + + /// Builds a control that performs the copy itself, so no extra gesture + /// detector or actionable semantics node is stacked on top of it. [onCopy] is + /// null when there is nothing to copy. + final Widget Function(BuildContext context, bool copied, VoidCallback? onCopy)? controlBuilder; + final Duration duration; @override @@ -31,6 +45,11 @@ class _CopyWrapperState extends State { if (widget.data == null) return; ClipboardUtil.setSensitiveDataToClipboard(widget.data!, isSensitive: widget.isSensitive); HapticFeedback.mediumImpact(); + // Screen readers learn about the copy from the transient "copied" state + // below, which build() marks as a live region, instead of from a push + // announcement: those are deprecated on Android and make TalkBack drop + // whatever it was saying. Where we don't render that state, android 13+ + // already shows its own clipboard confirmation. if (await shouldShowCopied()) { setState(() => copied = true); Future.delayed(widget.duration, () { @@ -41,11 +60,41 @@ class _CopyWrapperState extends State { @override Widget build(BuildContext context) { - return GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: widget.requireLongPress ? null : handleCopy, - onLongPress: !widget.requireLongPress ? null : handleCopy, - child: widget.builder(context, copied), + final VoidCallback? onCopy = widget.data == null ? null : handleCopy; + + // The control's own label carries the copied state (Copy -> Copied), so + // merging it into one node and marking that node a live region while copied + // is enough for a screen reader to pick the change up. + if (widget.controlBuilder != null) { + return MergeSemantics( + child: Semantics( + liveRegion: copied, + child: widget.controlBuilder!(context, copied, onCopy), + ), + ); + } + + final content = widget.builder!(context, copied); + + // Nothing to copy: don't leave behind a gesture detector that a screen + // reader would present as an actionable target that does nothing. + if (onCopy == null) return content; + + return MergeSemantics( + child: Semantics( + button: !widget.requireLongPress, + liveRegion: copied, + hint: widget.requireLongPress ? S.of(context).long_press_to_copy : S.of(context).copy, + customSemanticsActions: { + CustomSemanticsAction(label: S.of(context).copy): onCopy, + }, + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: widget.requireLongPress ? null : onCopy, + onLongPress: !widget.requireLongPress ? null : onCopy, + child: content, + ), + ), ); } diff --git a/lib/new-ui/widgets/currency_picker/chain_chip_strip.dart b/lib/new-ui/widgets/currency_picker/chain_chip_strip.dart index 76b1727a2..17910a4c5 100644 --- a/lib/new-ui/widgets/currency_picker/chain_chip_strip.dart +++ b/lib/new-ui/widgets/currency_picker/chain_chip_strip.dart @@ -56,24 +56,31 @@ class _ChainChip extends StatelessWidget { final colors = Theme.of(context).colorScheme; return Padding( padding: const EdgeInsetsDirectional.only(end: 8), - child: InkWell( - onTap: onTap, - borderRadius: BorderRadius.circular(80), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 10), - decoration: BoxDecoration( - color: isSelected ? colors.primary : colors.surfaceContainer, - borderRadius: BorderRadius.circular(20), - ), - child: Center( - child: Text( - label, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.w500, - fontSize: isSelected ? 14 : 12, - letterSpacing: -0.07, - color: isSelected ? colors.onPrimary : colors.primary, - ), + child: MergeSemantics( + child: Semantics( + button: true, + selected: isSelected, + inMutuallyExclusiveGroup: true, + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(80), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + color: isSelected ? colors.primary : colors.surfaceContainer, + borderRadius: BorderRadius.circular(20), + ), + child: Center( + child: Text( + label, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + fontSize: isSelected ? 14 : 12, + letterSpacing: -0.07, + color: isSelected ? colors.onPrimary : colors.primary, + ), + ), + ), ), ), ), diff --git a/lib/new-ui/widgets/currency_picker/currency_picker_row.dart b/lib/new-ui/widgets/currency_picker/currency_picker_row.dart index 54d712200..52ac4c065 100644 --- a/lib/new-ui/widgets/currency_picker/currency_picker_row.dart +++ b/lib/new-ui/widgets/currency_picker/currency_picker_row.dart @@ -24,55 +24,65 @@ class CurrencyPickerRow extends StatelessWidget { @override Widget build(BuildContext context) { final colors = Theme.of(context).colorScheme; - return InkWell( - onTap: onTap, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), - child: Row( - children: [ - _IconWithBadge(currency: currency, badgePath: chainBadgePath), - const SizedBox(width: 12), - Expanded( - child: Row( - children: [ - Flexible( - child: Text( - currency.fullName ?? currency.title, - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.w500, + return MergeSemantics( + child: Semantics( + button: true, + selected: isSelected, + child: InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + child: Row( + children: [ + ExcludeSemantics( + child: _IconWithBadge(currency: currency, badgePath: chainBadgePath), + ), + const SizedBox(width: 12), + Expanded( + child: Row( + children: [ + Flexible( + child: Text( + currency.fullName ?? currency.title, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + ), + ), + ), + if (chainPillLabel != null) ...[ + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: colors.surfaceContainerHigh, + borderRadius: BorderRadius.circular(10), ), - ), + child: Text( + chainPillLabel!, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w500, + color: colors.onSecondaryContainer, + ), + ), + ), + ], + ], ), - if (chainPillLabel != null) ...[ - const SizedBox(width: 8), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - decoration: BoxDecoration( - color: colors.surfaceContainerHigh, - borderRadius: BorderRadius.circular(10), - ), - child: Text( - chainPillLabel!, - style: Theme.of(context).textTheme.bodySmall?.copyWith( - fontWeight: FontWeight.w500, - color: colors.onSecondaryContainer, - ), - ), - ), - ], - ], - ), + ), + const SizedBox(width: 8), + trailing, + const SizedBox(width: 8), + ExcludeSemantics( + child: Icon( + Icons.chevron_right, + size: 20, + color: isSelected ? colors.primary : colors.onSurfaceVariant, + ), + ), + ], ), - const SizedBox(width: 8), - trailing, - const SizedBox(width: 8), - Icon( - Icons.chevron_right, - size: 20, - color: isSelected ? colors.primary : colors.onSurfaceVariant, - ), - ], + ), ), ), ); diff --git a/lib/new-ui/widgets/currency_picker/currency_picker_search_field.dart b/lib/new-ui/widgets/currency_picker/currency_picker_search_field.dart index 8a62c35a7..25876f0f1 100644 --- a/lib/new-ui/widgets/currency_picker/currency_picker_search_field.dart +++ b/lib/new-ui/widgets/currency_picker/currency_picker_search_field.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:flutter/material.dart'; @@ -27,30 +28,41 @@ class CurrencyPickerSearchField extends StatelessWidget { ), child: Row( children: [ - Icon(Icons.search, size: 20, color: colors.primary), + ExcludeSemantics(child: Icon(Icons.search, size: 20, color: colors.primary)), const SizedBox(width: 10), Expanded( - child: TextFormField( - controller: controller, - style: Theme.of(context).textTheme.bodyMedium, - decoration: InputDecoration( - isCollapsed: true, - border: InputBorder.none, - focusedBorder: InputBorder.none, - hintText: hintText, - hintStyle: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: colors.onSurfaceVariant, - ), + // The hint names the field only while it is empty, so the label is + // supplied once there is text to keep exactly one announcement. + child: MergeSemantics( + child: Semantics( + label: controller.text.isEmpty ? null : hintText, + child: TextFormField( + controller: controller, + style: Theme.of(context).textTheme.bodyMedium, + decoration: InputDecoration( + isCollapsed: true, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: hintText, + hintStyle: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: colors.onSurfaceVariant, + ), + ), + ), ), ), ), if (controller.text.isNotEmpty) - InkWell( - onTap: controller.clear, - customBorder: const CircleBorder(), - child: Padding( - padding: const EdgeInsets.all(4), - child: Icon(Icons.close, size: 16, color: colors.onSurfaceVariant), + Semantics( + button: true, + label: S.of(context).clear, + child: InkWell( + onTap: controller.clear, + customBorder: const CircleBorder(), + child: Padding( + padding: const EdgeInsets.all(4), + child: Icon(Icons.close, size: 16, color: colors.onSurfaceVariant), + ), ), ), ], diff --git a/lib/new-ui/widgets/currency_picker/select_network_page.dart b/lib/new-ui/widgets/currency_picker/select_network_page.dart index 29f18af48..b395ec08c 100644 --- a/lib/new-ui/widgets/currency_picker/select_network_page.dart +++ b/lib/new-ui/widgets/currency_picker/select_network_page.dart @@ -39,11 +39,14 @@ class SelectNetworkPage extends StatelessWidget { onLeadingPressed: () => Navigator.of(context).maybePop(), ), const SizedBox(height: 24), - CakeImageWidget( - imageUrl: assetIconPath, - width: 75, - height: 75, - fit: BoxFit.cover, + // Illustration of the asset named by the title below it. + ExcludeSemantics( + child: CakeImageWidget( + imageUrl: assetIconPath, + width: 75, + height: 75, + fit: BoxFit.cover, + ), ), const SizedBox(height: 12), Text( @@ -107,33 +110,42 @@ class _NetworkRow extends StatelessWidget { final networkIconPath = wt != null ? getCryptoCurrencyIconForWalletListItem(wt) : variant.iconPath; final networkName = chainNameForCurrency(variant); - return InkWell( - onTap: onTap, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14), - child: Row( - children: [ - CakeImageWidget( - imageUrl: networkIconPath, - width: 28, - height: 28, - fit: BoxFit.cover, + return MergeSemantics( + child: Semantics( + button: true, + child: InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14), + child: Row( + children: [ + ExcludeSemantics( + child: CakeImageWidget( + imageUrl: networkIconPath, + width: 28, + height: 28, + fit: BoxFit.cover, + ), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + networkName, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + ), + ), + ), + ExcludeSemantics( + child: Icon( + Icons.chevron_right, + size: 20, + color: colors.onSurfaceVariant, + ), + ), + ], ), - const SizedBox(width: 12), - Expanded( - child: Text( - networkName, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.w500, - ), - ), - ), - Icon( - Icons.chevron_right, - size: 20, - color: colors.onSurfaceVariant, - ), - ], + ), ), ), ); diff --git a/lib/new-ui/widgets/receive_page/payjoin_copy_modal.dart b/lib/new-ui/widgets/receive_page/payjoin_copy_modal.dart index 8fd7c1730..435417330 100644 --- a/lib/new-ui/widgets/receive_page/payjoin_copy_modal.dart +++ b/lib/new-ui/widgets/receive_page/payjoin_copy_modal.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart'; import 'package:cw_core/payment_uris.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/semantics.dart'; import 'package:flutter/services.dart'; class PayjoinCopyModal extends StatelessWidget { @@ -33,7 +34,7 @@ class PayjoinCopyModal extends StatelessWidget { "": [ ListItemRegularRow( keyValue: "btc", - label: "Standard", + label: S.of(context).standard, iconPath: "assets/new-ui/pjmodal_btc.svg", onTap: () { Clipboard.setData( @@ -42,6 +43,7 @@ class PayjoinCopyModal extends StatelessWidget { ? BitcoinURI(amount: uri.amount, address: uri.address).toString() : uri.address), ); + _announceCopied(context); Navigator.of(context).pop(); }), ListItemRegularRow( @@ -52,6 +54,7 @@ class PayjoinCopyModal extends StatelessWidget { Clipboard.setData( ClipboardData(text: uri.toString()), ); + _announceCopied(context); Navigator.of(context).pop(); }) ] @@ -63,4 +66,15 @@ class PayjoinCopyModal extends StatelessWidget { ), ); } + + // Copying pops this sheet right away, so no widget survives to carry a + // semantics state change: this path still needs a direct announcement. It is + // skipped on platforms that deprecate announcements (android, where they + // clear TalkBack's speech queue and the system shows its own clipboard + // confirmation anyway). + void _announceCopied(BuildContext context) { + if (!MediaQuery.supportsAnnounceOf(context)) return; + SemanticsService.sendAnnouncement( + View.of(context), S.of(context).copied, Directionality.of(context)); + } } diff --git a/lib/new-ui/widgets/receive_page/receive_address_type.dart b/lib/new-ui/widgets/receive_page/receive_address_type.dart index 46a5c6cea..7331885b8 100644 --- a/lib/new-ui/widgets/receive_page/receive_address_type.dart +++ b/lib/new-ui/widgets/receive_page/receive_address_type.dart @@ -42,52 +42,64 @@ class ReceiveAddressTypeDisplay extends StatelessWidget { iconPath = "assets/new-ui/address-type-picker-icons/litecoin.svg"; } - return GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () => _showPicker(context), - child: Row( - key: ValueKey("$text$largeQrMode"), - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - spacing: 12.0, - children: [ - if (iconPath != null) - CakeImageWidget( - imageUrl: iconPath, - width: 24, - height: 24, - colorFilter: ColorFilter.mode( - Theme.of(context).colorScheme.primary, - BlendMode.srcIn, - ), - ), - Text( - text, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.primary, - ), - ), - if (!largeQrMode) - Container( - width: 24, - height: 24, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainer, - borderRadius: BorderRadius.circular(999999), - ), - child: IconButton( - padding: EdgeInsets.zero, - constraints: BoxConstraints(), - onPressed: () => _showPicker(context), - icon: (Icon( + // The row and the chevron button trigger the same picker, so only the + // row is exposed and the chevron is treated as decoration. + return MergeSemantics( + child: Semantics( + button: true, + label: S.of(context).address_type, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => _showPicker(context), + child: Row( + key: ValueKey("$text$largeQrMode"), + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + spacing: 12.0, + children: [ + if (iconPath != null) + ExcludeSemantics( + child: CakeImageWidget( + imageUrl: iconPath, + width: 24, + height: 24, + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.primary, + BlendMode.srcIn, + ), + ), + ), + Text( + text, + style: TextStyle( + fontSize: 16, color: Theme.of(context).colorScheme.primary, - size: 20, - Icons.keyboard_arrow_down, - )), + ), ), - ), - ], + if (!largeQrMode) + ExcludeSemantics( + child: Container( + width: 24, + height: 24, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainer, + borderRadius: BorderRadius.circular(999999), + ), + child: IconButton( + padding: EdgeInsets.zero, + constraints: BoxConstraints(), + onPressed: () => _showPicker(context), + icon: (Icon( + color: Theme.of(context).colorScheme.primary, + size: 20, + Icons.keyboard_arrow_down, + )), + ), + ), + ), + ], + ), + ), ), ); }, diff --git a/lib/new-ui/widgets/receive_page/receive_address_type_selector.dart b/lib/new-ui/widgets/receive_page/receive_address_type_selector.dart index 1a3ce73d5..24e50ef3c 100644 --- a/lib/new-ui/widgets/receive_page/receive_address_type_selector.dart +++ b/lib/new-ui/widgets/receive_page/receive_address_type_selector.dart @@ -134,38 +134,49 @@ class _ReceiveAddressTypeSelectorState extends State borderRadius: BorderRadius.vertical( top: Radius.circular(20), bottom: _otherOptionsExpanded ? Radius.zero : Radius.circular(20)), - child: InkWell( - highlightColor: Theme.of(context).colorScheme.surfaceContainerHighest, - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - bottom: !_otherOptionsExpanded ? Radius.zero : Radius.circular(20)), - onTap: () { - setState(() { - _otherOptionsExpanded = !_otherOptionsExpanded; - }); - }, - child: Container( - height: 64.0, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 18.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - S.of(context).more_options, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.primary), + child: MergeSemantics( + child: Semantics( + button: true, + expanded: _otherOptionsExpanded, + child: InkWell( + highlightColor: + Theme.of(context).colorScheme.surfaceContainerHighest, + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + bottom: !_otherOptionsExpanded + ? Radius.zero + : Radius.circular(20)), + onTap: () { + setState(() { + _otherOptionsExpanded = !_otherOptionsExpanded; + }); + }, + child: Container( + height: 64.0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 18.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + S.of(context).more_options, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.primary), + ), + ExcludeSemantics( + child: AnimatedRotation( + duration: ReceiveAddressTypeSelector + .otherOptionsExpandDuration, + turns: _otherOptionsExpanded ? 0.0 : 0.5, + curve: Curves.easeOut, + child: CakeImageWidget( + imageUrl: "assets/new-ui/dropdown_arrow.svg")), + ) + ], ), - AnimatedRotation( - duration: - ReceiveAddressTypeSelector.otherOptionsExpandDuration, - turns: _otherOptionsExpanded ? 0.0 : 0.5, - curve: Curves.easeOut, - child: CakeImageWidget( - imageUrl: "assets/new-ui/dropdown_arrow.svg")) - ], + ), ), ), ), @@ -180,40 +191,45 @@ class _ReceiveAddressTypeSelectorState extends State duration: ReceiveAddressTypeSelector.otherOptionsExpandDuration, curve: Curves.easeOut, alignment: Alignment.topCenter, - child: Container( - height: _otherOptionsExpanded ? null : 0, - child: ListView.separated( - shrinkWrap: true, - padding: EdgeInsets.zero, - physics: NeverScrollableScrollPhysics(), - itemCount: otherOptions.length, - itemBuilder: (context, index) { - final opt = otherOptions[index]; + // Collapsed to zero height: keep the options out of + // the semantics tree so they cannot be focused. + child: ExcludeSemantics( + excluding: !_otherOptionsExpanded, + child: Container( + height: _otherOptionsExpanded ? null : 0, + child: ListView.separated( + shrinkWrap: true, + padding: EdgeInsets.zero, + physics: NeverScrollableScrollPhysics(), + itemCount: otherOptions.length, + itemBuilder: (context, index) { + final opt = otherOptions[index]; - return ReceiveAddressTypeRow( - option: opt, - roundedTop: false, - roundedBottom: index == otherOptions.length - 1, - selected: - widget.receiveOptionViewModel.selectedReceiveOption == opt, - onItemTap: () { - Navigator.of(context).pop(opt); - }, - receiveOptionViewModel: widget.receiveOptionViewModel, - ); - }, - separatorBuilder: (context, index) { - if ((widget.receiveOptionViewModel.selectedReceiveOption == - otherOptions[index]) || - (index != otherOptions.length - 1 && - widget.receiveOptionViewModel.selectedReceiveOption == - otherOptions[index + 1])) return Container(); + return ReceiveAddressTypeRow( + option: opt, + roundedTop: false, + roundedBottom: index == otherOptions.length - 1, + selected: + widget.receiveOptionViewModel.selectedReceiveOption == opt, + onItemTap: () { + Navigator.of(context).pop(opt); + }, + receiveOptionViewModel: widget.receiveOptionViewModel, + ); + }, + separatorBuilder: (context, index) { + if ((widget.receiveOptionViewModel.selectedReceiveOption == + otherOptions[index]) || + (index != otherOptions.length - 1 && + widget.receiveOptionViewModel.selectedReceiveOption == + otherOptions[index + 1])) return Container(); - return Padding( - padding: const EdgeInsets.only(left: 44.0, right: 36.0), - child: HorizontalSectionDivider(), - ); - }, + return Padding( + padding: const EdgeInsets.only(left: 44.0, right: 36.0), + child: HorizontalSectionDivider(), + ); + }, + ), ), ), ), @@ -264,65 +280,75 @@ class ReceiveAddressTypeRow extends StatelessWidget { top: roundedTop ? Radius.circular(20) : Radius.zero, bottom: roundedBottom ? Radius.circular(20) : Radius.zero, ), - child: InkWell( - onTap: onItemTap, - child: Container( - height: rowHeight, - decoration: BoxDecoration( - color: selected - ? Theme.of(context).colorScheme.surfaceContainerHigh - : Colors.transparent, - borderRadius: BorderRadius.vertical( - top: roundedTop ? Radius.circular(20) : Radius.zero, - bottom: roundedBottom ? Radius.circular(20) : Radius.zero, - )), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - mainAxisSize: MainAxisSize.max, - children: [ - Row( + // The row itself carries the selection state; the checkbox next to it is + // only a visual echo of it and must not be announced separately. + child: MergeSemantics( + child: Semantics( + selected: selected, + inMutuallyExclusiveGroup: true, + child: InkWell( + onTap: onItemTap, + child: Container( + height: rowHeight, + decoration: BoxDecoration( + color: selected + ? Theme.of(context).colorScheme.surfaceContainerHigh + : Colors.transparent, + borderRadius: BorderRadius.vertical( + top: roundedTop ? Radius.circular(20) : Radius.zero, + bottom: roundedBottom ? Radius.circular(20) : Radius.zero, + )), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, children: [ - if (iconPath != null) - CakeImageWidget( - imageUrl: iconPath!, - width: iconSize, - height: iconSize, - colorFilter: ColorFilter.mode( - Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn), - ) - else - Container(width: iconSize, height: iconSize), - Padding( - padding: const EdgeInsets.all(10.0), - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - option.value, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface), + Row( + children: [ + if (iconPath != null) + ExcludeSemantics( + child: CakeImageWidget( + imageUrl: iconPath!, + width: iconSize, + height: iconSize, + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn), + ), + ) + else + Container(width: iconSize, height: iconSize), + Padding( + padding: const EdgeInsets.all(10.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + option.value, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface), + ), + if (option.description != null) + Text( + option.description!, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant), + ) + ], ), - if (option.description != null) - Text( - option.description!, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurfaceVariant), - ) - ], - ), - ) + ) + ], + ), + ExcludeSemantics(child: RoundedCheckbox(value: selected)) ], ), - RoundedCheckbox(value: selected) - ], + ), ), ), ), diff --git a/lib/new-ui/widgets/receive_page/receive_amount_display.dart b/lib/new-ui/widgets/receive_page/receive_amount_display.dart index 882bea55f..a69e03aaa 100644 --- a/lib/new-ui/widgets/receive_page/receive_amount_display.dart +++ b/lib/new-ui/widgets/receive_page/receive_amount_display.dart @@ -22,50 +22,54 @@ class ReceiveAmountDisplay extends StatelessWidget { curve: Curves.easeOutCubic, heightFactor: largeQrMode || walletAddressListViewModel.displayAmount.isEmpty ? 0 : 1, alignment: Alignment.topCenter, - child: Container( - width: double.infinity, - child: Row( - spacing: 4, - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Theme.of(context).colorScheme.surfaceContainer), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - spacing: 8.0, - children: [ - Text( - walletAddressListViewModel.displayAmount, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontSize: 16, - fontWeight: FontWeight.w500), - ), - Text(walletAddressListViewModel.cryptoCurrencySymbol, + // Amount, currency symbol and fiat equivalent describe one value, so + // they are announced as a single node. + child: MergeSemantics( + child: Container( + width: double.infinity, + child: Row( + spacing: 4, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Theme.of(context).colorScheme.surfaceContainer), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + spacing: 8.0, + children: [ + Text( + walletAddressListViewModel.displayAmount, style: TextStyle( color: Theme.of(context).colorScheme.primary, fontSize: 16, - fontWeight: FontWeight.w500)) - ], + fontWeight: FontWeight.w500), + ), + Text(walletAddressListViewModel.cryptoCurrencySymbol, + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontSize: 16, + fontWeight: FontWeight.w500)) + ], + ), ), ), - ), - if (!walletAddressListViewModel.isFiatDisabled) - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - _getFiatAmount(), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant, - fontSize: 16, - fontWeight: FontWeight.w500), - ), - ) - ], + if (!walletAddressListViewModel.isFiatDisabled) + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + _getFiatAmount(), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontSize: 16, + fontWeight: FontWeight.w500), + ), + ) + ], + ), ), ), ), diff --git a/lib/new-ui/widgets/receive_page/receive_amount_modal.dart b/lib/new-ui/widgets/receive_page/receive_amount_modal.dart index bbc1daecf..4166750ba 100644 --- a/lib/new-ui/widgets/receive_page/receive_amount_modal.dart +++ b/lib/new-ui/widgets/receive_page/receive_amount_modal.dart @@ -66,54 +66,68 @@ class _ReceiveAmountModalState extends State { spacing: 12, children: [ if (widget.walletAddressListViewModel.hasTokensList) ...[ - Text("Token"), - GestureDetector( - onTap: () { - _presentTokenCurrencyPicker(context); - }, - child: Observer( - builder: (_) => Container( - height: 60, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHigh, - borderRadius: BorderRadius.circular(16), - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - spacing: 8, - children: [ - TokenImageWidget( - imageUrl: widget.walletAddressListViewModel.tokenCurrency - ?.iconPath ?? - widget.walletAddressListViewModel.currencies.first - .iconPath ?? - "", - size: 32, - ), - Text((widget.walletAddressListViewModel.tokenCurrency ?? - widget.walletAddressListViewModel.currencies.first - as CryptoCurrency) - .title - .toUpperCase()) - ], - ), - RotatedBox( - quarterTurns: 2, - child: CakeImageWidget( - imageUrl: "assets/new-ui/dropdown_arrow.svg")) - ], + // The caption is reused as the picker's semantics label, + // so it must not be announced as a separate node. + ExcludeSemantics(child: Text(S.of(context).token)), + MergeSemantics( + child: Semantics( + button: true, + label: S.of(context).select_token, + child: GestureDetector( + onTap: () { + _presentTokenCurrencyPicker(context); + }, + child: Observer( + builder: (_) => Container( + height: 60, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainerHigh, + borderRadius: BorderRadius.circular(16), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + spacing: 8, + children: [ + ExcludeSemantics( + child: TokenImageWidget( + imageUrl: widget.walletAddressListViewModel + .tokenCurrency?.iconPath ?? + widget.walletAddressListViewModel.currencies.first + .iconPath ?? + "", + size: 32, + ), + ), + Text((widget.walletAddressListViewModel.tokenCurrency ?? + widget.walletAddressListViewModel.currencies.first + as CryptoCurrency) + .title + .toUpperCase()) + ], + ), + ExcludeSemantics( + child: RotatedBox( + quarterTurns: 2, + child: CakeImageWidget( + imageUrl: "assets/new-ui/dropdown_arrow.svg")), + ) + ], + ), ), ), ), - )), + ), + ), + ), ], SizedBox(), - Text(S.of(context).amount), + // The caption is reused as the field's semantics label. + ExcludeSemantics(child: Text(S.of(context).amount)), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -133,74 +147,91 @@ class _ReceiveAmountModalState extends State { width: 2, ), ), - child: TextField( - textAlign: TextAlign.left, - textAlignVertical: TextAlignVertical.center, - controller: _amountController, - keyboardType: TextInputType.numberWithOptions( - signed: false, - decimal: - widget.walletAddressListViewModel.selectedCurrencyDecimals > 0, - ), - inputFormatters: [ - DecimalInputFormatter( - maxDecimals: - widget.walletAddressListViewModel.selectedCurrencyDecimals, - ), - ], - decoration: InputDecoration( - hint: Text( - widget.walletAddressListViewModel.useSatoshi ? "0" : "0.00000000", + child: MergeSemantics( + child: Semantics( + label: S.of(context).amount, + child: TextField( textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - color: Theme.of( - context, - ).colorScheme.onSurface.withValues(alpha: 0.5), + textAlignVertical: TextAlignVertical.center, + controller: _amountController, + keyboardType: TextInputType.numberWithOptions( + signed: false, + decimal: + widget.walletAddressListViewModel.selectedCurrencyDecimals > + 0, ), + inputFormatters: [ + DecimalInputFormatter( + maxDecimals: + widget.walletAddressListViewModel.selectedCurrencyDecimals, + ), + ], + decoration: InputDecoration( + hint: Text( + widget.walletAddressListViewModel.useSatoshi + ? "0" + : "0.00000000", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + color: Theme.of( + context, + ).colorScheme.onSurface.withValues(alpha: 0.5), + ), + ), + border: InputBorder.none, + filled: true, + fillColor: Colors.transparent, + ), + style: + TextStyle(color: Theme.of(context).colorScheme.onSurface), ), - border: InputBorder.none, - filled: true, - fillColor: Colors.transparent, ), - style: TextStyle(color: Theme.of(context).colorScheme.onSurface), ), ), ), Expanded( flex: 25, - child: GestureDetector( - onTap: () { - _presentFiatCurrencyPicker(context); - }, - child: Container( - height: 60, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(0), - bottomLeft: Radius.circular(0), - topRight: Radius.circular(18), - bottomRight: Radius.circular(18), - ), - color: Theme.of(context).colorScheme.surfaceContainerHigh, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 4.0, - children: [ - Observer( - builder: (_) => Text( - widget.walletAddressListViewModel.selectedCurrencySymbol, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - ), + child: MergeSemantics( + child: Semantics( + button: true, + label: S.of(context).select_fiat_currency_title, + child: GestureDetector( + onTap: () { + _presentFiatCurrencyPicker(context); + }, + child: Container( + height: 60, + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(0), + bottomLeft: Radius.circular(0), + topRight: Radius.circular(18), + bottomRight: Radius.circular(18), ), + color: Theme.of(context).colorScheme.surfaceContainerHigh, ), - Icon( - Icons.keyboard_arrow_down, - color: Theme.of(context).colorScheme.primary, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 4.0, + children: [ + Observer( + builder: (_) => Text( + widget.walletAddressListViewModel.selectedCurrencySymbol, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ), + ExcludeSemantics( + child: Icon( + Icons.keyboard_arrow_down, + color: Theme.of(context).colorScheme.primary, + ), + ), + ], ), - ], + ), ), ), ), diff --git a/lib/new-ui/widgets/receive_page/receive_bottom_buttons.dart b/lib/new-ui/widgets/receive_page/receive_bottom_buttons.dart index 1566ff88d..e3cca096e 100644 --- a/lib/new-ui/widgets/receive_page/receive_bottom_buttons.dart +++ b/lib/new-ui/widgets/receive_page/receive_bottom_buttons.dart @@ -52,32 +52,25 @@ class _ReceiveBottomButtonsState extends State { mainAxisAlignment: MainAxisAlignment.center, spacing: 16, children: [ - GestureDetector( - onTap: widget.copyData == null ? widget.onCopyButtonPressed : null, - behavior: HitTestBehavior.opaque, - child: IgnorePointer( - ignoring: widget.copyData == null, - child: CopyWrapper( - data: widget.copyData, - builder: (context, copied) => AnimatedSwitcher( - duration: const Duration(milliseconds: 200), - child: IgnorePointer( - child: ModernButton.svg( - key: ValueKey(copied), - size: 60, - iconSize: 32, - svgPath: "assets/new-ui/copy.svg", - onPressed: () {}, - label: copied ? S.of(context).copied : S.of(context).copy, - iconColor: copied - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.surfaceContainer, - backgroundColor: copied - ? Theme.of(context).colorScheme.surfaceContainerHighest - : Theme.of(context).colorScheme.primary, - ), - ), - ), + // The button itself is the only control: it copies when there + // is data to copy, otherwise it opens the payjoin copy modal. + CopyWrapper( + data: widget.copyData, + controlBuilder: (context, copied, onCopy) => AnimatedSwitcher( + duration: const Duration(milliseconds: 200), + child: ModernButton.svg( + key: ValueKey(copied), + size: 60, + iconSize: 32, + svgPath: "assets/new-ui/copy.svg", + onPressed: onCopy ?? widget.onCopyButtonPressed, + label: copied ? S.of(context).copied : S.of(context).copy, + iconColor: copied + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.surfaceContainer, + backgroundColor: copied + ? Theme.of(context).colorScheme.surfaceContainerHighest + : Theme.of(context).colorScheme.primary, ), ), ), diff --git a/lib/new-ui/widgets/receive_page/receive_info_box.dart b/lib/new-ui/widgets/receive_page/receive_info_box.dart index d2598b241..db34cef16 100644 --- a/lib/new-ui/widgets/receive_page/receive_info_box.dart +++ b/lib/new-ui/widgets/receive_page/receive_info_box.dart @@ -71,12 +71,14 @@ class ReceiveInfoBox extends StatelessWidget { spacing: 10, children: [ if (iconPath.isNotEmpty) - CakeImageWidget( - imageUrl: iconPath, - width: 16, - height: 16, - colorFilter: ColorFilter.mode( - Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn), + ExcludeSemantics( + child: CakeImageWidget( + imageUrl: iconPath, + width: 16, + height: 16, + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn), + ), ), Flexible( child: Column( @@ -96,15 +98,20 @@ class ReceiveInfoBox extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (bottomWidget != null) bottomWidget!, - GestureDetector( - onTap: onDismissed, - child: Text( - S.of(context).dismiss, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontSize: 12, - fontWeight: FontWeight.w300), - )), + MergeSemantics( + child: Semantics( + button: true, + child: GestureDetector( + onTap: onDismissed, + child: Text( + S.of(context).dismiss, + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontSize: 12, + fontWeight: FontWeight.w300), + )), + ), + ), ], ) ]), @@ -136,65 +143,69 @@ class InfoboxCurrencyRow extends StatelessWidget { final double stackWidth = iconSize + (overlap * (currenciesLimited.length)); - return Row( - spacing: 8, - children: [ - CakeImageWidget( - imageUrl: chainIconPath, - width: 20, - height: 20, - colorFilter: - ColorFilter.mode(Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn), - ), - Container( - height: 28, - width: 1, - color: Theme.of(context).colorScheme.surfaceContainerHigh, - ), - SizedBox( - height: iconSize + iconBorder * 2, - width: stackWidth, - child: Stack( - children: [ - Positioned( - top: iconBorder, - left: overlap * currenciesLimited.length, - child: Container( - width: 24, - height: 24, - decoration: BoxDecoration( - color: Colors.white.withAlpha(25), - borderRadius: BorderRadius.circular(9999999)), - child: Icon( - Icons.add, - size: 16, - color: Colors.white.withAlpha(128), + // Purely illustrative: the meaning ("receive any token on ") is + // carried by the infobox message text next to it. + return ExcludeSemantics( + child: Row( + spacing: 8, + children: [ + CakeImageWidget( + imageUrl: chainIconPath, + width: 20, + height: 20, + colorFilter: + ColorFilter.mode(Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn), + ), + Container( + height: 28, + width: 1, + color: Theme.of(context).colorScheme.surfaceContainerHigh, + ), + SizedBox( + height: iconSize + iconBorder * 2, + width: stackWidth, + child: Stack( + children: [ + Positioned( + top: iconBorder, + left: overlap * currenciesLimited.length, + child: Container( + width: 24, + height: 24, + decoration: BoxDecoration( + color: Colors.white.withAlpha(25), + borderRadius: BorderRadius.circular(9999999)), + child: Icon( + Icons.add, + size: 16, + color: Colors.white.withAlpha(128), + ), ), ), - ), - ...currenciesLimited - .asMap() - .entries - .map((entry) => Positioned( - left: 16.0 * entry.key, - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Theme.of(context).colorScheme.surfaceContainer, - width: iconBorder), - borderRadius: BorderRadius.circular(9999999)), - child: TokenImageWidget( - imageUrl: entry.value.iconPath ?? '', - size: 24, + ...currenciesLimited + .asMap() + .entries + .map((entry) => Positioned( + left: 16.0 * entry.key, + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: Theme.of(context).colorScheme.surfaceContainer, + width: iconBorder), + borderRadius: BorderRadius.circular(9999999)), + child: TokenImageWidget( + imageUrl: entry.value.iconPath ?? '', + size: 24, + ), ), - ), - )) - .toList() - .reversed, - ], - ), - ) - ], + )) + .toList() + .reversed, + ], + ), + ) + ], + ), ); } } diff --git a/lib/new-ui/widgets/receive_page/receive_label_modal.dart b/lib/new-ui/widgets/receive_page/receive_label_modal.dart index 60e4c01a1..bf2e5e528 100644 --- a/lib/new-ui/widgets/receive_page/receive_label_modal.dart +++ b/lib/new-ui/widgets/receive_page/receive_label_modal.dart @@ -92,27 +92,32 @@ class _ReceiveLabelModalState extends State { return SizedBox(width: 8); }, itemBuilder: (context, index) { - return Container( - height: 36, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHigh, - borderRadius: BorderRadius.circular(999)), - child: Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(999), - child: InkWell( - borderRadius: BorderRadius.circular(999), - onTap: () { - _controller.text = defaultLabels[index]; - }, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Center( - child: Text( - defaultLabels[index], - style: TextStyle( - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.primary), + return MergeSemantics( + child: Semantics( + button: true, + child: Container( + height: 36, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainerHigh, + borderRadius: BorderRadius.circular(999)), + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(999), + child: InkWell( + borderRadius: BorderRadius.circular(999), + onTap: () { + _controller.text = defaultLabels[index]; + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Center( + child: Text( + defaultLabels[index], + style: TextStyle( + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.primary), + ), + ), ), ), ), diff --git a/lib/new-ui/widgets/receive_page/receive_label_widget.dart b/lib/new-ui/widgets/receive_page/receive_label_widget.dart index f34eaa2a2..f0657d5fa 100644 --- a/lib/new-ui/widgets/receive_page/receive_label_widget.dart +++ b/lib/new-ui/widgets/receive_page/receive_label_widget.dart @@ -22,14 +22,16 @@ class ReceiveLabelWidget extends StatelessWidget { spacing: 8, mainAxisSize: MainAxisSize.min, children: [ - ClipRect( - child: CakeImageWidget( - imageUrl: "assets/new-ui/label.svg", - width: 24, - height: 24, - colorFilter: ColorFilter.mode( - Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn), - )), + ExcludeSemantics( + child: ClipRect( + child: CakeImageWidget( + imageUrl: "assets/new-ui/label.svg", + width: 24, + height: 24, + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn), + )), + ), Text(name, style: TextStyle( fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant)), diff --git a/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart b/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart index 6b33af206..f2185ce39 100644 --- a/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart +++ b/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart @@ -212,6 +212,10 @@ class _SwapSendExternalModalState extends State { child: Icon( copied ? Icons.check : Icons.copy, key: ValueKey(copied), + // Only the icon changes here, so label + // the copied state for CopyWrapper's + // live region to announce. + semanticLabel: copied ? S.of(context).copied : null, size: 18, color: Theme.of(context).colorScheme.primary, ), diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 648568f30..dc35bd152 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -557,6 +557,7 @@ "incorrect_seed": "The text entered is not valid.", "incorrect_seed_option": "Incorrect. Please try again", "incorrect_seed_option_back": "Incorrect. Please make sure your seed is saved correctly and try again.", + "info": "Info", "infobox_auto_address": "Your receive address will rotate every time you receive a transaction", "infobox_multichain": "Use this address to receive any token or collectible on", "infobox_rotation": "Your receive address will rotate every time you close and reopen this screen", @@ -623,6 +624,7 @@ "long_press_edit_address": "Long press to edit address", "long_press_hide_balance": "Long press card to hide balance", "long_press_show_balance": "Long press card to show balance", + "long_press_to_copy": "Long press to copy", "low_fee": "Low fee", "low_fee_alert": "You currently are using a low network fee priority. This could cause long waits, different rates, or canceled trades. We recommend setting a higher fee for a better experience.", "made_easy": "made easy", @@ -1134,6 +1136,7 @@ "sort_by": "Sort by", "spend_key_private": "Spend key (private)", "spend_key_public": "Spend key (public)", + "standard": "Standard", "starting_tor_proxy": "Starting Tor proxy", "status": "Status: ", "step": "Step", @@ -1211,6 +1214,7 @@ "to_lightning": "to Lightning", "to_on_chain": "to on-chain", "today": "Today", + "token": "Token", "token_already_exists": "Token already exists", "token_decimal": "Token decimal (eg: 6 for USDT)", "token_name": "Token name (eg: Tether)", From 76b04580f3ef7345d1dac60ed8cbbdfd7c956146 Mon Sep 17 00:00:00 2001 From: Seth For Privacy <40500387+sethforprivacy@users.noreply.github.com> Date: Wed, 5 Aug 2026 03:30:25 -0400 Subject: [PATCH 06/10] a11y: send flow and QR scanner semantics (fields, errors, status announcements) (#3466) * Make send flow controls announce their purpose and state Wraps the send-flow inputs and controls in localized Semantics so a screen reader can operate them: - address, amount, memo and manual scan fields get a persistent name and announce their validation errors as live regions - the asset picker, max-balance chip, recipient dots, dropdown toggles and scan page buttons become real buttons with selected/expanded state - send progress, send errors, sync status and multi-part QR progress are exposed as single status nodes (announced once, not per tick) - purely visual duplicates (address overlay, memo counter, max caption, full-screen tap-to-exit target, hidden confirm-sheet page) stop producing extra nodes - LoadingPrimaryButton/PrimaryButton keep their name while showing a spinner and report the disabled state - replaces hard-coded English "Synchronizing...", "Coin Control" and 'ok' with localized strings * Scope mounted guard to the new announcement only * Address review: liveRegion success, loading tap guard, drop redundant PrimaryButton wrapper * Stop the currency picker from swallowing the amount field node An on-device audit (CW-1574, D1) found the send screen's amount field missing from the Android accessibility tree entirely: without this branch the tree held an "Amount:" text node plus an EditText, with it there was no node for the field at all. The address field, wrapped the same way on the same branch, survived. The difference is FormField. Flutter wraps a FormField's builder output in its own non-container Semantics(validationResult:) annotation, and that annotation becomes the node parenting everything the field renders. The currency picker's Semantics had no `container: true`, so it is not a boundary either and its configuration was absorbed into that same wrapper node. The result was one node carrying isButton + a tap action + the picker's label, with the amount TextField as its child - so screen readers surfaced the container and never reached the field. Declaring `container: true` on the picker gives it a node of its own and leaves the FormField wrapper unlabelled, so the field, the paste button and the picker are three sibling nodes again. No visual change. The address field is unaffected because every Semantics inside its FormField is already a boundary; the memo field and the scan manual-entry field have no FormField and no absorbing sibling, so they were never hit. Also replaces the two send-page caption comments, whose "the field announces this label itself" claim is what let the regression through, with a statement of what actually guarantees it. * Name the amount field from its caption instead of labelling the field Closure audit of the D1 fix found the amount announced twice on device: [o420] ImageView "Amount: 0.00" [k527] EditText "Amount: 0.00" "BTC" The framework tree has no such duplication. Post-D1-fix it holds exactly one node carrying the label, and that node *is* the text field: a merge boundary with no children, reporting no children to the engine, with isImage false on every node in the tree. The only thing above it is FormField's own unlabelled Semantics(validationResult:) node, whose children are the field, the paste button and the currency. That wrapper is [o420] - its Flutter label is empty, so the text and the ImageView role the device shows on it are synthesized platform-side from its descendants. We cannot delete FormField's wrapper, so the only lever is to stop authoring a label on the field for the wrapper to reflect. This restores the pre-#3466 shape, which the device A/B already verified as good: the visible "Amount:" caption goes back into the semantics tree and the field carries no label of its own, giving caption + field as two adjacent stops. Both halves are required - un-excluding the caption while keeping the wrapper label produces two "Amount"-bearing nodes in the framework tree itself. The tradeoff is that the field has no programmatic accessible name any more; it is named by reading-order adjacency to its caption, so focusing it directly announces the value without the word "Amount". That is exactly how the field behaved before #3466. The address field keeps its merged label and excluded caption, because the device audit shows it as a single correct node. Memo and scan manual entry are untouched. The `container: true` D1 fix on the picker stays - it is what got the field node back in the first place. * Set headingLevel on the confirm-sheet title for the 3.41 engine --------- Co-authored-by: Omar Hatem --- lib/entities/qr_scanner.dart | 2 +- lib/new-ui/pages/scan_page.dart | 212 +++++++------ lib/new-ui/pages/send_page.dart | 28 +- lib/new-ui/widgets/dropdown_row.dart | 69 ++-- .../widgets/scan_page/network_list.dart | 18 +- .../widgets/send_page/fiat_amount_bar.dart | 95 +++--- .../widgets/send_page/recipient_dot_row.dart | 63 ++-- .../widgets/send_page/send_address_input.dart | 72 +++-- .../widgets/send_page/send_amount_input.dart | 107 ++++--- .../send_page/send_confirm_bottom_widget.dart | 115 ++++--- .../widgets/send_page/send_confirm_sheet.dart | 294 ++++++++++-------- .../widgets/send_page/send_memo_input.dart | 23 +- .../send_page/send_syncing_indicator.dart | 55 ++-- lib/src/widgets/primary_button.dart | 77 +++-- res/values/strings_en.arb | 4 + 15 files changed, 748 insertions(+), 486 deletions(-) diff --git a/lib/entities/qr_scanner.dart b/lib/entities/qr_scanner.dart index ad076cd8a..296d3c5e4 100644 --- a/lib/entities/qr_scanner.dart +++ b/lib/entities/qr_scanner.dart @@ -69,7 +69,7 @@ class _BarcodeScannerSimpleState extends State { return AlertWithOneAction( alertTitle: S.of(context).error, alertContent: S.of(context).error_dialog_content, - buttonText: 'ok', + buttonText: S.of(context).ok, buttonAction: () { Navigator.of(context).pop(); }, diff --git a/lib/new-ui/pages/scan_page.dart b/lib/new-ui/pages/scan_page.dart index 695382be1..65182b12f 100644 --- a/lib/new-ui/pages/scan_page.dart +++ b/lib/new-ui/pages/scan_page.dart @@ -76,46 +76,50 @@ class _ScanPageState extends State { controller: controller, onDetect: _handleBarcode, ), + // A full screen tap target would otherwise show up as one giant unlabeled + // node; leaving text mode is also possible with the back button. Positioned.fill( - child: GestureDetector( - onTap: () => setState(() { - _textInputMode = false; - }), - child: RepaintBoundary( - child: AnimatedSwitcher( - switchInCurve: Curves.easeOutCubic, - switchOutCurve: Curves.easeInQuad, - duration: textModeSwitchDuration, - child: _textInputMode - ? BackdropFilter( - key: ValueKey(1), - filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0), - child: Container( - color: _frontFlashMode ? Colors.white : Colors.black.withAlpha(153), - ), - ) - : TweenAnimationBuilder( - key: const ValueKey(0), - tween: Tween(begin: 0.0, end: targetRadius), - duration: const Duration(milliseconds: 500), - curve: Curves.easeOutCubic, - child: BackdropFilter( + child: ExcludeSemantics( + child: GestureDetector( + onTap: () => setState(() { + _textInputMode = false; + }), + child: RepaintBoundary( + child: AnimatedSwitcher( + switchInCurve: Curves.easeOutCubic, + switchOutCurve: Curves.easeInQuad, + duration: textModeSwitchDuration, + child: _textInputMode + ? BackdropFilter( + key: ValueKey(1), filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0), child: Container( color: _frontFlashMode ? Colors.white : Colors.black.withAlpha(153), ), - ), - builder: (context, radius, child) { - return ClipPath( - clipper: HoleClipper( - width: cutoutSize, - height: cutoutSize, - radius: radius, + ) + : TweenAnimationBuilder( + key: const ValueKey(0), + tween: Tween(begin: 0.0, end: targetRadius), + duration: const Duration(milliseconds: 500), + curve: Curves.easeOutCubic, + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0), + child: Container( + color: _frontFlashMode ? Colors.white : Colors.black.withAlpha(153), ), - child: child, - ); - }, - ), + ), + builder: (context, radius, child) { + return ClipPath( + clipper: HoleClipper( + width: cutoutSize, + height: cutoutSize, + radius: radius, + ), + child: child, + ); + }, + ), + ), ), ), ), @@ -241,20 +245,25 @@ class _ScanPageState extends State { spacing: 10, children: [ Expanded( - child: TextField( - enabled: _textInputMode, - controller: textController, - focusNode: textFocusNode, - onSubmitted: (val) { - if (val.isNotEmpty) { - Navigator.of(context).pop(val); - } else { - setState(() { - _textInputMode = false; - }); - } - }, - decoration: InputDecoration(hintText: S.of(context).enter_code), + child: MergeSemantics( + child: Semantics( + label: S.of(context).enter_code, + child: TextField( + enabled: _textInputMode, + controller: textController, + focusNode: textFocusNode, + onSubmitted: (val) { + if (val.isNotEmpty) { + Navigator.of(context).pop(val); + } else { + setState(() { + _textInputMode = false; + }); + } + }, + decoration: InputDecoration(hintText: S.of(context).enter_code), + ), + ), ), ), FloatingIconButton( @@ -336,6 +345,7 @@ class _ScanPageState extends State { } }, icon: Icons.question_mark, + semanticsLabel: S.of(context).help, buttonColor: buttonColor, buttonIconColor: buttonIconColor) ], @@ -366,27 +376,39 @@ class _ScanPageState extends State { child: AnimatedOpacity( duration: Duration(milliseconds: 500), opacity: isScanningURQR ? 1 : 0, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "${decoder.processedPartsCount()}", - style: TextStyle( - fontSize: 45, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary), + // Three separate digits mean nothing on their own: announce the progress + // as one node, and only while a multi part code is actually being scanned. + child: ExcludeSemantics( + excluding: !isScanningURQR, + child: Semantics( + container: true, + liveRegion: true, + label: S.of(context).qr_parts_scanned( + "${decoder.processedPartsCount()}", "${decoder.expectedPartCount() ?? 0}"), + excludeSemantics: true, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "${decoder.processedPartsCount()}", + style: TextStyle( + fontSize: 45, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary), + ), + Text( + "/", + style: TextStyle( + fontSize: 45, color: Theme.of(context).colorScheme.onSurfaceVariant), + ), + Text( + "${decoder.expectedPartCount()}", + style: TextStyle( + fontSize: 45, color: Theme.of(context).colorScheme.onSurface), + ), + ], ), - Text( - "/", - style: TextStyle( - fontSize: 45, color: Theme.of(context).colorScheme.onSurfaceVariant), - ), - Text( - "${decoder.expectedPartCount()}", - style: - TextStyle(fontSize: 45, color: Theme.of(context).colorScheme.onSurface), - ), - ], + ), ), ), ), @@ -406,7 +428,7 @@ class _ScanPageState extends State { return AlertWithOneAction( alertTitle: S.of(context).error, alertContent: S.of(context).error_dialog_content, - buttonText: 'ok', + buttonText: S.of(context).ok, buttonAction: () { Navigator.of(context).pop(); }, @@ -459,37 +481,51 @@ class ScanPageButton extends StatelessWidget { required this.onTap, required this.icon, this.label, + this.semanticsLabel, required this.buttonColor, required this.buttonIconColor}); final VoidCallback onTap; final IconData icon; final String? label; + + /// Name for the icon-only variant, which has no visible [label]. + final String? semanticsLabel; final Color buttonColor; final Color buttonIconColor; @override Widget build(BuildContext context) { - return GestureDetector( + return Semantics( + button: true, + enabled: true, + label: semanticsLabel ?? label, onTap: onTap, - behavior: HitTestBehavior.opaque, - child: Container( - decoration: BoxDecoration(color: buttonColor, borderRadius: BorderRadius.circular(99999)), - child: Padding( - padding: EdgeInsets.only( - top: 10, bottom: 10, left: label == null ? 10 : 16, right: label == null ? 10 : 20), - child: Row( - spacing: 10, - children: [ - Icon(icon, size: 28, color: buttonIconColor), - if (label != null) - Text(label!, - style: TextStyle( - fontSize: 16, fontWeight: FontWeight.w500, color: buttonIconColor)) - ], - ), - ), - )); + excludeSemantics: true, + child: GestureDetector( + onTap: onTap, + behavior: HitTestBehavior.opaque, + child: Container( + decoration: + BoxDecoration(color: buttonColor, borderRadius: BorderRadius.circular(99999)), + child: Padding( + padding: EdgeInsets.only( + top: 10, + bottom: 10, + left: label == null ? 10 : 16, + right: label == null ? 10 : 20), + child: Row( + spacing: 10, + children: [ + Icon(icon, size: 28, color: buttonIconColor), + if (label != null) + Text(label!, + style: TextStyle( + fontSize: 16, fontWeight: FontWeight.w500, color: buttonIconColor)) + ], + ), + ), + ))); } } diff --git a/lib/new-ui/pages/send_page.dart b/lib/new-ui/pages/send_page.dart index f03381734..d25b3440e 100644 --- a/lib/new-ui/pages/send_page.dart +++ b/lib/new-ui/pages/send_page.dart @@ -417,7 +417,12 @@ class _NewSendPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, spacing: 12, children: [ - Text(S.of(context).address_or_alias), + // NewSendAddressInput merges this label onto its + // own text-field node, so announcing the caption + // as well would read it twice. + ExcludeSemantics( + child: Text(S.of(context).address_or_alias), + ), NewSendAddressInput( displayName: output.displayName, validator: output.isParsedAddress @@ -481,6 +486,12 @@ class _NewSendPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, spacing: 12, children: [ + // This caption is the amount field's accessible name + // and must stay in the semantics tree: + // NewSendAmountInput deliberately carries no label of + // its own, because labelling the field made Android + // announce the amount twice. Covered by + // test/new-ui/widgets/send_page/send_amount_input_test.dart. Text(S.of(context).amount), NewSendAmountInput( validator: output.sendAll @@ -558,17 +569,18 @@ class _NewSendPageState extends State { label: S.of(context).fees, subtitle: "~${output.estimatedFee} ${widget.sendViewModel.currencySymbol} (${output.estimatedFeeFiatAmount} ${widget.sendViewModel.fiatCurrency})", - onTap: () { - if (widget.sendViewModel.feesViewModel - .hasFeesPriority) { - pickTransactionPriority(context, output); - } - }, + // Without fee priorities the row does nothing, + // so it must not be announced as interactive. + onTap: widget.sendViewModel.feesViewModel + .hasFeesPriority + ? () => + pickTransactionPriority(context, output) + : null, ), if (widget.sendViewModel.hasCoinControl) ListItemRegularRowWidget( keyValue: "", - label: "Coin Control", + label: S.of(context).coin_control, onTap: () { showCupertinoModalBottomSheet( enableDrag: false, diff --git a/lib/new-ui/widgets/dropdown_row.dart b/lib/new-ui/widgets/dropdown_row.dart index d06a2b291..7772cd8a9 100644 --- a/lib/new-ui/widgets/dropdown_row.dart +++ b/lib/new-ui/widgets/dropdown_row.dart @@ -11,38 +11,45 @@ class DropdownRow extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainer, - borderRadius: BorderRadius.vertical( - top: Radius.circular(18), - bottom: expanded ? Radius.zero : Radius.circular(18), + return Semantics( + button: true, + expanded: expanded, + label: text, + onTap: onTap, + excludeSemantics: true, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainer, + borderRadius: BorderRadius.vertical( + top: Radius.circular(18), + bottom: expanded ? Radius.zero : Radius.circular(18), + ), ), - ), - height: 48, - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: onTap, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - text, - style: TextStyle(fontSize: 14, color: Theme.of(context).colorScheme.primary), - ), - AnimatedRotation( - duration: Duration(milliseconds: 300), - turns: expanded ? 0.0 : 0.5, - curve: Curves.easeOut, - child: CakeImageWidget( - imageUrl: "assets/new-ui/dropdown_arrow.svg", - colorFilter: - ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn), - )) - ], + height: 48, + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + text, + style: TextStyle(fontSize: 14, color: Theme.of(context).colorScheme.primary), + ), + AnimatedRotation( + duration: Duration(milliseconds: 300), + turns: expanded ? 0.0 : 0.5, + curve: Curves.easeOut, + child: CakeImageWidget( + imageUrl: "assets/new-ui/dropdown_arrow.svg", + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.primary, BlendMode.srcIn), + )) + ], + ), ), ), ), diff --git a/lib/new-ui/widgets/scan_page/network_list.dart b/lib/new-ui/widgets/scan_page/network_list.dart index 007ba5167..4cc738188 100644 --- a/lib/new-ui/widgets/scan_page/network_list.dart +++ b/lib/new-ui/widgets/scan_page/network_list.dart @@ -11,6 +11,20 @@ import 'package:url_launcher/url_launcher.dart'; class ScanPageNetworkList extends StatelessWidget { const ScanPageNetworkList({super.key}); + /// Same icon the row would render from `trailingIconPath`, but it now carries the + /// information that following the row leaves the app. + Widget _externalLinkIcon(BuildContext context) => Semantics( + label: S.of(context).opens_in_browser, + excludeSemantics: true, + child: CakeImageWidget( + imageUrl: "assets/new-ui/external_link.svg", + height: 18, + width: 18, + colorFilter: + ColorFilter.mode(Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn), + ), + ); + @override Widget build(BuildContext context) { return Container( @@ -81,7 +95,7 @@ class ScanPageNetworkList extends StatelessWidget { keyValue: "wc", label: "WalletConnect", subtitle: S.of(context).wc_desc, - trailingIconPath: "assets/new-ui/external_link.svg", + trailingWidget: _externalLinkIcon(context), onTap: () { launchUrl(Uri.https("walletconnect.com")); }), @@ -90,7 +104,7 @@ class ScanPageNetworkList extends StatelessWidget { keyValue: "ocp", label: "OpenCryptoPay", subtitle: S.of(context).ocp_desc, - trailingIconPath: "assets/new-ui/external_link.svg", + trailingWidget: _externalLinkIcon(context), onTap: () { launchUrl(Uri.https("opencryptopay.io")); }) diff --git a/lib/new-ui/widgets/send_page/fiat_amount_bar.dart b/lib/new-ui/widgets/send_page/fiat_amount_bar.dart index 76cbcfc23..338cdc676 100644 --- a/lib/new-ui/widgets/send_page/fiat_amount_bar.dart +++ b/lib/new-ui/widgets/send_page/fiat_amount_bar.dart @@ -35,46 +35,65 @@ class FiatAmountBar extends StatelessWidget { final Color? allAmountTextColor; @override - Widget build(BuildContext context) => Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + Widget build(BuildContext context) { + final convertedAmount = fiatInputMode + ? "${cryptoAmount.isEmpty ? "0" : cryptoAmount.withMaxDecimals(8)} $cryptoCurrencySymbol" + : "${fiatAmount.isEmpty ? "0" : fiatAmount} $fiatCurrencySymbol"; + + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + spacing: 8, + children: [ + ModernButton.svg( + backgroundColor: foregroundElementColor, + size: 28, + svgPath: "assets/new-ui/switch.svg", + iconSize: 18, + onPressed: onSwitchButtonPressed, + semanticLabel: S.of(context).switch_input_currency, + ), + // Announced as the converted value only: the switch button next to it already + // exposes the same action, so this must not become a second control. + Semantics( + label: convertedAmount, + excludeSemantics: true, + child: GestureDetector( + onTap: onSwitchButtonPressed, + child: Text( + convertedAmount, + style: TextStyle(color: textColor ?? Theme.of(context).colorScheme.onSurface), + ), + ), + ), + ], + ), + if (allAmount != null && allAmount!.isNotEmpty) Row( spacing: 8, children: [ - ModernButton.svg( - backgroundColor: foregroundElementColor, - size: 28, - svgPath: "assets/new-ui/switch.svg", - iconSize: 18, - onPressed: onSwitchButtonPressed, - semanticLabel: S.of(context).switch_input_currency, - ), - GestureDetector( - onTap: onSwitchButtonPressed, + // The caption is part of the chip's label below. + ExcludeSemantics( child: Text( - fiatInputMode - ? "${cryptoAmount.isEmpty ? "0" : cryptoAmount.withMaxDecimals(8)} $cryptoCurrencySymbol" - : "${fiatAmount.isEmpty ? "0" : fiatAmount} $fiatCurrencySymbol", - style: TextStyle(color: textColor ?? Theme.of(context).colorScheme.onSurface), - ), - ), - ], - ), - if (allAmount != null && allAmount!.isNotEmpty) - Row( - spacing: 8, - children: [ - Text( "${S.of(context).max}.", style: TextStyle(color: textColor ?? Theme.of(context).colorScheme.onSurface), ), - Container( - decoration: BoxDecoration(borderRadius: BorderRadius.circular(999999)), - child: Material( - color: allAmountColor ?? - foregroundElementColor ?? - Theme.of(context).colorScheme.surfaceContainer, - borderRadius: BorderRadius.circular(99999), + ), + Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(999999)), + child: Material( + color: allAmountColor ?? + foregroundElementColor ?? + Theme.of(context).colorScheme.surfaceContainer, + borderRadius: BorderRadius.circular(99999), + child: Semantics( + button: true, + enabled: onAllButtonPressed != null, + label: S.of(context).max, + value: _formatAmount(allAmount!), + onTap: onAllButtonPressed, + excludeSemantics: true, child: InkWell( borderRadius: BorderRadius.circular(99999), onTap: onAllButtonPressed, @@ -90,10 +109,12 @@ class FiatAmountBar extends StatelessWidget { ), ), ), - ], - ), - ], - ); + ), + ], + ), + ], + ); + } String _formatAmount(String amount) { try { diff --git a/lib/new-ui/widgets/send_page/recipient_dot_row.dart b/lib/new-ui/widgets/send_page/recipient_dot_row.dart index 18c8f3df0..29ec16fe5 100644 --- a/lib/new-ui/widgets/send_page/recipient_dot_row.dart +++ b/lib/new-ui/widgets/send_page/recipient_dot_row.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/generated/i18n.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -179,32 +180,44 @@ class _RecipientDotState extends State { curve: Curves.easeOutCubic, top: _created ? 0 : widget.size, child: Material( - child: AnimatedSwitcher( - duration: Duration(milliseconds: 150), - child: GestureDetector( - key: ValueKey(widget.selected), + // Dots scaled all the way down are not visible, so they must not be + // reachable by a screen reader either. + child: ExcludeSemantics( + excluding: widget.textOpacity <= 0, + child: Semantics( + button: true, + selected: widget.selected, + label: S.of(context).recipient_number("${widget.index + 1}"), onTap: widget.onTap, - child: Container( - width: widget.size, - height: widget.size, - margin: EdgeInsets.symmetric(horizontal: widget.spacing / 2), - decoration: BoxDecoration( - color: widget.selected - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.surfaceContainer, - shape: BoxShape.circle, - ), - alignment: Alignment.center, - child: Opacity( - opacity: widget.textOpacity, - child: Text( - (widget.index + 1).toString(), - style: TextStyle( - color: widget.selected - ? Theme.of(context).colorScheme.onPrimary - : Theme.of(context).colorScheme.onSurface, - fontSize: 14, - fontWeight: FontWeight.w500), + excludeSemantics: true, + child: AnimatedSwitcher( + duration: Duration(milliseconds: 150), + child: GestureDetector( + key: ValueKey(widget.selected), + onTap: widget.onTap, + child: Container( + width: widget.size, + height: widget.size, + margin: EdgeInsets.symmetric(horizontal: widget.spacing / 2), + decoration: BoxDecoration( + color: widget.selected + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.surfaceContainer, + shape: BoxShape.circle, + ), + alignment: Alignment.center, + child: Opacity( + opacity: widget.textOpacity, + child: Text( + (widget.index + 1).toString(), + style: TextStyle( + color: widget.selected + ? Theme.of(context).colorScheme.onPrimary + : Theme.of(context).colorScheme.onSurface, + fontSize: 14, + fontWeight: FontWeight.w500), + ), + ), ), ), ), diff --git a/lib/new-ui/widgets/send_page/send_address_input.dart b/lib/new-ui/widgets/send_page/send_address_input.dart index 704a41571..87fc67fcc 100644 --- a/lib/new-ui/widgets/send_page/send_address_input.dart +++ b/lib/new-ui/widgets/send_page/send_address_input.dart @@ -86,22 +86,27 @@ class _NewSendAddressInputState extends State { Expanded( child: Stack( children: [ - TextField( - focusNode: widget.focusNode, - autocorrect: false, - enableSuggestions: false, - onSubmitted: (val) => FocusScope.of(context).unfocus(), - onChanged: state.didChange, - onEditingComplete: () { - widget.onEditingComplete(); - }, - onTapOutside: (_) { - widget.onEditingComplete(); - }, - controller: widget.addressController, - decoration: InputDecoration( - hintText: widget.hintText ?? S.of(context).search_or_enter, - errorMaxLines: 3, + MergeSemantics( + child: Semantics( + label: _fieldSemanticsLabel(context), + child: TextField( + focusNode: widget.focusNode, + autocorrect: false, + enableSuggestions: false, + onSubmitted: (val) => FocusScope.of(context).unfocus(), + onChanged: state.didChange, + onEditingComplete: () { + widget.onEditingComplete(); + }, + onTapOutside: (_) { + widget.onEditingComplete(); + }, + controller: widget.addressController, + decoration: InputDecoration( + hintText: widget.hintText ?? S.of(context).search_or_enter, + errorMaxLines: 3, + ), + ), ), ), Positioned.fill( @@ -113,9 +118,13 @@ class _NewSendAddressInputState extends State { widget.addressController.text.isEmpty) ? 0 : 1, - child: SendAddressOverlay( - address: widget.addressController.text, - displayName: widget.displayName, + // Purely visual copy of the field content; announcing it again + // would read the address twice. + child: ExcludeSemantics( + child: SendAddressOverlay( + address: widget.addressController.text, + displayName: widget.displayName, + ), )), ), ), @@ -150,9 +159,15 @@ class _NewSendAddressInputState extends State { if (state.hasError) Padding( padding: EdgeInsets.only(top: 6, left: 8), - child: Text( - state.errorText!, - style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.error), + child: Semantics( + container: true, + liveRegion: true, + label: "${S.of(context).address_or_alias}, ${state.errorText!}", + excludeSemantics: true, + child: Text( + state.errorText!, + style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.error), + ), ), ) ], @@ -161,6 +176,19 @@ class _NewSendAddressInputState extends State { ); } + String _fieldSemanticsLabel(BuildContext context) { + final label = S.of(context).address_or_alias; + final displayName = widget.displayName; + + if (displayName == null || + displayName.isEmpty || + displayName == widget.addressController.text) { + return label; + } + + return "$label, $displayName"; + } + Future _presentQRScanner(BuildContext context) async { bool isCameraPermissionGranted = await PermissionHandler.checkPermission(Permission.camera, context); diff --git a/lib/new-ui/widgets/send_page/send_amount_input.dart b/lib/new-ui/widgets/send_page/send_amount_input.dart index ff905d08e..051100bff 100644 --- a/lib/new-ui/widgets/send_page/send_amount_input.dart +++ b/lib/new-ui/widgets/send_page/send_amount_input.dart @@ -1,3 +1,4 @@ +import "package:cake_wallet/generated/i18n.dart"; import "package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart"; import "package:cake_wallet/new-ui/widgets/send_page/floating_icon_button.dart"; import "package:cake_wallet/src/widgets/cake_image_widget.dart"; @@ -67,6 +68,14 @@ class _NewSendAmountInputState extends State { mainAxisSize: MainAxisSize.max, spacing: 8, children: [ + // Deliberately unwrapped. Naming the field with + // MergeSemantics > Semantics(label:) made Android announce + // the amount twice: FormField's own wrapper node reflects + // its descendants' text, so the authored label came back a + // second time on the container. The visible "Amount:" + // caption on the send page carries the name instead, and it + // must stay in the semantics tree for this field to be + // named at all. Expanded( child: TextField( keyboardType: TextInputType.numberWithOptions( @@ -105,44 +114,58 @@ class _NewSendAmountInputState extends State { ), IntrinsicWidth( child: Observer( - builder: (_) => GestureDetector( - onTap: widget.onPickerClicked, - child: Container( - alignment: Alignment.center, - width: double.infinity, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topRight: Radius.circular(18), - bottomRight: Radius.circular(18), + // `container: true` is load bearing. FormField wraps this + // builder in its own non-container Semantics annotation, so + // without a container of its own this configuration is + // absorbed into that wrapper node — which then parents the + // amount TextField and hides it from screen readers. + builder: (_) => Semantics( + container: true, + button: widget.hasPicker ? true : null, + enabled: widget.hasPicker ? true : null, + label: widget.hasPicker ? S.of(context).select_asset : widget.currency, + value: widget.hasPicker ? widget.currency : null, + onTap: widget.hasPicker ? widget.onPickerClicked : null, + excludeSemantics: true, + child: GestureDetector( + onTap: widget.onPickerClicked, + child: Container( + alignment: Alignment.center, + width: double.infinity, + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topRight: Radius.circular(18), + bottomRight: Radius.circular(18), + ), + color: widget.hasPicker + ? Theme.of(context).colorScheme.surfaceContainerHigh + : Theme.of(context).colorScheme.surfaceContainer, ), - color: widget.hasPicker - ? Theme.of(context).colorScheme.surfaceContainerHigh - : Theme.of(context).colorScheme.surfaceContainer, - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - spacing: 8, - children: [ - if (widget.hasPicker && widget.currencyIconPath.isNotEmpty) - TokenImageWidget( - imageUrl: widget.currencyIconPath, - size: 24, - ), - Text(widget.currency), - if (widget.hasPicker) - CakeImageWidget( - imageUrl: "assets/new-ui/chooser.svg", - width: 12, - height: 12, - colorFilter: ColorFilter.mode( - Theme.of(context).colorScheme.primary, - BlendMode.srcIn, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + spacing: 8, + children: [ + if (widget.hasPicker && widget.currencyIconPath.isNotEmpty) + TokenImageWidget( + imageUrl: widget.currencyIconPath, + size: 24, ), - ), - ], + Text(widget.currency), + if (widget.hasPicker) + CakeImageWidget( + imageUrl: "assets/new-ui/chooser.svg", + width: 12, + height: 12, + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.primary, + BlendMode.srcIn, + ), + ), + ], + ), ), ), ), @@ -155,9 +178,15 @@ class _NewSendAmountInputState extends State { if (state.hasError) Padding( padding: const EdgeInsets.only(top: 6, left: 8), - child: Text( - state.errorText!, - style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.error), + child: Semantics( + container: true, + liveRegion: true, + label: "${S.of(context).amount}${state.errorText!}", + excludeSemantics: true, + child: Text( + state.errorText!, + style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.error), + ), ), ), ], diff --git a/lib/new-ui/widgets/send_page/send_confirm_bottom_widget.dart b/lib/new-ui/widgets/send_page/send_confirm_bottom_widget.dart index 540910b3e..950932e9a 100644 --- a/lib/new-ui/widgets/send_page/send_confirm_bottom_widget.dart +++ b/lib/new-ui/widgets/send_page/send_confirm_bottom_widget.dart @@ -80,18 +80,25 @@ class LoadingBottomWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 12, - children: [ - CupertinoActivityIndicator( - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - Text( - text, - style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant), - ) - ], + // One node per state so each step of the send is announced exactly once. + return Semantics( + container: true, + liveRegion: true, + label: text, + excludeSemantics: true, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 12, + children: [ + CupertinoActivityIndicator( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + Text( + text, + style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant), + ) + ], + ), ); } } @@ -106,45 +113,51 @@ class TransactionErrorActions extends StatelessWidget { return Column( spacing: 12, children: [ - Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.errorContainer.withAlpha(64), - borderRadius: BorderRadius.circular(16), - ), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Column( - spacing: 12, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 8, - children: [ - CakeImageWidget( - imageUrl: "assets/new-ui/warning.svg", - height: 24, - width: 24, - colorFilter: - ColorFilter.mode(Theme.of(context).colorScheme.error, BlendMode.srcIn), - ), - Text( - S.of(context).transaction_error, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.error), - ) - ], - ), - Text( - errorText, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.error), - textAlign: TextAlign.center, - ), - ], + Semantics( + container: true, + liveRegion: true, + label: "${S.of(context).transaction_error}\n$errorText", + excludeSemantics: true, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.errorContainer.withAlpha(64), + borderRadius: BorderRadius.circular(16), + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + spacing: 12, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 8, + children: [ + CakeImageWidget( + imageUrl: "assets/new-ui/warning.svg", + height: 24, + width: 24, + colorFilter: + ColorFilter.mode(Theme.of(context).colorScheme.error, BlendMode.srcIn), + ), + Text( + S.of(context).transaction_error, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.error), + ) + ], + ), + Text( + errorText, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.error), + textAlign: TextAlign.center, + ), + ], + ), ), ), ), diff --git a/lib/new-ui/widgets/send_page/send_confirm_sheet.dart b/lib/new-ui/widgets/send_page/send_confirm_sheet.dart index dccaf41ba..5b34686d3 100644 --- a/lib/new-ui/widgets/send_page/send_confirm_sheet.dart +++ b/lib/new-ui/widgets/send_page/send_confirm_sheet.dart @@ -87,11 +87,15 @@ class _SendConfirmSheetState extends State { offset: _committed ? const Offset(-1, 0) : Offset.zero, duration: const Duration(milliseconds: 300), curve: Curves.easeOutCubic, - child: SendTransactionDetails( - sendViewModel: widget.sendViewModel, - isPage: widget.isPage, - title: widget.title, - iconPath: widget.iconPath, + // Both screens stay mounted; only the visible one may be reachable. + child: ExcludeSemantics( + excluding: _committed, + child: SendTransactionDetails( + sendViewModel: widget.sendViewModel, + isPage: widget.isPage, + title: widget.title, + iconPath: widget.iconPath, + ), ), ), ), @@ -102,8 +106,11 @@ class _SendConfirmSheetState extends State { offset: _committed ? Offset.zero : const Offset(1, 0), duration: const Duration(milliseconds: 300), curve: Curves.easeOutCubic, - child: TransactionCommitedScreen( - sendViewModel: widget.sendViewModel, + child: ExcludeSemantics( + excluding: !_committed, + child: TransactionCommitedScreen( + sendViewModel: widget.sendViewModel, + ), ), ), ), @@ -154,9 +161,15 @@ class SendTransactionDetails extends StatelessWidget { width: 28, height: 28, ), - Text( - title ?? S.of(context).send, - style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20), + Semantics( + header: true, + // Android reads the heading from headingLevel since the + // Flutter 3.41 engine; header: alone only covers iOS. + headingLevel: 1, + child: Text( + title ?? S.of(context).send, + style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20), + ), ) ], ), @@ -250,37 +263,40 @@ class SendTransactionDetails extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, spacing: 24, children: [ - Column( - children: [ - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - spacing: 4, - children: [ - Flexible( - child: Text( - amount, - style: TextStyle( - fontSize: 36, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface), + // The amount being sent is the value under review: announce it as one group. + MergeSemantics( + child: Column( + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + spacing: 4, + children: [ + Flexible( + child: Text( + amount, + style: TextStyle( + fontSize: 36, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface), + ), ), - ), - Text(currencySymbol, - style: TextStyle( - fontSize: 36, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurfaceVariant)) - ], - ), - Text( - fiatAmount, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurfaceVariant), - ), - ], + Text(currencySymbol, + style: TextStyle( + fontSize: 36, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant)) + ], + ), + Text( + fiatAmount, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant), + ), + ], + ), ), if (outputs.length >= 1 && (outputs.first.extractedAddress.isNotEmpty || outputs.first.address.isNotEmpty) && @@ -352,32 +368,34 @@ class SendTransactionDetails extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.all(12.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(S.of(context).fee, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface)), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - "${fee.withLocalSeperator(sendViewModel.languageCode)} ${sendViewModel.currencySymbol}", + child: MergeSemantics( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(S.of(context).fee, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurfaceVariant), - ), - Text(fiatFee.withLocalSeperator(sendViewModel.languageCode), + color: Theme.of(context).colorScheme.onSurface)), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + "${fee.withLocalSeperator(sendViewModel.languageCode)} ${sendViewModel.currencySymbol}", style: TextStyle( fontSize: 14, fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurfaceVariant)) - ], - ) - ], + color: Theme.of(context).colorScheme.onSurfaceVariant), + ), + Text(fiatFee.withLocalSeperator(sendViewModel.languageCode), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant)) + ], + ) + ], + ), ), ), if (sendViewModel.isElectrumWallet) ...[ @@ -390,27 +408,29 @@ class SendTransactionDetails extends StatelessWidget { ), Padding( padding: const EdgeInsets.all(12.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(S.of(context).network, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface)), - Column( - children: [ - Text( - sendViewModel.selectedCryptoCurrency == CryptoCurrency.btcln - ? "Lightning" - : bitcoin!.getNetworkName(sendViewModel.wallet), - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurfaceVariant)) - ], - ) - ], + child: MergeSemantics( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(S.of(context).network, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface)), + Column( + children: [ + Text( + sendViewModel.selectedCryptoCurrency == CryptoCurrency.btcln + ? "Lightning" + : bitcoin!.getNetworkName(sendViewModel.wallet), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant)) + ], + ) + ], + ), ), ) ], @@ -459,9 +479,14 @@ class _TransactionCommitedScreenState extends State { SizedBox( height: 12, ), - Text( - S.of(context).transaction_sent_new, - style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600), + // The sheet swaps its content in place, so this title becoming visible is what + // tells a screen reader that the transaction went through. + Semantics( + liveRegion: true, + child: Text( + S.of(context).transaction_sent_new, + style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600), + ), ), SizedBox(), CakeImageWidget(width: 200, height: 200, imageUrl: "assets/new-ui/birthday_cake.svg"), @@ -552,37 +577,44 @@ class TransactionCommittedScreenActionButton extends StatelessWidget { @override Widget build(BuildContext context) { return Flexible( - child: GestureDetector( - onTap: onTap, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), - color: Theme.of(context).colorScheme.surfaceContainer), - child: Padding( - padding: EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 10, - children: [ - isLoading - ? CupertinoActivityIndicator() - : CakeImageWidget( - imageUrl: iconPath, - width: 24, - height: 24, - colorFilter: ColorFilter.mode( - Theme.of(context).colorScheme.primary, BlendMode.srcIn), - ), - Text( - text, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.w500), - ) - ], - ), - ), - ))); + child: Semantics( + button: true, + enabled: !isLoading, + label: text, + value: isLoading ? S.of(context).loading : null, + onTap: isLoading ? null : onTap, + excludeSemantics: true, + child: GestureDetector( + onTap: isLoading ? null : onTap, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: Theme.of(context).colorScheme.surfaceContainer), + child: Padding( + padding: EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 10, + children: [ + isLoading + ? CupertinoActivityIndicator() + : CakeImageWidget( + imageUrl: iconPath, + width: 24, + height: 24, + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.primary, BlendMode.srcIn), + ), + Text( + text, + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.w500), + ) + ], + ), + ), + )))); } } @@ -623,16 +655,28 @@ class _MultiSendAddressPreviewState extends State { style: TextStyle(fontFamily: "IBM Plex Mono"), ), if (!_expanded) - GestureDetector( - onTap: () { - setState(() { - _expanded = true; - }); - }, - child: Text(middleTruncate(widget.address, 8, 8), - style: TextStyle( - fontFamily: "IBM Plex Mono", - color: Theme.of(context).colorScheme.primary))) + Semantics( + button: true, + // Read the whole address rather than the truncated form. + label: widget.address, + hint: S.of(context).show_full_address, + onTap: () { + setState(() { + _expanded = true; + }); + }, + excludeSemantics: true, + child: GestureDetector( + onTap: () { + setState(() { + _expanded = true; + }); + }, + child: Text(middleTruncate(widget.address, 8, 8), + style: TextStyle( + fontFamily: "IBM Plex Mono", + color: Theme.of(context).colorScheme.primary))), + ) else AddressFormatter.buildSegmentedAddress( address: widget.address, diff --git a/lib/new-ui/widgets/send_page/send_memo_input.dart b/lib/new-ui/widgets/send_page/send_memo_input.dart index d3f408223..5dc69491a 100644 --- a/lib/new-ui/widgets/send_page/send_memo_input.dart +++ b/lib/new-ui/widgets/send_page/send_memo_input.dart @@ -31,11 +31,16 @@ class NewSendMemoInput extends StatelessWidget { child: Row( children: [ Expanded( - child: TextField( - maxLength: maxMemoLength, - controller: memoController, - decoration: InputDecoration( - hintText: hintText ?? S.of(context).memo_optional, counterText: ""), + child: MergeSemantics( + child: Semantics( + label: hintText ?? S.of(context).memo_optional, + child: TextField( + maxLength: maxMemoLength, + controller: memoController, + decoration: InputDecoration( + hintText: hintText ?? S.of(context).memo_optional, counterText: ""), + ), + ), ), ), SizedBox(width: 12), @@ -61,8 +66,12 @@ class NewSendMemoInput extends StatelessWidget { style: TextStyle( fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant)), ), - Text("${memoController.text.length} / ${maxMemoLength}", - style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.primary)) + // The field itself already reports the character count through + // maxValueLength/currentValueLength, so this visual counter stays silent. + ExcludeSemantics( + child: Text("${memoController.text.length} / ${maxMemoLength}", + style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.primary)), + ) ], ), ) diff --git a/lib/new-ui/widgets/send_page/send_syncing_indicator.dart b/lib/new-ui/widgets/send_page/send_syncing_indicator.dart index 946efa116..516e071ee 100644 --- a/lib/new-ui/widgets/send_page/send_syncing_indicator.dart +++ b/lib/new-ui/widgets/send_page/send_syncing_indicator.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cw_core/sync_status.dart'; import 'package:flutter/material.dart'; @@ -18,28 +19,40 @@ class SendSyncingIndicator extends StatelessWidget { eta = ""; } - return Container( - height: 48, - decoration: BoxDecoration(color: backgroundColor, borderRadius: BorderRadius.circular(99999)), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12.0), - child: Row( - mainAxisSize: MainAxisSize.min, - spacing: 10, - children: [ - if (status.progress() > 0) - SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - value: status.progress(), - strokeWidth: 3, - strokeCap: StrokeCap.round, - color: outlineColor, + final statusText = "${S.of(context).synchronizing}... ${eta}"; + + // A single status node: progress ticks keep updating the value, and without a live + // region they do not interrupt the user on every tick. + return Semantics( + container: true, + label: statusText, + value: status.progress() > 0 ? "${(status.progress() * 100).round()}%" : null, + excludeSemantics: true, + child: Container( + height: 48, + decoration: + BoxDecoration(color: backgroundColor, borderRadius: BorderRadius.circular(99999)), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 10, + children: [ + if (status.progress() > 0) + SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator( + value: status.progress(), + strokeWidth: 3, + strokeCap: StrokeCap.round, + color: outlineColor, + semanticsLabel: S.of(context).synchronizing, + ), ), - ), - Text("Synchronizing... ${eta}", style: TextStyle(color: outlineColor)), - ], + Text(statusText, style: TextStyle(color: outlineColor)), + ], + ), ), ), ); diff --git a/lib/src/widgets/primary_button.dart b/lib/src/widgets/primary_button.dart index 07915f867..48d00ba97 100644 --- a/lib/src/widgets/primary_button.dart +++ b/lib/src/widgets/primary_button.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:flutter/cupertino.dart'; @@ -92,35 +93,53 @@ class LoadingPrimaryButton extends StatelessWidget { @override Widget build(BuildContext context) { - return ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), - child: SizedBox( - width: double.infinity, - height: 52.0, - child: TextButton( - onPressed: (isLoading || isDisabled) - ? null - : () { - FocusScope.of(context).unfocus(); - onPressed.call(); - }, - style: ButtonStyle( - backgroundColor: WidgetStateProperty.all(isDisabled ? color.withOpacity(0.5) : color), - shape: WidgetStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18.0), - ), - )), - child: isLoading - ? CupertinoActivityIndicator(animating: true, color: textColor) - : Text( - text, - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - fontSize: 15.0, - fontWeight: FontWeight.w600, - color: isDisabled ? textColor.withOpacity(0.5) : textColor, - ), - ), + final isEnabled = !isLoading && !isDisabled; + + // The spinner replaces the label while loading, so the name is kept on a single + // semantics node that also reports the loading and disabled states. + return Semantics( + button: true, + enabled: isEnabled, + label: text, + value: isLoading ? S.of(context).loading : null, + onTap: isEnabled + ? () { + FocusScope.of(context).unfocus(); + onPressed.call(); + } + : null, + excludeSemantics: true, + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), + child: SizedBox( + width: double.infinity, + height: 52.0, + child: TextButton( + onPressed: (isLoading || isDisabled) + ? null + : () { + FocusScope.of(context).unfocus(); + onPressed.call(); + }, + style: ButtonStyle( + backgroundColor: + WidgetStateProperty.all(isDisabled ? color.withOpacity(0.5) : color), + shape: WidgetStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), + ), + )), + child: isLoading + ? CupertinoActivityIndicator(animating: true, color: textColor) + : Text( + text, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + fontSize: 15.0, + fontWeight: FontWeight.w600, + color: isDisabled ? textColor.withOpacity(0.5) : textColor, + ), + ), + ), ), ), ); diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index dc35bd152..d81f3dd52 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -733,6 +733,7 @@ "onramper_option_description": "Quickly buy crypto with many payment methods. Available in most countries. Spreads and fees vary.", "open_gift_card": "Open Gift Card", "open_wallet": "Open Wallet", + "opens_in_browser": "Opens in browser", "opens_externally": "Opens externally", "optional_description": "Optional description", "optional_email_hint": "Optional payee notification email", @@ -845,6 +846,7 @@ "qr_code_format_note": "Different QR code formats are used by different hardware wallets in the Bitcoin space", "qr_fullscreen": "Tap to open full screen QR code", "qr_instruction": "Use this address to receive any token or collectible on", + "qr_parts_scanned": "Scanned ${scanned} of ${total} QR code parts", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "quantity": "Quantity", "question_to_disable_2fa": "Are you sure that you want to disable Cake 2FA? A 2FA code will no longer be needed to access the wallet and certain functions.", @@ -856,6 +858,7 @@ "receiving": "Receiving", "recieving": "Recieving", "recipient_address": "Recipient address", + "recipient_number": "Recipient ${number}", "reconnect": "Reconnect", "reconnect_alert_text": "Are you sure you want to reconnect?", "reconnect_your_hardware_wallet": "Reconnect your Hardware Wallet", @@ -1094,6 +1097,7 @@ "show_balance_toast": "Long press to hide or show balance", "show_combined_balance": "Show combined balance", "show_details": "Show Details", + "show_full_address": "Show full address", "show_hidden_addresses": "Show hidden addresses", "show_keys": "Show seed/keys", "show_market_place": "Show Marketplace", From feeec2e42501104140b985b6871f7bc3c68eb65f Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Thu, 6 Aug 2026 14:49:18 +0200 Subject: [PATCH 07/10] CW-1581-trezor-fixes-enhancements (#3462) * feat: add Trezor auto connect * chore: update `trezor_flutter` * fix: correct method name for retrieving Trezor auto-pairing credentials * fix: update device connection prompt text across all languages [skip ci] * feat: add Trezor key image synchronization ui and improve hardware wallet UX * feat: add sync-balance icon asset for settings row visuals [skip ci] * feat: add sync-balance icon asset for settings row visuals [skip ci] * fix: remove unused Monero and sync key images settings actions from menus [skip ci] * fix: re-enable routing for UR QR Animated Page [skip ci] --- cw_monero/lib/monero_wallet.dart | 2 + cw_monero/lib/trezor.dart | 41 +-- cw_monero/pubspec.lock | 8 +- cw_monero/pubspec.yaml | 2 +- lib/di.dart | 4 +- lib/monero/cw_monero.dart | 6 + lib/new-ui/pages/send_page.dart | 36 +-- lib/new-ui/pages/settings_page.dart | 40 +-- .../sync_key_images_sheet.dart | 224 +++++++++++++++ .../widgets/new_future_primary_button.dart | 57 ++++ lib/router.dart | 19 +- lib/routes.dart | 1 + .../trezor_connect_view_model.dart | 222 +++++++++++---- .../settings_row_icons/sync-balance.svg | 19 ++ res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 5 +- res/values/strings_en.arb | 7 +- res/values/strings_es.arb | 3 +- res/values/strings_fa.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_gn.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_hy.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_pt_BR.arb | 1 - res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_vi.arb | 3 +- res/values/strings_yo.arb | 3 +- .../new_future_primary_button_test.dart | 265 ++++++++++++++++++ tool/configure.dart | 2 + 46 files changed, 854 insertions(+), 188 deletions(-) create mode 100644 lib/new-ui/widgets/hardware_wallet/sync_key_images_sheet.dart create mode 100644 lib/new-ui/widgets/new_future_primary_button.dart create mode 100644 res/pictures/settings_row_icons/sync-balance.svg create mode 100644 test/new-ui/widgets/new_future_primary_button_test.dart diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index d0e653907..afd9284be 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -370,6 +370,8 @@ abstract class MoneroWalletBase }; } + bool hasUnknownKeyImages() => currentWallet!.hasUnknownKeyImages(); + bool needExportOutputs(Money amount) { if (int.tryParse(currentWallet!.secretSpendKey()) != 0) { return false; diff --git a/cw_monero/lib/trezor.dart b/cw_monero/lib/trezor.dart index a9a387912..b851859cb 100644 --- a/cw_monero/lib/trezor.dart +++ b/cw_monero/lib/trezor.dart @@ -1,27 +1,28 @@ -import 'dart:convert'; +import "dart:convert"; -import 'package:cw_core/hardware/hardware_wallet_service.dart'; -import 'package:trezor_flutter/trezor_flutter.dart'; +import "package:cw_core/hardware/hardware_wallet_service.dart"; +import "package:trezor_flutter/trezor_flutter.dart"; class MoneroTrezorService extends HardwareWalletService { - final TrezorClient client; - MoneroTrezorService(this.client); + + final TrezorClient client; } class MoneroTrezorWatchCredentials { + const MoneroTrezorWatchCredentials(this.watchKey, this.address); + final String watchKey; final String address; - - const MoneroTrezorWatchCredentials(this.watchKey, this.address); } class Trezor { - final MoneroTrezorService service; - Trezor(this.service); + final MoneroTrezorService service; + String? _sessionPassphrase; + Future newPassphraseSession(String? passphrase) async { if (passphrase == null) return; @@ -42,21 +43,23 @@ class Trezor { final txIds = []; for (final tdi in tdisList) { - txIds.add(MoneroKeyImageTxData( - outKey: tdi["out_key"], - txPubKey: tdi["tx_pub_key"], - internalOutputIndex: tdi["internal_output_index"], - subAddrMajor: tdi["sub_addr_major"], - subAddrMinor: tdi["sub_addr_minor"], + txIds.add( + MoneroKeyImageTxData( + outKey: tdi["out_key"] as String, + txPubKey: tdi["tx_pub_key"] as String, + internalOutputIndex: tdi["internal_output_index"] as int, + subAddrMajor: tdi["sub_addr_major"] as int, + subAddrMinor: tdi["sub_addr_minor"] as int, additionalTxPubKeys: - (tdi["additional_tx_pub_keys"] as List?)?.map((e) => e as String).toList() ?? [])); + (tdi["additional_tx_pub_keys"] as List?)?.map((e) => e as String).toList() ?? [], + ), + ); } final keyImages = await TrezorMonero(service.client).syncKeyImages(txIds); return jsonEncode(keyImages.toMap()); } - Future signTransaction(String json) async { - return TrezorMonero(service.client).signTransaction(jsonDecode(json)); - } + Future signTransaction(String json) => + TrezorMonero(service.client).signTransaction(jsonDecode(json) as Map); } diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 275e7d4aa..0cc1a9e19 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -921,8 +921,8 @@ packages: dependency: "direct main" description: path: trezor-flutter - ref: "944080d950a62dd48a199b9736237cbe580351de" - resolved-ref: "944080d950a62dd48a199b9736237cbe580351de" + ref: "7a736320f6d53ad5c763734ab832d6bea560a327" + resolved-ref: "7a736320f6d53ad5c763734ab832d6bea560a327" url: "https://github.com/cake-tech/trezor-flutter.git" source: git version: "0.1.0" @@ -930,8 +930,8 @@ packages: dependency: transitive description: path: trezor_usb_transport - ref: "944080d950a62dd48a199b9736237cbe580351de" - resolved-ref: "944080d950a62dd48a199b9736237cbe580351de" + ref: "7a736320f6d53ad5c763734ab832d6bea560a327" + resolved-ref: "7a736320f6d53ad5c763734ab832d6bea560a327" url: "https://github.com/cake-tech/trezor-flutter.git" source: git version: "0.0.1" diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index 692103eba..3f1c10f7b 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -33,7 +33,7 @@ dependencies: trezor_flutter: git: url: https://github.com/cake-tech/trezor-flutter.git - ref: 944080d950a62dd48a199b9736237cbe580351de + ref: 7d27e19b7bcdcd6241df35953f9a6ec2df0c7a97 path: trezor-flutter dev_dependencies: diff --git a/lib/di.dart b/lib/di.dart index 6bb8bd98c..da00561a5 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -434,7 +434,9 @@ Future setup({ () => TrezorConnect("cakewallet://trezor_connect", appName: "Cake Wallet"), ); - getIt.registerLazySingleton(() => TrezorConnectViewModel(getIt())); + getIt.registerLazySingleton( + () => TrezorConnectViewModel(getIt(), getIt()), + ); getIt.registerFactory(() => KeyService(getIt.get())); diff --git a/lib/monero/cw_monero.dart b/lib/monero/cw_monero.dart index 7d2b8ec26..d1e421d30 100644 --- a/lib/monero/cw_monero.dart +++ b/lib/monero/cw_monero.dart @@ -420,6 +420,12 @@ class CWMonero extends Monero { return moneroWallet.needExportOutputs(amount); } + @override + bool hasUnknownKeyImages(Object wallet) { + final moneroWallet = wallet as MoneroWallet; + return moneroWallet.hasUnknownKeyImages(); + } + @override void monerocCheck() => checkIfMoneroCIsFine(); diff --git a/lib/new-ui/pages/send_page.dart b/lib/new-ui/pages/send_page.dart index d25b3440e..1b379df8e 100644 --- a/lib/new-ui/pages/send_page.dart +++ b/lib/new-ui/pages/send_page.dart @@ -19,6 +19,7 @@ import "package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_sheet import "package:cake_wallet/new-ui/widgets/currency_picker/fiat_currency_picker_sheet.dart"; import "package:cake_wallet/new-ui/widgets/keyboard_hide_overlay.dart"; import "package:cake_wallet/new-ui/widgets/modern_button.dart"; +import "package:cake_wallet/new-ui/widgets/new_future_primary_button.dart"; import "package:cake_wallet/new-ui/widgets/new_primary_button.dart"; import "package:cake_wallet/new-ui/widgets/picker.dart"; import "package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart"; @@ -42,7 +43,6 @@ import "package:cake_wallet/src/widgets/bottom_sheet/token_selection_bottom_shee import "package:cake_wallet/src/widgets/bottom_sheet/wallet_switcher_bottom_sheet.dart"; import "package:cake_wallet/src/widgets/cake_image_widget.dart"; import "package:cake_wallet/src/widgets/new_list_row/list_item_regular_row_widget.dart"; -import "package:cake_wallet/src/widgets/primary_button.dart"; import "package:cake_wallet/src/widgets/standard_checkbox.dart"; import "package:cake_wallet/store/app_store.dart"; import "package:cake_wallet/utils/payment_request.dart"; @@ -618,9 +618,9 @@ class _NewSendPageState extends State { selectedDot: _selectedOutput, ), Observer( - builder: (_) => LoadingPrimaryButton( + builder: (_) => NewFuturePrimaryButton( key: const ValueKey("send_page_send_button_key"), - onPressed: () { + onPressed: () async { //Request dummy node to get the focus out of the text fields FocusScope.of(context).requestFocus(FocusNode()); @@ -629,11 +629,11 @@ class _NewSendPageState extends State { } if (widget.mode == SendPageModes.normal) { - _handleSend(); + await _handleSend(); } else if (widget.mode == SendPageModes.lightningDeposit || widget.mode == SendPageModes.mwebDeposit) { - Navigator.of(context).push( + await Navigator.of(context).push( CupertinoPageRoute( builder: (context) => Material( child: L2ActionWalletSelector( @@ -652,7 +652,7 @@ class _NewSendPageState extends State { } else if (widget.mode == SendPageModes.lightningWithdrawal || widget.mode == SendPageModes.mwebWithdrawal) { - Navigator.of(context).push( + await Navigator.of(context).push( CupertinoPageRoute( builder: (context) => Material( child: L2ActionWalletSelector( @@ -673,13 +673,7 @@ class _NewSendPageState extends State { text: S.of(context).continue_text, color: Theme.of(context).colorScheme.primary, textColor: Theme.of(context).colorScheme.onPrimary, - isLoading: widget.sendViewModel.state is IsExecutingState || - widget.sendViewModel.state is TransactionCommitting || - widget.sendViewModel.state - is IsAwaitingDeviceResponseState || - widget.sendViewModel.state - is LoadingTemplateExecutingState, - isDisabled: !widget.sendViewModel.isReadyForSend || + disabled: !widget.sendViewModel.isReadyForSend || widget.sendViewModel.state is ExecutedSuccessfullyState, ), ), @@ -858,17 +852,11 @@ class _NewSendPageState extends State { for (final item in widget.sendViewModel.outputs) { amount += item.cryptoAmountMoney; } - if (monero!.needExportOutputs(widget.sendViewModel.wallet, amount)) { - if (widget.sendViewModel.wallet.hardwareWalletType == HardwareWalletType.trezor) { - await monero!.syncTrezor(widget.sendViewModel.wallet); - } else { - if (mounted) { - await Navigator.of(context).pushNamed( - Routes.urqrAnimatedPage, - arguments: monero!.exportOutputsUR(widget.sendViewModel.wallet), - ); - } - } + if (monero!.hasUnknownKeyImages(widget.sendViewModel.wallet) && mounted) { + await Navigator.of(context).pushNamed( + Routes.syncKeyImagesDevices, + arguments: monero!.exportOutputsUR(widget.sendViewModel.wallet), + ); await Future.delayed(const Duration(seconds: 1)); // wait for monero to refresh the state } if (monero!.needExportOutputs(widget.sendViewModel.wallet, amount)) { diff --git a/lib/new-ui/pages/settings_page.dart b/lib/new-ui/pages/settings_page.dart index 2183ec5d4..8aaec520d 100644 --- a/lib/new-ui/pages/settings_page.dart +++ b/lib/new-ui/pages/settings_page.dart @@ -9,10 +9,9 @@ import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cw_core/wallet_info.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; import "package:cw_core/wallet_type.dart"; +import 'package:flutter/material.dart'; +import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; bool _trueFunc(DashboardViewModel _) => true; @@ -26,10 +25,21 @@ bool _hasMweb(DashboardViewModel vm) => vm.hasMweb; bool _hasWalletConnect(DashboardViewModel vm) => vm.hasWalletConnect; -bool _isCupcake(DashboardViewModel vm) => - vm.wallet.hardwareWalletType == HardwareWalletType.cupcake; +bool _requiresKeyImageSync(DashboardViewModel vm) => + vm.wallet.type == WalletType.monero && + [HardwareWalletType.cupcake, HardwareWalletType.trezor].contains(vm.wallet.hardwareWalletType); class SettingsListItem { + const SettingsListItem( + this.iconPath, + this.title, + this.route, { + this.requireAuth = false, + this.use2fa = _falseFunc, + this.condition = _trueFunc, + this.routeArgs, + }); + final String iconPath; final String title; final String route; @@ -37,21 +47,15 @@ class SettingsListItem { final bool requireAuth; final bool Function(DashboardViewModel) use2fa; final bool Function(DashboardViewModel) condition; - - const SettingsListItem(this.iconPath, this.title, this.route, - {this.routeArgs = null, - this.requireAuth = false, - this.use2fa = _falseFunc, - this.condition = _trueFunc}); } class SettingsSectionData { + const SettingsSectionData(this.title, this.titleIconPath, this.items); + final String title; final String titleIconPath; final List items; - const SettingsSectionData(this.title, this.titleIconPath, this.items); - static SettingsSectionData walletSettings = SettingsSectionData(S.current.wallet_settings, "assets/new-ui/wallet-setting.svg", [ SettingsListItem( @@ -71,9 +75,13 @@ class SettingsSectionData { condition: _hasWalletConnect), //SettingsListItem("assets/new-ui/settings_row_icons/silent-payments.svg", S.current.silent_payments_settings, Routes.silentPaymentsSettings, condition: _isBtc), //SettingsListItem("assets/new-ui/settings_row_icons/mweb.svg", S.current.litecoin_mweb_settings, Routes.mwebSettings, condition: _hasMweb), - SettingsListItem("assets/new-ui/settings_row_icons/cupcake.svg", S.current.export_outputs, - Routes.urqrAnimatedPage, - routeArgs: {'export-outputs': 'export-outputs'}, condition: _isCupcake), + SettingsListItem( + "assets/new-ui/settings_row_icons/sync-balance.svg", + S.current.resync_device, + Routes.syncKeyImagesDevices, + routeArgs: {'export-outputs': 'export-outputs'}, + condition: _requiresKeyImageSync, + ), SettingsListItem( "assets/new-ui/settings_row_icons/other.svg", S.current.other, Routes.otherSettingsPage), ]); diff --git a/lib/new-ui/widgets/hardware_wallet/sync_key_images_sheet.dart b/lib/new-ui/widgets/hardware_wallet/sync_key_images_sheet.dart new file mode 100644 index 000000000..d8febdcbf --- /dev/null +++ b/lib/new-ui/widgets/hardware_wallet/sync_key_images_sheet.dart @@ -0,0 +1,224 @@ +import "package:cake_wallet/generated/i18n.dart"; +import "package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart"; +import "package:cake_wallet/new-ui/widgets/send_page/directional_switcher.dart"; +import "package:cake_wallet/routes.dart"; +import "package:cake_wallet/src/screens/connect_device/connect_device_page.dart"; +import "package:cake_wallet/src/widgets/alert_with_two_actions.dart"; +import "package:cake_wallet/src/widgets/base_alert_dialog.dart"; +import "package:cake_wallet/src/widgets/cake_image_widget.dart"; +import "package:cake_wallet/src/widgets/primary_button.dart"; +import "package:cake_wallet/store/app_store.dart"; +import "package:cake_wallet/utils/show_pop_up.dart"; +import "package:cake_wallet/view_model/hardware_wallet/trezor_connect_view_model.dart"; +import "package:cw_core/wallet_base.dart"; +import "package:cw_core/wallet_info.dart"; +import "package:flutter/cupertino.dart"; +import "package:flutter/material.dart"; + +class SyncKeyImagesSheet extends StatefulWidget { + const SyncKeyImagesSheet({ + required this.appStore, + required this.trezorConnectVM, + super.key, + }); + + final AppStore appStore; + final TrezorConnectViewModelBase trezorConnectVM; + + WalletBase get wallet => appStore.wallet!; + + @override + State createState() => _HardwareWalletProceedOnDeviceSheetState(); +} + +class _HardwareWalletProceedOnDeviceSheetState extends State { + _KeyImageSyncState _state = _KeyImageSyncState.initial; + + @override + Widget build(BuildContext context) => PopScope( + canPop: false, + child: SafeArea( + bottom: false, + child: Container( + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), + ), + child: SafeArea( + child: Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: Column( + children: [ + ModalTopBar( + title: S.of(context).resync_device, + leadingIcon: Icon( + Icons.close, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + onLeadingPressed: () => showPopUp( + context: context, + builder: (context) => AlertWithTwoActions( + alertTitle: S.of(context).are_you_sure_exit, + alertContent: S.of(context).resync_device_cancel_warning_desc, + leftButtonText: S.of(context).cancel, + rightButtonText: S.of(context).yes_exit, + rightAlertButtonStyle: AlertButtonStyle.error(context), + actionLeftButton: Navigator.of(context).pop, + actionRightButton: () { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + }, + ), + ), + ), + Expanded( + child: Column( + spacing: 12, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CakeImageWidget( + imageUrl: hardwareWalletIcon, + width: 100, + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.onSurfaceVariant, + BlendMode.srcIn, + ), + ), + DirectionalAnimatedSwitcher( + duration: const Duration(milliseconds: 400), + child: content, + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: AnimatedOpacity( + curve: Curves.easeOutQuad, + opacity: _state == _KeyImageSyncState.initial ? 1 : 0, + duration: const Duration(milliseconds: 300), + child: PrimaryButton( + text: S.of(context).continue_text, + color: Theme.of(context).colorScheme.primary, + textColor: Theme.of(context).colorScheme.onPrimary, + onPressed: _onContinuePressed, + ), + ), + ), + ], + ), + ), + ), + ), + ), + ); + + Widget get content { + if (_state == _KeyImageSyncState.syncing) { + return _syncingKeyImages(); + } + + return _initial(); + } + + String? get hardwareWalletIcon { + switch (widget.wallet.hardwareWalletType) { + case HardwareWalletType.bitbox: + return "assets/new-ui/hardware_wallets/device_bitbox.svg"; + case HardwareWalletType.ledger: + return "assets/new-ui/hardware_wallets/device_ledger_nano_x.svg"; + case HardwareWalletType.trezor: + return "assets/new-ui/hardware_wallets/device_trezor_safe_7.svg"; + case HardwareWalletType.cupcake: + return "assets/images/cupcake.svg"; + case HardwareWalletType.coldcard: + case HardwareWalletType.seedsigner: + case HardwareWalletType.keystone: + case null: + return "assets/images/hardware_wallet/device_qr.svg"; + } + } + + Widget _initial() => Column( + key: const ValueKey(0), + spacing: 12, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + S.of(context).resync_device_desc, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ], + ); + + Widget _syncingKeyImages() => Column( + key: const ValueKey(1), + spacing: 12, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + S.of(context).proceed_on_device, + style: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 20, + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 20), + child: Text( + S.of(context).proceed_on_device_description, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ) + ], + ); + + Future _onContinuePressed() async { + setState(() => _state = _KeyImageSyncState.syncing); + + if (!widget.trezorConnectVM.isConnected(widget.wallet.type)) { + await Navigator.of(context).pushNamed( + Routes.connectDevices, + arguments: ConnectDevicePageParams( + walletType: widget.wallet.type, + hardwareWalletType: widget.wallet.walletInfo.hardwareWalletType!, + onConnectDevice: (_, __) { + widget.trezorConnectVM.initWallet(widget.wallet); + Navigator.of(context).pop(); + }, + isReconnect: false, + ), + ); + + // Recheck to handle tap-backs + if (!widget.trezorConnectVM.isConnected(widget.wallet.type)) { + setState(() => _state = _KeyImageSyncState.initial); + return; + } + } else { + await widget.trezorConnectVM.initWallet(widget.wallet); + } + + final result = await widget.trezorConnectVM.syncKeyImages(widget.wallet); + if (result && context.mounted) { + Navigator.of(context).pop(); + } + } +} + +enum _KeyImageSyncState { + initial, + syncing; +} diff --git a/lib/new-ui/widgets/new_future_primary_button.dart b/lib/new-ui/widgets/new_future_primary_button.dart new file mode 100644 index 000000000..2440f1938 --- /dev/null +++ b/lib/new-ui/widgets/new_future_primary_button.dart @@ -0,0 +1,57 @@ +import "package:cake_wallet/new-ui/widgets/new_primary_button.dart"; +import "package:flutter/material.dart"; +import "package:flutter_svg/flutter_svg.dart"; + +class NewFuturePrimaryButton extends StatefulWidget { + const NewFuturePrimaryButton({ + required this.onPressed, + required this.text, + required this.color, + required this.textColor, + this.borderColor = Colors.transparent, + this.disabled = false, + this.image, + super.key, + }); + + final Future Function() onPressed; + final bool disabled; + final SvgPicture? image; + final Color color; + final Color textColor; + final Color borderColor; + final String text; + + @override + State createState() => _NewFuturePrimaryButtonState(); +} + +class _NewFuturePrimaryButtonState extends State { + bool isLoading = false; + + Future _onPressed() async { + if (isLoading) { + return; + } + setState(() => isLoading = true); + try { + await widget.onPressed.call(); + } finally { + if (mounted) { + setState(() => isLoading = false); + } + } + } + + @override + Widget build(BuildContext context) => NewPrimaryButton( + onPressed: _onPressed, + image: widget.image, + text: widget.text, + color: widget.color, + textColor: widget.textColor, + isLoading: isLoading, + borderColor: widget.borderColor, + disabled: widget.disabled, + ); +} diff --git a/lib/router.dart b/lib/router.dart index 837eab8c8..39a28a42f 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -4,7 +4,6 @@ import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; import 'package:cake_wallet/core/new_wallet_arguments.dart'; import 'package:cake_wallet/new-ui/new_dashboard.dart'; import 'package:cake_wallet/new-ui/pages/about_page.dart'; -import 'package:cake_wallet/new-ui/pages/bridge/bridge_confirm_sheet.dart'; import 'package:cake_wallet/new-ui/pages/bridge/bridge_history_page.dart'; import 'package:cake_wallet/new-ui/pages/bridge/bridge_network_page.dart'; import 'package:cake_wallet/new-ui/pages/bridge/bridge_receiving_wallet_page.dart'; @@ -13,6 +12,7 @@ import 'package:cake_wallet/new-ui/pages/addresses_page.dart'; import 'package:cake_wallet/new-ui/pages/lightning_username_page.dart'; import "package:cake_wallet/new-ui/pages/receive_page.dart"; import 'package:cake_wallet/new-ui/pages/send_page.dart'; +import 'package:cake_wallet/new-ui/widgets/hardware_wallet/sync_key_images_sheet.dart'; import 'package:cake_wallet/order/order.dart'; import 'package:cake_wallet/core/new_wallet_type_arguments.dart'; import 'package:cake_wallet/core/totp_request_details.dart'; @@ -51,6 +51,7 @@ import 'package:cake_wallet/src/screens/dev/monero_background_sync.dart'; import 'package:cake_wallet/src/screens/dev/moneroc_cache_debug.dart'; import 'package:cake_wallet/src/screens/dev/moneroc_call_profiler.dart'; import 'package:cake_wallet/src/screens/dev/network_requests.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/src/screens/dev/qr_tools_page.dart'; import 'package:cake_wallet/src/screens/dev/secure_preferences_page.dart'; @@ -126,7 +127,6 @@ import 'package:cake_wallet/src/screens/trade_details/trade_details_page.dart'; import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; -import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; import 'package:cake_wallet/src/screens/ur/animated_ur_page.dart'; import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; import 'package:cake_wallet/src/screens/wallet_connect/services/walletkit_service.dart'; @@ -146,7 +146,7 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/sign_view_model.dart'; import 'package:cake_wallet/view_model/hardware_wallet/hardware_wallet_view_model.dart'; -import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; +import 'package:cake_wallet/view_model/hardware_wallet/trezor_connect_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; @@ -908,6 +908,19 @@ Route createRoute(RouteSettings settings) { case Routes.setup2faInfoPage: return MaterialPageRoute(builder: (_) => getIt.get()); + case Routes.syncKeyImagesDevices: + final hardwareWalletType = getIt().wallet!.hardwareWalletType; + if (hardwareWalletType == HardwareWalletType.trezor) { + return MaterialPageRoute( + builder: (_) => SyncKeyImagesSheet( + appStore: getIt(), + trezorConnectVM: getIt(), + ), + ); + } + return MaterialPageRoute( + builder: (_) => getIt.get(param1: settings.arguments)); + case Routes.urqrAnimatedPage: return MaterialPageRoute( builder: (_) => getIt.get(param1: settings.arguments)); diff --git a/lib/routes.dart b/lib/routes.dart index 236196bf7..b21e2bc38 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -133,6 +133,7 @@ class Routes { static const signPage = '/sign_page'; static const connectDevices = '/device/connect'; + static const syncKeyImagesDevices = '/device/sync_key_images'; static const urqrAnimatedPage = '/urqr/animated_page'; static const walletGroupsDisplayPage = '/wallet_groups_display_page'; static const walletGroupDescription = '/wallet_group_description'; diff --git a/lib/view_model/hardware_wallet/trezor_connect_view_model.dart b/lib/view_model/hardware_wallet/trezor_connect_view_model.dart index c048edf7c..28116e3cb 100644 --- a/lib/view_model/hardware_wallet/trezor_connect_view_model.dart +++ b/lib/view_model/hardware_wallet/trezor_connect_view_model.dart @@ -1,43 +1,43 @@ -import 'dart:async'; -import 'dart:io'; +import "dart:async"; +import "dart:convert"; +import "dart:io"; -import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cake_wallet/entities/hardware_wallet/hardware_wallet_device.dart'; -import 'package:cake_wallet/evm/evm.dart'; -import 'package:cake_wallet/main.dart'; -import 'package:cake_wallet/monero/monero.dart'; -import 'package:cake_wallet/new-ui/widgets/hardware_wallet/proceed_on_device_sheet.dart'; -import 'package:cake_wallet/view_model/hardware_wallet/hardware_wallet_view_model.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; -import 'package:cw_core/hardware/device_connection_type.dart'; -import 'package:cw_core/hardware/hardware_wallet_service.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:device_info_plus/device_info_plus.dart'; -import 'package:flutter/material.dart'; -import 'package:mobx/mobx.dart'; -import 'package:permission_handler/permission_handler.dart'; -import 'package:trezor_connect/trezor_connect.dart' as connect_sdk; -import 'package:trezor_flutter/trezor_flutter.dart' as sdk; +import "package:cake_wallet/bitcoin/bitcoin.dart"; +import "package:cake_wallet/core/secure_storage.dart"; +import "package:cake_wallet/entities/hardware_wallet/hardware_wallet_device.dart"; +import "package:cake_wallet/evm/evm.dart"; +import "package:cake_wallet/main.dart"; +import "package:cake_wallet/monero/monero.dart"; +import "package:cake_wallet/new-ui/widgets/hardware_wallet/proceed_on_device_sheet.dart"; +import "package:cake_wallet/view_model/hardware_wallet/hardware_wallet_view_model.dart"; +import "package:cake_wallet/wallet_type_utils.dart"; +import "package:cw_core/encryption_file_utils.dart"; +import "package:cw_core/hardware/device_connection_type.dart"; +import "package:cw_core/hardware/hardware_wallet_service.dart"; +import "package:cw_core/key.dart"; +import "package:cw_core/root_dir.dart"; +import "package:cw_core/utils/print_verbose.dart"; +import "package:cw_core/wallet_base.dart"; +import "package:cw_core/wallet_info.dart"; +import "package:cw_core/wallet_type.dart"; +import "package:device_info_plus/device_info_plus.dart"; +import "package:flutter/material.dart"; +import "package:mobx/mobx.dart"; +import "package:permission_handler/permission_handler.dart"; +import "package:trezor_connect/trezor_connect.dart" as connect_sdk; +import "package:trezor_flutter/trezor_flutter.dart" as sdk; -part 'trezor_connect_view_model.g.dart'; +part "trezor_connect_view_model.g.dart"; class TrezorConnectViewModel = TrezorConnectViewModelBase with _$TrezorConnectViewModel; abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with Store { - final connect_sdk.TrezorConnect trezorConnect; - - late final sdk.TrezorInterface trezorBLE; - late final sdk.TrezorInterface trezorUSB; - - sdk.ThpState _state = sdk.ThpState(); - - TrezorConnectViewModelBase(this.trezorConnect) { + TrezorConnectViewModelBase(this.trezorConnect, this._secureStorage) { if (_doesSupportHardwareWallets) { reaction((_) => isBleEnabled, (_) { - if (isBleEnabled) _initBLE(); + if (isBleEnabled) { + _initBLE(); + } }); updateBleState(); @@ -47,11 +47,21 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S } } + final connect_sdk.TrezorConnect trezorConnect; + final SecureStorage _secureStorage; + + late final sdk.TrezorInterface trezorBLE; + late final sdk.TrezorInterface trezorUSB; + + sdk.ThpState? _state; + bool get _doesSupportHardwareWallets { if (isMoneroOnly) { return DeviceConnectionType.supportedConnectionTypes( - WalletType.monero, HardwareWalletType.trezor, Platform.isIOS) - .isNotEmpty; + WalletType.monero, + HardwareWalletType.trezor, + Platform.isIOS, + ).isNotEmpty; } return true; @@ -63,9 +73,11 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S if (isBleEnabled && !_bleIsInitialized) { trezorBLE = sdk.TrezorInterface.ble( onPermissionRequest: (_) async { - if (Platform.isMacOS) return true; + if (Platform.isMacOS) { + return true; + } - Map statuses = await [ + final Map statuses = await [ Permission.bluetoothScan, Permission.bluetoothConnect, Permission.bluetoothAdvertise, @@ -73,7 +85,7 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S return statuses.values.where((status) => status.isDenied).isEmpty; }, - bleOptions: sdk.BluetoothOptions(maxScanDuration: Duration(minutes: 5)), + bleOptions: sdk.BluetoothOptions(maxScanDuration: const Duration(minutes: 5)), ); _bleIsInitialized = true; } @@ -99,21 +111,27 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S final newState = bleState == sdk.AvailabilityState.poweredOn; - if (newState != isBleEnabled) isBleEnabled = newState; + if (newState != isBleEnabled) { + isBleEnabled = newState; + } } @override Stream scanForBleDevices() => - trezorBLE.scan().map((d) => TrezorHardwareWalletDevice(d)); + trezorBLE.scan().map(TrezorHardwareWalletDevice.new); @override - Future> getAllUsbDevices() => trezorUSB.devices - .then((devices) => devices.map((d) => TrezorHardwareWalletDevice(d)).toList()); + Future> getAllUsbDevices() => + trezorUSB.devices.then((devices) => devices.map(TrezorHardwareWalletDevice.new).toList()); @override Future stopScanning() async { - if (_bleIsInitialized) await trezorBLE.stopScanning(); - if (!Platform.isIOS) await trezorUSB.stopScanning(); + if (_bleIsInitialized) { + await trezorBLE.stopScanning(); + } + if (!Platform.isIOS) { + await trezorUSB.stopScanning(); + } } sdk.TrezorClient? _client; @@ -127,10 +145,17 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S @override @action - Future connectDevice(HardwareWalletDevice device, WalletType type, - [bool isRetry = false]) async { - if (!(device is TrezorHardwareWalletDevice)) return false; - if (isConnecting) return false; + Future connectDevice( + HardwareWalletDevice device, + WalletType type, [ + bool isRetry = false, + ]) async { + if (device is! TrezorHardwareWalletDevice) { + return false; + } + if (isConnecting) { + return false; + } isConnecting = true; paringState = TrezorParingState.initial; @@ -140,16 +165,19 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S final connection = await trezorInterface.connect(device.device); if (!isRetry) { - showModalBottomSheet( - context: navigatorKey.currentContext!, - isScrollControlled: true, - isDismissible: false, - enableDrag: false, - useSafeArea: true, - builder: (context) => HardwareWalletProceedOnDeviceSheet( + unawaited( + showModalBottomSheet( + context: navigatorKey.currentContext!, + isScrollControlled: true, + isDismissible: false, + enableDrag: false, + useSafeArea: true, + builder: (_) => HardwareWalletProceedOnDeviceSheet( hardwareWalletType: hardwareWalletType, trezorConnectVM: this, - onRetry: () => connectDevice(device, type, true)), + onRetry: () => connectDevice(device, type, true), + ), + ), ); } @@ -159,15 +187,18 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S final res = await _pinCompleter!.future; paringState = TrezorParingState.verifyingPin; - if (res == null) throw Exception(); + if (res == null) { + throw Exception(); + } return res; } final deviceInfo = await _deviceName; + _state ??= await _getState(); _client = sdk.TrezorClient.getClientForConnection( connection, - _state, + _state!, "Cake Wallet", deviceInfo, onPinCode, @@ -175,6 +206,16 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S await _client!.createChannel(); + if (!_state!.pairingCredentials.any((c) => c.autoconnect == true)) { + if (_client case final sdk.TrezorClientV2 clientV2) { + try { + final auto = await clientV2.getAutoPairingCredentials(); + _state!.setPairingCredentials([auto]); + await _saveState(); + } catch (_) {} + } + } + paringState = TrezorParingState.success; return true; } catch (e) { @@ -192,8 +233,12 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S Future get _deviceName async { final deviceInfo = DeviceInfoPlugin(); - if (Platform.isAndroid) return (await deviceInfo.androidInfo).model; - if (Platform.isIOS) return (await deviceInfo.iosInfo).name; + if (Platform.isAndroid) { + return (await deviceInfo.androidInfo).model; + } + if (Platform.isIOS) { + return (await deviceInfo.iosInfo).name; + } return "Computer"; } @@ -231,9 +276,61 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S case WalletType.polygon: return evm!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type)); default: - throw Exception('Unexpected wallet type: ${wallet.type} for trezor'); + throw Exception("Unexpected wallet type: ${wallet.type} for trezor"); } } + + final EncryptionFileUtils _encryptionFileUtils = encryptionFileUtilsFor(true); + static const String _secureStorageKey = "com.cakewallet.trezor/thp_state"; + + Future get _thpJsonFile async => "${(await getAppDir()).path}/thp_state.json.enc"; + + Future _getState() async { + final password = await _secureStorage.read(key: _secureStorageKey); + if (password == null) { + return _saveState(); + } + try { + final state = await _encryptionFileUtils.read(path: await _thpJsonFile, password: password); + return sdk.ThpState.fromJson(state); + } catch (_) { + return _saveState(); + } + } + + Future _saveState() async { + try { + final password = generateKey(); + await _secureStorage.write(key: _secureStorageKey, value: password); + + final file = File(await _thpJsonFile); + if (!file.existsSync()) { + file.createSync(); + } + + final state = _state ?? sdk.ThpState(); + await _encryptionFileUtils.write( + path: file.path, + password: password, + data: jsonEncode(state.toMap()), + ); + _state = state; + return state; + } catch (_) { + throw Exception("Unable to save Trezor State"); + } + } + + Future syncKeyImages(WalletBase wallet) async { + if (wallet.type == WalletType.monero) { + try { + await monero!.syncTrezor(wallet); + } catch (_) { + return false; + } + } + return true; + } } abstract class TrezorParingState { @@ -241,6 +338,7 @@ abstract class TrezorParingState { static TrezorParingState enterPin = EnterPinTrezorParingState(); static TrezorParingState verifyingPin = VerifyingPinTrezorParingState(); static TrezorParingState success = SuccessTrezorParingState(); + static TrezorParingState fail(String message) => FailTrezorParingState(message); } @@ -253,7 +351,7 @@ class VerifyingPinTrezorParingState extends TrezorParingState {} class SuccessTrezorParingState extends TrezorParingState {} class FailTrezorParingState extends TrezorParingState { - final String message; - FailTrezorParingState(this.message); + + final String message; } diff --git a/res/pictures/settings_row_icons/sync-balance.svg b/res/pictures/settings_row_icons/sync-balance.svg new file mode 100644 index 000000000..fc3274a66 --- /dev/null +++ b/res/pictures/settings_row_icons/sync-balance.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 125537f7b..815de2868 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -529,7 +529,6 @@ "i_understand": "أفهم", "icon_style": "نمط الأيقونة", "id": "المعرّف: ", - "if_you_dont_see_your_device": "إذا لم يظهر جهازك أعلاه، يُرجى التأكد من أن Ledger قيد التشغيل ومفتوح القفل!", "ignor": "تجاهل", "import": "استيراد", "importNFTs": "استيراد رموز NFT", @@ -1451,4 +1450,4 @@ "wallet_balance": "رصيد المحفظة", "wc_desc": "اتصل بسهولة بتطبيقات DApps", "yes_exit": "نعم. اخرج" -} \ No newline at end of file +} diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 59d11edb6..45136deab 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -529,7 +529,6 @@ "i_understand": "Разбирам", "icon_style": "Стил на иконата", "id": "ID: ", - "if_you_dont_see_your_device": "Ако не виждате устройството си по-горе, моля, уверете се, че вашият Ledger е буден и отключен!", "ignor": "Игнорирай", "import": "Импортиране", "importNFTs": "Импортиране на NFT", @@ -1451,4 +1450,4 @@ "wallet_balance": "Баланс на портфейла", "wc_desc": "Свържете се лесно с dApps", "yes_exit": "Да. Изход" -} \ No newline at end of file +} diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index c2c5c49c0..c3df26ca8 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -529,7 +529,6 @@ "i_understand": "Rozumím", "icon_style": "Styl ikony", "id": "ID: ", - "if_you_dont_see_your_device": "Pokud své zařízení výše nevidíte, ujistěte se, že je váš Ledger zapnutý a odemčený!", "ignor": "Ignorovat", "import": "Importovat", "importNFTs": "Importovat NFT", @@ -1451,4 +1450,4 @@ "wallet_balance": "Zůstatek peněženky", "wc_desc": "Snadno se připojte k dApps", "yes_exit": "Ano. Ukončit" -} \ No newline at end of file +} diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 2b8d0b5e7..9a39f7bda 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -530,7 +530,7 @@ "i_understand": "Ich verstehe", "icon_style": "Symbolstil", "id": "ID: ", - "if_you_dont_see_your_device": "Wenn Sie Ihr Gerät oben nicht sehen, stellen Sie bitte sicher, dass Ihr Ledger eingeschaltet und entsperrt ist!", + "if_you_dont_see_your_device": "Wenn Sie Ihr Gerät oben nicht sehen, stellen Sie bitte sicher, dass Ihr Gerät eingeschaltet und entsperrt ist!", "ignore": "Ignorieren", "import": "Importieren", "importNFTs": "NFTs importieren", @@ -882,6 +882,9 @@ "restore_wallet": "Wallet wiederherstellen", "restore_wallet_name": "Wallet-Name", "restore_wallet_restore_description": "Beschreibung der Wallet-Wiederherstellung", + "resync_device": "Gerät resyncen", + "resync_device_desc": "Um das Guthaben aktuell zu halten muss Cake Wallet gelegentlich sich mit dem Gerät synchonisieren.", + "resync_device_cancel_warning_desc": "Dadurch wird der laufende Synchronisierungsprozess mit Ihrem Hardware-Gerät beendet.", "return_address_desc": "Im seltenen Fall eines fehlgeschlagenen Swaps können unsere Partner Ihre Zahlung automatisch an die angegebene Rückerstattungsadresse erstatten.", "return_address_desc_external": "Da Sie „Von extern senden“ ausgewählt haben, legen Sie bitte unten manuell eine Erstattungsadresse fest.", "robinhood_option_description": "Kaufen und übertragen Sie sofort mit Ihrer Debitkarte, Ihrem Bankkonto oder Ihrem Robinhood-Guthaben. Nur USA.", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index d81f3dd52..30e506aef 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -544,11 +544,11 @@ "how_to_connect": "How to Connect", "how_to_use": "How to use", "how_to_use_card": "How to use this card", - "hww_exit_desc": "This will ed the ongoing pairing process with your hardware device", + "hww_exit_desc": "This will end the ongoing pairing process with your hardware device", "i_understand": "I understand", "icon_style": "Icon style", "id": "ID: ", - "if_you_dont_see_your_device": "If you don't see your device above, please be sure your Ledger is awake and unlocked!", + "if_you_dont_see_your_device": "If you don't see your device above, please be sure your device is awake and unlocked!", "ignor": "Ignore", "import": "Import", "importNFTs": "Import NFTs", @@ -926,6 +926,9 @@ "restore_wallet": "Restore Wallet", "restore_wallet_name": "Wallet name", "restore_wallet_restore_description": "Wallet restore description", + "resync_device": "Resync device", + "resync_device_desc": "Balance updating requires occasional resyncing Cake Wallet with the device.", + "resync_device_cancel_warning_desc": "This will end the ongoing sync process with your hardware device", "return_address_desc": "In the rare case of a failed swap, our partners can automatically refund your payment to the provided refund address.", "return_address_desc_external": "Since you chose Send From External, please set a refund address manually below.", "robinhood_option_description": "Buy and transfer instantly using your debit card, bank account, or Robinhood balance. USA only.", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 91c41c6f2..4f3590fb7 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -529,7 +529,6 @@ "i_understand": "Entiendo", "icon_style": "Estilo de icono", "id": "ID: ", - "if_you_dont_see_your_device": "Si no ves tu dispositivo arriba, asegúrate de que tu Ledger esté encendido y desbloqueado.", "ignor": "Ignorar", "import": "Importar", "importNFTs": "Importar NFTs", @@ -1454,4 +1453,4 @@ "wallet_balance": "Saldo de la cartera", "wc_desc": "Conéctate fácilmente a dApps", "yes_exit": "Sí. Salir" -} \ No newline at end of file +} diff --git a/res/values/strings_fa.arb b/res/values/strings_fa.arb index 40b83e118..6a15e0c9a 100644 --- a/res/values/strings_fa.arb +++ b/res/values/strings_fa.arb @@ -527,7 +527,6 @@ "i_understand": "متوجه شدم", "icon_style": "سبک آیکون", "id": "شناسه: ", - "if_you_dont_see_your_device": "اگر دستگاه خود را در بالا نمی‌بینید، لطفاً مطمئن شوید که Ledger شما روشن است و قفل آن باز شده است!", "ignor": "نادیده گرفتن", "import": "درون‌ریزی", "importNFTs": "وارد کردن NFTها", @@ -1451,4 +1450,4 @@ "wallet_balance": "موجودی کیف پول", "wc_desc": "به‌راحتی به dAppها متصل شوید", "yes_exit": "بله. خروج" -} \ No newline at end of file +} diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 5327d2029..397529fb1 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -529,7 +529,6 @@ "i_understand": "Je comprends", "icon_style": "Style d'icône", "id": "ID : ", - "if_you_dont_see_your_device": "Si vous ne voyez pas votre appareil ci‑dessus, assurez‑vous que votre Ledger est allumé et déverrouillé !", "ignor": "Ignorer", "import": "Importer", "importNFTs": "Importer des NFTs", @@ -1451,4 +1450,4 @@ "wallet_balance": "Solde du portefeuille", "wc_desc": "Connectez-vous facilement aux dApps", "yes_exit": "Oui. Quitter" -} \ No newline at end of file +} diff --git a/res/values/strings_gn.arb b/res/values/strings_gn.arb index 693fe80b0..7cb149af0 100644 --- a/res/values/strings_gn.arb +++ b/res/values/strings_gn.arb @@ -1285,7 +1285,6 @@ "hide": "Mokañy", "how_to_connect": "Mba'éichapa Oñembojoaju", "hww_exit_desc": "Kóva omboty pe joaju oikóva ne hardware mba'e'oka ndive", - "if_you_dont_see_your_device": "Ndehecháiramo ne mba'e'oka yvate, ehecha porãke ne Ledger hesãi ha ipe'apyre!", "incorrect_seed_option": "Hekope'ỹ. Eha'ã jey", "incorrect_seed_option_back": "Hekope'ỹ. Ehecha porãke ne seed oñeñongatu hekopete ha eha'ã jey.", "input": "Jeikeha (input)", @@ -1459,4 +1458,4 @@ "you_will_receive_estimated_amount": "Rehupytýta (jehaipyre)", "youCanGoBackToYourDapp": "Ikatúma rejevy ne dApp-pe", "your": "Nde" -} \ No newline at end of file +} diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index b4c142360..db0b67879 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -529,7 +529,6 @@ "i_understand": "Na fahimta", "icon_style": "Salon icon", "id": "ID: ", - "if_you_dont_see_your_device": "Idan ba ka ga na'urarka a sama ba, da fatan ka tabbatar Ledger ɗinka yana kunne kuma a buɗe!", "ignor": "Yi watsi", "import": "Shigo da", "importNFTs": "Shigo da NFT", @@ -1454,4 +1453,4 @@ "wallet_balance": "Ma'aunin walat", "wc_desc": "Haɗa da DApps cikin sauƙi", "yes_exit": "Eh. Fita" -} \ No newline at end of file +} diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 6f21d5d86..413a19131 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -529,7 +529,6 @@ "i_understand": "मैं समझता/समझती हूँ", "icon_style": "चिह्न शैली", "id": "ID: ", - "if_you_dont_see_your_device": "यदि आपको ऊपर अपना डिवाइस नहीं दिख रहा है, तो कृपया सुनिश्चित करें कि आपका Ledger चालू है और अनलॉक है!", "ignor": "नज़रअंदाज़ करें", "import": "इम्पोर्ट", "importNFTs": "NFTs आयात करें", @@ -1453,4 +1452,4 @@ "wallet_balance": "वॉलेट बैलेंस", "wc_desc": "DApps से आसानी से कनेक्ट करें", "yes_exit": "हाँ। बाहर निकलें" -} \ No newline at end of file +} diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index eb66c8e61..11a9ffe88 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -529,7 +529,6 @@ "i_understand": "Razumijem", "icon_style": "Stil ikone", "id": "ID: ", - "if_you_dont_see_your_device": "Ako gore ne vidite svoj uređaj, provjerite je li vaš Ledger uključen i otključan!", "ignor": "Zanemari", "import": "Uvoz", "importNFTs": "Uvezi NFT-ove", @@ -1451,4 +1450,4 @@ "wallet_balance": "Stanje novčanika", "wc_desc": "Jednostavno se povežite s DApp-ovima", "yes_exit": "Da. Izađi" -} \ No newline at end of file +} diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index c81c4e463..0d0c47ef5 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -529,7 +529,6 @@ "i_understand": "Հասկացա", "icon_style": "Սրբապատկերների ոճը", "id": "ID: ", - "if_you_dont_see_your_device": "Եթե վերևում չեք տեսնում ձեր սարքը, համոզվեք, որ ձեր Ledger-ը միացված է և ապակողպված է։", "ignor": "Անտեսել", "import": "Ներմուծում", "importNFTs": "Ներմուծել NFT-ներ", @@ -1451,4 +1450,4 @@ "wc_action_approve": "Հաստատել", "wc_desc": "Հեշտությամբ միացեք DApps-երին", "yes_exit": "Այո։ Դուրս գալ" -} \ No newline at end of file +} diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 877fac35f..ae2e5ca6b 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -529,7 +529,6 @@ "i_understand": "Saya mengerti", "icon_style": "Gaya ikon", "id": "ID: ", - "if_you_dont_see_your_device": "Jika Anda tidak melihat perangkat Anda di atas, pastikan Ledger Anda menyala dan tidak terkunci!", "ignor": "Abaikan", "import": "Impor", "importNFTs": "Impor NFT", @@ -1454,4 +1453,4 @@ "wc_action_approve": "Setujui", "wc_desc": "Hubungkan dengan mudah ke DApps", "yes_exit": "Ya. Keluar" -} \ No newline at end of file +} diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 2bd228544..7997f91d2 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -529,7 +529,6 @@ "i_understand": "Ho capito", "icon_style": "Stile dell'icona", "id": "ID: ", - "if_you_dont_see_your_device": "Se non vedi il tuo dispositivo qui sopra, assicurati che il tuo Ledger sia acceso e sbloccato!", "ignor": "Ignora", "import": "Importa", "importNFTs": "Importa NFT", @@ -1454,4 +1453,4 @@ "wc_action_approve": "Approva", "wc_desc": "Connettiti facilmente alle dApp", "yes_exit": "Sì. Esci" -} \ No newline at end of file +} diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 87f1193ca..f8ab953de 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -530,7 +530,6 @@ "i_understand": "理解しました", "icon_style": "アイコンのスタイル", "id": "ID: ", - "if_you_dont_see_your_device": "上記にデバイスが表示されない場合は、Ledgerが起動していてロック解除されていることを確認してください!", "ignor": "無視", "import": "インポート", "importNFTs": "NFTをインポート", @@ -1452,4 +1451,4 @@ "wc_action_approve": "承認", "wc_desc": "dApp に簡単に接続", "yes_exit": "はい。終了する" -} \ No newline at end of file +} diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index b756745bb..299814e60 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -529,7 +529,6 @@ "i_understand": "이해했습니다", "icon_style": "아이콘 스타일", "id": "ID: ", - "if_you_dont_see_your_device": "위에서 기기가 보이지 않으면 Ledger가 켜져 있고 잠금 해제되어 있는지 확인하세요!", "ignor": "무시", "import": "가져오기", "importNFTs": "NFT 가져오기", @@ -1451,4 +1450,4 @@ "wc_action_approve": "승인", "wc_desc": "DApp에 손쉽게 연결", "yes_exit": "예. 종료" -} \ No newline at end of file +} diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 51f7c231f..d58b1add9 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -529,7 +529,6 @@ "i_understand": "နားလည်ပါတယ်", "icon_style": "အိုင်ကွန်စတိုင်", "id": "ID: ", - "if_you_dont_see_your_device": "အထက်မှာ သင့်စက်ကို မတွေ့ပါက သင့် Ledger ကို ဖွင့်ထားပြီး လော့ခ်ဖွင့်ထားကြောင်း သေချာပါစေ။", "ignor": "လျစ်လျူရှုပါ", "import": "တင်သွင်း", "importNFTs": "NFT များကို တင်သွင်းပါ", @@ -1451,4 +1450,4 @@ "wc_action_approve": "အတည်ပြု", "wc_desc": "dApp များသို့ လွယ်ကူစွာ ချိတ်ဆက်ပါ", "yes_exit": "ဟုတ်ကဲ့။ ထွက်ပါ" -} \ No newline at end of file +} diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 9285015d8..d538ef215 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -527,7 +527,6 @@ "i_understand": "Ik begrijp het", "icon_style": "Pictogramstijl", "id": "ID: ", - "if_you_dont_see_your_device": "Als je je apparaat hierboven niet ziet, zorg er dan voor dat je Ledger ontgrendeld is!", "ignor": "Negeren", "import": "Importeren", "importNFTs": "NFT's importeren", @@ -1452,4 +1451,4 @@ "wc_action_approve": "Goedkeuren", "wc_desc": "Maak eenvoudig verbinding met dApps", "yes_exit": "Ja. Afsluiten" -} \ No newline at end of file +} diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 16045cd4b..530163022 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -528,7 +528,6 @@ "i_understand": "Rozumiem", "icon_style": "Styl ikony", "id": "ID: ", - "if_you_dont_see_your_device": "Jeśli nie widzisz swojego urządzenia powyżej, upewnij się, że Twój Ledger jest aktywny i odblokowany!", "ignor": "Ignoruj", "import": "Importuj", "importNFTs": "Importuj NFT", @@ -1451,4 +1450,4 @@ "wc_action_approve": "Zatwierdź", "wc_desc": "Łatwo łącz się z aplikacjami dApp", "yes_exit": "Tak. Wyjdź" -} \ No newline at end of file +} diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 5ef972b66..e357dc89d 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -529,7 +529,6 @@ "i_understand": "Eu entendo", "icon_style": "Estilo do ícone", "id": "ID: ", - "if_you_dont_see_your_device": "Se você não vir seu dispositivo acima, verifique se o seu Ledger está ligado e desbloqueado!", "ignor": "Ignorar", "import": "Importar", "importNFTs": "Importar NFTs", @@ -1454,4 +1453,4 @@ "wc_action_approve": "Aprovar", "wc_desc": "Ligue-se facilmente a DApps", "yes_exit": "Sim. Sair" -} \ No newline at end of file +} diff --git a/res/values/strings_pt_BR.arb b/res/values/strings_pt_BR.arb index ea1a3a4ab..215136300 100644 --- a/res/values/strings_pt_BR.arb +++ b/res/values/strings_pt_BR.arb @@ -524,7 +524,6 @@ "i_understand": "Eu entendo", "icon_style": "Estilo do ícone", "id": "ID: ", - "if_you_dont_see_your_device": "Se você não vir seu dispositivo acima, certifique-se de que seu Ledger esteja ligado e desbloqueado!", "ignor": "Ignorar", "import": "Importar", "importNFTs": "Importar NFTs", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index aaac422dd..9ce39e077 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -529,7 +529,6 @@ "i_understand": "Я понимаю", "icon_style": "Стиль иконок", "id": "ID: ", - "if_you_dont_see_your_device": "Если вы не видите свое устройство выше, пожалуйста, убедитесь, что ваш Ledger включен и разблокирован!", "ignor": "Игнорировать", "import": "Импорт", "importNFTs": "Импортировать NFT", @@ -1452,4 +1451,4 @@ "wc_action_approve": "Одобрить", "wc_desc": "Легко подключайтесь к dApps", "yes_exit": "Да. Выйти" -} \ No newline at end of file +} diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 669153910..9c575933f 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -529,7 +529,6 @@ "i_understand": "ฉันเข้าใจ", "icon_style": "สไตล์ไอคอน", "id": "ID: ", - "if_you_dont_see_your_device": "หากคุณไม่เห็นอุปกรณ์ของคุณด้านบน โปรดตรวจสอบให้แน่ใจว่า Ledger ของคุณเปิดอยู่และปลดล็อกแล้ว!", "ignor": "เพิกเฉย", "import": "นำเข้า", "importNFTs": "นำเข้า NFT", @@ -1451,4 +1450,4 @@ "wc_action_approve": "อนุมัติ", "wc_desc": "เชื่อมต่อกับ DApps ได้อย่างง่ายดาย", "yes_exit": "ใช่ ออก" -} \ No newline at end of file +} diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 8e23566a4..91b49c2e8 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -529,7 +529,6 @@ "i_understand": "Naiintindihan ko", "icon_style": "Estilo ng icon", "id": "ID: ", - "if_you_dont_see_your_device": "Kung hindi mo nakikita ang iyong device sa itaas, pakitiyak na gising at naka-unlock ang iyong Ledger!", "ignor": "Huwag pansinin", "import": "I-import", "importNFTs": "Mag-import ng mga NFT", @@ -1451,4 +1450,4 @@ "wc_action_approve": "Aprubahan", "wc_desc": "Madaling kumonekta sa mga DApp", "yes_exit": "Oo. Lumabas" -} \ No newline at end of file +} diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index beb1e6f02..765fa2f15 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -529,7 +529,6 @@ "i_understand": "Anladım", "icon_style": "Simge stili", "id": "ID: ", - "if_you_dont_see_your_device": "Cihazınızı yukarıda görmüyorsanız, lütfen Ledger'ınızın açık, uyanık ve kilidinin açılmış olduğundan emin olun!", "ignor": "Yoksay", "import": "İçe aktar", "importNFTs": "NFT'leri İçe Aktar", @@ -1451,4 +1450,4 @@ "wc_action_approve": "Onayla", "wc_desc": "DApp'lere kolayca bağlanın", "yes_exit": "Evet. Çık" -} \ No newline at end of file +} diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 53fee6efb..f9421be02 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -529,7 +529,6 @@ "i_understand": "Я розумію", "icon_style": "Стиль значка", "id": "ID: ", - "if_you_dont_see_your_device": "Якщо ви не бачите свій пристрій вище, будь ласка, переконайтеся, що ваш Ledger увімкнений і розблокований!", "ignor": "Ігнорувати", "import": "Імпорт", "importNFTs": "Імпорт NFT", @@ -1452,4 +1451,4 @@ "wc_action_approve": "Схвалити", "wc_desc": "Легко підключайтеся до dApp", "yes_exit": "Так. Вийти" -} \ No newline at end of file +} diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index b28375292..89c767ea8 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -529,7 +529,6 @@ "i_understand": "میں سمجھ گیا/گئی ہوں", "icon_style": "آئیکن اسٹائل", "id": "ID: ", - "if_you_dont_see_your_device": "اگر آپ کو اوپر اپنا ڈیوائس نظر نہیں آ رہا، تو براہِ کرم یقینی بنائیں کہ آپ کا Ledger آن ہے اور اَن لاک ہے!", "ignor": "نظر انداز کریں", "import": "درآمد کریں", "importNFTs": "NFTs درآمد کریں", @@ -1453,4 +1452,4 @@ "wc_action_approve": "منظور کریں", "wc_desc": "DApps سے آسانی سے کنیکٹ کریں", "yes_exit": "ہاں۔ باہر جائیں" -} \ No newline at end of file +} diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index c5eb9647b..6963c9a44 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -528,7 +528,6 @@ "i_understand": "Tôi hiểu", "icon_style": "Kiểu biểu tượng", "id": "ID: ", - "if_you_dont_see_your_device": "Nếu bạn không thấy thiết bị của mình ở trên, hãy đảm bảo rằng Ledger của bạn đang bật và đã được mở khóa!", "ignor": "Bỏ qua", "import": "Nhập", "importNFTs": "Nhập NFT", @@ -1452,4 +1451,4 @@ "wc_action_approve": "Phê duyệt", "wc_desc": "Dễ dàng kết nối với các dApp", "yes_exit": "Có. Thoát" -} \ No newline at end of file +} diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 089e19207..8a073f320 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -530,7 +530,6 @@ "i_understand": "Mo ye mi", "icon_style": "Aami ara", "id": "ID: ", - "if_you_dont_see_your_device": "Ti o ko ba ri ẹrọ rẹ loke, jọwọ rii daju pe Ledger rẹ wa ni titan ati pe o ti ṣí i silẹ!", "ignor": "Foju kọ", "import": "Gbe wọle", "importNFTs": "Gbe NFTs wọle", @@ -1452,4 +1451,4 @@ "wc_action_approve": "Fọwọ́sí", "wc_desc": "So pọ̀ mọ́ àwọn DApp ní rọrùn", "yes_exit": "Bẹ́ẹ̀ni. Jáde" -} \ No newline at end of file +} diff --git a/test/new-ui/widgets/new_future_primary_button_test.dart b/test/new-ui/widgets/new_future_primary_button_test.dart new file mode 100644 index 000000000..858dc5fda --- /dev/null +++ b/test/new-ui/widgets/new_future_primary_button_test.dart @@ -0,0 +1,265 @@ +import "dart:async"; + +import "package:cake_wallet/new-ui/widgets/new_future_primary_button.dart"; +import "package:cake_wallet/new-ui/widgets/new_primary_button.dart"; +import "package:flutter/material.dart"; +import "package:flutter_svg/flutter_svg.dart"; +import "package:flutter_test/flutter_test.dart"; + +const _svg = ''; + +void main() { + Widget wrap(Widget child) => MaterialApp(home: Scaffold(body: child)); + + NewPrimaryButton inner(WidgetTester tester) => + tester.widget(find.byType(NewPrimaryButton)); + + Future? fire(WidgetTester tester) { + final result = (inner(tester).onPressed as dynamic)(); + return result is Future ? result : null; + } + + Widget build({ + required Future Function() onPressed, + bool disabled = false, + SvgPicture? image, + Color color = Colors.blue, + Color textColor = Colors.white, + Color borderColor = Colors.transparent, + String text = "Send", + }) => + wrap( + NewFuturePrimaryButton( + onPressed: onPressed, + text: text, + color: color, + textColor: textColor, + borderColor: borderColor, + disabled: disabled, + image: image, + ), + ); + + group("NewFuturePrimaryButton", () { + group("prop forwarding", () { + testWidgets("passes every prop through to NewPrimaryButton", (tester) async { + final image = SvgPicture.string(_svg); + + await tester.pumpWidget( + build( + onPressed: () async {}, + text: "Confirm", + color: Colors.green, + textColor: Colors.black, + borderColor: Colors.red, + disabled: true, + image: image, + ), + ); + + final button = inner(tester); + expect(button.text, "Confirm"); + expect(button.color, Colors.green); + expect(button.textColor, Colors.black); + expect(button.borderColor, Colors.red); + expect(button.disabled, isTrue); + expect(button.image, same(image)); + }); + + testWidgets("defaults: transparent border, not disabled, no image", (tester) async { + await tester.pumpWidget( + wrap( + NewFuturePrimaryButton( + onPressed: () async {}, + text: "Send", + color: Colors.blue, + textColor: Colors.white, + ), + ), + ); + + final button = inner(tester); + expect(button.borderColor, Colors.transparent); + expect(button.disabled, isFalse); + expect(button.image, isNull); + }); + + testWidgets("starts out not loading", (tester) async { + await tester.pumpWidget(build(onPressed: () async {})); + + expect(inner(tester).isLoading, isFalse); + }); + }); + + group("loading lifecycle", () { + testWidgets("flips isLoading true while pending, false once resolved", (tester) async { + final completer = Completer(); + await tester.pumpWidget(build(onPressed: () => completer.future)); + + final pressed = fire(tester); + await tester.pump(); + expect( + inner(tester).isLoading, + isTrue, + reason: "should be loading while the future is in flight", + ); + + completer.complete(); + await pressed; + await tester.pump(); + expect(inner(tester).isLoading, isFalse); + }); + + testWidgets("synchronous-ish callback still settles back to not loading", (tester) async { + var calls = 0; + await tester.pumpWidget(build(onPressed: () async => calls++)); + + await fire(tester); + await tester.pump(); + + expect(calls, 1); + expect(inner(tester).isLoading, isFalse); + }); + + testWidgets("invokes the callback exactly once per press", (tester) async { + var calls = 0; + await tester.pumpWidget(build(onPressed: () async => calls++)); + + await fire(tester); + await tester.pump(); + await fire(tester); + await tester.pump(); + + expect(calls, 2); + }); + }); + + testWidgets("ignores presses while a previous future is pending", (tester) async { + final completer = Completer(); + var calls = 0; + await tester.pumpWidget( + build( + onPressed: () { + calls++; + return completer.future; + }, + ), + ); + + final pressed = fire(tester); + await tester.pump(); + + unawaited(fire(tester)); + unawaited(fire(tester)); + unawaited(fire(tester)); + await tester.pump(); + + expect(calls, 1, reason: "extra presses must be swallowed"); + + completer.complete(); + await pressed; + await tester.pump(); + + await fire(tester); + await tester.pump(); + expect(calls, 2); + }); + + group("handle errors", () { + testWidgets("clears the loading flag when the callback throws", (tester) async { + await tester.pumpWidget( + build(onPressed: () async => throw StateError("boom")), + ); + + await expectLater(fire(tester), throwsA(isA())); + await tester.pump(); + + expect(inner(tester).isLoading, isFalse, reason: "the finally block must reset the flag"); + }); + + testWidgets("rethrows instead of swallowing the failure", (tester) async { + await tester.pumpWidget( + build(onPressed: () async => throw StateError("boom")), + ); + + await expectLater(fire(tester), throwsA(isA())); + }); + + testWidgets("stays pressable after the callback throws", (tester) async { + var calls = 0; + await tester.pumpWidget( + build( + onPressed: () { + calls++; + throw StateError("boom"); + }, + ), + ); + + await expectLater(fire(tester), throwsA(isA())); + await tester.pump(); + await expectLater(fire(tester), throwsA(isA())); + await tester.pump(); + + expect(calls, 2, reason: "the re-entrancy guard must not latch on failure"); + expect(inner(tester).isLoading, isFalse); + }); + }); + + group("disposal mid-flight", () { + testWidgets("does not setState after being disposed", (tester) async { + final completer = Completer(); + await tester.pumpWidget(build(onPressed: () => completer.future)); + + final pressed = fire(tester); + await tester.pump(); + + await tester.pumpWidget(wrap(const SizedBox.shrink())); + expect(find.byType(NewPrimaryButton), findsNothing); + + completer.complete(); + await pressed; + await tester.pump(); + + expect( + tester.takeException(), + isNull, + reason: "the mounted check must guard the second setState", + ); + }); + + testWidgets("still propagates a throw when disposed", (tester) async { + final completer = Completer(); + await tester.pumpWidget(build(onPressed: () => completer.future)); + + final pressed = fire(tester); + await tester.pump(); + await tester.pumpWidget(wrap(const SizedBox.shrink())); + + completer.completeError(StateError("boom")); + + await expectLater(pressed, throwsA(isA())); + expect( + tester.takeException(), + isNull, + reason: "no setState-after-dispose FlutterError on the error path", + ); + }); + }); + + testWidgets("disabled is forwarded but not enforced by this wrapper", (tester) async { + // Press-blocking lives in NewPrimaryButton; this widget only relays the + // flag. If that ever moves up here, this expectation should change. + var calls = 0; + await tester.pumpWidget( + build(onPressed: () async => calls++, disabled: true), + ); + + expect(inner(tester).disabled, isTrue); + + await fire(tester); + await tester.pump(); + expect(calls, 1); + }); + }); +} diff --git a/tool/configure.dart b/tool/configure.dart index 66c302799..022eaa2cd 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -442,6 +442,8 @@ abstract class Monero { Map exportOutputsUR(Object wallet); bool needExportOutputs(Object wallet, Money amount); + + bool hasUnknownKeyImages(Object wallet); bool importKeyImagesUR(Object wallet, String ur); From 14d2862b397988f3fc255b9c825043f43201260a Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Thu, 6 Aug 2026 14:28:56 +0100 Subject: [PATCH 08/10] Add tbb to solana default tokens (#3461) * fix android CI * deat: add The Bitcoin Bull to solana default tokens list * add verification status for solana tokens --- assets/images/tbb_icon.png | Bin 0 -> 137591 bytes cw_solana/lib/default_spl_tokens.dart | 9 + cw_solana/lib/solana_client.dart | 44 +++ cw_solana/lib/solana_wallet.dart | 3 + lib/entities/default_settings_migration.dart | 40 +++ lib/main.dart | 2 +- lib/solana/cw_solana.dart | 6 + .../screens/dashboard/edit_token_page.dart | 86 ++--- .../dashboard/home_settings_view_model.dart | 8 + res/values/strings_ar.arb | 35 +++ res/values/strings_bg.arb | 35 +++ res/values/strings_cs.arb | 35 +++ res/values/strings_de.arb | 78 ++--- res/values/strings_en.arb | 4 +- res/values/strings_es.arb | 37 ++- res/values/strings_fa.arb | 38 +++ res/values/strings_fr.arb | 35 +++ res/values/strings_gn.arb | 296 ++++++++++++++++++ res/values/strings_ha.arb | 35 +++ res/values/strings_hi.arb | 35 +++ res/values/strings_hr.arb | 35 +++ res/values/strings_hy.arb | 38 +++ res/values/strings_id.arb | 36 +++ res/values/strings_it.arb | 37 +++ res/values/strings_ja.arb | 37 +++ res/values/strings_ko.arb | 36 +++ res/values/strings_my.arb | 37 +++ res/values/strings_nl.arb | 40 +++ res/values/strings_pl.arb | 38 +++ res/values/strings_pt.arb | 37 +++ res/values/strings_pt_BR.arb | 1 + res/values/strings_ru.arb | 37 +++ res/values/strings_th.arb | 37 +++ res/values/strings_tl.arb | 37 +++ res/values/strings_tr.arb | 37 +++ res/values/strings_uk.arb | 37 +++ res/values/strings_ur.arb | 37 +++ res/values/strings_vi.arb | 41 +++ res/values/strings_yo.arb | 37 +++ res/values/strings_zh.arb | 75 ++--- tool/configure.dart | 1 + 41 files changed, 1494 insertions(+), 115 deletions(-) create mode 100644 assets/images/tbb_icon.png diff --git a/assets/images/tbb_icon.png b/assets/images/tbb_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..744b9e3e13fb94217554974ca88bc2f6b084d821 GIT binary patch literal 137591 zcmZ^K1ymi)vhD^p?oNQoGg!#tqp^Lv8|yAgPV=rKLP+gH=a+@#>B~h$j!$3rz4LW zKgqu&cs}WWsu@X${w3mM#ZRIkr${7X>tI5}!NA18L?Qr3L`1~rU~I~xEGqtA>Yr!) zB<4;|c07!XuCA^OuB;5U4rYwZ+}zxZOe~BnEcBle^p5U7oebRQe>#%>yOIBHN7Tg8 z$ic$S$-?$0(Le1P7}`2J@sp7JW9WbX{_UrUo5lZF`sw&zVSNV3_z#DXnSqJ%|E1<+ zVfz13`-k&ywSUF+Z*zSAG{&Q7;bvm3DQaP3^3(CtH34R378bsL+4;X%|KsU@sA~NG zRsVzaf2xYuTH89P*clj^2r&Pbwg0I459xnA=TUI5F!}7%f4c4;@&BvtzvTHC|LNEN z=;wbA;=gJ?M^ONdkMVzB5dv`jA6l{iz&C)DsF11~*jc-))B0f2;nR($+YkT@9M~nx z9EL%zjD|_2U7Kgpnz`<9HKivv3(~70P9yf&~7%7T-;Nk{kYMB`Ey^d-Hr>NA!Ri8 zBRQH3rE^FXi|BhIn@&M}Q)UI^Tq1+@IN!m6es`qJu)26b9`^ z>!+Lj%*@Q=v@~-v|0Tm37~2w6e>Dc&D1YbxLVLCz^gy&o@`G@7ff^!vz|>ZNMETWC z9IP+vgdJDHu&lg7HoxZs=z2H6EJQwA!24pYd3bnud3m{{#6kun3=N;x`znDYV)7y) zj6L)Ei#RY#7m?+3TMXO~nZ?6Tc!KiVjaZy*D#;IQ&YmX9i@al<ZZoVMm1V>`qMLOYfDRO^Ww5Wq}dW<8iJV7dPx|W9l|qX zxDZ%WNCFKOus|^Cwmc?E$m?7T1eAz=Q6dEKP}y#PZc%Ko;HK_qkT7%lxV)T#i79I@ zX|EX+v_dA22lLT1Kj0}aJ9b{hW9BqEjw zto!MQZECDNeXw~Po34z4poCb=FPW|gk5#k{maxrOeR+G8XlLgJ`tfmo9e!H%iZhLt z`i>6254#f4nNS`1YKj*bF8qN&W3($vQ5DmuC2s#7H(x4!RKU;@pe>4eMCR)5mN_1R z;LkRa_Pq#0y#3F>h(OZFf&H+suT?285r9FHcQhHS3E|jNJf*v(*ex#H|nR%J{1;Ibs{7I6gs9`Ni zJYCS4US8gqUY=f=2_GikxmIj87LjIT_j3dQJh<$H^dDzFnr1Y97aVQfKZ`Ew|bIaRyXc? zX(|iw=30)+hbmE$A|l9;Asg?@7k-cW$DueT-{HTBWhlQQufZkt&%Z)uGrWKUX_nB;>K0quDEuQg8)|qy$OB z6CMVDTVwY(I3OH>la`sH`62v>k7R@m2T~}(*aq$?ocvqooxSbc)OH_ zYrq1aowa2X|6G3)6T$8%W>aVeRQs}|?C|Ij=mtCuL+?Xv%fMy^{KBKdP9oa#x<5ea zJm13SR~Z&nn7pA~s90?=IlZ~aQk4rgsMaVwW2=?V+mFL~?g~}toyUS%plXXDfr(n- zsp&yaEQNy$mN$|ND)MJ{VTvdHO@s#AMJETJ2Ib@(DAFA51GbForBiYyA*&_Ap|%CE zaG=4I6!WOGW~TKM&MqhiF5wQ2muz$XXYxZy?J zagjqcx|?!;<1o_p!$mB1LD))+v^iYQU?I~f0^!T{zA&oU!PiYrS64Rv+z-#9|C|!n z{>I$~q#1`Fm>Buz=g+gsDxTBD;L!Fev6Ah*6wG(f($`w%S+>S*6a7vgkz@?SvKA3b zLTC=}p@iKVW2T&h@6J#yfcPPe3NVBW_|cU$^M{?#7Xg}AiAxG%7afw6tQ`Z$yeOpj zW8aP}o3VP-W2?&#ThGJ(Tp3@&{6sG{$zgfhvRq) zyA?0bispeux?iwD#q@8s_0mWH8;kQn1}YbkxmH(qQ5dc=0=u!WP^41=GB$7t4gmvN zO51^{)dd1ko(Sk(dm)g~5^U=$ssr^C#aaUa+`>6#AkNX}UEgdp_<*QhetC2h zYJYP8_Z2>HNmlrjL`$$D9O`s{Igg56ITv5HNL!S9O{^$X{Kr=t08z4S&-&H@^Og|J zf;NV)f@F;r%Cl%tB9)gvzOZyrIefvDWHOs3wd7EnN(+oSof{L^H5!m86c`UkzT)mf z2}J|X2$Ts8iQ>mUsNap^+;ls;9(?@DHS`o>cwO--H5$Y?HK{TN;gxr5$PnfxgLV9x zY%KlF*x$R7G3mi8Ri8#2X7cqYhp3++cBbb{ND00xg?z6zR4UQE;C>vbYp>B}wbA?K z0h2a)&I@pBQiX7Q5Y5Tp9|=2+jo1 z4@8J}H_YoQyN@8i8v6#MSSi^?6mgqGBGLf*7e+3E!EV9Ai7>$cHAPD>a#2%`{OtWP z$qi#D8N}65Bld5Cb}8lgK6>C|1mE2@YmA!nzB*_?a+#4}Z5QM!{{S|}(FKdKp>!4+ zD>S?9Ak0@&yhEYt*GEBc!O#+Mz>`*{*|;Q zW)z?#luUF6$q>vn1as!@*UvEKwS*3>((Jnw@gN*fAn=gq?`5r+7n{<9!mIc0WytuX zJcBhbX`o*1XaT*ufylYmRXA==rZseE!BM%&Z>y)svXB#_uH3ThAG?qbOG6)$e2$wy z=4q&vb#!fC&$mkHM4F^UEE$SvV$mEo9{BC-z)!S!>In+5y$^f~1CQ*M34nwP=8t*z zgUC-w9AFolMZ_P$q>P7Ca0i6y8kFKv0&oE?{c))JWx~6pv3;c=)$jFD{on>GZ!kqN zUIbs4NEHO1FkCfdk}NF59x?*^2xJ#~9rOG_pJAp+ryTP!dKqGy3LpqENgo55lXl>x z5olQTnu%`33MUmvsjl*_@Kc4-WW*pbk!X%NAY=he6@MFr>1#DRT*lMzTsQ2-AI{~X zqUJb}T(ru*U_OfBB(CLxyJ=;~fqvAH7B47F#pjd^!%(X zQ?!^&0+{+r(jAWhzA!l$%u3ZVW?qcnS#nXUuw`OXPnMQ&9OtqHue!3@U*P(|rAY^P zI!nRxI*Vg~R|5ADJ&rg5JXADPWTDqH2a+0GTzXoHMI{mFaa%cpf|HJYT`zr4sqdmA(-7f7|t_2y1wGTzr zXPBT5prU|+iI~zDO!ago4=zO$PE5naiIeizSLWod^aj<$QSITO5i?-2_E_S@8=LF* zh2eY?2Kp9gk}3{`H>$zz+(#zWgH&wtNr+&4MKBxyiKr4sbB>BkI?9j2U9=-F0LkC^ zG(y}s#DHW%*?vb=nNOOi@nHOaUSaCi2aPBMoiyVq@ zI2I`8u6RC)o*p47bh%g^H`bmfTsk^t99}*3eyD4Iesx9I7%vGxHfp7lZj;doqLN~{kWv@dmGr11nD1SU0E{n0%q4m6X_6|Mu7Z*WmOZst z3`WfiICWcK!dHI+tU|B2ZQ9Xlh;P(@&2V;H2v^Wm?#pH8N6DY89Ui2+9C9pNDJXX( zGvU$_h&J+eY?ctEws0LTF~)6Wx_Eqy`^_ZO_?m%%V7$uBrwi9kE6qce6Nx10m)afV zxr}T_qZgCJ51uS+b`VoU3H zDZbtfn6Wj6ozT-E-tvwZvw+<7{2nMWbI#(4jc4r>oIhx%86sGOC*-sRRJ zUywP>^)9NPE)2|WtOogs~UaF5x$4vqO(F(*p4l0zJM>#h={u!>z z;8-BU{*~Y5j`9N(gDiM+B5Lc(pvq4qnuB6u|x$_jlS+c|MkFl6!=8RTP6$0=1_kCG=W|`rYIP- zV2F6)%^_1yw8*K(SS1NQpTl1E#m90lvLGKnYlSJ`rjwAg0A?sg8c{!5rCcK1+5k%d zALxUQ{h3YRE zmOu9~4~2*@kww-hC1ni^7(}Wskuu$u8b&-RAxkU>xbF#I=mzhjRq7FmQ3=-%C4mJ4 zji5?y=hjEFp)LQ~+H&puX#bPtQ`+Sv!EtmTg#zqPJK9`|yR#)hf5?FoQo_nLkI6(w zaPTmU!C35}%i@B04W^sxDw4yy@V@kHvhF}rIx}RoCuZ$Z{awX62N6JOp+g4+IL7t~ zN8?u_xO!49yGf&!d_gJ1g{xtRlQu~6GP3|!U%Tu2bLCz2lMv5<6#()Ap}SW4FY;le zLxaP$C@_%$2U(#=;&(I?<9qKM|AvgHNa5oi_!5NEJJ;Bcr|w7IcQ2MQUS zA-6f-7kA3YpU=Ql(rugCzib5_uC9yT*`U4<0Z?~zVdjIMNDWR*|1rlGsNu*8 zfISk0GEW)vmyH%hTI5!W6a4WWya3z~e*$XQZmI@|D6|}o*r6ZLXzz!?kpfL zgbN0EpCYY`>l^6lq2Oy78CRpxBS78gIJlF>US`{RzVOhvVB|eW@uz4^psdK;PVvYV z%F~2FJ@Od+$oQ~YuMZ{wg9%-AmW~(@TJjDKOA$3{YRFy`$zku&q=~#g?4*d zcdVC~(X=%~tL!+`k_t=(&!$(dky_rxeYCK$D++Q0ePUTcH@%8^l9mFSC|y{C;s?2m=jWOuf6 z|67DxqWokl%|`v#MP0TDe4^0UK)Z%N?9nJ==iU0H_vO60?tXuYx~_YwZJaSe(t+~1 zPwbX9cMoj%w+05BwklH-{IM0O4y$@;xtl zfebpJi$taT2-1_q-wrnH(vQ2xJ24bin5aNQRWY0#?$7`%OX=>0IDnZ7y8qk6wHQEI z7_ird;%^s*fU7?~3}&a#Rk@Wq@av`O!+NVPHzDMafY&FluCA=4q)>z5I&EE!b8QH2 z{|>;owdATiRHHUx+fNN|OImU}8`jkQnqFO;h@HHJTbaaLC9~$b=}q`_6@rU*3g7IN zu@X9f^g!_b(A4?Xm!P2hlxlr&&*^HrR_!ww{Z*IcOqIfA|8#YJ_lZJGBnK=nzzo$7 z8Qd2Z3bM?eYUG7%&j3tZoU!uzzA`brm{fG9M3DoLbi1!A3DvhBKzn7_NLk2R#8OId z1=6l-wISfHOzj~#6@pSR{n9o~&~BVzoUxaZM*(zSL=}cuFbXR0+W&fAbThlz#x6`otgW|Y&Cj*K}#JZmC8!50Jijp>zV%3n8>UIg89LEYU&t_-YhrRohbxfSdv zm+xx0`3|RE=0shCeu}fiX8vFpg&KW3Ky*ktsjQ7edn$vRM4%V<^sXl{0l=bU=SOr7 zwydXvhL!s3r1WpHDK)(};Brz1y1sk&(;1aB>eghmeh@ z?btscT1$~V>D1WN_OkF;Utf1+VwJWTJ1Wwx4*27!&rQOw*Z0R?UFg$MQBiDs1lDHi zMJ2i0w0ch?Y3x?!v}?tR%m9_yV#L-7Sg(F{>Ap9=u9H<01-BtPqN{G0U?@KzyC2Z^ z+nwlkhA-RzsLW;sS7{zL23a_s+%G2$g=ra-0sj@`exhlyh6+PSgzG>Y~fm@QDj-waZ-A|s4K{3_w4o| zg}z@P^9A}{e1l}4PS&(yFlDsoB-Gj|*IEAMuaB4JkSJ8YKJcfS zz|OblP5%2m6+}eDHY!0@*3nCHJHDZ_JLC>fVTE=h6O^z;%3LW0*=qhWvF0)v4NL%= zA?JmZk*)pc877EpoH$X|)7oCob38~;r=)@0|$WWiV0OwcIZ@yZ}?mGXL z%MlEsgmJB81Ing}?xVs~0iemS-%m)t88E`b22A|9+5U7S0;2CgBJW|hNI+-+g)zc} zlq3oiDe)(;_ML)8LrMl$33%;HG+FoU6JKyYc)}i_G-V0eIXbeV!RpvuZ<39Q;d{A5 zM~oWR;U68vH^c~+(MmaMF~Jsub^uM~(rw0(bZu~RZ;H@3Q$MUePO5)X{1b7q4S$qZ z(+R5_ALomd&T0L6=lyt3cR9T0;9`@)f28X1@!qcYvf7DzL#pQUp;TF;(LzT7 zsLu=lCP3Yq094;9s+j9;Zfa@V4rL`Ye{x`?&g1@8E=D-T4r9k%Pv;BghYJsHW@K=3 zkqYPe(rXy<`peB|ReQ_hRYU8=-?w(co!dS`>Pak3k~FuA=EL{w&etl5==*0?pyZdT z+l-};1tHd+QHPGRz6Q5;{#`z-p8|I8TJn7)O`9I0?T;N*96EYVDYf~`o-bQL*m|!6 zOwBx)*dYSK1Z$s8gv-t`9+YbtL!Z$>%}VtG-SeQ27d>H zP|PCd7eq{~$Wm1(ls8`N+`(fzzNE5YtCstBWr@2}N+$FTVVGEgt#U$8iCBf@@^^MP zlvl-YRvfo|u99$j{Y+G24we89B^48G&US=5tmBULf=QPy9NAW8$uj@>Q)^|T(cvk) zvht$wp-_%*B3rtDU7%w0uSwQN4J+@%!K#@RH)n8!UMNmroe^RPd8nf>*C_;D)uc4%ClL4&P*s?xOX zv`#7bzJ2(KO(k(Y+?Q|IU7Ed9X=YdZOmr>Bb-tcyu!ip<_ee&bxU)aLPL|$*1Vv)bX;Q;I*^MhJ{OBF_qR?rq1p?Pgo7D zhyWf_Duj9S#&=g(EuQOTMp`e9jKwd#Bub*E?B@kD`K zOganShEa`!>xM1GA(%AE(ep&&gC2RO+iH4G=(Qb@Uey*4ZW3r$F`FzK!}mOd{0r1; z%(ASpX?NdfQ@=>s-o9)d-PmaG7Ay$5NjZkJ5JI3n2`<4*601%Nx>G7JpJ?&2BI)2J z@^_&Ve;P@_;YTR5Z#D(y5Xk{4aRgxiB9R{PIXO>1Grw#0_Z!}^3`P_F+VX?`m=>6M zVz&jWo%KyU?zRnlsZZqLu&~l+{ZdEj7%6$eAGyGQV4vBjL1S$C$BdG40x^?-&)YiZ z1GIIVP&a!>vhT%$6;`K(uqr@y_${*c6@->I_G&E2p_Q%z3!=kAEzykkO){7YVz>%b zUJ~Wf5CfKL^nTh;aW6^J9XLqi>o)g>qiGE^uxHUT+vRPla3BqRu|g(Hw|jceMwCsX21+sbtKj5gnCD)U)SN+AWRGb z97-HQEacw2z&1&$AdIc+>alM4-l)Eo=V12J1%anNbh=!X5@P|*(Z2Rpv;FbQ=BDNn z1E;;SQ$~T+ItORRQ#825TDs&BtA+CIZN{tw9_Q!!cqYuUq zf#w41J*7Y+#*xZkhMEP-AK#ypl8}F01$5qacqW7ul&RBttRSi55Wd~#3qB1ifR>Yj zTUx9dZM1*&KkM<|l}*<$oBo*F!|uEavRSQkm@Hi8fpdRVp#{q^fu_}9idUN@Lj(&} zx@IqQk`Zb^peoGL=p!dib4h!c@as!GVBiG}sU~_w*oDJ>V}Q^PM52fb9oWe~6wmfK zNF{tfl0fDIZEg2TfEXsULbNMuM)tLMP7UAVIklS&f}I3ksh64{8=NyYn3`M1ThcWK(gu+%5wof_I)K#bN`^}ujnMN+MO5<5US6W{*F2e0VVWB1DbU#0 z{F^LF=w~ZL>NAMbA?Y|MW_y*t>ZiH}{~6m+G2|L`=py1D5Ys9jS-$;*OVtht7>9Sz z==6Y~B8if@25U_b5&oA$4n&xwr(6RM@`rfN%fIf{US5VrcQTWL?Oyk3!O4xnVT*DV zWXnA*+XHyqM?7A8p;mc~Y8U+sP_YyR$jsIL5yp3YpE(cxlFb-V*!&^BvNLM_Y(yBP zw&tKaNQxY3(K#M8V;k+w6~>vm+Qp(uCoT z%Pdc>_MFt2Ec>KAGR+Pvuu`Kh1w&r+J^r@|8Y7u5#4kepLwgZpw`m6xU|XU^s=oFD z3uCLWV59^+STZzc*<@(wDzkhkH|v)^mvIsVy!Jc5L4==Ej^B;u!{!`1e!GerGZ|_5 zF-QAQpk)m^f-oD%NmQ)@Rr?J;}1fl4?+$C@!mJeuE`>@EU+4U328_}MP0w0oc{ z=uiblcb9O2s=|`S);jOKv8|=4lHu*#u`^j3)O<%{Xex}bWvUYgOT4%XVy;BymvZCL z$nlhcCpvZbk->Q95ukJo7|aYhB%;782;Yt*Iz5hZSp&=*WchDj zV~b7G3v2;MU2HVh52+>4D_Azf;vh-lNdZ|u;wY6W2QpoRe(7x-aGZ={8HZ!G0zRF* zpQ0i}l3wNbXn4nY%;A~ihd&sgr{-(w8)|&K44pRL`5`Ey6=D!WWZcW+pl}W0Lww>? zz&PJEIp{IfQPfDUpTta@$jwK15A(YMh|EotqtJ-jB*F(qCQrI}<yP(J=^FBjd7H(h4+c=rV=B z#e2=&IbpvaaE$;XiOb}fI>M*xtCGY1dSUpI!7xfQb?2D*;b;gU`}TE{_=1a8479Xl zCDHzRTiRW=4i4J6PJpOWF`^4@O{rRH@s==ku=d5Y->ivJ*ZmSjsT4gn#X4PcoeneF z(xT`7WI{m!qe>HTSJ*`oCWa-u(_|d@eRl%9YVGeaa>w2N19?ULH_nfGC6tDvbcIX; z(8*#44-1cSdZhvN5LqsV+U-z&%!F~RnS^-JAG3?L+i2dOodMmmD^1dRSmyj&PbOI` zB@f%Ig%?f0*fz9t7d&pb7Gxo6EK48p78t z=<>JcXu_uc;XdGM7M*!RuZ4_YI-Qn7ylIiq>0diy41>DxN99GfU|WsFJHM~%*9b9GabA-veHB*9tsLw>wNrJKRkrG~Q?J*osbpI!$088Ca3bg% z#shy~F@YRX4N_ASsky~P8NQgB&l6wQ2_9TL##3$}z5Het}9f#fMQf2KM z{cz}T)zpYEGs_0B=+x9<4lCjiO0iYIJj5Xx_f@I|;I{3CvA<#XJ~L7c6Rca9xvEp7 zdtN+Yn~Nc=c{xnato^lLKRKAV2o4@d)5xp3oSM#;;IJ|6`!+XHKp9{rP*D;$k1JD_(Yt|Th*Qn&)^j;nm*f)<#gD? zD}q*WTlIcom6~e75ajUHcsCd^<8bYx?&Uc5_Eq?KOjhEsmeKqDmc1l#o@U}WoYFU( zMbvp>mmM|N-?U{yDZ*h3Y{-Aezt6Cn@_U7xaTb(#zdteDQlkxBKF6xjXfh(s#QW0u z>oaGE{l}YNdPb^Wa3wT+!Sqzp)-DxRc(ANNa1mzh7%<}ZR=k`0Vdqx_1{-Jr0rVQW8k zy9{(U?RSlmMP&B|LN8!IJF6o`TGq=1Z(K5T3pLw?;F@k1*5$q9FaZw*Z4F243855CA+ zjeQd%Q_lM7oHkzP`|80H2pk+_8rY8WV5nzEn+`8uz5mD~W*UZohK`1YlGJSveHTUu zU3iMTem>n05JdXy-Y*VP45ZF7t{^16yKkC_7ISysIwA4c1`1i4*diTkLorV5yDS&~ zS>1G89Ta@9M|#tkpOUUH_**1&n{&`{Jzn*g&9_l!t?6PKoMObKDD$(pU%>Ozm{i(5(mWy@FtY^SY6vYZMMomP4tiwQ@6rvLFS@4AEfxKEhEV>s@z z86yZ^1z*911^gOE|DCc2}-|NV#$SSyHX+$C;cCg1m*PNtRteBV5 zV&L5S;b!%C*p$NQ5_tNXao^1ScTGkqav|PR9*goArsM4PTKRdzN~4rT<8P`%hp4zz zHF_i03hFbB`DE&W7m1r~Wj-`Udy`SB<$QZm2GZPgo~fxX^U~Jfxt#t~6l|KkjG@lRLVpiAp~uMA zwmg`foIn7eKqNy!tmYFTZQz!ww&zFVw>#R3@d4#S`#g1pCA>9KMfNiZ9%O@xQXQ{& zwmI5Kg_KREcGPXuIV3tAR>K+BH8$ttX#>+ng6!hHPQ{*kQ>Y*g8_VS-j!#BT%14RA zsd&kmq0?AXV~kLq1*zd(^`thYjUk>IS|yXqBc%+O&Jg?Hk`jciBymj~+K3Nt(DD^` zX+$EjqSb!u=X!!po8LunG!@@-2&3iBST(Kfw@&Sot|R@!dKhfEJDq$`1S5ef3ue71 z`a4QBnfhH#f*!ubu)r?SDv1(AG%(|Y`G@6BD3)TnnTQU2O6XhLUNkeVqgIWfn62LC zhBx#~i8;*x>qg;i5$BjpytvABzQff`dDyr@GYQ4#RHW#`R ztJxaKQ1w&S4L2hjoAs_#Fb-JpV2S3buAl}+@9kS>XT*B;RQ!@+b3hw7KsAiAs~+QX zjPURBx}jsxiMT(DX=f3$4YVi@@ljR;J!X#+n6HWgSY{5GX_;wM z4VBccI-|{Ebi8PY%+f6Jrs!?DnDXMi&9YR(utw#-^%hnCdgyqtso-W&_4mL&7);HX zAgb7(Z?s6t#s?rq0bOeS!d+y;q>_byOhdZ-NiNqtkH-$dTb3ne<&PVc=d7rt6qDta&r1As7mjymyoHA$e_b9|bYf%4qj99W8HR>XN%BJU|4&Qj6Wf*fTmBx=R zBI>3SE(MQAO`Z1@Xtu#vH)Hl5EiD_KkL!ca(OG=UlQ!RO6wrMx`7hfaT2AYlBf~Yu zLro*tl!bB%)hdYf6nefPY#GSB_3&Up!E)&z5qGJ=^z2U^gvkIw1vaL88A>g`=AN^> zUpk*Tf8Ac?$3#X(o2Cxeyp{ZNg8lh!(e^tp{p;WUh;gL+Laqv4)REVX#tFfWnnrG& zEk0lVco;#Q5&tMBjdHPB`^K0E*4(ip4Tk2uhhIr;@5p$I>u%3Oqd{T0HwT`E>%1gE zcJ*%2N<3~^9>=F#uS3|%N9Wn*1(HJ?cJ%?IMb+g0(~Y`*|tsCrvEXF zTSyKba6NdaS_N1N{@`-={WteR{Et8F*8 zmg^b?+VCX=3Qi1vGq9lbbmB||S(IlZhFrGXK6qZXr_?f!meK6*v2I4lDad)Bo^Dbd z)EQS7)`V$#ig%eIqwajM$g4gO;10?#drZ%iMZj`c{O>vb8u@F)MGGTlr*g`@e6FyPb`PepD2I^^OYu#FsCWA8#dW^5R$Z<)DXeBqT#V)SZ*BEc z6N6WVW~wt>Td_A3_FU@CgRaZCC=TlYyn@xzImFewBY6yZlBR<@g|e0Sw5F^o^mr+2 zuh+_@C0;JS4w`NEdYz*l->VQ;JL5HeS#3vUW8WS+uoa;t7&4Gx!e6hX*||HaJJ4bC zaNtVY_j02tB&80_tnW#N9Go#Mc5Ri9)zi(o|K4e#M%GvP?jtghMgak}-}^vnHOvYD z(Y$P}?di#vX}Gg}wyafM3!4h?;+{_l$IdS3+Ts)Uy;3V0(Tn9m^#%XEOM7&Ul5guN zame`VO_3qHLSc$M==20HL|i=P?tY$wtzz@9{n^^lv$NGp^!<&%$b!x4Z_jkhwC4pa zDc_*Nahc6EelD-%+S*VtUW;0sn+P0(SULA(!ahde>`rEj>xTW|rPmciMgnR<#w7Ar zI$!Hcfr){)Fr#*_?!Lv;S5tPverH$bI%WX@W|xC8%?p3U*~^am?>-tS;<9SZP_|h~ z31xy+I5o;rVlV_OUa?u?)un5*0fF&3gBr)sIFKSxexlr3cyIc9@9+eashdv|uD_lY zKE|+PifL{|qQ7LH)&+oftBeNM1TIl;m$%==jU#3+eMgV37Rq}Oxm$l=HYjJ)33u&t z@p5XkQDK-z%g!8%$*5fRGFuPkwIX3}-Z1O&^wF4g7JGiK!pPr0POv?2`4vGe!Iubg z&8^D!Ba&?R2Q`+$pw)tN6T$?>r2HIt>T8j+ z8bC!fa;_tlf-Et&IBGF{<}^YY&IYzRq4t;Y_4Dy47gqm@BI{^9M4pw!Ci~eW#3)44 zUJ;oz+-&!glIUm?S-mf>Cf1T7Txvtud+IvQ_oucU!`rFEaWC?%O&mR=(n|bXslO&$ zZC|>e1-ho>g;s?7QUk-o#%k0+d$W^#pa{LIByEMs+RxoEOm~hxLj!XqDt{i%)@59I z*x7Zo)gQxN1Yr4j6iHx&{9$u{X3UqcAgHjTnft35?!(v`!TUC(j07Wq~46qEOqbM5z*#5`ctrWV@RObUGTELgczS4bC17FGPw zAi#zjmmA05@4Q(lTVrYPnMJ&xIr)0cXc%bj+e&wwwUMS+?6o_QN%(XWVqT8;q@bD*KB~B>h8(tAi!d8;!1~lA^8! z-5=wVZ<@i?mCf5g8AOhvv6C}-=SJ&@O#{g`(tW4GHBJo6vDQCh7Ux!Xf>NSe7brQ` z(6#Gm(X6NrB~0~Rg&fWl{VV3&5PO~aE{vAGCGUup+EfeHZ%; zyIKh!g(w5jAC^m9`c!gCvb34Ua>h`mlWC?NtV^nw6Vc6B+nl|9V9D&Hf4PxW+4xXt zvMo7s(DYhYy48W0+Q1P75q}xse*?W6Ktfb}^LPi~x}s6jM?VCD*J;r%ucg65lOk*& zoMSNd9sJO#-kiWI@I=CwCO2Bs&k;$@!qIGU!8~2B%QqUAqh}A>BWtp(O+}}Cu3E9D z&xay(pN>uSn;JqDuu5t45EzQhK&CLBZba%Bnjc*yC=urJ!7)y!%%Bz)L znVy!lU;W~G`9hW+Qyc|$1Ff4rw8Ae1o+RxoCZ}E30<@V|@c72iBs_wYSqzsYNHIR` zCJoAguA;g+s>(6xuE7~VBJN@A0L?UY+|xh&Z3Z{u)IV#5w(7zKkgJ6I0#PDurIzXu zjcXe5pGV}_wNu1z9)^OW6z+N!DnscpcWNB?lxYyove#}$OE%Qe@9D!9knk+HMv1@( zn58)+(pn9}aOubgwTCiKSZJ7|CbF-<*86Hi)R zwF3bgF0p5_i1B#vk0rE&_LvYt4=PkzMk{R=F20co6;CVHy4lJswHG9U^0G31#{<OH*7cp*iRk$~~eUQYgMUb}y}pFUAeTEU0h&j0A4)PlsvgC!o(e#GRKXxw74`7X$)* z?h=EBg32jy3Kkdt>HgSS*W7zev$|gDK<_6*`!cwK|M%5&O}gy-_gX z142gfp_fl1`>dKHGL2;|&wd^^(|Gr{)@?tp>D!XT3zf>i*A=20C{vsMt zKuh3@yPbf-x>?_>zB?$|NA9XeJD*rtHR?K^Cuuj<)buI3yIdit-v&cLHCcD2Dfm@H zN{u6SnvP!ZHJ6qBsjJ%!I@IfmjHCPdgXG|gQUfOJLx;JS9n!L46w{C(Aq66w`FyF` z=LC3YIcqVO>tsI8r56qGdb7LQ>iz^6Uw%lH$x&F&HfUG2J+Cc+ipI5}p(f@EcAToM z7Av_O?#wGSo|gs%HdF^k25Dxcd!xiK7-!2QnPoo2d({*qBPvvbXAws9!%)a2{G=Td zj%m~Y0xjEH~?0&2l5{G=r1;khIS+|d}gRL>^0$d z)L;1%`a$Nh*7bjLCl_iC?_HCPGX3SmYJMA&g;7~BLAvetv%0%_b)+^+Y0Ll`Ki)%=OFoiRfA-7(VH`zbJN~qjX~i@BIb2@ z92S!8pT4rRv?TPrTlC6j7f2{vwU(w_U0Lm!?vvx}jClKwwxZ-_43XNtr4_%X{< zo!|Zzk^SLiB~w>x^F!ViGeo;f%+%DZXpcr*DVNSfrq|?w?Fb~0s+Mn!nuP_{=!*k zcCP4hC66J@XSh4oKPCwm%uTfi$W3ZcC+w3M9+zHq;q4D6{Cu*W4TfPIVRGF(2gggk zmDQumrdPlo6yer2cEq|IKuUq6)h>rx0-J-VbCNI?i5wqi(zMD6u483K+El!|o9eoW zcG2GBY|O3wLY11MK^0*cMx>-ux4*!h)X2y{8*F(D8-~1%-)4?aEoL*K!SZ0k8lfS> zLWTdk`)c@4*2y{V1U5x+f62_=92aHL8nT6j_R8AYYae<{6TO8&Ui)R#{{o^wUB5TG zSFURB>az0~r@J(C0?i^fZQQ{A#2c@_W-U-v<;c9Y0CThrM$LycmdwXr28P^ospaDz z{U~b zKQ~T~ebY@hV*%{MUWS zYse}k!ohgwqX0n4ucT|H9ewhNryhFv;Zyymcu9$MARj1c4206is*a#{;3TRV>4F$o zsI;NI%xM7))lE4w_NBM_R@+W+6F?gpvxwrnuGGCH(Lxb%&(oHT*%mo>_5c7t07*na zRQ?0$sR4Q;a>$89OW}0x`M;YUJL`;s?WRH~*`93a#-h1(O4mlcU^i^hP!Xl;FCd%byY0iV+hJYW+JK%q(A_7gvsu&^|4^t2Da^} z3msZALECxLuCdwKbRv;Xr-r$THJjPHZ_i(U^{<|P;aQeW>(;G%^Uc>;4K82W^iMzj zVa9d`-BXb+Y2;BFhxhG$?X_112hXlr zwTc(D`J9(8N?30wb0*7GlIDaJ3vweQ-FqdWYI3SA=|Fb84g!SnH5w!XDfv($lOTYn z$6Q}~@f@$a+^!$|sj{zyXqMRnBnoxM{(wgk-7|n*0Mr+?T z^3ZyDgn~UwGkV%oE?Q35CV8oL`PGGRn#CB)>qss?dg4HB{#=Yx0&f17%9&gy9ICOe zCNL1@Sl06Gi~A6tLUEMfEXIu$OmOX$i`rOmWfRss8!B`C#m?ACk$=vtOcjzuXOyvC z#_cwleU`&+{fn}us*OEN{@j2#%jPhj{D&h44)^vQJ2o|Vg7J>6Y-fM6KHEt{vWh~! zN*Gu{lB3w6@r4iUimOr)1aTr342v&q05J*x_LO9fjNGvEhICCG9eZnIBiR}lK9?y+ zpML&@pZvp5UVHVm!NH+eGyp)Du{yQjr|5iDjcy`qG!ac+(9#0l`D? zn>bVSy!3gJyb>2BGsaMuLwRl$KxvZ{Q_$>CMF1B;U%w+2t|TrSpj zuTSpy_)O<5lj(KiwQFX(ZmhfYPeb)BXu!b_U-y=CgEME3#7dn0a~A+~k*jY!z=j1v zkdBty60@aHCS0=1ahNGdX}iUb?dU)jqzM2C+tVyIsl_tw8afKgNNtd0|0rLGCu)wI z96WsN_^I9l^aIS`DFcm4&+sUX#%f+FaXgA8X3&H)FbfN|BxicHDzl%CxwX{E|F zrqwGM0#@;@U}HK>Y9nKlNBd6J*VfU{cHMHz7ryZ2cfI>oe&A#xo9A-dqrZM|Vq%;Q zi0Y9v5>>k*=bVzV`}n7S@~3=)2#xfaqm|des|taq3BuM`-=?!`N~LSBy_T5dVC zJxEkACG@5dKl|)6$BrK38*SdMr_^~Ux~{fv-4*LstXRV!L!OvqrxMA&zGF0%4I4MI zZH_2653Lrrw01sGKlnq{%yl2|FZQH|7FRizE-pK z_bm63lug~a+PUZNOK10)90nsSfw2y)?XHV$XwvLjYm0P<3Q(Q%_a1vf#dQ*>%Q?D=35^km?o77W{eAGEhgcKv8BQuu!%s~t zX>H~A13H#1Z)$2fu>W8*UDr_G6px0crl%VDw4}ScXfLn0hT(Q5t-M`Lm|?i2*(t!3 zVuhJlIZHCEXfOy@)s89)6YJ~&u-CP znRL-)WrLPG$E9MKFT5g@4NG7d@F6);MJje?% ztcJNY+}2XR zaDZ(CEwfEa*V;GsMrUXx&`^fyF zKx=awy~dG)M;PaGv$HQf_Y6ITS)kovsBD&^17{wjg=3v{-F4S}=F^|93}pdrD@rfo z&s!LwFBFOLL2U1LKJWp)kaVrZ9)0ly*{4N;s_sbwBssSv=!e*1AkKPr8$(cm z4xLz8uGc{PlyM=41KRp*f)TnS&0Wl_TGmW4^qZ)dWFW4(R3nOS!pU?=x- zDkEUzK#wmxm7;o)a79TO(Fi7%%5gNN1|k^XBvW-EvB-3kl`10$JG3;JrAynFEbYkV zi@dhRIzLrcv**CUC!T$Q3&1Zu!-}allgr&OM5i33a)RWU=$iHl?pxu>ZWbXH|@z z4J>VazC>0bhRxk^eeAKvZ8v+C=4*{INGw=L;7hqV1O&+jD?KjSP*|*oF*WiAyIo$f zk;XOy7zOPZBp*w*Z%n4^nKi{BPbM0$nK0El2|9fckWSoy2 z7&$Ys#PavmZhAL&tC%>^PG~ILTBAro@J+5w(95BbnJ6z}*t@|tnFC`;KvziTJ+vYM zohq6+SQsHyq=FesX$>ReV?2ey1)A}Z5q^cnWVxb|PzjW8X;!V8SYUkBmnQ%~cvS`= z2+Rs%e9s)K%a-dnIid3a=UI>gj6)QzBH698+3@V@>K+&xp30W`&rTfbJ;4RZ+1XtG z>4DB=U2E2FxNg_YE$!`{ol7@uT-&v5$;snKo_Xd;JC}AXk_^(J_{L+}Gc_$S2u1$z zOJCl+ag$G43M|sEG|(V*Aj7_LEFL_LWVjuA z^YbR$Ev&7tqm!2N})Ix7nnfN zP$+wpBSo4g1y3p#v@y_5|8OjvI5OkviM!ureHHtDEK_*KftshYx8GW@RjTpX;=wg^ zMQNd&7>zCjCOHOi{?eqDl^^7I`6vcF3JT9Br*QL41ih+Vty>p z9H#ihPAFHw*xN^k`I+bg#xn}3i>-eFPk%>trT+GD~(%r*mOornMKHs8V zO}Zb!unPD2g%q&lT#6(CY+Y28r}L=^61HxE!Ne?-Zr=urNKJm0qcc7_=hy7qm}#4? z(isWJ#3wC~5@_2@tZfo;zC+`srffb-tT#fJqN`L_wPNvdh@ImkA79x~ELS!Lr+6Qt zrX`-u%}Nl%qJ4M6?i9!C@g?h5fBHYfYMLXHquEs3RDl~=42qG+_~hvE<4HRp=Ue-7 zf{lrAaiW--sqa|bP@l<{a;7{c#b*-;V_sle^US{)2q_V?;7QGRc!qKK_-JE3lIJ@L z*O;x+%*w5SnT{%IH8sJ~oYGQ|IwC1i0;?P_HdlCyb-UiB!ZB;HdNcFD z2Pr^eD>Mo?`&6t7O{M4Qm6m+Bq%}4Lp~OMy8G(ty(LC%xzZB}~>}W{W@|YTfX;WRz znq_Tu>y~qGu>ZvI6&tQiXYk-jD40nzJDYM~OZfJt0|w>vr(yAf4SZiP881y)1E77< zDqRb6@~j*IC`TWxn4(6+h|ZOk@yn(Yz6%Y3DHG1l7i>HoR*qyJlB z^Jns%yYemD3rlYaZ~fiX_x&H4)^+T(a6nF%K;xiVuJkwhmE9S$w1P2sW zudHjV7%3qONn3n!5$x|wKXA)k5Y60te>N? zC+xxp>A_(C!l99ok=?s@^EMG1mf6f~M{BG7$_Qj!;-1a$Y1Zt_1bY&6FsDwQnBu|X zP=0iLoYQ>?V_zl8f;Lo`-Sf|1jYPkjZduZ}bVXz9vc^09G}hR{!2++Su^-6VE)q%< z5=~(qawq$AJ*7OmgnYEX0x=aWOuhQO$ncv9o^i5LK|cz_hB~ID(P(aPHuCgQhFs1c z^ENu#4FTwAK{n#L>a(UyPiNglHFqu}7E*E1n$gw>tk8gor)%Ny3*N2aia~+zV1|ZA zc~hS^6WqS935Lj8Np-T|OAI+GG+zrYIoFb0rI>VAu)YSth(-FKFa&bGs38U;;V8%9 zqJ7>GO%$^E8av&NoEaUXwPiB7>FmV#O#Zq9hax;}T$pL=>gF+v@>F)s$`w4H*Eeu# z-`+jf@4U%MQCnxE;hKc>k@loSCGvXpAO69Y|J{H1_cPP>+_T7(olE)F@-F4D0!7hI z`HiHz?zo+q5mMn{JDUX1$p$5-5ZV9>Nq2bQzyW?N790i76?-ntFa_oNiLPZ`D_5;z z7xc$J`iCc;d}45Dh+oX3@+KzE@p&7=4r!_ET)kTQDrK6833ojx4F(ujEr^P7+D0E^ zigU!mVXX@uTPIZ-0g)iYC<*vV5r8Oj;V}D2yk$Uv(<3fij=@+7lni_y1wd3FmQk&E zCKr40RK6Uo;c$TkA*(j#0GI_kC^e;gZE?Ijcwl<>BfZc4B9zZ1cr9%9-0q+L$KwzD z*VtG;Ujf)JPuOWgI3KSmBts}GR-Bwd}UT>FkD7tfF zlRS2YG|Jz~#8rV&Tc9G=g3f{QRRfEXBL+OdU^g#>p3QK~K(HyMfu)nlq zP9w&-eqm1pt5F~nvCsboUcj=2?L(g%n=8bSYEx)`o_rmc}IGW4P4V z*jnGv5{aeau_Bk5r&+g8%p5&@C_6iyOr;UU5&*H%lT@rUT$!MfHTkkF4nOq455MvH zn> ztY^ys4LF5Ae*6UQh;H1x`RFk&i1LV4GbfF0EzKO(legO18qCy-LOBZ8YPDi5R0b`R zJXVYcN>?f8Ek`<3^K5uv1@V1Q7$1a7umB2_&V}D>;eej~E~<`LoX?;KB*zCY3e2aG zDCU$5Q}IadTp{|vq1mNZ*Vl)}tg+B{(6-DllyEp(2-U5)CX}ctm17eJUyM$T#5y-c z>RZ?Zi46BnKl}H^(y3CcHp!#Eky0u&&4(YMuz^%0>y%JZN@CYA2M7@v&r*HwD;z;=ZBHk;oFMP=n4gT^9K~fUA}^%5(pNQnrx;Wl-Ak zZ=E-wwE-IuFSWq7eCm}xpCYASC!6VBqa3!j=p{imomGPb0J2QNo=D>FjNR)P2 zJ%YIsmm`ZzT3~>KQn;3Sqk37jYG~*>#arLkvt`qU65UhV-Fxmo*wWGSt#5tjwO3xg zborc?qyNg)k)h$U7cbcT3gP6fiF0Sqz!M@@@M1#nAu7#~NPhNoN79j^Yr5w5-+!M@ zY4Epj>94TfQ^G1xaHT|KW5g#v`3VQ%WklL5w--X5dMIK-#;`5+E-fB=*OW{n94(Cv zK3WZ}Cn$C)yGzV~*xruW1A;Wcb{R0E8 zZ^BEukeDN#VtjH}KUcbiCveq~pH3E{zOz6Tfq1)i3*4>%5c6G-AL=yteV(2Sa zP>!x2emR~BRqWUNAWQ zDi|Eq2bse)q17Cf8ZfdiX*h(Ja$Ge!GU|$JRbnNMJXH{c)G~>Lqsp`-gip2X0#2-@ z+2*2mk%A#<+QQLEoUSyJyYnzUjGXgJn|{y4L5;owprHg9>?yMQC6V z)R2iB4BI9V-Hte?;)wbeKlj-WJ@zPI;hC=w*pV}n{2%bGeu^ac;DHAigHIAIOQ-<= zqbdOx)9sT19L;@QoxRSsp;?VlRF2MgpuNfZL~U(*Pq!-uTAG_SuV1@m{aQCVOpOlJ zSs}Z#aQ58UeY^KGH#F!6Ds{=>Y*D;Oi&3J=9{2CiX~N}NySStvIvASE%pU?mwk!FK zNXSc7%uE4*mOGJiNP+=V8r$$MNLF3Be8u%mm&y`LT+!lL?8$3&x30`wS!JtyYeUn?Z~pq3*T27E)4KT! zuXo7uy@sgz9k->vG3tqWGxiDL7IAgkVa@#AhPH2CX#7_%&0nu+s9UOSteG(*FFmml zgAz3rijr4EKe@y|9my7-TA(WNKAB_%&#J;i?QT_H)P4 zmh4sfO#+f3X)BRxib8!B7~QQo_X0R@B44p#6xnh9gII8iS}8uju=0n@%rnppFDZOnF%Ym z3$uCwrf_P#z1-W?<-ELI+UL%knV*?$>*$!7nHnD-LH5wiAxom}$Z##u{)2~CP$<^Jx)8J|%XAYFOSqc;eRZ#{>QlTL_B~cX@LPe|Q3k>p7&LS}LunZ9W-b%hA z(XW2>k1t%jsJeqc^H{}`4!~(X@X2!}fM^fP2RAS_0GY~s zX_u4FjsUOj?mhhQ!v_4u3JtN1&_%={s7k4%rJ(#4oV?_?e8ZEDv;jb`nO|sVn~nRi z7L-cVF|r7v&=U=B^il&|p{0T61$)pJuLBOfAWW2jWydg_HOCz?rUpWzt*)q zOT@IJXSEfw2M<2ra?um-9@BJ;j*LL1+i+`U&NveKLx&z(-PgCwjYun!53)n>f)!D1 zSLSRAF|{tzrvgWh9Zg0B{EwKwTnTGxKJ|%D?7Q#2s2Zgf$yI(rxXT~EEUE}7)gih0 z{`bD`Hu%P-Mi;Rdoo`sTzPY8563)%c*a$W_FyIhKXIIDG{Rebzo0=LHC#U!9+;!#R zd7b;Ixut^-9mcWfHw2?YZAyv61M8}qMH_?{m4Q7Tac-L^ME8+{tQJO8s6d%w*@5NRv5r5zTR_wz~5&I6NqY%R5Aje zEX(L;N4R~U_5Cw-=f)O08e2L&QMI(nrMe1OyKfQDT#0@mk5Dhwx-D4t;o-gwL#yn` z!z$&k%8#W29nQ#9L)*DqZU5$njbA&vIMZlgC}xx1?!7usJL#vz4tQ!vh9&<20~sHr za%3xqGm!J-L**0xz04PvAQa8bxrx+h+M&g}tJ|B_^|ZFv-+S|iKe%?~st&kEbE65% ziwUE~2!x4NT&9XMlMu=jFvVQkSk4eG-g7yR3Oa6AEs`iwDqE%4(>H4Gf*h0e-Rz0^ z>L2{>#La8_c5GU+y3-PNQ$wQ-yUs^ABG%r!X7{e$FFpTUTYHP!e=lCVU?2L(=q;(c zJH&=2W0PIG_wMvaX3_R2v@$(ORD;_}C8~q)W)zQzir6q=$IhMS&Yg3sVl`_YaQv9= zD0JfQ*}3DfM;}qOY9oBAI~BPfiA2UrwId}`5)^dJet5 z*;&&%8}=HSnjU}RL!O_v1*E&9>sIr`fd?OT)4=6Rmk{6G(Q@+qmEjvV)@|J4b`(fu zHYGI@B&;5=xa&SKStO0fLTO~%V5PBs!G>*%-f{I^XeWgY{X`bh6s<@BoaG(F%U1N> z2o{%}qIOP9O-`F1x^lHYUc({{PSqM}$4Ym^{m+_2UInY9RZ^^a$_{rD!;!h;p#jrs zHPqd?wovnbpO|{EyZPb1rVTxJJL~V1VRckV(>j+%LDm^OGJ*1tNpl89kMV?z!FW@& zGjPfJy$eH)-@VlQ&HknFJ4?+Ckr!%AgX2Eo01hdM@)UrM!X=c_9JJB8q-~{2kf>Pm z092?&Pa0VW&%$1@)G~Y`BG%W|nMRwMoapFT`|uMzXO6t}&ENlxZTlbi%ol%JU)Z&8 zavamVgb6*Rj52B1l2JUFNFq9xArD13L*nVh-Fpq~OB3@#S~_q=!ACE*uop=PfK--) z5aQI>aQW=1tH<9uw0(_biJPONDspp&>o;w@@8CmIOSKO_@w9>8)hn0XZSnT86ZXxJ zk;c}}!RuGLRw?Sa>(>XMkIntC$8{g}=#}-|!i&g5j0<#n|L0~(LtKBvyk7~Em-p_u{PdY;o^k%DWFDRn7j75D0g)E3Qp>!@eV*#S5zo0y zOaRub=|&qSIwn86IAiY4^Q=V)U>uV+6WW99RD41Yp83|qSdZyZ)q^Yq6ze( zj`^Fe<{A^Mbv3h7vrVrK)V(w~eRbNfHeL*!zS{(>-jQFoKxsPlN6q?%>fwYH3fwgB zuWAU|lhkx%8;Hov6lU-#k|64P;=~8-31f+j1CK+uP5el&rE6k#slB~*uBlmW-+b=5 zzP8rBP3yfUvvKo|?zQXZ77g>FQ_V;V0Srf!RMAGZ&q%jo0O|>-ikjMIUaW0AJX6=9 za~jQJi4GnhcyM|+F#%>n*6hr0{)d0Rv@q4Tdfn>2-dUp?*LB~yw{_Rv^;>pq+`hNH zXU)x_;io?O%&RZI_|}_mTh-pMrq}$TsfddD=_=PY0_V4{((pKWVXT4tui*O4(^x%UVH*Jz>DM3^LFI)8>UM9d$Lmwx;H00$SHn?_HXI^Kbvp)h>u{ZaT1kzkTGm zhNFBxfT6BHC%3;)*3!`2y#D^) z4R@9tT(SpmX>ragbTcz9`gK6j7-z9CWl`4x14@5F^QFoODMu8Nl6W;K;xki8as@ye zrq(Q8AZ1Og@)boU3KLr$Vhiq)!+R4`(=WaJ(&)tS?b}o9H?CKA^t85(&5VBUTVH$P zi$!X8LMkzJA|a$EMnQu6LknvDE?Zfn`DaQj8%j zOLzY8xBkP#&CC0DZF7~=-27~#Bf1T(`UdTN>uZ`@*KXK!dvd0|rOD2)(cz&D8`mP$ zyI?j~TJA1G=q0@+??!9h$iH)E1Ot&tQZfOxKG{CgP5{K<#^*o(`5(UW>g6k!c_zCu zzwGxbA);5ULdS`gk6n;Wu~svhaETzHHb4ciizSfN~yc2%PsdeM{n9L zGdeQ7X?@?OjT=v$yVQSe@WBTjoSvQ<9vw9x?(ArB1Nr>ylDmy(7Vp0J?LYtG&;9M# zY`i?iB^xA+9F~NlywykO$wI2FnVM)>yQ*!y84k76k`YvNa7uwJS0W`!p^8iO(NOo? z_rH7o?8&-&cg~&lh>AUfZG`#!rT&}4Bhf}ID^fMr>40LTPoOP^KUNSyT9=KRPY!mL z4W==s*VvkitSpoM1gKyxRI31V(g=|5Tu4;(YGUOkCinwD-c|h}a&eqcWq~LQkKv9b zcsEFC9!)LOH8dLq(0pXs)3~;;ySt+^@^*LC?c2B9eST|lW_)^Tc6NsPL!oV^MCd8S z8g)>iP}Y=Y@O0S+4Hyv(APxvYeAO1lKYZ@onVFeE+hd0hO^n_A5C7M{UA@lksqW2t z_MbR)b^V6kfx)YP_iq^G zE(?g0Bjr60<4uAG5)zX)t-?D9_xP6Q?@6|NP@$_(>1V8Vyr-y-~Fp){-9eQmAB5 z6V#GNtO&0AA)V26LxLzsRm~S!7Dd%idL|f0kiYR~U;B6e{@-5Nig@TXv_NLZpO{Hq|T zx)VR&(6?ZxicIEF}1u(<_{HRMDMK2^iab)ejWX z1a)sukM~%6yV|$)bZ?I;D!#O={rw1 zd>Z)k76LIbMB9Ak%(*}Lqd)rkH@{`!ZU4Ug`}Xd(AG5u!d1!p>KmF-n*b4F!pMTq( zSFK&EyE}X5+yfA`XRMh}rAU?T`-r|KuF!VE7-XrK=5^oovTK}{!nL3=yn|3t)rhK) z+H*%=fBu_at(}{G_|QRj;g3&GU%q(s{(ZaFZfV%I`@sE=Jz)y#`nBsXJpY434;`9! zeL+**;U^yd@~?kod~CAa0hRjIw+Zpm+|s?q4jXKoznq^Zka2lVa6;o76;LW4s<@SO z@T&-nq7Q{BDq|<=(@#9{{Gmf{9yx-_QhJdQ<~=3!A@Zj6>s|Y)RG5|g6%>gT7!E;L zBAZ5ijH1FSQPlJ_u(h?-$dJF0?%<7^8~XajFJ7FjyLb4|16JgxrbeeG$A$;5n0lIO zZrZYS+s2*yKKaEjz4rWfx2#*Qm^N$OQD?2hnP63) zYC?K@k;7sN1;tt}f{MRr%jBg`f@>{Tq*y2@0mQ{EV`k2*-3?y9LBQ2y4s9qbjiejk zz0tRA$95Ou*~X-m92y?-JgpePO;bO$4T}U1A+Zn=`+3xIQDKxe2h-9agHoe@c)}s# z;Lyl#|Nid}T)%F@{OZ8KM?U)WsiQ}T&47y(7M4Etp@;fUzk2=ZmAj5GZ@urM&;DdX zYnz^)NrkvOJT@*wT2#-#6IU#qMkOO%0XmwY1lF$A3sg4rGnPT>8W#xI#Y-pNe(mo3 zE5GyGU)jEO zOHW7Z8?PR@c>aQFps}T6@ow$tt=mxR`!~5fF3MKvmJUfu*NSE-12uh$A6>!qD2iyQ zI59*G^)p}k(uq?i=cA5%&%93wN!W*z!n1Em_QGg|FsRQ6i_=E=b(mzoOl0;cn z{{VbN3iph=S}Y>p7#?lwT0Jv6Jvp=J9hkR|o@njtedp-WpZb}fYi{f8S-l3EcisP> zsjV}|-qwD4=Ke#EIMx2fAOG%eJ@DvL-buB>W5rSBSlfW@v=C*%?vlj{osnV`!+Rqx z^+Pn^dh{_WtDTshc=3hrz461B-#LEL=3TITed~_CbF{go{n=+fb^iRhul?Dd5>sPE zQOYW8q6}Nc<=O^xd=!d5diiP`!pB|7Z-plTk1${icU7GtpqRqCa3#RX&nl{_Bcr7K zV?8ryWh#j_@vlrGsmkOK=={5a)7cukJ$dEYH6raAuAc7BP3t#o+PLBHp+jxWZNuYZ z12=A5zj4zTsZJ@@S! z(j%H#yuC1X^yJB@g~ct~cl52@aQX7kw$*(n-+E!->o#rQxOH27OZVNnCi3emY!6|V^_|eS-3sYShKXLuj|8~`nl%z&KIA5 z;rOdBwl_C^=#hu#W>)oW+Wd(x{zUh>jpWIcp}C1ITQ(d1IbQh6E3e!f9@@Em`}vC( zd;9vF>K>n(ZLDi`KsH#tcLuo^@7Fg}rrCsh^!OG82SA2{Hi-tRp3 zJ&-)J>?%r_UiJ#?+qW;O@%LA{i4F|ZOaikBn?H$$G8X9%3W_1MsoB# zmQ9OGvknK%H#PNk^_@F=VaL`jPFpNCF1lew)nO>o*4;ZYK4#aQPT<7o(BkaWqxbKe zxOx7q?_J)wZAaJY4Grzxb&Z{7HcFwmV2=`3a*irF%3M|HS;IjZjb49I16R~;*1BHFS6Pz|aAF9*hN6(GT?FdS8P75;rNK9(y5 zf~;-Prl>5V`&2gW$<+Mp-Kp7;f$PIHM~}5OH?QqmyK(admy$fV|G?bL?3MnjSFR0= zPfdYORM?UvvH2tc9KoV;h|nsy2T3WWn`Vi|4}S1MPgjrHbN!lix5r;xvv&Q$s^*z{ zP48U1x@L99$3ObafBc>QG(S3c;@(1g_nPj$4ISNmYd3G!INMtXNjb#e9mZzojNGp?>Kn4v9--vr0;(7oA18<%J!YRcJJHY zyM5R6#W7;?Y?BTrRBtQW_0nPN~MM5Uz!Vn7vba!s7&t*^UzeW1Ce<>tu9 z&aGRvY~5t&apU@RuT%WQPyLMso4n_zZeAbi=vw`SFa7NB^=q%a^x~TC?vH$I_nLKU z4U`?_dh_zdk?~s(9DK01Z{6+rdtH4S+guOgSad^^7jt7aA+Beq7#gNU@@4nm;NZZ? zkzZl5r(^jYanU;r8S13~GT7=9FB zCECP52*ME+Q)QhK!cu3Ht`rH0MTF9yEaPi93qWKeBZe^k3RMxJ-%z_&rjXD z(SCQLaoxJ>SNrGZOf1Z;-LTD-ien>V=g*&Qx;J;<-uu>V-mz+Ca!pt3_Kk<*WaiSH zrjFHZ-K$%BdTU!dCa(=lkB&V3)YIJ?wzl=HTfJ%fzI7YP`)jYfcKrC!#~*w6=<&C& z_g{4y*9zg~D;Jey|CIq}obKQIKx121|IJY^FylsDcZUJ<&b1p{dsqga@9*FQYYAWJ zlhf7G4q+)yM$r_FWQ8^^-SN2EXP*7^AN=7TW(^J?D){JNth#sbfd{s2-Aajqoy$wE zI&y%RD4T+XTNE~!kcp^NW5GaC0wJ$-5FLhyZu_Cu_pMpKZms^3g`(jxZS5^d4-Ac{51xAB(YE@U z{Gh#umGy0H+{6T}(;IIoJ!)e-*IN{R zhFGTPS8e(l?uzaOyM0x`s*YgY{~xBJ8>OT&eRO28L{TC(M#^Q*W0^dp$_?dFnCMTV zhSBa1jg1eDjU796s;jeo$F}WzV&}-tk+HE$SFem=xLpKsqz233jTS)tm}8bEdmx$` zX{UW#45`A#T3}RM>##tvU z@{dc=EdmisvX!Awsz&%T!RaCcIaVw^)z5wQvp;Xgm$vHz=%63!au96WgFxffpaP8%Lsm}6@Lkxu2P9}^8}G1Y|x*-2&vLrR}KepaYl z)Hv@q0Z=^Cet%$m{bl|?3i)5>vy8t`9@7{V3i($vvl4R@YB45Yr| z`Rg}toH={u+O=zX3J=_Wz>PsfaB3>{f`l-{t5ORaH*VDDClXG~=n5HGfj@QnRA*QB z_MJOVpE-lKR>J=7-~HvCdv?9>gYV4GO?~m_f2pat-IDs)?a{s4clHmCKKSG_eOq_l zo|*6H?9ofQF>-77frn~ZI-6U&JVe#r+0(aa$E-W&T08bU_-IpmueTIT{aSDz9~o(B zYjGI2t)p}MzI`8h=2LfTn_9b9uid!Ctc`V2_xeqa4!Lyo^0{*^A{!eWnVXrmc(@R! zOYWV%-0vo&O{;q@_Yc^uEK{zAXtXup&f?=wJbC{E2lf7fAw}iX(ZR0d-Ljk{W3vdN zzfrWN0$JFLb&kFqJ$5Yl9Nkf99F@@8Xti`L6FWP3DsmP~lwUFYqvk8$5e*MiGH-Gr*YumPL!-(#_H8)2`#)d~XuJ0Qk9h$jw zccy>Fy`ya%?S>6I?>pGu*?r#whvuiWQnzp3ntlD)$;)TX{*dQP`6wteo8IZJw1g#(tYpqgJ3SLP@rb?*UJ>-_ z=Z`v80{>{}kM;RLDlk-ZFS?mRss?46^%y=ywUyB6o>dpGagvH#G-tL`jtIp7^P6_n z2cD`wcluXDIaYdRLMt(>g#WAED`O>|A<=&$e6J^a+Q(?$6e&UPDWLM>j#e|B=VP^{@Zc z=ayD=_O7*D)xBZE*sW<#3yn{@#(jExY_z$fWBrybEuGyBt?gY)_ZDa8d%M@QwRO$S zFDd%rn>R0<|AVKWdg9w(|I*bGuq&bx-dP z-#I!5Zg%$e^whq+yS8lFI6OK=i>4+fTt;gBZbaeT82rYc{aHt6 z=jzqH_HZ0|>y2%jHhI26{blz@S9j0$ox9uDtnKOTJAU-&g9i^i`P9>@Ra4gsb2Gd5 z>|VcqqfIupfZP}!``MrS*`d*q$%$Ks9yz>m zXZ7{*vGu(+PIaDs_vre~Th^@IfW2lzZEaB<58N2s#B<&HlgE!wP2N8I$YY~pl$i1Iy+or>%}2^lq^Dg_s_q2=J-2S zsHeuq9N!rlyG795iT1{uZ=20^8>x%`jCXGg-Z*pq%5A$v-Q-Z?s+l;#XBJ`O<}F|N z!cUe=$6OcDAtkYJQaF>kK#F{_nZmOOTPaN8W@yvBd+XP&d;927GZFRf=6&d)hr}Um z3JNDZ9=Lvu#B@zrsU`+aRXz`d$n>KN0#H7Re1b-2m8k$^SRa?L6}w@I)rx-{&*zV*kC9qU_1 zvo`JCv&U(fvEgAg?V7$m^L4i-Z*SeX)9J6xYQ*NoP4V#DYE@ZVdza}Z^)XT29Pje< zPS4DeZ=Fwd5^ko1;cQueuJpR)B63&^cjmq7Nd7E`fABYftGZgg_>eY8hqHP=V3euG$<4p8)@_?96)>D>s7-;zAH5#9vK1HabSO z_U^mS+0pS^<7$ZPVY!2Jc%*Ld`k=0mo1l5x(tYO4d7B5!zP5FCoOt)0ixkb`$WNd6i%|1Ijb@9@roxAtU-kR9DW7h)@9e(qT z*Uy|jwWh1Hxw&ocz5~NI2D|}w{_H7BBkoUEN)L^R;)J&?Or;>_l*#`K?J8 zkM7^QXMF6|xeMn#2m9^sJ?}!v1-ID69>`i-e)L3@y;=7M9yr)+v7~H5Kwq*NrOCr; zDfp~yn_*?UkW07f- z>+7)Pm21}zKJ>^NZ@e)!F?H7fzpDy>^{8Wn^@$)(+=bW@>!n%{QH@ zZg20i>(;tb$<%rO)d6+m z;EmzG^T|(oL-;p-^Ed9>xt&gHWttls1_%08l)WZEdwPx^IWj&x?T&^3Z|4uJ+msS4Sr1T()e9|Dl5iE({D_xN^O|zS+EejHA4zV)uecQiR)!+tg}G zPt!vumbp@Cc<{M!BBTXBh2kwY_9kT24UD@2Oe5yz9(m;9=bn46&Zbg55X{Q<3yT?` zOrr298aJPGm%y;npUq$KgCSe*zI#HA*woxqB_-h%Kg7ByRa9xi8S-@@i-uJ(M z|`E{{Qqxf8-V^CHJMD`qG(Gr#EfhX!-KFzj*HK>9glAT(tj4--;y}Fr9Yo%EhtK8#f8Wxl=c+T^&36z309+I5_zGzx$OodNDuaIMR#HfB)!_ zw_Mz1`^PrDryYA{fk5A6pS+BLg0bB2#vWYwE z?#6Ki6F)!y^S_W~5uC)C!cRHHoYXxwH?aqXMaggg>7S7Au`U+W@7Yq;)7$Hzq$qFI zY4R@Foe|OvVBg2lKzBi5>wVUDH`I(#72VZ&V zB^Ty*_jWq~@z(1vuiv=gd*A!c^we$gy*M}bh0lHF-1!TJRO;tl`}P{wpFe%}on!Cl z#@KpmulD5uD~K0zm@Ib)M!$T8pfN>~s$V?PUFAuD6mhJ=R2>n0*(6NLdI~yTWhDg! zGpI)v6%C<0!Jp+WC4@;B8-_%=GSN&C3L;09jZ(CGC?z24D^m!K4j9 z^p&=VrH2^|DLR-`gq=}1G8J|r3ZaaDLA;4X2sLN7rzT&0{k7rIp$|QV|1|^G23uO{ zAA9Ja`Eb&|er;cCQ^Tpj>$6jn7tWlpNu#}?-X7`kYv;fDwPDluFa7WpD_cMFlYhCh;U9*1u)r;pJeeBW87te3o zx}~eF&4R;24<35)g%uwpL4082SA3&#zy<_Iux< zpOYVc`sv$~(@kwH&P~nQ7DEL~)Mc2rBX3vl2glkX1Jah)fs3s8wXrLKrYM z%zU^rt^X1`k&ByR<5L&({P_!-WzX3v$D!+PU1+#`rQh{KW~Xh$Zf$QLxqbWiiIc9) zH~edAe)RaM(|_^Y3pMpkj<#sfM@GjD`?u}c{r20(skz$h`_FxE^yc+j7=~z?S_>pIxkuU5u>QY>oqX|ku zN*)Tu&q_U1=~-2H#$Tup3}KR`Y5SxXb&o#$FxF=&R*R4$jrbgyJa>Mw6TP6~7t+j; zHMd5|dc&1#{pB;dG@=6_9@%G!N>@qCQhlu*6{bzwJG!i1^!E>#U$GFsW5>?8Mc>+A zyx_O!;R@Y0PmF%&yWgQ^F8Q#kdZu(KNr{tSke@!|5stHFU#%I=&RSw!(i*?|@++rL zpXpw`rlGm@+uwf9d?^~RDJUtzntZ9S>c{<5!Bz%JZsljXi5((y8dJuTX~?5{M3CWD za>>c$8?dUTaqwJeqyjhuW7+1DoUih~N(mnrAWY>?n-AKO`D|=Y__X<;Cr#2;6^m+) zC@0K}C>aZdLb=nCcEYdpNr23hd^l3<)$x7z@9*mBJa+t;QF`pMy0bJlKQn&YX`6e7 z>l4%SR)eoz?RTx<>GM~O@F%9{tX&_vf1h__2Zx8esCVnuuF@1fgX#pZ3KX}Ag?G)DxpsR z8N?^uRY;$b$kM{P!o8?UITWWL_zTLwnTBVY1Ou6lDw1@tGwU3wioiJ7d?KY15i0nN zS|R6?aYf{x(W`dVCmo4D-0^Rf8KLXfZcV@iL-aI2wytD{4`YXW`)YZ}1 zTwiCW%gD6X!DAb!#@IXZ7QHTB?LU9v{K)XA$6I>3yPS!8;J`umyU$F|n&XM%pl8pK zJO^xS6^3nOV!ExV!N~80mtUa>_ z=`Dw$ZAWgZuQM|=F=L3h%HZc${{G)L&Z@En7nF)mxl4x79->c$@WsSU48aNv=3q0h zD(f-|e?*F_d@;N3qfbB0#o#iCG(N$FCuWp$gZP+*20#!S9iosR>G^~){n=~R+RPdM zn(AC5;6mEUMHSIlGlsQ+HPljNBau=Q-__`?S+~Jq@2<{ny|&5e8N%kwyOoUCS2H%| zq6l05*7mJAd*+*Wq#+|_>WG0e{YCf5WFFa7x#0ijh zZNNO!u8K9h{2wVKI#oUT!QRr z*O`T-$+<-v2J~sEnFpA(0{K+8Xm?9f)hH=Qrs| z_a!~#y1(%=UwZ1v58HShoWWsPTh3i(ljxf?aurDo1>H0iH}Tj*LoESfV}+B+;ba|D zsZBgFs?rkr$nt=fBYDRWslKP~(OhPbsMJqc`V<$&1mjj(><#NToH}{Rt!j4gMv8Hy zXrB6+H3b}5a-XK-A>7Is`x+ghzk`|PIt}FP!@fN=vv<$#c+YU-CiUO-p_@J3-Q-|& ze0l>gD|a*>KYrqwr=RR@Z&%NDsfHaAn3=;~4?a&!OgdAnmY<%T^J1xEpgT6LbuM>k zV)nw|(Bb-Swo$`N)$1JkkNif_Co{1NGr2h;?sB^&yzZ$Fe>ek@^;PNd35OsY zhlsyu$yqjj1^VR#0H=YSgMUv?kHOx_(J0Lz@BoPV&T7?6C@@C-F5dMGfF2%;ghNXMqC zPV$S+G=dlcxge1Wd!m1~2WwrqB)=-Q2&)|QPj-Z^&sjoSvJSnNk%Yn)0v_V`$#dYUZw~ zqrHvDO&SMU5^HKO5C2d8=YMLKWl^Pom05LLHG{#i*h~}RRlh`Uy~^%A72%a3Lvk#> zOBI~FiqGQ1K}dwuee9zj6^5a_n3Y^p;Y;H^{;p6$p279fY$7e1hUFe?aYj3^ZTq&N zk>M*>ui(CYId)r_pFkF=3OTO#sB+xPCUu*k**Dchdu;PhH#&Rk|K8S$^6QLs`q! zEnZ-zXQ$1z$d~70bef$WvY0+?*3yx>xWddRH*U+Go|_vS8#O8c*3r>vrBP?<#?Y`n zErGEkRCkIf&CWSNT4!~^kx|p04ri01){vHlTel}YSfzP%ON_3mQ%N)P^VZ5jPvQnw z|8yQ}^ftQM+td(fm@+6@T+{}78UDZfNB@J#B+G`9!@t6kV2->e6J)2X_Q7b2joF=O zw@Uk0nScppE78Qlr8LPLLGT1evOAhQVrK#wz^(ulRZJM36`0Zs^(jr4eOkIECgWPjNi(YpHs(Qs=A=CB3KxoGqs^umpe&s?jr%DK-MIco-9878;8xo&^bh%w6@epP~a5EVM zOmYx1=m~X;RgmDPON|SHXs#hlBVuCaDHKjNcV;B*f+es41|T%k&Cq0#P!aiLDEmiE z>Sc(6F#odyWg&fGe)HzdrVV&UIhq}abzH}0o#C!PF?>pIBB zR`W2<0y{BCupDw)yyH5j)|S@)_V4`ilg~U8_pe7UG?@+`c_2ElmgjolD8~X(m?Uzg{bN0U6aXu*DE&n# z45+9g&#DiwbSJNY36*-Z@Wq6dlo`lWLO~fN;S-gF7)rv1O$Ipxfk}9dEE@hvSSFOZ z%`L7}%$Nbtw1N?ZCpSAkp+XUV26CRMpBykqm*LNV6eME0`Db!IIfOEaq#z5CifGFw z2QBFtbN_{1AW=)B*i;Jw1dA3*7@aCkpn9%%>s&G=nOOa|YS-n8Dz&X%Xk%;Zmd%^& zXR~|Tc{C#5*3xEjZe~tnM&oQqp0p@L1_;Td4T>0m z%hqE@kGfR1lvj{~^=h~f$?~Wuq=6(xp=Fw<$Qb}ry(+~_0suPGj%`^n(zC7hj-ewB z)WDK#iOQY-3RrWhjQNUEp#5Tlr>Xdf2N&Q#;{y+TK$3LO|M@uwpAyPp+2ZPki z9g>noJo!|3TBJ093zNa%?Q*_?nURrFpN2G7aIUKR@Z*msTS24)oM1MeOrX?8Q71(_ zzUt1buawYoxrz%IS(yf#xUn@*Yu2pUy?gh&@1D?75f;T^x&?E!W(gk(X}d!%CzfS5 zq~otd^tmg!FIknoC>Wt3MUXy1Av=7)lS=^NDq0Reg@6!E4n8YQ$w$Q_Ls$A_0E9dt zXG@n!$4Wfu=Fh;B2KU55iBA9-N|bRa)rnT?M6s?S*l)e_RzfGt$6rNv}2YyeUT*`i2=%_LPx9vBF@C6_*IFzF9c85G5?+$a-_ zC`aKkaYl2#-Rib)5J`HI#shoEp>L_q$Gq0 zb9F|6p+`E1G8ByZ_zvkWQ;`x6S+#)R`4_8yb#XN5-o4dbU1mhBXIP4`7SXEbU$e?) z@qhF`{o{up{ZJhDi8e5LA7#`RG!}sj!VsA@&m@>#(U%oU7`^%OS%tygYD6@r8+9=| znha$JQfWK8VYXGR9MV%NV}-XYfAA{*!l@|B_$)y%@?^411Xb#^QqNgAbREBoJ>Bo5 z4kwM^HB?51=*Kuanh{kNb4yiGt|v-Dlhz8wB?)8$R?n&PP#bwI^F1<2nGryGG`7*M zmdZQ12E$)%g7_7Ntox!!RsL|KyHHWFGKM6osU$sV^W+c2s>ivO-Mz;;ye$^7CXFz(20seDRp=83k@@bD{)st~!{JxM-fP{obP)WB>8 z<10f#R3wK9(Gmu>B6X_Qy|MbU#pM}Z95)Fad;cOA;E#>piV-fXnf=B-+ z`)?#6s9klhrM|wiv7x)8Y5kgR&-L|mbSy5+kLt26u5$6W2XiFx@FS1?qyO<&H*MP< z(Ty5|sOVmDM^#YDQHq6xu((kKf4b9-C{dTi=35kI@g*co5p7xb3g$p3A5oAHVQ2yM z2xq+PV>v}ODPv?;PboIlMeC<}2}lK5ieG6(c+?g_jUZ_tK7^xGtB3$8$e7nX2>;|C z|KmUX+Sk7SgCCeCRiX1Y3*(S#TuD0@Th~n(oBMOAtDdG2BMKw01tH8bX1s@b2}YJ; zG;FaXGQ#9Mji54#6PM4@AGhmE1)Tx$mzyF7@MLNMM?QF}CPZIpTjpmm`Az{nRrbzfq6DXEVw1*+k;llx@ z(K`iDI375)ofsK0u&dcgov1gg6m++DdQhjuL z1a!9b{^U=8>DkYI76tRO-fs+2%Q|4Sc$W|WRu`5{9nnyLM3k#aE!&KZYv~-!_aZ1mtLy1VtJ8U}9;1w*3jYn+IVO)#;GqOym}s4My-)k>sL zf+-S;)Jviqq%f7XkoG>SN?z4B^Mx2bsP&n4Fslse_`{a0=dNPlBQ05=26}g9^9XAq zNmb!b0pMZtPb~_KZES)i6H2mUNln{Wdaxj+OFl9PSUPwnVE`CzCh>EiN)|$@Tz^)K zPsb@4#3VeJG<-lpXhI9+szvG%@FL7t6kZfF@Chj+vIdoe(8EO9WwI1)a3+NuK^Ych zho+QB`XoFI2@IZr9JTTeCW%b);OCzlh$Urh0-VuR)bi-~#D(1K7%3MdlM^ngyl0We z>n8VHsJF@uCR5FA?Pl=2UgZ|U=?PanHGb^rk9^@LzPM}mZjF{HR&=8wI)s5diZbZ; zQ=}^kH_1ReVu1Nf`jgJ2u(ZK3I`zpP492oE7g>}gkq{m6VXLh0CUg+t4OH8x)tYyj z=ITr&8TH2%F$lEBysEUY6!KzHC@>Z~NRir#j#(5>>7(K)_#{Z_60c{UefF`(9($>n z@zF69^9QD@WR7{l9ibLXqvuv@UQg-ZvYp)KpY4E=f*VLI>ZqVH&6ER#z(WNQ8pK3k z+-Aowpa@CZR?hJ(kW)E16R1)b?%wE?G_4lqV~Opg6fAZaG!0!v+njp46U zBGK$tlvL4KxEOT@cy{7X?gee+qZBH_0Hlem7F8@bf*y2g(( z!v=$LvLJVb^6<=za6}OFF=mXZ3g4NWp-0U>{k309CMraAtAQ4yUDEs@iIzs;L>eVc zqm)t;vy;ng$pjUJTl_11$5JQ7IH$-ioCQg6zrcnbg@V@E_I~U5@#8PN@WQ1_msG%f zD7N)LT#h+DbA3&**joCfwZw?BBF3CdEMPEY_A3Z32Fn#E#3^dRc_)#4s-Bsd57-C; zjLWFaAjGKk84f{d!w(MtVCl&%u25QGs)GbGeCQYep{d5$2?n2{E{iUHL%5(Tgz4suB)*xA1EVFUq?O=PQfLYN94qLvHEi~*R@TIo&2pf1TygrY}| z3S;j@pDSJ-!Z)<&S!TLC!HC5`o;I8`AvBQf-`t$(7F^9q7ck;xbfnr+@3^f^6ftCN zZgJ|u!-k|cs{p)WLc=@><_*&2-h}Lki?+m*IR%LZndRWm&KyOG%ZYNM86H7ZY=9wT zXK3WKz!&BP9zIG`D`Liw19*YOd4J?K;^K_f(PDihU6|{pHW&8o+jHMT2M-=Nc(8Bn z8ksWYWZ;xUFd}|J45|4s`A^im9vyMpa5au&DB!4(&dRVkWk5#>MBffgq`>irpOU2V%4VrR;Hiea1=R#RV76IA%%xeDXwqSP&wfo2L=rc+EJHDWQA1`ubMa)wffB z=_Vhb1<#<0k5~v3om-ZJ?L{7-MSo@i0RMy+F#$5gN zoy+xi+a?;eORcoAfjl~gl20Ycp>T$OnMA0b|7vJ^q9nN=eVB7zijxZc?b{ z$saH`2grnhMC+mbA?S?a_bQ!O;(|0AV>+`qL<=9l5>izgZovZ*25E5!g_bhbET#hR ztFTnTiNzK@l9`^4eOl$7yYO))U~$~&6@r$ff2GfRVF4O| za^4*ER!sIfl+x7`*GX^QyvYqIn>KIiUA@|sqk1FyBnnmbkeaPWq7C7xOt=I#M6v}T zhFu&Xw@fuCN+Q%Qw&&cfZEh2e=(UQ7gG$K6E^1 zv?O1u`XcwJ$vjk)c$p%;e8_dAmH7l(jL&38@MhJL7s*;TZrr(b+owPAaq?kr8ewwN zx=Usqq;S8b8=dU~j*G=+ zKyt)L)a(@I)rPi^(O6(8`&}eNEXWxL8^J`)+^;*mxcNW}q2h@;ymT{DjB?$gVa^er zxC)gmJJ4!v<0MYmFpzSec|;_KRHA^?o6*Zio$b9R_+c7gp2$rQESi&0(sfM)3K81I8#iPP1EFEUs3Rd@d&6d6Mm3U0ig-9TDQ-2TJNZt!Pma{<}-{p^cibW=KIO9!Mg3 zAc&RvO0@uI!5>-4i~%U!0B}U06kJGE$a*m{@7IZm$VxsfJpZUyZG_&7-{s%B5Nw9G+qNwuRAJ0k^(SJZe2mu zSl@JqW;wXH6wQ~YvCTkHMmuTQXrXSE8QwaoVzebm7*=E^7I)<=vcWE$I-yB{3Ge8K_f*sv}- z|Aa{zl6bs=g!1T}>f{Ro1{=ae)Us^e9G4ZKpMldNC;7d2;i7GFTjGvp7#|=K~u3o+RxzBwL@N?h)9)!ww@18w}9z1mA>Q%Q0 zJ^QIoee&ZUClYtfp)l4R?3cM?zj3?_k!i7u({E&h1zR|yVTgKA2GyQUj;KKqhRCEX z-6c}Qio}=gbR-_`{7e9D3MV7^38u((6lm46@Fc+Q)s&~g>q{#YB-N=kW4^h_UUVCa zQHU8G@@Tm5g|bFUB^h58&$@a$>%1U-w{CpyUUxkBs3Ru(+D044;##|=>81P(SfPuc*RyoS5zSfom?0Tj`UtQ1}(0VvFfi9t|et2**iC?91M)l8Wj^C@l= zS47c^klZSLn1A-a{o+u|Ad51D4HOrGvh8Ho1TguP@!|BtrmcjdP5>DNVL+@%_P|AKr=9#C@8#% zF}-NIYEP+MZ!XRg%hq4*KWzaIQfArm$PO0N#kNEwaRO!}7wjtH#HJOxm)o{&+qG-g zyYIeB6^|S_^3+pLfrrG)wU0dV$hvjwWQU0x=i?a&%N06tD)(q@f}b9jaO*-@Zc#dJ z(ML>TKt<7tAkTj($^tSJQ$#FA6jY@v*=Q|ioBPKpio;h5D`Q#ArmH(R*;dQ zqE39!rGVu^uApH@Ca_-8$%0Z9C2}c>n8LvkNvIvS}cBCA+YROU>+xCVY}0 zH+=YKP=<<2;zcYqLR92gw5fzXITVf1R3z^7l$@kP3ap6EM0B$;F5iY$lw_cU0B1y$ z@JEBIu!e?i>bX($lrT|@uZX5gBIqIFW3biLC9cMtdMAYrwmUZ6R1*t>sv>QuX^}`S zia2I*jm)t<2rAN9)G#(Dpc$zkIb6bRT=2|CpP?SW^cM_S4?cJh5*Mf0sA&8emo3aM z#GFB)-^e#>73CwFo;oa|5f`_)&Cmc=Hzf+mRSb)I5L}1}5+pZQX2NV?4`C|vj(#mB zLuC}?5}06OStLWAh@$aG6UmoCT=ocpxYHA4`4p=%6N64+2@oSlxM?5WgdZW)77ErH zN7ak~7%+{N0hKz>IMfRt4n`C}B{4Q!gdUKMY-{e0uWy*Vy{gAJ)W$KjA3cbwNfi`m zA|Ht^Fcc3M_+W7qRQZ#>F97^eK!gK0^H&@`8KL|XA#$NFUMdki$UMyu6|f$<0BFfm zV1Qq}8#xV=43#5pDWX=CqH0kswYSI9Ag9lqK5^3hH_^j{0B|NPN+2ve)qs#lz$Ft= zztTekHK!eTMoI-3L&S|M8H|=3%z*pVl|1x$tEIXUE2boo-LE*3O=${OrS2N zj2d!%D2iO%xa_{1g;fvwl(Z%^iLb_$DF%_odmL!cZ#N9PcI7HfGc()M-P6|6VlZu5 z30fF%PpzT#gG9?T}taF(9aO11lXqi>^QIx@asu#nVAiLbEB9vP!IYMTBA^^^^ za5;yDjT<+b=kDz8yg773@sUy2Amr+*XreRng^eN3@Yd9-;Hw zzfX`=V8TUA{AKI}1{v%q>K%b04@DU(JN{ysM1pWiKhzaYL&s3U(t@X`aWj?3prg-O zKUveZ;oj(YO-Eei7J6MepoROe;Bv;TIDC|f93JAYJhB*ka#Uz7%?La`)07k=qR*^W zqqU({_gquwRP>^K1~Jf6<3=vaLT3>dQDh5po{%W`M8!uP9~g@e2#uPxw)WDM%U}8J zuYCKv-%&8=0hT%tIE&IIRoo<)>=H*f(i1$-?A>u=sJKd3?SA9NjZ9kWLC&;7*REX~ z85v126$GIu6azea*REZH^bFa0P4JiEsbnO`E&&YZ!4ih=|$Ad*{xd^(x+$En8dL+UYDG)GBTm%w7??xOqXV zxIzQvIx~)7MlRC9GcvcVsFKFg3`#Je)C`!<#K2~f8|e=Cz!66D^fc7v;1djf;zJ)2 zL8^%zxd|r-C5!42`Mh&)bX9kGG0{7lXpi}Ws!612N8A!nQjE+nf~skARB}=%5E^af z3IGvHq=*%e3E)~+P&xpm=7=aIKM`F;SW2B+VXM@Mc;+G#Wy>JBz|7O9Pk;G0zWmOS zBLJeWQkL?n{DJ{6Pf4>Wnd%ySlr!Y~K9B3orighd zn%>?XG~61WKp2{3uxKC#teW%O^4K_Pl^!J&@x*Z#=HKI2JpI1CyesOxP*yzP%B$`0jJJBV|%X{^s6|rUXDnT zqT(PBjAcfbRet^J-#Bybtko)02SqH9R$*>XRd^(cLQcs-5L=Npp766pB#tH!K*F3N zE5Br&E>SJS11n+?T1~QvcrrP42C0By6CD8lshYJy?icc=ACe?07bo97w0CH4 z;r)HSnE=?5_Aaib=Ry7I$;!&g%B;+?59a;sXFoG>r9{R`jRfKzo|eXfNBP#UUG+8t zb3`){psen+(o~t1j97Jzq9oL#f{e1Gja-;?d z&6_@j@RKh-SE$#B6!cl7Md|5g?K!Dr6nYg@#qiKCA#pC40|P_ZWmX!9&)x3LaB-n? z!H}U6IGJmGWq4q3+k!|5xtgL1hlS7)-!<~KyJKHhkV^7u_@_Vl2~a<}q(FwJ)x(Jl zbA-r~Inl$qq-xJ^juKr&eHA2Q;fw00a#CZp%yl;EevCcD})`eX2N=*HA+F++et+v8Uj;ZO=$p=^L#aOoJ#BpxaxlW7qb z!;u@_*XN&q@xvef2nr3Pv>bk~#RjKF{4?Yu$}poO4DHod+a{Xg>hk~`|B8)LE?`+i z)SZr0(QAd+r?kxjxWl+!6@Y{0~3<=_j9jf>BI5Q;Ax5q$}ctEtrr- z#|O@W+gezjbmti-3)Y3gCbPkY17!pfFH;Og-NjQCXCtR3Z7RT}%a<-cUU_1GYoYg> zZ@+b<=uiIiPhD83jeM?)cVq6@*A3{HNh3^#(2d=cP>nF$_mypi-P~Az_~7o`%p8KH z{NWGZnS3%A^`lRJJUKNTIUF2N9j=6bIy=mXb?{$o#F0vb{&XX>$cWcyF&4=Opbf;* z(3#5#eCRLPNUhsVE5FIxc!wrHjGgwkFYMi38=Nv>X~`ak)g65K{(-_U6r-FJ8VVpCs#k z0%mASPe_gtrxbBdMUz6Z3o`Ys%_8ilx8U-zbUXk6KmbWZK~(km4WqATI;1q1T;ep4 zEs~d5lO7ZvOJvq0u3x{-@iTN(G$Li;D8|(r83CVJpYicdhe}>0dL^#J;|7fM2vP_) z@&J%Lk`0XIu>fa4n7q7^DjBN34 zo48~%Ox9)Nv3Kn|_bxcPjl8}_H zCa<8FlP56P{3I;md0pXs{3q~K8E6yJxf-~+ph{i;7KsKRUN+4DQws_p;Jd_?l@;qz z|MXA)l&kV;vJQaSwE&UJ7V*Y^B5Hm%T4K!-0`5S>GR6%r7-4%*}t{pH);Ou5nkl^PDXXa+- z$i052W=f7a4#3Lo4yE(L1HWKxAA+>lJ*8hN0uA5{b`%DN?budD`@KsS*JRT`)5BV|AN!0_P846VaAZUAMceH^vlU>kA zWKID2(MKQMy?>vau`o8%#1|PDFmwb4o6yvHiighQ;3ty&Qbg9IoVpwN;|Yuyh?;u< zpcLAofeA6Rq`Y;KgnjkZR|rrq;3o9Q7OHODx`hDJDS-DKh1?8NdmR-7Ayf*b08N#6 zH%+&cvZOaouapiF9&aTQIN7D3A5UnPS3;u_K^ubrSVSTWOroba#S@Vco<<9-`601; zgs!9X?ixJR>&(JDZ#;U>1+C2q%{|IYaU}W)ztAl8e7y45$+f@!>%WHKH^2D}vfaw} z@ZrP1`@8>k>C!TF`Y(U^mpA@!VU5 zs?5Ao=9QI4dMr4RZ5OUS4hH}uK$q&-6%^@uosh(!@mDn~>vwM8)ysi}H$!t=QRe{T zXdX+#amM`hzwDi&v#fQ^!QYSm#qNO3h7KBMi+8Oi)Tkn>IN^{iXlS0`gY0ofaU4PY zl-fXznhI*1{>T3?HX_0?hZT;AAf`vkc9PfoM%6IzE1xCtGc!|^TE`K@xk)7_CyBBe z#s9YBP8V`?*t}VVXu&w)2pgu9_D3vA94%+r?o5yry0+mw_^z)teel6`U^nk*!Mg-b zUPu76hWIHUtZmLolXS$Bq-thw?7;e}Z$tT> zV(jFr*Ds$weZt(Wt*;r9Rc{b+HxRUn$KSFDX~@(iY9#oZhn*4@6eVbr-meq~GnE4` z1!1jt;!@BCxErOL3@SvDQLMKiCb6+`JEV<8d$CR(d3VO#GMhWm;et>#8DW4ELO;c& z=$YK&HotIsVd1n3yDTIWJ$r8MLW@Q;m)mAmx{Lx05E{m3$|Ki`?z(fxLWRBwLj5TZ znvXz}&o7?+$yZ;VJ-c}B+#>zd;I0GnJwu~D+*9`Hc^?S!eFbeaYP|iy_3I?+*6q8# zzu;@mRyN$_&ShO&d#7?!lUZ<59V|kOCrUg!h||9apsff8JKIBJ+XrL2hI*NkF!;zi zgc=kuCT9#tbPNV9bcj1A@4lJ{H}M#rHqWMN`7cThw}R-Nx~J8IW<_(u&loX(@YGWq zD@t4<2tT`6@uoZJrb_DyGx1I&r6QeIe7ret-t;K?|$*if8dQM zT?2b!2YKy&u}SJun$8q=9K01;!Q_P;rTRX#^Am>7C;}(Jl@4Aa5to=+TR*7jO(+oy zOk%Hf4&weJm@gbZafBXYo)s64Jf4cJ65b@9c z?9U<*g9DBU(tB%-WJl*FJJXZ3`<>mT#l??5{utlviSyQ8isw(`6IqhEckiwa1ac>p zHJ?^cbTdl5PJ%?@?k97yeK>Af#jwgrdeo8{ob)O%)%!*HsFju*8g=7=Jlk4$;D8ot z>ReZvi-UQMnOCEP<-n!rh(P@)R6*F04B@;~OlnmSNYqY>_lg=x?DXU))^}4?i$o#| zG8m<|h=7;q*@=xAe;bcEqtNV#M|exL_sx5T2QiGJ>5y#pDP2Su6hun1wQ!@2tboCY zU8n29wXBtGJGQgFq493s{2qH=yng-k`LicabCL)R&BP`NhLf6B_V-=uBWFpv0IWlp z*Bx4onk1@AtAXkZ@C(53%}>;F!w4xSGm2Ym(H=An@#vA)GqtNyL|UvN0o)?eS}Fx3 zFi(XxJ${P6pWfIIDPUB;67O97ltt;@!s+RX#8y#n{e&4>ln4m$)YUTkMShA^DTz%< z!$@?0BQKN_=uQttsigD31SYLhBfwmVDCe<@8$`7>+a)T${`xon{N(AA|NIw!;X8!J&#WaIXiP{6*WRt_<1F@m^694^UBB)w3wJWyymjN_ zk3XW!%rfN{AsVKCnEzs=IvzE#S{JvD%#WW4>%_z1QP&skQ^6xE6G&C|)>AlAigd}U zxW}_HTp^M9Y(+bHt-RH^8Ei;c6wJfx7#3_ z(+vkG%=c4v6zo}ZnwWu6-ZWz+W?m^rmV=4E!K7Hj?H-7jn&8$iK3;irdVW!#mpuGT zpD17RdDcDiX0G~v;}YANoM3EGttwsNpsXM@FDj&aptz1{T{2H89H17`h-SFq5#>nbs?VF8}P(GGV_+hoi~ zUDKTUK7&^V(5TF4JZi2(QCzG%V1$1Y)brVFt8a`oCZr#ncSp4v0>_f#-z@fO;&N%mtkK`NeBP}%G{i2s#(X7R9; zEn|z&3?`Ao{ZU71UDVuv&Lq zskoiaSP}>kj24awL&Z_3Jh7x`k&|qRxZ=ajs-pu=9pbR#<_Ing#H5;pbl+n-8pkZW zYByl8i%SLLe1;if!`eTwoW?5VWI$+$j|Vxv=y(zjL>c6RJn7ms_J#B3`Bpb>-g^Gc zQ!_Er_<*`1Ifll-kx?-tOg@)``C(njyU{6xp%#rRV8Il!Rax9(P zcf>2{E%z}}^_D|SP0Vw&=BNVQviVa`v_x5&hAyI0G-uSP?gJ0i&UNkK6!;H{&`i&5kPo4qbz{2QgMP&+{FtQ ze5})F22*hebM*;sWE?>ybs3Ih$nLH6K=d@n?Q8RT6S*NBaFI>1l=bt}$LSyj(sWY>u^$gai%+Nl6`O>F$C(OFi4-dvrUXsr%hy znFAva3mT)8{hYogb+BWy<8buQO&Jk%qS9lqHs9iG8g%JGOCvl}T>c0pRY%mM{&tAR zX*9E&&&H*~x%NwO>#J^V$fA?+hID&Ao;-QBVw=;`$JV0Vqi@6&w7RjVUfLTrPa(f6 zr6YeV{n#7nx1r~#XAGdYC*V$m2k$&jvTLD!TS|2_E#4VZY7szCkRfPDqAHPG%H?aa zhO{sfGCx%rjJI^a6B5V;KRwAki#0Jm2^b9mZcs(^wUrO{LlZ~LWR`}UeBvn*;DGf*Ay(P zuY-eb@h}DI;D?n}=P+s)_hwcF4)-rEEnWZMD!b1px=M%E7 zmnEw_%f-Mn9k`ZIWpstY`q!GNH%Fwzh=sg|+s^WBtPg%Yv;bZ8W3J)KI!6iokyTT> zu5~h&L}do@*uPDQwgDc!DB)9f|CEgYAP8rhJJOqHO@wmHXZnBJ0Cu2`7ZFh9Y3bS; zn_NgU=NVpyZ1k&e?9x$B5aMJZ2i{e+Q)NsvS8hv{4Nb&?6$@3emHS5n4Ia3o-+cF- z&(pIkVWN=fswlb&1jn%kB0H2<=u%+ox1_2g076}b_v1`^#r3mSi7S4W~Dw=c|%Tgy6Zf8o4+SYO2>q7Eb}gjCLA@PoFw>Z0lDQW3$hv~}8tH(UDY^XY zeKt0l(k`zQjej7)$Y|8baG;Dm>}g)r1eT^G0LEi!3i>SajEuGhnr$4>}@B_FN;_Me)bIx~Oz((=X2mzLdsFz(LU8a&$w%IlLi zo*AvrtU*F7Np&>nQH82XIt9{Je+VOfM@31qmZV{_bHqxE6MZ$Xw3&I)k-_~fQyt!C zV0GMCx9CHtlqxU}F+XE0s%URWm=(J$*|nw=9SAOAuFUEWI+UHLN^+~rh>zk942|zQ z8iM2?3IuD*Kq#z)KRp9=P1|ZK^+*G!f@z0>NQwP3NvWz4ir2`**`3{dK-D&RGoRL6 zpFGYk3S$OlG1bD1wDIuhVRi$a zw{9FYQjrQ$I)shKvm+8&E)|P^W_Gd0V`;EnVY8I7lX@vi)gU2EGLr8WK`ChSL_?v9 zh<8eK)a50FX=pH4gVJ-Ht;Pn^q*69`yn>;tBSIAo;l}fo0I=d&GrqME|zCJrMGea@hK-h>#`hX&p2Lhmus${Gqqq?gd-ladNr<=f&ejL!I zXxSC#DY@NgSIzlCwLONG`0m`fqr;g^8SFtpTcf53FhaK>4R zBQ|w5*EFljee@v5m3A34W(W(Ub1`l8afA_^V|{L04_ziDZ^a5`O6QqkgCm9zG{hX2DN&)z?-a<@xvD|!14hjXJ* z?f|OuJ0z4yNYN>>O6_EamTKk*a9I+y=!%dJiP}b?o+0Qs9FZaQ_^lKH22a@|e-$8U z{3_n+lw>gbOjckNp~A^kju3{pr`>Q))d(B_#P@8z>|I0`dW5<9X({l~B?OXsS{|_* z9ogB9aq|{%UR6b^{E*tU(<=09bI5mBhUt%7I8oB({^^`Z96uzZqtK4{NS2A}lGo$) zv8=XhQEBAHP68D-B%^_vz*lS{Rp|&KblMlO$`w=-wFp3%fh#p|M#Se7EVZK(g(r*^ zIZ5d_w#XP#$KyC?P*ch-@3KRU9oE`y=$NT@S~4DxNg0Yp*CO2 zD`N(yr%uK5s}eOF_C>ynLi}>NiFE1!+P8^vR+ZG2j^(Q?PU4!#L2~8FwCAA3MiQL` z{qX^}>iaQ%Flc7T)zn$nk6x22d205=ToeXsFU3WlIkBXOf>u9}cv{W9!1$1Z8?|OI z=sI+AX1u7Ik1mns6PBrlJgQWTOVq3M>zrK7ErTs{`Zp*GFLfvbiz+GQ38Yie8wCnX zU=`sve8)ycqOv^opr@xNUz)>y@xnoABSOo&w{PEO2u*GHyp9v%&dC8@TU~e6iorcC zl?y#W3!*204idGZ*3`O!5~VjKUWpVH=@F`GWoxUyAh=bdbTq&q5df3R&e#l1>L?Qt z^=P!MY~)6Yl?ekLDGjXXbTr2YAkhh-XBXiaLle%0Fu-yN^p@^APzYyNL84;8=hX>U ztNJlPagMS@L3b8?D4PsEeSgi`g-hyaUZHHhg4DDL&V1(3(dg8|9o^#@l5z!wyy6mI z7^HN@CZKusM`mi?+KZ>Ys&kUwd_GB$OMuNL8^sAImqn0h?6)(#rAA#@Eo6R5wHFu9 ze0=4~rHkiHz|72?#s=Ep)4iwXbKW97MAgW%3+ksChkUJxlv0m9cWM~&MAX4jA7Zjk zs;P?!!cwp(ASNC9Mpz8g*ua6_>%f49*hjtV=~D#*SuW-~54cs0AlD&M zbDwJ(aTj_e2ltT|lUzq=6G7OKN~i{?SiPx<)pu|2-@i|Se)qfI-?(+lfiXhhn3-*v zXd}U+<4$TG+KA{16SW#2o`Bx$HY7qSaLoO1uhfR@LfEDEvtc~_1g6OmARsUK3qz+U zB6TZO^z=$fV+N2Chtt)GLv@sLd|*ns;L+T#nhe>oQHk=x(-PMB{iKNDa1G3i!36Un zQg|y&qAZQGDeUYLkF(G~pRPX|4Q8*2F1(5ZKsvPgQPp(e6_Q>|3kPaOKpkXJDC;Cp z3?n^FC1a{r)f7MBn3NM@60a2q5e%oOp57`-L732x9dDk1?7%@liSAPA;0-`n_4s}D zIRmI>r>7RqFI~BMdFkBZf-_pPr^$llT(tE0q48w;b69X@XclY1z`zRd=?%`n01Wz4q%pSaj@y+n!*1&`rQSP0f2*Fgh z`v4dAx8KGG7ADQ4Dx^*aJ(1P z6OQUTqnCxm`;^*}R`n@o_HfWXF8UWnql~cXW8#FCgPqY4y~T_A?nQOm#__a6&D#ti zk6?vEl;L2{81Qk{1cfI{7ccza;~)O`$3M2C!quWVQvK%j(`U~gK6>=+H{Wqk4SvwZ z?zc=M6&^uiks8CLE{$J70+^0?rara007j(KPqLqYshZF@C5kX98nfeUl((|$zddEg zI>Lv0el|%>o}cIuI$d_a^6K4zHa1UENal!RtAVHSrr*OkVK>6~lRRKDo{&nQP=zj2 zTzZwRvU7|ZrG$hPPF+<=R|?Iiw`%4C@jZo$r1+w>MglW8F&8GI)#tzx@1*tkjH-&z?E! zYhG*XtLS%f!v6lrscu0`*EA%#B_F<|bHz1Ad}vx4Y0q2>(?woM1h;i^V9hH0=HQrp zq_jxKnuAFcXK-M1aGc_9a^bfvn;q_CX(D2f=G`A085rGhF%wTWzI=IkTGsrf_gwWV z9uMiWr>4O?_ZH{iRCXwpu<~a0P(5;Jx`E0FS|%`hSH(rc^$z=cwvjTP>BkwF9M+(v zDzrZoc40QHj^3&`#>)zm{3@RTQTW@m^&pv_0|)HOi{(er_xe@D@Y`KtDr8Sth7af2-OnA zNm~;GUeN98m*Wb>!>{YKM)IKu-XJybq_;#zi`%-XT>subaTCE(N|{h~aYIl+O=!sfG8UuT99?>T@ilXzI|(bZFT9KZNujtK61m}782qy6)XnpVbTg4u$UCn@X#G^KH4+=1 zrTYnzWFNs>Hmq(-zXiDAJrx8}xhGH9T0=tNVJ3$vl5)X_i!hJW8TSNbNem^$6Dc?Y zi6Bi8dG%fZpnp+2r8HP$2I;3Eggt=X(m>lD?93P&dHej;^VK&m8T=RTd~RTK@$~G> z+^jS8G)Z$C>)B7TzqLLz5i^HG#X39&8zn?{oW%;5hNc)YiKY>~WD^Ib^zzc<=E#y| zcnGwdxg2=S%f!^F5~Y%dmhkX#;E1vQNRkWkm@&Unt>#Q(aK_>D73|`jdUjPYj3eLi zN(-m3SO#pXjD@=9i@eAhFFYohhEhCe3$+0Y=ZRz5Ktw5B8FY@2G#w@R?`7Muc=7tq?HIZ)QK7_0=!Qo$8oUx|Z4?(yYARk-2SAoovi7n_?~Kh2QsO57n6agQ z>U3~cx-4FG1U5k~uLQ20Ynnv7mA8@ji5OXgewDl>vdRqwg#^4R*(L@$lS0RgRCHBga=xxgC@hWS2Z1=qFN-0!!Joi)_V7;MNupt%a^l4z4 zEsZC{hKo^4!7D66UieiNl)dOZ8gc`GttshTx|J>tShT1Vruhu9fucB)jEvm}zA!ht zeDNa8w{G1+o3#_DD5@6VPKo<8f}6YXNS~oqc(--Vt<8wqC=QLR8Fd0+E;Q3jaa1S)l`_{E&5cIW$4n(hQwqCZS`e^bpj8L!#QYRc z*d0*@_xKy`)jNJ%olMGm)$4R|FhzGR!^dREx#evv%Js>11Y?UdK?$PH)yzSOeKkwa zr!H}^;)pxHJh(YH`EvZ+#e;hf2Cr<7oHC;08OL~o9T>1E&l2kL4Fa_dDGW`uLCmo` zGX+ncJ$qoiesjyMK0p5CNB`~b|9g*gn`ZKX{;pbA7|xb}2B<>*)dPC3FhonsD_2Qd z=m!TC8Hx~Cvo7XQZx|UJ3mZjEHuV(vIjAk8$gr>m43SML{22w*glA)x&hq*v(mZKkkO>Cr$K6NM0O!#gvEx}& zf16*(JBfJP)OOJkvg6J^b%_PbbW|62LX7l|dwO;9l&&{vOeAs zb>Dx_1VFcg z?T{(4C9jpL1;X=var9FyJge|jN&J{6kr-&{bUba9F&m(g<}GTLU+g=%`HFASiO~nz`?A4NTO3y2W<_mV|bbtwJ)K4iLfQb}%WvOFRt%rWAPGx~B2L+w+ zB|<3t=J)@ywZ6{oY4@{BXVGY8e0A;Z+1ggFBh%gQZEuj;(Wwc2j4#t!|I5A26YE;PoEw%RW4=D7Hvp1Hn$AS<`Jyy!%&LO>Z* zW+M|xsDZlG{I~!Z!SB}zs5NF9LjQ4pU^fH2c~eYO5T+@<8E3Mak5DU!)m_BWray5g zX=Hc|N~93Ylqa7BPwSY8WgeISiy*729JMwHD8A!9#lca%O9<_`1Ywc|x+4`(7P6?YTbA3}#eSm8F87 z3X&_lc(3986r^_|FsS@w+z3GnC4jV0VT-$P%pxf`kvS5YR-QaaiCrA4)kVjx%h~@U z>D=DSVm;~XQaTGQ>Rh~4we|`O-E;2V6G@&@L@ZVChSTzRJ~DJ_H8%i6UTycw#D))s z=aL(f4@#Fs=t`j{U1fU11m)_m>^OlFj3?Fmt;u+ReDGKrm5uRF*M)Y-?Z|7dST9YiH*`SAs=O< zhu!2PHV#-E8nLRQw>oi@_^H(u??oijTTrE4vWH;*mzeo0l>Rf9`FbhB1Dr`+pG`}> z6ezFyii!A%@o9#Bm;8|WQ9-;Kqwpp@`a`C(X)mbLkg|q8yEq2-&+M)24UN7VJ-;0t z=e6eBEXrb%6b?%oGJiufLtB3m^;;@v1}rEIg49j8TMFU|J%{khmup5^v!~x*)DYg1^v)GhpQPii|>~k^J-& z%nH^rbdIhgTZ)^YYQ^wW%x2BM+bIG@qno0 zJV!?8tZI4!Nu!sZ)X!89&6SHlba$O`DHs6#79K2+Q2>mA;HhHwXq^Zim@IyZ3n2U1 z!i+ZYpr_e>G+~c?im?pS^`xQ{Rq!e3nLqwdV(m=&@ z{q#RrQj7`rWbDHIg)o*-eiiHAZH@vIf-opdPXU=ZXURfkPoJ{r6in7pJB{6j5MSB0 zobXH%@aa=B#e#fhQJ^i~!{(;LmUd~um-(LE;!2-EhCna_dO zZ(dzozJ$d(#mw5Dnsz!H+8)K!m9pt;(Ts9|h%_Z9DH6NN&GCZzSC0@-f+%l0wA5Zo z^%}AUb4xRZ`k5_~dfYODezx>9cz66Q+`6AS=o`0Y_IU4 zgE-{!8f78Cm{36$9@0&WPdG8;gpv5{`q9TpktE%@yLMumFxi{(CaL3uLvaAw(uxRD zLU6e!kp`p6vi~9|$qL1BFNRKNAw-qQ6aZdfv8U<_$y=8)T5}g~UP}?Y?XpBV{p1M} zL%=l6uytOM@zDueyRTlk`uN3jlTr_!JY9MI%&NUpj*AQPGe_UR*}8b){NkBKU$Ju+ z6?!x~)i4ey-ew5IkSZPiF0}EpYMG}gpQ#0@(>o6M{hyWbj~!5~04b*GgNNJ93bmDl zEq!V!DjijfW|kd}ierxd)e0$|Fw#1TQ1+xZ5R@CE*OR{ML(}CM1EpzdmA)b4A>S~3 zJ+zQp^DUE5xy&Q=vQHRyth^%SV}*{$abCq>`oduboU$>o(feGcbU=PMUAeAjd+Yw4 zyUKGWg>(PG)k}*@7cI>@O22&hGSVMEc}n=KV^L^Z+XxO3Z~O+Z&ATp9qDaT3BcM}6 zI`QPENXsSR07=RajWzT@x*&_t^3m+_lhAlJ=2k7N5{bC=*4g7;#&j^uyBXDInNC0e z`{uqDM8U%@D$~G^AyZtp5g4z`OuT%RkIxvSN%4vT*hr*f^489{sqslxfp*eT$AMvB zI=}%#TUV{A5*M@v^;0e@s4O@u5L0@^mr0}RHb^UA89lKALL{Oe0eTnzG^(}otTCk~={V7KY5zhBfM#+?ISy*qU=k2Rh_RsP$;=HuYi?%hlOKHe)31K~ z?f2ikeuE!x*H<@I->$!Y{nl>Ai|3c7d2H4^t4h>DPnn(pw+-8}s#1|`{Ucgn|7UW%$cT8yLVU5dG3f*)VI+hy$s)fucEI+3_Ma(AZbk8_arvT%ce9Zt22#-6tm7`0V7O z!mF!0_3ZU4M{jsfdU}Y6+mAl^(XW5=doEpSQGSjJi+4Dt_DI?M6pmm1+rR2XV!Do+ zTon>{hzS zu0Jp?fN~qT>p*Z*+yHp95Ox&Gaa z@0XX(+hKr#i)RNWPEBVnlOvjm%(6sTj!yLjy@u&d?OS6g2joq;j7%N8+B}#eK&fVK z2CXqz2|#n;gxc~vOOxB84(?qXxPSlP3a*b2>~AmwB%E2Q#S6KLt7*~Lz8bY1O**3t zHL!=zHUA(IzgdMVD4kZc+yZV2NCy2G8Q32mbTf`mTbn42J(XBEj-)mf)i9bdolyQL z+&crH45T4|$Z(krj{wAc^BEl279%%j<`-tBrgP`{`ld-g>%j~23qB96IpuTC#n?bU z@slsUbi()b8+VPSMT7D$6|fP_Sxs5K191kf~usgbS(Jtdm~QYlm}bCA_}DFtv3r9`M4gd(Vt2!@?u z6+4}QVp}9KW)#;nkZX7zJbK7o-J8nL(Jl`~G)Y}93c*WkR9#03rA?%u*;8m%^i!hJ z`>DPO$Eu53XfZ?tun0@&vL+!pOqrUUaWUh_ArqYyKP{9d$Vr?nHr zt;9}mwtA&rWV&I9I9V@9s3L+b7P2&a<&MnxNe!C0o=TCc#l7i?hF0g>Y6%!}2%!W| zB~(i;YZ!1UrORULc$ijASx{v29T&#M586SQ1NUnUc0I+_Q`)SBhd}` zg(goV!d(HW5(VI0I)tsIVC3~vIi2{BU)mhj?iMoWs%?%OVW#_H!2Gi!T zPx=%k0

pjzY7mRa9I-AB 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 _jupiterVerificationCache = {}; + bool connect(Node node) { try { _isStopped = false; @@ -1905,6 +1907,48 @@ class SolanaWalletClient { return []; } } + + Future isTokenVerifiedOnJupiter(String mintAddress) async { + if (_jupiterVerificationCache.containsKey(mintAddress)) { + return _jupiterVerificationCache[mintAddress]; + } + + try { + final uri = Uri.https( + "lite-api.jup.ag", + "/tokens/v2/search", + {"query": mintAddress}, + ); + + final response = await client.get( + uri, + headers: {"Accept": "application/json"}, + ); + + if (response.statusCode < 200 || response.statusCode >= 300) { + printV("Jupiter token API returned status: ${response.statusCode}"); + return null; + } + + final decodedResponse = jsonDecode(response.body) as List; + + for (final item in decodedResponse) { + final tokenData = item as Map; + + if (tokenData["id"] == mintAddress) { + final isVerified = tokenData["isVerified"] as bool? ?? false; + _jupiterVerificationCache[mintAddress] = isVerified; + return isVerified; + } + } + + // this means Jupiter doesn't index this mint at all, so we can't say either + return null; + } catch (e) { + printV("Error checking Jupiter verification: ${e.toString()}"); + return null; + } + } } class MoralisSolanaTokenBalance { diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index 2305f27fb..31a1bc3d2 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -902,6 +902,9 @@ abstract class SolanaWalletBase } } + Future isTokenVerifiedOnJupiter(String mintAddress) => + _client.isTokenVerifiedOnJupiter(mintAddress); + void _setTransactionUpdateTimer() { if (_transactionsUpdateTimer?.isActive ?? false) { _transactionsUpdateTimer!.cancel(); diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index c4011172c..3934b6330 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -635,6 +635,9 @@ Future defaultSettingsMigration( enabled: false, ); break; + case 70: + await _addTbbTokenToExistingSolanaWallets(); + break; default: break; } @@ -1325,3 +1328,40 @@ Future _addXaut0TokenToExistingSolanaWallets() async { printV('Error in XAUT0 migration: $e'); } } + +Future _addTbbTokenToExistingSolanaWallets() async { + try { + final tbbToken = SPLToken( + name: "The Bitcoin Bull", + symbol: "TBB", + mintAddress: "42cXQvAAr7hcPBPWAS4ocVtDyeJ4Fa6gRR2uG4gppump", + decimal: 6, + mint: "tbb", + enabled: false, + iconPath: "assets/images/tbb_icon.png", + ); + + final allWallets = await WalletInfo.getAll(); + + final solanaWallets = allWallets.where((wallet) => wallet.type == WalletType.solana).toList(); + + for (final walletInfo in solanaWallets) { + final sanitizedName = walletInfo.name.replaceAll(" ", "_"); + final boxName = "${sanitizedName}_${SPLToken.boxName}"; + + Box tokenBox; + if (CakeHive.isBoxOpen(boxName)) { + tokenBox = CakeHive.box(boxName); + } else { + tokenBox = await CakeHive.openBox(boxName); + } + + final tbbAddress = tbbToken.mintAddress; + if (!tokenBox.containsKey(tbbAddress)) { + await tokenBox.put(tbbAddress, tbbToken); + } + } + } catch (e) { + printV("Error in TBB migration: $e"); + } +} diff --git a/lib/main.dart b/lib/main.dart index 068755dcb..2f248858e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -316,7 +316,7 @@ Future initializeAppConfigs({bool loadWallet = true}) async { payjoinSessionSource: payjoinSessionSource, anonpayInvoiceInfo: anonpayInvoiceInfo, havenSeedStore: havenSeedStore, - initialMigrationVersion: 69, + initialMigrationVersion: 70, ); } diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart index 58999d0e5..77656732c 100644 --- a/lib/solana/cw_solana.dart +++ b/lib/solana/cw_solana.dart @@ -116,6 +116,12 @@ class CWSolana extends Solana { return await solanaWallet.getSPLToken(mintAddress); } + @override + Future isTokenVerifiedOnJupiter(WalletBase wallet, String mintAddress) { + final solanaWallet = wallet as SolanaWallet; + return solanaWallet.isTokenVerifiedOnJupiter(mintAddress); + } + @override CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) { if (transaction.amount.currency.symbol == CryptoCurrency.sol.symbol) { diff --git a/lib/src/screens/dashboard/edit_token_page.dart b/lib/src/screens/dashboard/edit_token_page.dart index 97e43411f..9becae8cd 100644 --- a/lib/src/screens/dashboard/edit_token_page.dart +++ b/lib/src/screens/dashboard/edit_token_page.dart @@ -40,13 +40,11 @@ class EditTokenPage extends BasePage { : S.current.add_token; @override - Widget body(BuildContext context) { - return EditTokenPageBody( + Widget body(BuildContext context) => EditTokenPageBody( homeSettingsViewModel: homeSettingsViewModel, token: token, initialContractAddress: initialContractAddress, ); - } } class EditTokenPageBody extends StatefulWidget { @@ -83,6 +81,11 @@ class _EditTokenPageBodyState extends State { bool _disclaimerChecked = false; bool isEditingToken = false; bool _isTokenVerified = false; + bool _isJupiterVerified = false; + String? _jupiterVerifiedAddress; + + bool get _isJupiterVerifiedForCurrentAddress => + _isJupiterVerified && _jupiterVerifiedAddress == _contractAddressController.text; @override void initState() { @@ -129,14 +132,28 @@ class _EditTokenPageBodyState extends State { final isVerified = widget.homeSettingsViewModel.checkIfTokenIsWhitelisted(contractAddress); if (!mounted) return; + setState(() { _isTokenVerified = isVerified; }); + + _checkIfTokenIsVerifiedOnJupiter(contractAddress); + } + + Future _checkIfTokenIsVerifiedOnJupiter(String contractAddress) async { + final isVerified = + await widget.homeSettingsViewModel.checkIfTokenIsVerifiedOnJupiter(contractAddress); + + if (!mounted || _contractAddressController.text != contractAddress) return; + + setState(() { + _isJupiterVerified = isVerified ?? false; + _jupiterVerifiedAddress = contractAddress; + }); } @override - Widget build(BuildContext context) { - return GestureDetector( + Widget build(BuildContext context) => GestureDetector( onTap: () => FocusScope.of(context).unfocus(), child: ScrollableWithBottomSection( contentPadding: EdgeInsets.zero, @@ -174,8 +191,7 @@ class _EditTokenPageBodyState extends State { SizedBox(height: 20), ], Observer( - builder: (context) { - return Row( + builder: (context) => Row( children: [ Expanded( child: LoadingPrimaryButton( @@ -210,14 +226,12 @@ class _EditTokenPageBodyState extends State { if (isTokenAlreadyAdded) { showPopUp( context: context, - builder: (dialogContext) { - return AlertWithOneAction( + builder: (dialogContext) => AlertWithOneAction( alertTitle: S.current.warning, alertContent: S.of(context).token_already_exists, buttonText: S.of(context).ok, buttonAction: () => Navigator.of(dialogContext).pop(), - ); - }, + ), ); return; } @@ -225,13 +239,15 @@ class _EditTokenPageBodyState extends State { final isWhitelisted = await widget.homeSettingsViewModel .checkIfTokenIsWhitelisted(_contractAddressController.text); - final hasPotentialError = !isWhitelisted && + final isTrusted = isWhitelisted || _isJupiterVerifiedForCurrentAddress; + + final hasPotentialError = !isTrusted && await widget.homeSettingsViewModel .checkIfERC20TokenContractAddressIsAPotentialScamAddress( _contractAddressController.text, ); - bool isPotentialScam = hasPotentialError && !isWhitelisted; + bool isPotentialScam = hasPotentialError && !isTrusted; // Normalize to catch homoglyph spoofing attacks final tokenSymbol = normalizeHomoglyphs( @@ -243,7 +259,7 @@ class _EditTokenPageBodyState extends State { // (e.g. fake ETH on Ethereum, fake SOL on Solana) final nativeSymbol = widget.homeSettingsViewModel.nativeToken.title.toUpperCase(); - if (tokenSymbol == nativeSymbol && !isWhitelisted) { + if (tokenSymbol == nativeSymbol && !isTrusted) { isPotentialScam = true; } @@ -252,7 +268,7 @@ class _EditTokenPageBodyState extends State { if (widget.homeSettingsViewModel.checkIfTokenSymbolMatchesDefaultToken( tokenSymbol, ) && - !isWhitelisted) { + !isTrusted) { isPotentialScam = true; } @@ -277,23 +293,20 @@ class _EditTokenPageBodyState extends State { } catch (e) { showPopUp( context: context, - builder: (dialogContext) { - return AlertWithOneAction( + builder: (dialogContext) => AlertWithOneAction( alertTitle: S.current.warning, alertContent: e.toString(), buttonText: S.of(context).ok, buttonAction: () => Navigator.of(dialogContext).pop(), - ); - }, + ), ); } }; - if (hasPotentialError && !isWhitelisted) { + if (hasPotentialError && !isTrusted) { showPopUp( context: context, - builder: (dialogContext) { - return AlertWithTwoActions( + builder: (dialogContext) => AlertWithTwoActions( alertTitle: S.current.warning, alertContent: S.current.contract_warning, rightButtonText: S.of(context).continue_text, @@ -303,8 +316,7 @@ class _EditTokenPageBodyState extends State { await actionCall(); }, actionLeftButton: () => Navigator.of(dialogContext).pop(), - ); - }, + ), ); } else { try { @@ -312,14 +324,12 @@ class _EditTokenPageBodyState extends State { } catch (e) { showPopUp( context: context, - builder: (dialogContext) { - return AlertWithOneAction( + builder: (dialogContext) => AlertWithOneAction( alertTitle: "Unable to add token", alertContent: "$e", buttonText: S.of(context).ok, buttonAction: () => Navigator.of(context).pop(), - ); - }, + ), ); } if (mounted) { @@ -334,14 +344,12 @@ class _EditTokenPageBodyState extends State { ), ), ], - ); - }, + ), ), ], ), ), ); - } void _getTokenInfo() async { if (_contractAddressController.text.isNotEmpty) { @@ -377,8 +385,7 @@ class _EditTokenPageBodyState extends State { } } - Widget _tokenForm() { - return Form( + Widget _tokenForm() => Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, @@ -402,7 +409,7 @@ class _EditTokenPageBodyState extends State { size: 75, ), ), - if (_isTokenVerified) + if (_isTokenVerified || _isJupiterVerifiedForCurrentAddress) Positioned( bottom: 0, right: 0, @@ -425,6 +432,16 @@ class _EditTokenPageBodyState extends State { ), ], ), + if (_isJupiterVerifiedForCurrentAddress) ...[ + const SizedBox(height: 12), + Text( + S.of(context).token_verified_on_jupiter, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary, + ), + ), + ], SizedBox(height: 25), AddressTextField( controller: _contractAddressController, @@ -517,5 +534,4 @@ class _EditTokenPageBodyState extends State { ], ), ); - } } diff --git a/lib/view_model/dashboard/home_settings_view_model.dart b/lib/view_model/dashboard/home_settings_view_model.dart index e030f8e25..5039c927b 100644 --- a/lib/view_model/dashboard/home_settings_view_model.dart +++ b/lib/view_model/dashboard/home_settings_view_model.dart @@ -408,6 +408,14 @@ abstract class HomeSettingsViewModelBase with Store { return null; } + Future checkIfTokenIsVerifiedOnJupiter(String mintAddress) async { + if (_balanceViewModel.wallet.type != WalletType.solana) { + return null; + } + + return solana!.isTokenVerifiedOnJupiter(_balanceViewModel.wallet, mintAddress); + } + CryptoCurrency get nativeToken => _balanceViewModel.wallet.currency; void _updateFiatPrices(CryptoCurrency token) async { diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 815de2868..c74f1a2ab 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -76,6 +76,7 @@ "approve_tokens": "الموافقة على الرموز", "apps": "التطبيقات", "arbiscan_history": "سجل ArbiScan", + "are_you_sure_exit": "هل أنت متأكد أنك تريد الخروج؟", "arrive_in_this_address": "سيصل ${currency} ${tag} إلى هذا العنوان", "ascending": "تصاعديًا", "ask_each_time": "اسأل في كل مرة", @@ -89,6 +90,7 @@ "auto_generate_addresses": "إنشاء العناوين تلقائيًا", "auto_generate_subaddresses": "إنشاء العناوين الفرعية تلقائيًا", "automatic": "تلقائي", + "available": "متاح", "available_balance": "الرصيد المتاح", "available_balance_description": "يشير “Available Balance” أو “Confirmed Balance” إلى الأموال التي يمكن إنفاقها فورًا. إذا ظهرت الأموال في الرصيد السفلي ولكن ليس في الرصيد العلوي، فعليك الانتظار بضع دقائق حتى تحصل الأموال الواردة على المزيد من تأكيدات الشبكة. بعد حصولها على المزيد من التأكيدات، ستصبح قابلة للإنفاق.", "avg_savings": "متوسط التوفير", @@ -125,6 +127,7 @@ "block_remaining": "كتلة واحدة متبقية", "Blocks_remaining": "${status} كتل متبقية", "bluetooth": "بلوتوث", + "bridging": "جسر العملات", "bright_theme": "ساطع", "bscscan_history": "سجل BSCScan", "bump_fee": "زيادة الرسوم", @@ -216,6 +219,8 @@ "color_theme": "سمة الألوان", "coming_soon_tag": "قريبًا", "commit_transaction_amount_fee": "تأكيد المعاملة\nالمبلغ: ${amount}\nالرسوم: ${fee}", + "compatible_services": "الخدمات المتوافقة", + "compatible_services_desc": "استخدم أداة المسح لقراءة الأنواع التالية من رموز QR المدعومة في Cake Wallet:", "configure": "تهيئة", "confirm": "تأكيد", "confirm_delete_template": "سيؤدي هذا الإجراء إلى حذف هذا القالب. هل ترغب في المتابعة؟", @@ -279,6 +284,7 @@ "creating_new_wallet": "جارٍ إنشاء محفظة جديدة", "creating_new_wallet_error": "خطأ: ${description}", "creation_date": "تاريخ الإنشاء", + "crypto_addresses": "عناوين العملات المشفرة", "csv_nothing_to_export": "لا يوجد شيء للتصدير", "current_swap": "المبادلة الحالية", "current_wallet": "المحفظة الحالية", @@ -301,6 +307,7 @@ "default_sell_provider": "مزود البيع الافتراضي", "delete": "حذف", "delete_account": "حذف الحساب", + "delete_this_node": "حذف هذه العقدة", "delete_wallet": "حذف المحفظة", "delete_wallet_confirm_message": "هل أنت متأكد أنك تريد حذف محفظة ${wallet_name}؟", "deleteConnectionConfirmationPrompt": "هل أنت متأكد أنك تريد حذف الاتصال بـ", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO هو عملة مستقرة لامركزية بالكامل، مضمونة بضمانات ومربوطة باليورو — آمنة، متعددة الاستخدامات، ومقاومة للرقابة دون الحاجة إلى الاعتماد على الأوراكل. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "لتفعيل dEURO، يجب أن يكون لديك ETH في محفظتك.", "deuro_tx_commited_content": "قد يستغرق الأمر بضع ثوانٍ حتى يتم تأكيد المعاملة وتنعكس على الشاشة", + "device_confirmation": "تأكيد الجهاز", "device_is_signing": "الجهاز يقوم بالتوقيع", "dfx_option_description": "اشترِ العملات المشفرة بـ EUR و CHF. للعملاء الأفراد والشركات في أوروبا", "did_you_back_up_seeds": "هل قمت بعمل نسخة احتياطية لجميع عبارات الاسترداد الخاصة بك؟", @@ -466,6 +474,8 @@ "extracted_address_content": "ستقوم بإرسال الأموال إلى\n${recipient_name}", "failed_authentication": "فشلت المصادقة. ${state_error}", "faq": "الأسئلة الشائعة", + "favorite_token": "التوكن المفضل", + "favorite_token_desc": "سيظهر رصيد التوكن المفضل على بطاقة الرصيد.", "features": "الميزات", "fee": "رسوم", "fee_less_than_min": "الرسوم المحددة أقل من الحد الأدنى. يُرجى زيادة الرسوم لتتمكن من إرسال المعاملة", @@ -491,6 +501,7 @@ "frozen": "مجمَّد", "frozen_balance": "الرصيد المجمّد", "full_balance": "الرصيد الكامل", + "gallery": "المعرض", "gas_exceeds_allowance": "الغاز المطلوب للمعاملة يتجاوز الحدّ المسموح به.", "gas_price": "سعر الغاز", "general": "عام", @@ -526,6 +537,7 @@ "how_to_connect": "كيفية الاتصال", "how_to_use": "كيفية الاستخدام", "how_to_use_card": "كيفية استخدام هذه البطاقة", + "hww_exit_desc": "سيؤدي هذا إلى إنهاء عملية الإقران الجارية مع جهازك الصلب", "i_understand": "أفهم", "icon_style": "نمط الأيقونة", "id": "المعرّف: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "سيدور عنوان الاستلام الخاص بك تلقائيًا في كل مرة تستلم فيها معاملة", "infobox_multichain": "استخدم هذا العنوان لاستلام أي توكن أو مقتنى على", "infobox_rotation": "سيتم تدوير عنوان الاستلام الخاص بك في كل مرة تُغلق فيها هذه الشاشة وتعيد فتحها", + "input": "إدخال", "inputs": "المدخلات", "insufficient_funds_for_tx": "أموال غير كافية لتنفيذ المعاملة بنجاح.", "insufficient_lamport_for_tx": "ليس لديك ما يكفي من SOL لتغطية المعاملة ورسومها. يُرجى إضافة المزيد من SOL إلى محفظتك أو تقليل مبلغ SOL الذي ترسله.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "إدارة عُقَد PoW", "manage_providers": "إدارة المزوّدين", "manage_yats": "إدارة Yats", + "manual_input": "إدخال يدوي", "mark_as_redeemed": "وضع علامة كمسترد", "market_place": "المتجر", "mask": "قناع", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "جميع أحدث النماذج (GPT-5.3، Claude 4.6).\nبدون اشتراك، ادفع بالعملات المشفرة.", "narrow": "ضيق", "network": "الشبكة", + "networks": "الشبكات", "new_first_wallet_text": "الحفاظ على أمان عملاتك المشفرة سهل للغاية", "new_node_testing": "اختبار العقدة الجديدة", "new_subaddress_create": "إنشاء", @@ -678,8 +693,10 @@ "node_new": "عقدة جديدة", "node_port": "منفذ العقدة", "node_reset_settings_title": "إعادة تعيين الإعدادات", + "node_share_desc": "امسح رمز QR هذا من شاشة المسح لاستيراد هذه العقدة.", "node_test": "اختبار", "nodes": "العُقَد", + "nodes_desc": "إدارة العقد الموجودة أو إضافة عقدة مخصصة.", "nodes_list_reset_to_default_message": "هل أنت متأكد أنك تريد إعادة تعيين الإعدادات إلى الإعدادات الافتراضية؟", "none_of_selected_providers_can_exchange": "لا يمكن لأيٍّ من المزوّدين المحدّدين إجراء هذه المبادلة", "noNFTYet": "لا توجد رموز NFT بعد", @@ -689,6 +706,7 @@ "note_tap_to_change": "ملاحظة (اضغط للتغيير)", "notification_permission_denied": "تم رفض إذن الإشعارات بشكل دائم. يُرجى تمكينه يدويًا من الإعدادات", "nullURIError": "URI فارغ", + "ocp_desc": "ادفع بالعملات المشفرة في المتاجر", "offer_expires_in": "ينتهي العرض خلال: ", "offline": "غير متصل", "ok": "موافق", @@ -715,8 +733,13 @@ "outputs": "المخرجات", "overshot": "تجاوز الحد", "overwrite_amount": "استبدال المبلغ", + "pairing_code": "رمز الإقران", + "pairing_code_desc_1": "سيعرض جهازك رمز إقران.", + "pairing_code_desc_2": "أدخله هنا للمتابعة", + "pairing_error": "خطأ في الإقران", "pairingInvalidEvent": "حدث إقران غير صالح", "passphrase": "عبارة المرور (اختياري)", + "passphrase_view_keys": "عبارة المرور", "passphrases_doesnt_match": "عبارتا المرور غير متطابقتين، يرجى المحاولة مرة أخرى", "password": "كلمة المرور", "paste": "لصق", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "يتطلب استلام معاملة Payjoin أن يكون لديك بيتكوين جاهز للاستخدام.\n\nبمجرد أن تحتوي محفظتك على رصيد، سيتم تفعيل Payjoin تلقائيًا.", "payjoin_unavailable_sheet_title": "لماذا Payjoin غير متاح؟", "payment_id": "معرّف الدفع: ", + "payment_invoices": "فواتير الدفع", "payment_made_easy": "المدفوعات أصبحت أسهل", "payment_was_received": "تم استلام دفعتك.", "payments": "المدفوعات", @@ -887,6 +911,7 @@ "save": "حفظ", "save_backup_password": "يرجى التأكد من أنك حفظت كلمة مرور النسخة الاحتياطية. لن تتمكن من استيراد ملفات النسخ الاحتياطي بدونها.", "save_backup_password_alert": "حفظ كلمة مرور النسخة الاحتياطية", + "save_contact": "حفظ جهة الاتصال", "save_to_downloads": "حفظ في التنزيلات", "saved_the_trade_id": "لقد حفظت معرّف الصفقة", "savings": "المدخرات", @@ -1036,6 +1061,7 @@ "setup_your_debit_card": "قم بإعداد بطاقة الخصم الخاصة بك", "share": "مشاركة", "share_address": "مشاركة العنوان", + "share_this_node": "مشاركة هذه العقدة", "shared_seed_wallet_groups": "مجموعات محافظ عبارة الاسترداد المشتركة", "shared_seed_wallets": "محافظ العبارة الأولية المشتركة", "show": "إظهار", @@ -1043,6 +1069,7 @@ "show_balance": "اضغط مطولًا لإظهار الرصيد", "show_balance_send_page": "انقر للكشف", "show_balance_toast": "اضغط مطولًا لإخفاء الرصيد أو إظهاره", + "show_combined_balance": "إظهار الرصيد المجمّع", "show_details": "عرض التفاصيل", "show_hidden_addresses": "إظهار العناوين المخفية", "show_keys": "إظهار عبارة الاسترداد/المفاتيح", @@ -1108,6 +1135,7 @@ "swap_providers": "مزودو المبادلة", "sweeping_wallet": "محفظة السحب الشامل", "sweeping_wallet_alert": "لن يستغرق هذا وقتًا طويلًا. لا تغادر هذه الشاشة وإلا فقد تُفقد الأموال المُسحوبة.", + "swipe_to_bridge": "اسحب لإجراء الجسر", "swipe_to_send": "اسحب للإرسال", "switch_wallet": "تبديل المحفظة", "switchToETHWallet": "يرجى التبديل إلى محفظة Ethereum والمحاولة مرة أخرى", @@ -1148,6 +1176,7 @@ "testnet_coins_no_value": "عملات شبكة الاختبار (Testnet) لا قيمة لها", "third_intro_content": "توجد Yats خارج Cake Wallet أيضًا. يمكن استبدال أي عنوان محفظة في العالم بـ Yat!", "third_intro_title": "Yat يعمل بسلاسة مع الآخرين", + "this_can_take_few_seconds": "قد يستغرق هذا بضع ثوانٍ", "this_pair_is_not_supported_warning": "هذا الزوج غير مدعوم مع منصّة/منصّات التداول المحددة حاليًا. يُرجى اختيار منصّة تداول أخرى.", "thorchain_contract_address_not_supported": "THORChain لا يدعم الإرسال إلى عنوان عقد", "thorchain_taproot_address_not_supported": "لا يدعم مزوّد ThorChain عناوين Taproot. يُرجى تغيير العنوان أو اختيار مزوّد آخر.", @@ -1161,6 +1190,7 @@ "token_decimal": "عدد المنازل العشرية للتوكن (مثال: USDT)", "token_name": "اسم التوكن (مثال: Tether)", "token_symbol": "رمز التوكن (مثل: USDT)", + "token_verified_on_jupiter": "تم التحقق من هذا الرمز المميز على Jupiter", "tokenID": "المعرّف", "tokens": "التوكنات", "tokens_strong_warning": "لا تُرسل الرموز المميّزة إلى هذا العنوان أبداً!", @@ -1289,6 +1319,7 @@ "username": "اسم المستخدم", "username_available": "اسم المستخدم متاح", "username_character_error": "يجب أن تحتوي أسماء المستخدمين فقط على", + "username_check_your_network": "تعذّر التحقق من اسم المستخدم. يُرجى التحقق من اتصالك بالشبكة.", "username_length_error": "يجب أن تتكون أسماء المستخدمين من 6 إلى 32 حرفًا أو رقمًا.", "username_length_error_1_64": "يجب أن تحتوي أسماء المستخدمين على 1 إلى 64 حرفًا أو رقمًا.", "username_not_available": "اسم المستخدم هذا غير متاح.", @@ -1299,6 +1330,7 @@ "verify_message": "التحقق من الرسالة", "verify_seed": "تحقق من عبارة الاسترداد", "verify_with_2fa": "تحقق عبر Cake 2FA", + "verifying_code": "جارٍ التحقق من الرمز", "version": "الإصدار ${currentVersion}", "view_all": "عرض الكل", "view_in_block_explorer": "عرض في مستكشف الكتل", @@ -1310,6 +1342,7 @@ "waitFewSecondForTxUpdate": "يرجى الانتظار بضع ثوانٍ حتى تنعكس المعاملة في سجل المعاملات", "wallet": "محفظة", "wallet_accounts": "حسابات المحفظة", + "wallet_balance": "رصيد المحفظة", "wallet_group": "مجموعة المحفظة", "wallet_group_description_existing_seed": "لقد اخترت استخدام عبارة الاسترداد (Seed) الموجودة لهذه المحفظة. يمكنك التحقق من عبارة الاسترداد (Seed) مرة أخرى إذا كنت بحاجة إلى تأكيدها أو تدوينها.", "wallet_group_description_four": "لإنشاء محفظة بعبارة استرداد جديدة تمامًا.", @@ -1351,6 +1384,7 @@ "wc_approve_request_title": "الموافقة على الطلب", "wc_connect_request_title": "طلب الاتصال", "wc_connected_to": "متصل بـ ${name}", + "wc_desc": "اتصل بسهولة بتطبيقات DApps", "wc_max_network_fee": "الحد الأقصى لرسوم الشبكة", "wc_message_to_sign": "رسالة للتوقيع", "wc_network_fee": "رسوم الشبكة", @@ -1401,6 +1435,7 @@ "yat_popup_content": "يمكنك الآن إرسال واستلام العملات المشفرة في Cake Wallet باستخدام Yat - اسم مستخدم قصير يعتمد على الرموز التعبيرية. يمكنك إدارة Yats في أي وقت من شاشة الإعدادات", "yat_popup_title": "يمكن تحويل عنوان محفظتك إلى رموز تعبيرية.", "yes": "نعم", + "yes_exit": "نعم. اخرج", "yesterday": "الأمس", "you_now_have_debit_card": "لديك الآن بطاقة خصم", "you_pay": "أنت تدفع", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 45136deab..21bc47177 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -76,6 +76,7 @@ "approve_tokens": "Одобряване на токени", "apps": "Приложения", "arbiscan_history": "История в ArbiScan", + "are_you_sure_exit": "Сигурни ли сте, че искате да излезете?", "arrive_in_this_address": "${currency} ${tag}ще пристигне на този адрес", "ascending": "Възходящ", "ask_each_time": "Питай всеки път", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Автоматично генериране на адреси", "auto_generate_subaddresses": "Автоматично генериране на подадреси", "automatic": "Автоматично", + "available": "Налично", "available_balance": "Наличен баланс", "available_balance_description": "„Наличният баланс“ или „Потвърденият баланс“ са средства, които могат да бъдат изразходвани веднага. Ако средствата се появяват в долния баланс, но не и в горния, трябва да изчакате няколко минути, докато входящите средства получат повече мрежови потвърждения. След като получат повече потвърждения, те ще могат да бъдат изразходвани.", "avg_savings": "Средни спестявания", @@ -125,6 +127,7 @@ "block_remaining": "Остава 1 блок", "Blocks_remaining": "Остават ${status} блока", "bluetooth": "Bluetooth", + "bridging": "Прехвърляне", "bright_theme": "Светла", "bscscan_history": "История в BSCScan", "bump_fee": "Увеличи таксата", @@ -216,6 +219,8 @@ "color_theme": "Цветова тема", "coming_soon_tag": "Очаквайте скоро", "commit_transaction_amount_fee": "Потвърдете транзакцията\nСума: ${amount}\nТакса: ${fee}", + "compatible_services": "Съвместими услуги", + "compatible_services_desc": "Използвайте инструмента за сканиране, за да четете следните типове QR кодове, поддържани в Cake Wallet:", "configure": "Конфигуриране", "confirm": "Потвърди", "confirm_delete_template": "Това действие ще изтрие този шаблон. Желаете ли да продължите?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Създаване на нов портфейл", "creating_new_wallet_error": "Грешка: ${description}", "creation_date": "Дата на създаване", + "crypto_addresses": "Крипто адреси", "csv_nothing_to_export": "Няма какво да се експортира", "current_swap": "Текущ суап", "current_wallet": "Текущ портфейл", @@ -301,6 +307,7 @@ "default_sell_provider": "Доставчик за продажба по подразбиране", "delete": "Изтрий", "delete_account": "Изтриване на акаунта", + "delete_this_node": "Изтриване на този възел", "delete_wallet": "Изтриване на портфейл", "delete_wallet_confirm_message": "Сигурни ли сте, че искате да изтриете портфейла ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Сигурни ли сте, че искате да изтриете връзката с", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO е напълно децентрализиран, обезпечен стабилкойн, обвързан с еврото — сигурен, универсален и устойчив на цензура, без да се налага да се разчита на оракули. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "За да активирате dEURO, трябва да имате ETH в портфейла си.", "deuro_tx_commited_content": "Може да отнеме няколко секунди, докато транзакцията се потвърди и се отрази на екрана", + "device_confirmation": "Потвърждение от устройството", "device_is_signing": "Устройството подписва", "dfx_option_description": "Купете крипто с EUR и CHF. За частни и корпоративни клиенти в Европа", "did_you_back_up_seeds": "Архивирахте ли всички свои seed фрази?", @@ -466,6 +474,8 @@ "extracted_address_content": "Ще изпратите средства до\n${recipient_name}", "failed_authentication": "Неуспешно удостоверяване. ${state_error}", "faq": "ЧЗВ", + "favorite_token": "Любим токен", + "favorite_token_desc": "Балансът на любимия токен ще се показва на картата с баланса.", "features": "Функции", "fee": "Такса", "fee_less_than_min": "Избраната такса е по-ниска от минималната. Моля, увеличете таксата, за да можете да изпратите транзакцията.", @@ -491,6 +501,7 @@ "frozen": "Замразено", "frozen_balance": "Замразен баланс", "full_balance": "Пълен баланс", + "gallery": "Галерия", "gas_exceeds_allowance": "Газът, необходим за транзакцията, надвишава допустимото.", "gas_price": "Цена на gas", "general": "Общи", @@ -526,6 +537,7 @@ "how_to_connect": "Как да се свържете", "how_to_use": "Как да използвате", "how_to_use_card": "Как да използвате тази карта", + "hww_exit_desc": "Това ще прекрати текущия процес на сдвояване с вашето хардуерно устройство", "i_understand": "Разбирам", "icon_style": "Стил на иконата", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Вашият адрес за получаване ще се сменя всеки път, когато получите транзакция", "infobox_multichain": "Използвайте този адрес, за да получавате всеки токен или колекционерски предмет в", "infobox_rotation": "Вашият адрес за получаване ще се сменя всеки път, когато затворите и отворите отново този екран", + "input": "Вход", "inputs": "Входове", "insufficient_funds_for_tx": "Недостатъчни средства за успешно изпълнение на транзакцията.", "insufficient_lamport_for_tx": "Нямате достатъчно SOL, за да покриете транзакцията и таксата за нея. Моля, добавете още SOL към портфейла си или намалете количеството SOL, което изпращате.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Управление на PoW възли", "manage_providers": "Управление на доставчици", "manage_yats": "Управление на Yats", + "manual_input": "Ръчно въвеждане", "mark_as_redeemed": "Маркирай като осребрен", "market_place": "Пазар", "mask": "Маска", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Всички най-нови модели (GPT-5.3, Claude 4.6).\\nБез абонамент, плащайте с крипто.", "narrow": "Тесен", "network": "Мрежа", + "networks": "Мрежи", "new_first_wallet_text": "Да пазите криптовалутата си в безопасност е лесно като парче торта", "new_node_testing": "Тестване на нов възел", "new_subaddress_create": "Създай", @@ -678,8 +693,10 @@ "node_new": "Нов възел", "node_port": "Порт на възела", "node_reset_settings_title": "Нулиране на настройките", + "node_share_desc": "Сканирайте този QR код от екрана за сканиране, за да импортирате този възел.", "node_test": "Тест", "nodes": "Възли", + "nodes_desc": "Управлявайте съществуващите възли или добавете персонализиран.", "nodes_list_reset_to_default_message": "Сигурни ли сте, че искате да възстановите настройките по подразбиране?", "none_of_selected_providers_can_exchange": "Нито един от избраните доставчици не може да извърши този суап", "noNFTYet": "Все още няма NFT", @@ -689,6 +706,7 @@ "note_tap_to_change": "Бележка (докоснете, за да промените)", "notification_permission_denied": "Разрешението за известия е окончателно отказано. Моля, включете го ръчно в настройките.", "nullURIError": "URI е null", + "ocp_desc": "Плащайте с крипто в магазини", "offer_expires_in": "Офертата изтича след: ", "offline": "Офлайн", "ok": "ОК", @@ -715,8 +733,13 @@ "outputs": "Изходи", "overshot": "Надвишено", "overwrite_amount": "Презапиши сумата", + "pairing_code": "Код за сдвояване", + "pairing_code_desc_1": "Вашето устройство ще покаже код за сдвояване.", + "pairing_code_desc_2": "Въведете го тук, за да продължите", + "pairing_error": "Грешка при сдвояване", "pairingInvalidEvent": "Невалидно събитие при сдвояване", "passphrase": "Парола за достъп (по избор)", + "passphrase_view_keys": "Парола за достъп", "passphrases_doesnt_match": "Пасфразите не съвпадат, моля, опитайте отново", "password": "Парола", "paste": "Поставяне", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Получаването на Payjoin транзакция изисква да имате наличен Bitcoin за използване.\n\nВеднага щом портфейлът ви има средства, Payjoin ще бъде автоматично активиран.", "payjoin_unavailable_sheet_title": "Защо Payjoin не е наличен?", "payment_id": "ID на плащане: ", + "payment_invoices": "Фактури за плащане", "payment_made_easy": "Плащанията са лесни", "payment_was_received": "Плащането ви беше получено.", "payments": "Плащания", @@ -887,6 +911,7 @@ "save": "Запази", "save_backup_password": "Моля, уверете се, че сте запазили паролата за резервното копие. Няма да можете да импортирате файловете от резервното си копие без нея.", "save_backup_password_alert": "Запазване на паролата за резервно копие", + "save_contact": "Запазване на контакт", "save_to_downloads": "Запази в „Изтегляния“", "saved_the_trade_id": "Запазих ID на сделката", "savings": "Спестявания", @@ -1036,6 +1061,7 @@ "setup_your_debit_card": "Настройте дебитната си карта", "share": "Споделяне", "share_address": "Споделяне на адрес", + "share_this_node": "Споделяне на този възел", "shared_seed_wallet_groups": "Групи портфейли със споделена seed фраза", "shared_seed_wallets": "Портфейли със споделена seed фраза", "show": "Покажи", @@ -1043,6 +1069,7 @@ "show_balance": "Натиснете и задръжте, за да покажете баланса", "show_balance_send_page": "Докоснете, за да разкриете", "show_balance_toast": "Натиснете и задръжте, за да скриете или покажете баланса", + "show_combined_balance": "Показване на общия баланс", "show_details": "Покажи подробности", "show_hidden_addresses": "Показване на скритите адреси", "show_keys": "Показване на seed/ключове", @@ -1108,6 +1135,7 @@ "swap_providers": "Доставчици за суап", "sweeping_wallet": "Изчистване на портфейл", "sweeping_wallet_alert": "Това не би трябвало да отнеме много време. НЕ НАПУСКАЙТЕ ТОЗИ ЕКРАН, ИНАЧЕ ИЗМЕТЕНИТЕ СРЕДСТВА МОГАТ ДА БЪДАТ ЗАГУБЕНИ.", + "swipe_to_bridge": "Плъзнете, за да прехвърлите", "swipe_to_send": "Плъзнете, за да изпратите", "switch_wallet": "Превключване на портфейл", "switchToETHWallet": "Моля, превключете към портфейл за Ethereum и опитайте отново", @@ -1148,6 +1176,7 @@ "testnet_coins_no_value": "Монетите в тестовата мрежа нямат стойност", "third_intro_content": "Yats също съществуват извън Cake Wallet. Всеки адрес на портфейл по света може да бъде заменен с Yat!", "third_intro_title": "Yat работи добре с другите", + "this_can_take_few_seconds": "Това може да отнеме няколко секунди", "this_pair_is_not_supported_warning": "Тази двойка не се поддържа от избраната(ите) в момента борса(и). Моля, изберете друга борса.", "thorchain_contract_address_not_supported": "THORChain не поддържа изпращане към адрес на смарт договор", "thorchain_taproot_address_not_supported": "Доставчикът на ThorChain не поддържа Taproot адреси. Моля, променете адреса или изберете друг доставчик.", @@ -1161,6 +1190,7 @@ "token_decimal": "Десетични знаци на токена (напр.: USDT)", "token_name": "Име на токен (напр.: Tether)", "token_symbol": "Символ на токена (напр.: USDT)", + "token_verified_on_jupiter": "Този токен е проверен на Jupiter", "tokenID": "ID", "tokens": "Токени", "tokens_strong_warning": "Никога не изпращайте токени на този адрес!", @@ -1289,6 +1319,7 @@ "username": "Потребителско име", "username_available": "Потребителското име е налично", "username_character_error": "Потребителските имена трябва да съдържат само", + "username_check_your_network": "Неуспешна проверка на потребителското име. Моля, проверете мрежовата си връзка.", "username_length_error": "Потребителските имена трябва да съдържат 6–32 буквено-цифрови знака.", "username_length_error_1_64": "Потребителските имена трябва да съдържат 1-64 буквено-цифрови знака.", "username_not_available": "Това потребителско име не е налично.", @@ -1299,6 +1330,7 @@ "verify_message": "Потвърдете съобщението", "verify_seed": "Потвърдете seed фразата", "verify_with_2fa": "Потвърдете с Cake 2FA", + "verifying_code": "Проверка на кода", "version": "Версия ${currentVersion}", "view_all": "Виж всички", "view_in_block_explorer": "Преглед в Block Explorer", @@ -1310,6 +1342,7 @@ "waitFewSecondForTxUpdate": "Моля, изчакайте няколко секунди, докато транзакцията се появи в историята на транзакциите", "wallet": "Портфейл", "wallet_accounts": "Акаунти на портфейла", + "wallet_balance": "Баланс на портфейла", "wallet_group": "Група портфейли", "wallet_group_description_existing_seed": "Избрали сте да използвате съществуваща seed фраза за този портфейл. Можете да я проверите отново, ако трябва да я потвърдите или да я запишете.", "wallet_group_description_four": "за да създадете портфейл с изцяло нова seed фраза.", @@ -1351,6 +1384,7 @@ "wc_approve_request_title": "Одобряване на заявката", "wc_connect_request_title": "Заявка за свързване", "wc_connected_to": "Свързан с ${name}", + "wc_desc": "Свържете се лесно с dApps", "wc_max_network_fee": "Максимална мрежова такса", "wc_message_to_sign": "Съобщение за подпис", "wc_network_fee": "Мрежова такса", @@ -1401,6 +1435,7 @@ "yat_popup_content": "Вече можете да изпращате и получавате крипто в Cake Wallet с вашия Yat – кратко потребителско име, базирано на емоджита. Управлявайте своите Yats по всяко време от екрана с настройки", "yat_popup_title": "Адресът на вашия портфейл може да бъде превърнат в емоджита.", "yes": "Да", + "yes_exit": "Да. Изход", "yesterday": "Вчера", "you_now_have_debit_card": "Вече имате дебитна карта", "you_pay": "Вие плащате", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index c3df26ca8..8bc91b7a0 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -76,6 +76,7 @@ "approve_tokens": "Schválit tokeny", "apps": "Aplikace", "arbiscan_history": "Historie ArbiScan", + "are_you_sure_exit": "Opravdu chcete ukončit aplikaci?", "arrive_in_this_address": "${currency} ${tag}dorazí na tuto adresu", "ascending": "Vzestupně", "ask_each_time": "Zeptat se pokaždé", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Automaticky generovat adresy", "auto_generate_subaddresses": "Automaticky generovat podadresy", "automatic": "Automaticky", + "available": "Dostupné", "available_balance": "Dostupný zůstatek", "available_balance_description": "„Dostupný zůstatek“ nebo „Potvrzený zůstatek“ jsou prostředky, které lze okamžitě utratit. Pokud se prostředky zobrazují ve spodním zůstatku, ale ne v horním, musíte několik minut počkat, než příchozí prostředky získají více síťových potvrzení. Jakmile získají více potvrzení, bude možné je utratit.", "avg_savings": "Prům. úspora", @@ -125,6 +127,7 @@ "block_remaining": "Zbývá 1 blok", "Blocks_remaining": "Zbývá ${status} bloků", "bluetooth": "Bluetooth", + "bridging": "Přemostění", "bright_theme": "Světlý", "bscscan_history": "Historie BSCScan", "bump_fee": "Navýšit poplatek", @@ -216,6 +219,8 @@ "color_theme": "Barevné téma", "coming_soon_tag": "Již brzy", "commit_transaction_amount_fee": "Potvrdit transakci\nČástka: ${amount}\nPoplatek: ${fee}", + "compatible_services": "Kompatibilní služby", + "compatible_services_desc": "Pomocí nástroje pro skenování načtěte následující typy QR kódů podporované v Cake Wallet:", "configure": "Konfigurovat", "confirm": "Potvrdit", "confirm_delete_template": "Tato akce odstraní tuto šablonu. Přejete si pokračovat?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Vytváření nové peněženky", "creating_new_wallet_error": "Chyba: ${description}", "creation_date": "Datum vytvoření", + "crypto_addresses": "Krypto adresy", "csv_nothing_to_export": "Není co exportovat", "current_swap": "Aktuální swap", "current_wallet": "Aktuální peněženka", @@ -301,6 +307,7 @@ "default_sell_provider": "Výchozí poskytovatel pro prodej", "delete": "Smazat", "delete_account": "Smazat účet", + "delete_this_node": "Smazat tento uzel", "delete_wallet": "Smazat peněženku", "delete_wallet_confirm_message": "Opravdu chcete smazat peněženku ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Opravdu chcete odstranit připojení k", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO je plně decentralizovaný, kolateralizovaný stablecoin navázaný na euro — bezpečný, všestranný a odolný vůči cenzuře, aniž by se musel spoléhat na orákly. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Abyste mohli povolit dEURO, musíte mít v peněžence ETH.", "deuro_tx_commited_content": "Může trvat několik sekund, než se transakce potvrdí a projeví se na obrazovce", + "device_confirmation": "Potvrzení na zařízení", "device_is_signing": "Zařízení podepisuje", "dfx_option_description": "Kupte krypto za EUR a CHF. Pro maloobchodní a firemní zákazníky v Evropě", "did_you_back_up_seeds": "Zálohovali jste všechny své seed fráze?", @@ -466,6 +474,8 @@ "extracted_address_content": "Budete odesílat prostředky na\n${recipient_name}", "failed_authentication": "Ověření se nezdařilo. ${state_error}", "faq": "FAQ", + "favorite_token": "Oblíbený token", + "favorite_token_desc": "Zůstatek oblíbeného tokenu se zobrazí na kartě zůstatku.", "features": "Funkce", "fee": "Poplatek", "fee_less_than_min": "Vybraný poplatek je nižší než minimum. Zvyšte prosím poplatek, abyste mohli transakci odeslat.", @@ -491,6 +501,7 @@ "frozen": "Zmrazeno", "frozen_balance": "Zmrazený zůstatek", "full_balance": "Celkový zůstatek", + "gallery": "Galerie", "gas_exceeds_allowance": "Plyn vyžadovaný transakcí překračuje povolený limit.", "gas_price": "Cena gasu", "general": "Obecné", @@ -526,6 +537,7 @@ "how_to_connect": "Jak se připojit", "how_to_use": "Jak používat", "how_to_use_card": "Jak tuto kartu používat", + "hww_exit_desc": "Tímto ukončíte probíhající proces párování s vaším hardwarovým zařízením", "i_understand": "Rozumím", "icon_style": "Styl ikony", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Vaše přijímací adresa se bude měnit pokaždé, když obdržíte transakci", "infobox_multichain": "Použijte tuto adresu k přijetí jakéhokoli tokenu nebo sběratelského předmětu na", "infobox_rotation": "Vaše přijímací adresa se bude měnit pokaždé, když zavřete a znovu otevřete tuto obrazovku", + "input": "Vstup", "inputs": "Vstupy", "insufficient_funds_for_tx": "Nedostatečné prostředky pro úspěšné provedení transakce.", "insufficient_lamport_for_tx": "Nemáte dostatek SOL na pokrytí transakce a transakčního poplatku. Přidejte do své peněženky více SOL nebo snižte množství SOL, které odesíláte.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Spravovat PoW uzly", "manage_providers": "Spravovat poskytovatele", "manage_yats": "Spravovat Yats", + "manual_input": "Ruční zadání", "mark_as_redeemed": "Označit jako uplatněné", "market_place": "Marketplace", "mask": "Maska", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Všechny nejnovější modely (GPT-5.3, Claude 4.6).\nBez předplatného, plaťte kryptem.", "narrow": "Úzké", "network": "Síť", + "networks": "Sítě", "new_first_wallet_text": "Udržet vaše krypto v bezpečí je hračka", "new_node_testing": "Testování nového uzlu", "new_subaddress_create": "Vytvořit", @@ -678,8 +693,10 @@ "node_new": "Nový uzel", "node_port": "Port uzlu", "node_reset_settings_title": "Obnovit nastavení", + "node_share_desc": "Naskenováním tohoto QR kódu na obrazovce skenování tento uzel importujete.", "node_test": "Test", "nodes": "Uzly", + "nodes_desc": "Spravujte stávající uzly nebo přidejte vlastní.", "nodes_list_reset_to_default_message": "Opravdu chcete obnovit nastavení na výchozí?", "none_of_selected_providers_can_exchange": "Žádný z vybraných poskytovatelů nemůže tento swap provést", "noNFTYet": "Zatím žádné NFT", @@ -689,6 +706,7 @@ "note_tap_to_change": "Poznámka (klepnutím změnit)", "notification_permission_denied": "Oprávnění k oznámením bylo trvale zamítnuto, prosím ručně jej povolte v nastavení", "nullURIError": "URI je prázdné", + "ocp_desc": "Plaťte kryptem v obchodech", "offer_expires_in": "Platnost nabídky vyprší za: ", "offline": "Offline", "ok": "OK", @@ -715,8 +733,13 @@ "outputs": "Výstupy", "overshot": "Přestřelení", "overwrite_amount": "Přepsat částku", + "pairing_code": "Párovací kód", + "pairing_code_desc_1": "Vaše zařízení zobrazí párovací kód.", + "pairing_code_desc_2": "Zadejte ho zde a pokračujte", + "pairing_error": "Chyba párování", "pairingInvalidEvent": "Neplatná událost párování", "passphrase": "Přístupová fráze (volitelné)", + "passphrase_view_keys": "Přístupová fráze", "passphrases_doesnt_match": "Heslové fráze se neshodují, zkuste to znovu", "password": "Heslo", "paste": "Vložit", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Přijetí transakce Payjoin vyžaduje, abyste měli Bitcoin připravený k použití.\n\nJakmile bude mít vaše peněženka prostředky, Payjoin se automaticky povolí.", "payjoin_unavailable_sheet_title": "Proč je Payjoin nedostupný?", "payment_id": "ID platby: ", + "payment_invoices": "Platební faktury", "payment_made_easy": "Platby snadno", "payment_was_received": "Vaše platba byla přijata.", "payments": "Platby", @@ -887,6 +911,7 @@ "save": "Uložit", "save_backup_password": "Ujistěte se prosím, že máte uložené heslo k záloze. Bez něj nebudete moci importovat záložní soubory.", "save_backup_password_alert": "Uložit heslo k záloze", + "save_contact": "Uložit kontakt", "save_to_downloads": "Uložit do složky Stažené", "saved_the_trade_id": "Uložil jsem si ID obchodu", "savings": "Úspory", @@ -1036,6 +1061,7 @@ "setup_your_debit_card": "Nastavte si debetní kartu", "share": "Sdílet", "share_address": "Sdílet adresu", + "share_this_node": "Sdílet tento uzel", "shared_seed_wallet_groups": "Skupiny peněženek se sdílenou seed frází", "shared_seed_wallets": "Peněženky se sdíleným seedem", "show": "Zobrazit", @@ -1043,6 +1069,7 @@ "show_balance": "Dlouhým stisknutím zobrazíte zůstatek", "show_balance_send_page": "Klepnutím odhalíte", "show_balance_toast": "Dlouhým stisknutím skryjete nebo zobrazíte zůstatek", + "show_combined_balance": "Zobrazit souhrnný zůstatek", "show_details": "Zobrazit podrobnosti", "show_hidden_addresses": "Zobrazit skryté adresy", "show_keys": "Zobrazit seed/klíče", @@ -1108,6 +1135,7 @@ "swap_providers": "Poskytovatelé swapu", "sweeping_wallet": "Peněženka pro sweep", "sweeping_wallet_alert": "To by nemělo trvat dlouho. NEOPUŠTĚJTE TUTO OBRAZOVKU, JINAK MOHOU BÝT PŘESUNUTÉ PROSTŘEDKY ZTRACENY.", + "swipe_to_bridge": "Přemostění přejetím prstem", "swipe_to_send": "Přejeďte pro odeslání", "switch_wallet": "Přepnout peněženku", "switchToETHWallet": "Přepněte na peněženku Ethereum a zkuste to znovu", @@ -1148,6 +1176,7 @@ "testnet_coins_no_value": "Testnetové mince nemají žádnou hodnotu", "third_intro_content": "Yaty existují i mimo Cake Wallet. Jakákoli adresa peněženky na světě může být nahrazena Yatem!", "third_intro_title": "Yat si dobře rozumí s ostatními", + "this_can_take_few_seconds": "Může to trvat několik sekund", "this_pair_is_not_supported_warning": "Tento pár není podporován aktuálně vybranou burzou (burzami). Vyberte prosím jinou burzu.", "thorchain_contract_address_not_supported": "THORChain nepodporuje odesílání na adresu kontraktu", "thorchain_taproot_address_not_supported": "Poskytovatel ThorChain nepodporuje Taproot adresy. Změňte adresu nebo vyberte jiného poskytovatele.", @@ -1161,6 +1190,7 @@ "token_decimal": "Desetinná místa tokenu (např.: USDT)", "token_name": "Název tokenu (např.: Tether)", "token_symbol": "Symbol tokenu (např.: USDT)", + "token_verified_on_jupiter": "Tento token je ověřen na Jupiteru", "tokenID": "ID", "tokens": "Tokeny", "tokens_strong_warning": "Nikdy neposílejte tokeny na tuto adresu!", @@ -1289,6 +1319,7 @@ "username": "Uživatelské jméno", "username_available": "Uživatelské jméno je k dispozici", "username_character_error": "Uživatelská jména mohou obsahovat pouze", + "username_check_your_network": "Nelze ověřit uživatelské jméno. Zkontrolujte prosím připojení k síti.", "username_length_error": "Uživatelská jména musí obsahovat 6–32 alfanumerických znaků.", "username_length_error_1_64": "Uživatelská jména musí obsahovat 1–64 alfanumerických znaků.", "username_not_available": "Toto uživatelské jméno není k dispozici.", @@ -1299,6 +1330,7 @@ "verify_message": "Ověřit zprávu", "verify_seed": "Ověřit seed", "verify_with_2fa": "Ověřit pomocí Cake 2FA", + "verifying_code": "Ověřování kódu", "version": "Verze ${currentVersion}", "view_all": "Zobrazit vše", "view_in_block_explorer": "Zobrazit v průzkumníku bloků", @@ -1310,6 +1342,7 @@ "waitFewSecondForTxUpdate": "Počkejte prosím několik sekund, než se transakce zobrazí v historii transakcí", "wallet": "Peněženka", "wallet_accounts": "Účty v peněžence", + "wallet_balance": "Zůstatek peněženky", "wallet_group": "Skupina peněženek", "wallet_group_description_existing_seed": "Zvolili jste použití existující seed fráze pro tuto peněženku. Seed frázi můžete znovu ověřit, pokud ji potřebujete potvrdit nebo si ji zapsat.", "wallet_group_description_four": "vytvořit peněženku se zcela novým seedem.", @@ -1351,6 +1384,7 @@ "wc_approve_request_title": "Schválit žádost", "wc_connect_request_title": "Žádost o připojení", "wc_connected_to": "Připojeno k ${name}", + "wc_desc": "Snadno se připojte k dApps", "wc_max_network_fee": "Max síťový poplatek", "wc_message_to_sign": "Zpráva k podpisu", "wc_network_fee": "Síťový poplatek", @@ -1401,6 +1435,7 @@ "yat_popup_content": "Nyní můžete v Cake Wallet posílat a přijímat kryptoměny pomocí svého Yatu – krátkého uživatelského jména složeného z emoji. Yaty můžete kdykoli spravovat na obrazovce nastavení", "yat_popup_title": "Adresa vaší peněženky může být emojifikována.", "yes": "Ano", + "yes_exit": "Ano. Ukončit", "yesterday": "Včera", "you_now_have_debit_card": "Nyní máte debetní kartu", "you_pay": "Platíte", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 9a39f7bda..b55be3560 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -77,6 +77,7 @@ "approve_tokens": "Tokens genehmigen", "apps": "Apps", "arbiscan_history": "ArbiScan-Verlauf", + "are_you_sure_exit": "Möchten Sie die App wirklich verlassen?", "arrive_in_this_address": "${currency} ${tag} wird an dieser Adresse eingehen", "ascending": "Aufsteigend", "ask_each_time": "Jedes Mal fragen", @@ -90,6 +91,7 @@ "auto_generate_addresses": "Adressen automatisch generieren", "auto_generate_subaddresses": "Unteradressen automatisch generieren", "automatic": "Automatisch", + "available": "Verfügbar", "available_balance": "Verfügbares Guthaben", "available_balance_description": "Der „Verfügbare Kontostand“ bzw. „Bestätigter Kontostand“ sind Guthaben, die sofort ausgegeben werden können. Wenn Guthaben im unteren Kontostand angezeigt wird, aber nicht im oberen, müssen Sie ein paar Minuten warten, bis die eingehenden Gelder weitere Netzwerkbestätigungen erhalten. Sobald sie mehr Bestätigungen haben, können sie ausgegeben werden.", "avg_savings": "Durchschn. Ersparnis", @@ -126,6 +128,7 @@ "block_remaining": "1 Block verbleibend", "Blocks_remaining": "${status} Blöcke verbleibend", "bluetooth": "Bluetooth", + "bridging": "Bridge-Vorgang", "bright_theme": "Hell", "bscscan_history": "BSCScan-Verlauf", "bump_fee": "Gebühr erhöhen", @@ -217,6 +220,8 @@ "color_theme": "Farbschema", "coming_soon_tag": "Demnächst verfügbar", "commit_transaction_amount_fee": "Transaktion bestätigen\nBetrag: ${amount}\nGebühr: ${fee}", + "compatible_services": "Kompatible Dienste", + "compatible_services_desc": "Verwenden Sie das Scan-Tool, um die folgenden von Cake Wallet unterstützten QR-Code-Typen zu lesen:", "configure": "Konfigurieren", "confirm": "Bestätigen", "confirm_delete_template": "Diese Aktion wird diese Vorlage löschen. Möchten Sie fortfahren?", @@ -280,6 +285,7 @@ "creating_new_wallet": "Neues Wallet wird erstellt", "creating_new_wallet_error": "Fehler: ${description}", "creation_date": "Erstellungsdatum", + "crypto_addresses": "Krypto-Adressen", "csv_nothing_to_export": "Nichts zum Exportieren", "current_swap": "Aktueller Swap", "current_wallet": "Aktuelle Wallet", @@ -302,6 +308,7 @@ "default_sell_provider": "Standardanbieter für Verkäufe", "delete": "Löschen", "delete_account": "Konto löschen", + "delete_this_node": "Diesen Node löschen", "delete_wallet": "Wallet löschen", "delete_wallet_confirm_message": "Sind Sie sicher, dass Sie die Wallet ${wallet_name} löschen möchten?", "deleteConnectionConfirmationPrompt": "Sind Sie sicher, dass Sie die Verbindung zu", @@ -331,6 +338,7 @@ "deuro_savings_welcome_description": "dEURO ist ein vollständig dezentraler, besicherter Stablecoin, der an den Euro gekoppelt ist – sicher, vielseitig und zensurresistent, ohne auf Orakel angewiesen zu sein. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Um dEURO zu aktivieren, müssen Sie ETH in Ihrem Wallet haben.", "deuro_tx_commited_content": "Es kann ein paar Sekunden dauern, bis die Transaktion bestätigt wird und auf dem Bildschirm angezeigt wird.", + "device_confirmation": "Gerätebestätigung", "device_is_signing": "Das Gerät signiert", "dfx_option_description": "Kaufen Sie Krypto mit EUR & CHF. Für Privat- und Unternehmenskunden in Europa", "did_you_back_up_seeds": "Haben Sie alle Ihre Seeds gesichert?", @@ -369,6 +377,8 @@ "duress_PIN": "Notfall-PIN", "duress_pin_description": "Dadurch wird eine Notfall-PIN eingerichtet, eine erweiterte Funktion, die von den meisten Nutzern nicht verwendet werden sollte. Diese PIN sollte nur verwendet werden, wenn Sie in Gefahr sind. Nachdem Sie diese PIN verwendet haben, werden alle Ihre Wallets gelöscht. Stellen Sie daher bitte sicher, dass alle Ihre Seeds gesichert sind, bevor Sie sie verwenden.", "duress_PIN_set_up_successfully": "Die Notfall-PIN wurde erfolgreich eingerichtet", + "durres_PIN": "Notfall-PIN", + "durres_PIN_set_up_successfully": "Die Notfall-PIN wurde erfolgreich eingerichtet", "e_sign_consent": "Einwilligung zur E-Signatur", "edit": "Bearbeiten", "edit_account": "Konto bearbeiten", @@ -467,6 +477,8 @@ "extracted_address_content": "Sie senden Guthaben an\n${recipient_name}", "failed_authentication": "Authentifizierung fehlgeschlagen. ${state_error}", "faq": "FAQ", + "favorite_token": "Bevorzugter Token", + "favorite_token_desc": "Der Kontostand des bevorzugten Tokens wird auf der Guthabenkarte angezeigt.", "features": "Funktionen", "fee": "Gebühr", "fee_less_than_min": "Die ausgewählte Gebühr liegt unter dem Minimum. Bitte erhöhen Sie die Gebühr, um die Transaktion senden zu können.", @@ -492,6 +504,7 @@ "frozen": "Eingefroren", "frozen_balance": "Eingefrorenes Guthaben", "full_balance": "Gesamtsaldo", + "gallery": "Galerie", "gas_exceeds_allowance": "Das für die Transaktion erforderliche Gas überschreitet das Limit.", "gas_price": "Gaspreis", "general": "Allgemein", @@ -527,6 +540,7 @@ "how_to_connect": "So verbinden Sie sich", "how_to_use": "So verwenden Sie", "how_to_use_card": "So verwenden Sie diese Karte", + "hww_exit_desc": "Dadurch wird der laufende Kopplungsvorgang mit Ihrem Hardware-Gerät beendet", "i_understand": "Ich verstehe", "icon_style": "Symbolstil", "id": "ID: ", @@ -542,6 +556,7 @@ "infobox_auto_address": "Ihre Empfangsadresse wird jedes Mal gewechselt, wenn Sie eine Transaktion erhalten", "infobox_multichain": "Verwenden Sie diese Adresse, um ein beliebiges Token oder Sammlerstück zu empfangen auf", "infobox_rotation": "Ihre Empfangsadresse wird jedes Mal rotiert, wenn Sie diesen Bildschirm schließen und erneut öffnen", + "input": "Eingabe", "inputs": "Eingaben", "insufficient_funds_for_tx": "Unzureichendes Guthaben, um die Transaktion erfolgreich auszuführen.", "insufficient_lamport_for_tx": "Sie haben nicht genug SOL, um die Transaktion und die Transaktionsgebühr zu decken. Bitte fügen Sie Ihrer Wallet mehr SOL hinzu oder reduzieren Sie den SOL-Betrag, den Sie senden.", @@ -607,6 +622,7 @@ "manage_pow_nodes": "PoW-Nodes verwalten", "manage_providers": "Anbieter verwalten", "manage_yats": "Yats verwalten", + "manual_input": "Manuelle Eingabe", "mark_as_redeemed": "Als eingelöst markieren", "market_place": "Marktplatz", "mask": "Maske", @@ -652,6 +668,7 @@ "nanogpt_subtitle": "Alle neuesten Modelle (GPT-5.3, Claude 4.6).\nKein Abonnement, bezahle mit Krypto.", "narrow": "Schmal", "network": "Netzwerk", + "networks": "Netzwerke", "new_first_wallet_text": "Ihre Kryptowährungen sicher aufzubewahren ist ein Kinderspiel", "new_node_testing": "Testen des neuen Nodes", "new_subaddress_create": "Erstellen", @@ -680,8 +697,10 @@ "node_new": "Neuer Node", "node_port": "Node-Port", "node_reset_settings_title": "Einstellungen zurücksetzen", + "node_share_desc": "Scannen Sie diesen QR-Code im Scan-Bildschirm, um diesen Node zu importieren.", "node_test": "Test", "nodes": "Nodes", + "nodes_desc": "Verwalten Sie bestehende Nodes oder fügen Sie einen benutzerdefinierten Node hinzu.", "nodes_list_reset_to_default_message": "Sind Sie sicher, dass Sie die Einstellungen auf die Standardeinstellungen zurücksetzen möchten?", "none_of_selected_providers_can_exchange": "Keiner der ausgewählten Anbieter kann diesen Swap durchführen", "noNFTYet": "Noch keine NFTs", @@ -691,6 +710,7 @@ "note_tap_to_change": "Notiz (zum Ändern tippen)", "notification_permission_denied": "Die Benachrichtigungsberechtigung wurde dauerhaft verweigert. Bitte aktivieren Sie sie manuell in den Einstellungen.", "nullURIError": "URI ist null", + "ocp_desc": "Mit Krypto im Geschäft bezahlen", "offer_expires_in": "Angebot läuft ab in: ", "offline": "Offline", "ok": "OK", @@ -717,8 +737,13 @@ "outputs": "Ausgänge", "overshot": "Überschuss", "overwrite_amount": "Betrag überschreiben", + "pairing_code": "Kopplungscode", + "pairing_code_desc_1": "Ihr Gerät zeigt einen Kopplungscode an.", + "pairing_code_desc_2": "Geben Sie ihn hier ein, um fortzufahren", + "pairing_error": "Kopplungsfehler", "pairingInvalidEvent": "Ungültiges Pairing-Ereignis", "passphrase": "Passphrase (Optional)", + "passphrase_view_keys": "Passphrase", "passphrases_doesnt_match": "Passphrasen stimmen nicht überein, bitte versuchen Sie es erneut", "password": "Passwort", "paste": "Einfügen", @@ -734,6 +759,7 @@ "payjoin_unavailable_sheet_content": "Um eine Payjoin-Transaktion zu empfangen, müssen Sie Bitcoin in Ihrem Wallet verfügbar haben.\n\nSobald Ihr Wallet über Guthaben verfügt, wird Payjoin automatisch aktiviert.", "payjoin_unavailable_sheet_title": "Warum ist Payjoin nicht verfügbar?", "payment_id": "Zahlungs-ID: ", + "payment_invoices": "Zahlungsanfragen", "payment_made_easy": "Zahlungen leicht gemacht", "payment_was_received": "Ihre Zahlung ist eingegangen.", "payments": "Zahlungen", @@ -763,8 +789,8 @@ "please_choose_one": "Bitte wählen Sie eine Option", "please_fill_totp": "Bitte geben Sie den 8-stelligen Code ein, der auf Ihrem anderen Gerät angezeigt wird", "please_make_selection": "Bitte treffen Sie unten eine Auswahl, um Ihre Wallet zu erstellen oder wiederherzustellen.", - "please_reference_document": "Bitte beachten Sie die untenstehenden Dokumente für weitere Informationen.", "Please_reference_document": "Weitere Informationen finden Sie in den Dokumenten unten.", + "please_reference_document": "Bitte beachten Sie die untenstehenden Dokumente für weitere Informationen.", "please_select": "Bitte auswählen:", "please_select_backup_file": "Bitte wählen Sie eine Sicherungsdatei aus und geben Sie das Sicherungskennwort ein.", "please_try_to_connect_to_another_node": "Bitte versuchen Sie, eine Verbindung zu einem anderen Node herzustellen", @@ -893,6 +919,7 @@ "save": "Speichern", "save_backup_password": "Bitte stellen Sie sicher, dass Sie Ihr Sicherungskennwort gespeichert haben. Sie können Ihre Sicherungsdateien ohne dieses nicht importieren.", "save_backup_password_alert": "Backup-Passwort speichern", + "save_contact": "Kontakt speichern", "save_to_downloads": "In „Downloads“ speichern", "saved_the_trade_id": "Ich habe die Trade-ID gespeichert", "savings": "Ersparnisse", @@ -1042,6 +1069,7 @@ "setup_your_debit_card": "Richten Sie Ihre Debitkarte ein", "share": "Teilen", "share_address": "Adresse teilen", + "share_this_node": "Diesen Node teilen", "shared_seed_wallet_groups": "Geteilte Seed-Wallet-Gruppen", "shared_seed_wallets": "Wallets mit gemeinsamem Seed", "show": "Anzeigen", @@ -1049,6 +1077,7 @@ "show_balance": "Lange drücken, um den Kontostand anzuzeigen", "show_balance_send_page": "Tippen, um anzuzeigen", "show_balance_toast": "Lange drücken, um den Kontostand auszublenden oder anzuzeigen", + "show_combined_balance": "Kombinierten Kontostand anzeigen", "show_details": "Details anzeigen", "show_hidden_addresses": "Versteckte Adressen anzeigen", "show_keys": "Seed/Schlüssel anzeigen", @@ -1114,6 +1143,7 @@ "swap_providers": "Swap-Anbieter", "sweeping_wallet": "Wallet leeren", "sweeping_wallet_alert": "Das sollte nicht lange dauern. Verlassen Sie diesen Bildschirm nicht, sonst können die geleerten Guthaben verloren gehen.", + "swipe_to_bridge": "Zum Bridging wischen", "swipe_to_send": "Zum Senden wischen", "switch_wallet": "Wallet wechseln", "switchToETHWallet": "Bitte wechseln Sie zu einer Ethereum-Wallet und versuchen Sie es erneut", @@ -1154,6 +1184,7 @@ "testnet_coins_no_value": "Testnet-Coins haben keinen Wert", "third_intro_content": "Yats existieren auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!", "third_intro_title": "Yat kommt gut mit anderen zurecht", + "this_can_take_few_seconds": "Dies kann einige Sekunden dauern", "this_pair_is_not_supported_warning": "Dieses Paar wird von den derzeit ausgewählten Börsen nicht unterstützt. Bitte wählen Sie eine andere Börse.", "thorchain_contract_address_not_supported": "THORChain unterstützt das Senden an eine Vertragsadresse nicht", "thorchain_taproot_address_not_supported": "Der ThorChain-Anbieter unterstützt keine Taproot-Adressen. Bitte ändern Sie die Adresse oder wählen Sie einen anderen Anbieter aus.", @@ -1167,6 +1198,7 @@ "token_decimal": "Token-Dezimalstelle (z. B.: USDT)", "token_name": "Token-Name (z. B.: Tether)", "token_symbol": "Token-Symbol (z. B.: USDT)", + "token_verified_on_jupiter": "Dieser Token ist auf Jupiter verifiziert", "tokenID": "ID", "tokens": "Token", "tokens_strong_warning": "Senden Sie niemals Token an diese Adresse!", @@ -1307,6 +1339,7 @@ "verify_message": "Nachricht verifizieren", "verify_seed": "Seed verifizieren", "verify_with_2fa": "Mit Cake 2FA verifizieren", + "verifying_code": "Code wird überprüft", "version": "Version ${currentVersion}", "view_all": "Alle anzeigen", "view_in_block_explorer": "Im Block Explorer anzeigen", @@ -1319,6 +1352,7 @@ "waiting_payment_confirmation": "Warte auf Zahlungsbestätigung", "wallet": "Wallet", "wallet_accounts": "Wallet-Konten", + "wallet_balance": "Wallet-Guthaben", "wallet_group": "Wallet-Gruppe", "wallet_group_description_existing_seed": "Sie haben sich entschieden, für diese Wallet einen vorhandenen Seed zu verwenden. Sie können den Seed erneut überprüfen, wenn Sie ihn bestätigen oder aufschreiben müssen.", "wallet_group_description_four": "um eine Wallet mit einem völlig neuen Seed zu erstellen.", @@ -1360,6 +1394,7 @@ "wc_approve_request_title": "Anfrage genehmigen", "wc_connect_request_title": "Verbindungsanfrage", "wc_connected_to": "Verbunden mit ${name}", + "wc_desc": "Einfach mit DApps verbinden", "wc_max_network_fee": "Maximale Netzwerkgebühr", "wc_message_to_sign": "Zu signierende Nachricht", "wc_network_fee": "Netzwerkgebühr", @@ -1410,6 +1445,7 @@ "yat_popup_content": "Sie können jetzt in Cake Wallet mit Ihrem Yat Krypto senden und empfangen – ein kurzer, emoji-basierter Benutzername. Verwalten Sie Yats jederzeit im Einstellungsbildschirm", "yat_popup_title": "Ihre Wallet-Adresse kann in Emojis umgewandelt werden.", "yes": "Ja", + "yes_exit": "Ja, beenden", "yesterday": "Gestern", "you_now_have_debit_card": "Sie haben jetzt eine Debitkarte", "you_pay": "Sie zahlen", @@ -1424,41 +1460,5 @@ "zcash_card_enable_later": "Sie können diese Karte jederzeit später in den Einstellungen aktivieren", "zcash_card_missing_funds": "Fehlende Gelder?", "zcash_card_scan": "Scannen", - "zcash_card_warning": "Schließen Sie die App nicht, bis der Vorgang abgeschlossen ist. Andernfalls muss der Vorgang von Grund auf neu gestartet werden.", - "are_you_sure_exit": "Möchten Sie die App wirklich verlassen?", - "available": "Verfügbar", - "bridging": "Bridge-Vorgang", - "compatible_services": "Kompatible Dienste", - "compatible_services_desc": "Verwenden Sie das Scan-Tool, um die folgenden von Cake Wallet unterstützten QR-Code-Typen zu lesen:", - "crypto_addresses": "Krypto-Adressen", - "delete_this_node": "Diesen Node löschen", - "device_confirmation": "Gerätebestätigung", - "durres_PIN": "Notfall-PIN", - "durres_PIN_set_up_successfully": "Die Notfall-PIN wurde erfolgreich eingerichtet", - "favorite_token": "Bevorzugter Token", - "favorite_token_desc": "Der Kontostand des bevorzugten Tokens wird auf der Guthabenkarte angezeigt.", - "gallery": "Galerie", - "hww_exit_desc": "Dadurch wird der laufende Kopplungsvorgang mit Ihrem Hardware-Gerät beendet", - "ignor": "Ignorieren", - "input": "Eingabe", - "manual_input": "Manuelle Eingabe", - "networks": "Netzwerke", - "node_share_desc": "Scannen Sie diesen QR-Code im Scan-Bildschirm, um diesen Node zu importieren.", - "nodes_desc": "Verwalten Sie bestehende Nodes oder fügen Sie einen benutzerdefinierten Node hinzu.", - "ocp_desc": "Mit Krypto im Geschäft bezahlen", - "pairing_code": "Kopplungscode", - "pairing_code_desc_1": "Ihr Gerät zeigt einen Kopplungscode an.", - "pairing_code_desc_2": "Geben Sie ihn hier ein, um fortzufahren", - "pairing_error": "Kopplungsfehler", - "passphrase_view_keys": "Passphrase", - "payment_invoices": "Zahlungsanfragen", - "save_contact": "Kontakt speichern", - "share_this_node": "Diesen Node teilen", - "show_combined_balance": "Kombinierten Kontostand anzeigen", - "swipe_to_bridge": "Zum Bridging wischen", - "this_can_take_few_seconds": "Dies kann einige Sekunden dauern", - "verifying_code": "Code wird überprüft", - "wallet_balance": "Wallet-Guthaben", - "wc_desc": "Einfach mit DApps verbinden", - "yes_exit": "Ja, beenden" -} + "zcash_card_warning": "Schließen Sie die App nicht, bis der Vorgang abgeschlossen ist. Andernfalls muss der Vorgang von Grund auf neu gestartet werden." +} \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 30e506aef..66b1c9e75 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -757,8 +757,8 @@ "pairing_error": "Pairing Error", "pairingInvalidEvent": "Pairing Invalid Event", "passphrase": "Passphrase (Optional)", - "passphrase_raw": "Passphrase", "passphrase_entry": "Passphrase entry", + "passphrase_raw": "Passphrase", "passphrase_view_keys": "Passphrase", "passphrases_doesnt_match": "Passphrases do not match, please try again", "password": "Password", @@ -1091,7 +1091,6 @@ "share_this_node": "Share this node", "shared_seed_wallet_groups": "Shared Seed Wallet Groups", "shared_seed_wallets": "Shared Seed Wallets", - "share_this_node": "Share this node", "shielding": "Autoshield", "show": "Show", "show_address_book_popup": "Show Address Book popup", @@ -1226,6 +1225,7 @@ "token_decimal": "Token decimal (eg: 6 for USDT)", "token_name": "Token name (eg: Tether)", "token_symbol": "Token symbol (eg: USDT)", + "token_verified_on_jupiter": "This token is verified on Jupiter", "tokenID": "ID", "tokens": "Tokens", "tokens_strong_warning": "Never send tokens to this address!", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 4f3590fb7..16a6b5a3e 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -76,6 +76,7 @@ "approve_tokens": "Aprobar tokens", "apps": "Apps", "arbiscan_history": "Historial de ArbiScan", + "are_you_sure_exit": "¿Seguro que quieres salir?", "arrive_in_this_address": "${currency} ${tag}llegará a esta dirección", "ascending": "Ascendente", "ask_each_time": "Preguntar cada vez", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Generar direcciones automáticamente", "auto_generate_subaddresses": "Generar subdirecciones automáticamente", "automatic": "Automático", + "available": "Disponible", "available_balance": "Saldo disponible", "available_balance_description": "El “Saldo Disponible” o “Saldo Confirmado” son fondos que pueden gastarse de inmediato. Si los fondos aparecen en el saldo inferior pero no en el saldo superior, deberás esperar unos minutos a que los fondos entrantes obtengan más confirmaciones de la red. Una vez que tengan más confirmaciones, podrás gastarlos.", "avg_savings": "Ahorro prom.", @@ -125,6 +127,7 @@ "block_remaining": "1 bloque restante", "Blocks_remaining": "${status} bloques restantes", "bluetooth": "Bluetooth", + "bridging": "Transfiriendo entre cadenas", "bright_theme": "Brillante", "bscscan_history": "Historial de BSCScan", "bump_fee": "Aumentar comisión", @@ -216,6 +219,8 @@ "color_theme": "Tema de color", "coming_soon_tag": "Próximamente", "commit_transaction_amount_fee": "Confirmar transacción\nCantidad: ${amount}\nComisión: ${fee}", + "compatible_services": "Servicios compatibles", + "compatible_services_desc": "Usa la herramienta Escanear para leer los siguientes tipos de códigos QR compatibles con Cake Wallet:", "configure": "Configurar", "confirm": "Confirmar", "confirm_delete_template": "Esta acción eliminará esta plantilla. ¿Deseas continuar?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Creando una nueva billetera", "creating_new_wallet_error": "Error: ${description}", "creation_date": "Fecha de creación", + "crypto_addresses": "Direcciones cripto", "csv_nothing_to_export": "No hay nada que exportar", "current_swap": "Intercambio actual", "current_wallet": "Cartera actual", @@ -301,6 +307,7 @@ "default_sell_provider": "Proveedor de venta predeterminado", "delete": "Eliminar", "delete_account": "Eliminar cuenta", + "delete_this_node": "Eliminar este nodo", "delete_wallet": "Eliminar monedero", "delete_wallet_confirm_message": "¿Seguro que deseas eliminar la wallet ${wallet_name}?", "deleteConnectionConfirmationPrompt": "¿Estás seguro de que quieres eliminar la conexión con", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO es una stablecoin totalmente descentralizada y colateralizada, vinculada al euro — segura, versátil y resistente a la censura sin tener que depender de oráculos. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Para habilitar dEURO, debes tener ETH en tu billetera.", "deuro_tx_commited_content": "Puede tardar un par de segundos en que la transacción se confirme y se refleje en la pantalla", + "device_confirmation": "Confirmación del dispositivo", "device_is_signing": "El dispositivo está firmando", "dfx_option_description": "Compra cripto con EUR y CHF. Para clientes minoristas y corporativos en Europa", "did_you_back_up_seeds": "¿Hiciste una copia de seguridad de todas tus semillas?", @@ -466,6 +474,8 @@ "extracted_address_content": "Enviarás fondos a\n${recipient_name}", "failed_authentication": "Falló la autenticación. ${state_error}", "faq": "Preguntas frecuentes", + "favorite_token": "Token favorito", + "favorite_token_desc": "El saldo del token favorito se mostrará en la tarjeta de saldo.", "features": "Funciones", "fee": "Comisión", "fee_less_than_min": "La comisión seleccionada es inferior a la mínima. Por favor, aumenta la comisión para poder enviar la transacción.", @@ -491,6 +501,7 @@ "frozen": "Congelado", "frozen_balance": "Saldo congelado", "full_balance": "Saldo total", + "gallery": "Galería", "gas_exceeds_allowance": "El gas requerido por la transacción excede el límite permitido.", "gas_price": "Precio del gas", "general": "General", @@ -526,6 +537,7 @@ "how_to_connect": "Cómo conectarse", "how_to_use": "Cómo usar", "how_to_use_card": "Cómo usar esta tarjeta", + "hww_exit_desc": "Esto finalizará el proceso de emparejamiento en curso con tu dispositivo de hardware", "i_understand": "Entiendo", "icon_style": "Estilo de icono", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Su dirección de recepción rotará cada vez que reciba una transacción", "infobox_multichain": "Utilice esta dirección para recibir cualquier token o coleccionable en", "infobox_rotation": "Su dirección de recepción rotará cada vez que cierre y vuelva a abrir esta pantalla", + "input": "Entrada", "inputs": "Entradas", "insufficient_funds_for_tx": "Fondos insuficientes para ejecutar correctamente la transacción.", "insufficient_lamport_for_tx": "No tienes suficiente SOL para cubrir la transacción y su comisión. Por favor, añade más SOL a tu billetera o reduce la cantidad de SOL que estás enviando.", @@ -554,8 +567,8 @@ "keys": "Claves", "label": "Etiqueta", "label_address": "Etiquetar dirección", - "last_7_days": "Últimos 7 días", "last_30_days": "Últimos 30 días", + "last_7_days": "Últimos 7 días", "learn_more": "Más información", "ledger_connection_error": "No se pudo conectar a tu Ledger. Inténtalo de nuevo.", "ledger_error_device_locked": "El Ledger está bloqueado", @@ -606,6 +619,7 @@ "manage_pow_nodes": "Gestionar nodos PoW", "manage_providers": "Gestionar proveedores", "manage_yats": "Gestionar Yats", + "manual_input": "Entrada manual", "mark_as_redeemed": "Marcar como canjeado", "market_place": "Marketplace", "mask": "Máscara", @@ -651,6 +665,7 @@ "nanogpt_subtitle": "Todos los modelos más recientes (GPT-5.3, Claude 4.6).\nSin suscripción, paga con cripto.", "narrow": "Estrecho", "network": "Red", + "networks": "Redes", "new_first_wallet_text": "Mantener tus criptomonedas seguras es pan comido", "new_node_testing": "Prueba de nuevo nodo", "new_subaddress_create": "Crear", @@ -679,8 +694,10 @@ "node_new": "Nuevo nodo", "node_port": "Puerto del nodo", "node_reset_settings_title": "Restablecer configuración", + "node_share_desc": "Escanea este código QR desde la pantalla Escanear para importar este nodo.", "node_test": "Prueba", "nodes": "Nodos", + "nodes_desc": "Administra los nodos existentes o añade uno personalizado.", "nodes_list_reset_to_default_message": "¿Seguro que deseas restablecer la configuración a los valores predeterminados?", "none_of_selected_providers_can_exchange": "Ninguno de los proveedores seleccionados puede realizar este swap", "noNFTYet": "Aún no hay NFT", @@ -690,6 +707,7 @@ "note_tap_to_change": "Nota (toca para cambiar)", "notification_permission_denied": "El permiso de notificaciones se ha denegado permanentemente. Por favor, habilítalo manualmente en la configuración.", "nullURIError": "El URI es nulo", + "ocp_desc": "Paga con cripto en tiendas", "offer_expires_in": "La oferta caduca en: ", "offline": "Sin conexión", "ok": "OK", @@ -716,8 +734,13 @@ "outputs": "Salidas", "overshot": "Excedido", "overwrite_amount": "Sobrescribir monto", + "pairing_code": "Código de emparejamiento", + "pairing_code_desc_1": "Tu dispositivo mostrará un código de emparejamiento.", + "pairing_code_desc_2": "Introdúcelo aquí para continuar", + "pairing_error": "Error de emparejamiento", "pairingInvalidEvent": "Evento de emparejamiento no válido", "passphrase": "Frase de contraseña (opcional)", + "passphrase_view_keys": "Frase de contraseña", "passphrases_doesnt_match": "Las frases de contraseña no coinciden, inténtelo de nuevo", "password": "Contraseña", "paste": "Pegar", @@ -733,6 +756,7 @@ "payjoin_unavailable_sheet_content": "Recibir una transacción Payjoin requiere que tenga Bitcoin listo para usar.\n\nEn cuanto su billetera tenga fondos, Payjoin se habilitará automáticamente.", "payjoin_unavailable_sheet_title": "¿Por qué Payjoin no está disponible?", "payment_id": "ID de pago: ", + "payment_invoices": "Facturas de pago", "payment_made_easy": "Pagos fáciles", "payment_was_received": "Tu pago fue recibido.", "payments": "Pagos", @@ -889,6 +913,7 @@ "save": "Guardar", "save_backup_password": "Asegúrate de haber guardado tu contraseña de copia de seguridad. No podrás importar tus archivos de copia de seguridad sin ella.", "save_backup_password_alert": "Guardar contraseña de la copia de seguridad", + "save_contact": "Guardar contacto", "save_to_downloads": "Guardar en Descargas", "saved_the_trade_id": "He guardado el ID de la operación", "savings": "Ahorros", @@ -1038,6 +1063,7 @@ "setup_your_debit_card": "Configura tu tarjeta de débito", "share": "Compartir", "share_address": "Compartir dirección", + "share_this_node": "Compartir este nodo", "shared_seed_wallet_groups": "Grupos de carteras con semilla compartida", "shared_seed_wallets": "Carteras con semilla compartida", "show": "Mostrar", @@ -1045,6 +1071,7 @@ "show_balance": "Mantén pulsado para mostrar el saldo", "show_balance_send_page": "Toca para revelar", "show_balance_toast": "Mantén pulsado para ocultar o mostrar el saldo", + "show_combined_balance": "Mostrar saldo combinado", "show_details": "Mostrar detalles", "show_hidden_addresses": "Mostrar direcciones ocultas", "show_keys": "Mostrar frase semilla/claves", @@ -1110,6 +1137,7 @@ "swap_providers": "Proveedores de intercambio", "sweeping_wallet": "Cartera de barrido", "sweeping_wallet_alert": "Esto no debería tardar mucho. NO SALGAS DE ESTA PANTALLA O LOS FONDOS BARRIDOS PODRÍAN PERDERSE.", + "swipe_to_bridge": "Desliza para transferir entre cadenas", "swipe_to_send": "Desliza para enviar", "switch_wallet": "Cambiar cartera", "switchToETHWallet": "Por favor, cambia a una billetera de Ethereum y vuelve a intentarlo.", @@ -1150,6 +1178,7 @@ "testnet_coins_no_value": "Las monedas de testnet no tienen valor", "third_intro_content": "Los Yats también existen fuera de Cake Wallet. ¡Cualquier dirección de billetera del mundo puede reemplazarse por un Yat!", "third_intro_title": "Yat se lleva bien con otros", + "this_can_take_few_seconds": "Esto puede tardar unos segundos", "this_pair_is_not_supported_warning": "Este par no es compatible con el/los exchange(s) seleccionado(s) actualmente. Seleccione otro exchange.", "thorchain_contract_address_not_supported": "THORChain no admite envíos a una dirección de contrato", "thorchain_taproot_address_not_supported": "El proveedor de ThorChain no admite direcciones Taproot. Por favor, cambia la dirección o selecciona otro proveedor.", @@ -1163,6 +1192,7 @@ "token_decimal": "Decimales del token (ej.: USDT)", "token_name": "Nombre del token (p. ej., Tether)", "token_symbol": "Símbolo del token (p. ej.: USDT)", + "token_verified_on_jupiter": "Este token está verificado en Jupiter", "tokenID": "ID", "tokens": "Tokens", "tokens_strong_warning": "¡Nunca envíes tokens a esta dirección!", @@ -1291,6 +1321,7 @@ "username": "Nombre de usuario", "username_available": "Nombre de usuario disponible", "username_character_error": "Los nombres de usuario solo deben contener", + "username_check_your_network": "No se pudo verificar el nombre de usuario. Comprueba tu conexión de red.", "username_length_error": "Los nombres de usuario deben contener entre 6 y 32 caracteres alfanuméricos.", "username_length_error_1_64": "Los nombres de usuario deben contener entre 1 y 64 caracteres alfanuméricos.", "username_not_available": "Este nombre de usuario no está disponible.", @@ -1301,6 +1332,7 @@ "verify_message": "Verificar mensaje", "verify_seed": "Verificar frase semilla", "verify_with_2fa": "Verificar con Cake 2FA", + "verifying_code": "Verificando código", "version": "Versión ${currentVersion}", "view_all": "Ver todo", "view_in_block_explorer": "Ver en el explorador de bloques", @@ -1312,6 +1344,7 @@ "waitFewSecondForTxUpdate": "Por favor, espera unos segundos para que la transacción se refleje en el historial de transacciones.", "wallet": "Cartera", "wallet_accounts": "Cuentas de la cartera", + "wallet_balance": "Saldo de la cartera", "wallet_group": "Grupo de billeteras", "wallet_group_description_existing_seed": "Has elegido usar una frase semilla existente para esta billetera. Puedes verificar la frase semilla de nuevo si necesitas confirmarla o anotarla.", "wallet_group_description_four": "para crear una billetera con una frase semilla completamente nueva.", @@ -1353,6 +1386,7 @@ "wc_approve_request_title": "Aprobar solicitud", "wc_connect_request_title": "Solicitud de conexión", "wc_connected_to": "Conectado a ${name}", + "wc_desc": "Conéctate fácilmente a dApps", "wc_max_network_fee": "Tarifa máxima de red", "wc_message_to_sign": "Mensaje para firmar", "wc_network_fee": "Tarifa de red", @@ -1404,6 +1438,7 @@ "yat_popup_content": "Ahora puedes enviar y recibir criptomonedas en Cake Wallet con tu Yat, un nombre de usuario corto basado en emojis. Administra tus Yats en cualquier momento desde la pantalla de configuración", "yat_popup_title": "La dirección de tu billetera se puede convertir en emojis.", "yes": "Sí", + "yes_exit": "Sí. Salir", "yesterday": "Ayer", "you_now_have_debit_card": "Ahora tienes una tarjeta de débito", "you_pay": "Tú pagas", diff --git a/res/values/strings_fa.arb b/res/values/strings_fa.arb index 6a15e0c9a..bbdc78adc 100644 --- a/res/values/strings_fa.arb +++ b/res/values/strings_fa.arb @@ -76,6 +76,7 @@ "approve_tokens": "تأیید توکن‌ها", "apps": "برنامه‌ها", "arbiscan_history": "تاریخچه ArbiScan", + "are_you_sure_exit": "آیا مطمئن هستید که می‌خواهید خارج شوید؟", "arrive_in_this_address": "${currency} ${tag}به این آدرس خواهد رسید", "ascending": "صعودی", "ask_each_time": "هر بار بپرس", @@ -89,6 +90,7 @@ "auto_generate_addresses": "تولید خودکار آدرس‌ها", "auto_generate_subaddresses": "تولید خودکار زیرآدرس‌ها", "automatic": "خودکار", + "available": "در دسترس", "available_balance": "موجودی در دسترس", "available_balance_description": "«موجودی قابل‌دسترس» یا «موجودی تأییدشده» وجوهی هستند که می‌توان بلافاصله خرج کرد.\nاگر وجوه در موجودی پایین‌تر ظاهر شوند اما در موجودی بالا نباشند، باید چند دقیقه صبر کنید تا وجوه ورودی تأییدهای شبکه بیشتری دریافت کنند.\nپس از دریافت تأییدهای بیشتر، قابل خرج کردن خواهند بود.", "avg_savings": "میانگین صرفه‌جویی", @@ -118,11 +120,14 @@ "bitcoin_amount_display": "نمایش مقدار بیت‌کوین", "bitcoin_dark_theme": "تم تیره بیت‌کوین", "bitcoin_light_theme": "تم روشن بیت‌کوین", + "bitcoin_lightning_deposit": "واریز", + "bitcoin_lightning_withdraw": "برداشت", "bitcoin_payments_require_1_confirmation": "پرداخت‌های بیت‌کوین به ۱ تأیید نیاز دارند که ممکن است ۲۰ دقیقه یا بیشتر طول بکشد.\nاز شکیبایی شما سپاسگزاریم! پس از تأیید پرداخت، از طریق ایمیل به شما اطلاع داده خواهد شد.", "block_height": "ارتفاع بلاک", "block_remaining": "۱ بلاک باقی مانده", "Blocks_remaining": "${status} بلاک باقی‌مانده", "bluetooth": "بلوتوث", + "bridging": "در حال پل‌زدن", "bright_theme": "روشن", "bscscan_history": "تاریخچه BSCScan", "bump_fee": "افزایش کارمزد", @@ -214,6 +219,8 @@ "color_theme": "تم رنگ", "coming_soon_tag": "به‌زودی", "commit_transaction_amount_fee": "ثبت تراکنش\nمقدار: ${amount}\nکارمزد: ${fee}", + "compatible_services": "سرویس‌های سازگار", + "compatible_services_desc": "از ابزار اسکن برای خواندن انواع کدهای QR زیر که در Cake Wallet پشتیبانی می‌شوند استفاده کنید:", "configure": "پیکربندی", "confirm": "تأیید", "confirm_delete_template": "این اقدام این قالب را حذف می‌کند.\nآیا مایلید ادامه دهید؟", @@ -277,6 +284,7 @@ "creating_new_wallet": "در حال ایجاد کیف پول جدید", "creating_new_wallet_error": "خطا: ${description}", "creation_date": "تاریخ ایجاد", + "crypto_addresses": "آدرس‌های رمزارز", "csv_nothing_to_export": "چیزی برای صدور وجود ندارد", "current_swap": "سواپ فعلی", "current_wallet": "کیف پول فعلی", @@ -299,6 +307,7 @@ "default_sell_provider": "ارائه‌دهنده پیش‌فرض فروش", "delete": "حذف", "delete_account": "حذف حساب", + "delete_this_node": "حذف این نود", "delete_wallet": "حذف کیف پول", "delete_wallet_confirm_message": "آیا مطمئن هستید که می‌خواهید کیف پول ${wallet_name} را حذف کنید؟", "deleteConnectionConfirmationPrompt": "آیا مطمئن هستید که می‌خواهید اتصال به", @@ -328,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO یک استیبل‌کوین کاملاً غیرمتمرکز و وثیقه‌گذاری‌شده است که به یورو متصل است — امن، چندمنظوره و مقاوم در برابر سانسور، بدون نیاز به تکیه بر اوراکل‌ها. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "برای فعال‌سازی dEURO، باید در کیف پول خود ETH داشته باشید.", "deuro_tx_commited_content": "ممکن است چند ثانیه طول بکشد تا تراکنش تأیید شود و در صفحه نمایش داده شود", + "device_confirmation": "تأیید دستگاه", "device_is_signing": "دستگاه در حال امضا کردن است", "dfx_option_description": "خرید کریپتو با EUR و CHF.\nبرای مشتریان خرد و شرکتی در اروپا", "did_you_back_up_seeds": "آیا از تمام عبارت‌های بازیابی خود نسخهٔ پشتیبان تهیه کرده‌اید؟", @@ -464,6 +474,8 @@ "extracted_address_content": "شما در حال ارسال وجه به\n${recipient_name} هستید", "failed_authentication": "احراز هویت ناموفق بود. ${state_error}", "faq": "پرسش‌های متداول", + "favorite_token": "توکن موردعلاقه", + "favorite_token_desc": "موجودی توکن موردعلاقه روی کارت موجودی نمایش داده می‌شود.", "features": "ویژگی‌ها", "fee": "کارمزد", "fee_less_than_min": "کارمزد انتخاب‌شده کمتر از حداقل است؛ لطفاً برای اینکه بتوانید تراکنش را ارسال کنید، کارمزد را افزایش دهید", @@ -489,6 +501,7 @@ "frozen": "منجمد", "frozen_balance": "موجودی فریز شده", "full_balance": "موجودی کامل", + "gallery": "گالری", "gas_exceeds_allowance": "گس (Gas) مورد نیاز برای تراکنش از حد مجاز فراتر می‌رود.", "gas_price": "قیمت گس", "general": "عمومی", @@ -524,6 +537,7 @@ "how_to_connect": "چگونه متصل شویم", "how_to_use": "نحوه استفاده", "how_to_use_card": "چگونه از این کارت استفاده کنیم", + "hww_exit_desc": "این کار، فرایند جفت‌سازی در حال انجام با دستگاه سخت‌افزاری شما را پایان می‌دهد", "i_understand": "متوجه شدم", "icon_style": "سبک آیکون", "id": "شناسه: ", @@ -538,6 +552,7 @@ "infobox_auto_address": "آدرس دریافت شما هر بار که یک تراکنش دریافت می‌کنید تغییر می‌کند", "infobox_multichain": "از این آدرس برای دریافت هر توکن یا کالکتیبل در", "infobox_rotation": "هر بار که این صفحه را ببندید و دوباره باز کنید، آدرس دریافت شما تغییر می‌کند", + "input": "ورودی", "inputs": "ورودی‌ها", "insufficient_funds_for_tx": "موجودی کافی برای انجام موفقیت‌آمیز تراکنش وجود ندارد.", "insufficient_lamport_for_tx": "شما SOL کافی برای پوشش تراکنش و کارمزد آن ندارید.\nلطفاً SOL بیشتری به کیف پول خود اضافه کنید یا مقدار SOL ارسالی را کاهش دهید.", @@ -603,6 +618,7 @@ "manage_pow_nodes": "مدیریت نودهای PoW", "manage_providers": "مدیریت ارائه‌دهندگان", "manage_yats": "مدیریت Yatها", + "manual_input": "ورود دستی", "mark_as_redeemed": "علامت‌گذاری به‌عنوان بازخریدشده", "market_place": "بازار", "mask": "ماسک", @@ -648,6 +664,7 @@ "nanogpt_subtitle": "همه جدیدترین مدل‌ها (GPT-5.3, Claude 4.6).\nبدون اشتراک، پرداخت با کریپتو.", "narrow": "باریک", "network": "شبکه", + "networks": "شبکه‌ها", "new_first_wallet_text": "امن نگه داشتن رمزارزهای شما مثل آب خوردن است", "new_node_testing": "آزمایش نود جدید", "new_subaddress_create": "ایجاد", @@ -676,8 +693,10 @@ "node_new": "گره جدید", "node_port": "پورت نود", "node_reset_settings_title": "بازنشانی تنظیمات", + "node_share_desc": "برای وارد کردن این نود، این کد QR را از صفحهٔ اسکن اسکن کنید.", "node_test": "آزمایشی", "nodes": "نودها", + "nodes_desc": "نودهای موجود را مدیریت کنید یا یک نود سفارشی اضافه کنید.", "nodes_list_reset_to_default_message": "آیا مطمئن هستید که می‌خواهید تنظیمات را به حالت پیش‌فرض بازنشانی کنید؟", "none_of_selected_providers_can_exchange": "هیچ‌یک از ارائه‌دهندگان انتخاب‌شده نمی‌توانند این سواپ را انجام دهند", "noNFTYet": "هنوز هیچ NFT‌ای وجود ندارد", @@ -687,6 +706,7 @@ "note_tap_to_change": "یادداشت (برای تغییر ضربه بزنید)", "notification_permission_denied": "مجوز اعلان‌ها به‌طور دائمی رد شده است، لطفاً آن را به‌صورت دستی در تنظیمات فعال کنید", "nullURIError": "URI تهی است", + "ocp_desc": "پرداخت با رمزارز در فروشگاه‌ها", "offer_expires_in": "این پیشنهاد تا این زمان معتبر است: ", "offline": "آفلاین", "ok": "تأیید", @@ -713,6 +733,10 @@ "outputs": "خروجی‌ها", "overshot": "فراتر رفت", "overwrite_amount": "بازنویسی مقدار", + "pairing_code": "کد جفت‌سازی", + "pairing_code_desc_1": "دستگاه شما یک کد جفت‌سازی نمایش می‌دهد.", + "pairing_code_desc_2": "برای ادامه، اینجا وارد کنید", + "pairing_error": "خطای جفت‌سازی", "pairingInvalidEvent": "رویداد نامعتبر جفت‌سازی", "passphrase": "عبارت عبور (اختیاری)", "passphrase_view_keys": "عبارت عبور (Passphrase)", @@ -731,6 +755,7 @@ "payjoin_unavailable_sheet_content": "برای دریافت یک تراکنش Payjoin باید بیت‌کوین آمادهٔ استفاده داشته باشید.\n\nبه محض اینکه کیف پول شما موجودی داشته باشد، Payjoin به‌طور خودکار فعال می‌شود.", "payjoin_unavailable_sheet_title": "چرا Payjoin در دسترس نیست؟", "payment_id": "شناسه پرداخت: ", + "payment_invoices": "صورتحساب‌های پرداخت", "payment_made_easy": "پرداخت‌ها آسان شده‌اند", "payment_was_received": "پرداخت شما دریافت شد.", "payments": "پرداخت‌ها", @@ -886,6 +911,7 @@ "save": "ذخیره", "save_backup_password": "لطفاً مطمئن شوید که رمز عبور پشتیبان خود را ذخیره کرده‌اید.\nبدون آن نمی‌توانید فایل‌های پشتیبان خود را وارد کنید.", "save_backup_password_alert": "ذخیره گذرواژهٔ پشتیبان", + "save_contact": "ذخیره مخاطب", "save_to_downloads": "ذخیره در پوشهٔ دانلودها", "saved_the_trade_id": "شناسه معامله را ذخیره کردم", "savings": "پس‌انداز", @@ -1035,6 +1061,7 @@ "setup_your_debit_card": "راه‌اندازی کارت دبیت خود", "share": "اشتراک‌گذاری", "share_address": "اشتراک‌گذاری آدرس", + "share_this_node": "اشتراک‌گذاری این نود", "shared_seed_wallet_groups": "گروه‌های کیف پول با سید مشترک", "shared_seed_wallets": "کیف پول‌های سید مشترک", "show": "نمایش", @@ -1042,6 +1069,7 @@ "show_balance": "برای نمایش موجودی، لمس طولانی کنید", "show_balance_send_page": "برای آشکار کردن ضربه بزنید", "show_balance_toast": "برای مخفی یا نمایش دادن موجودی، لمس طولانی کنید", + "show_combined_balance": "نمایش موجودی ترکیبی", "show_details": "نمایش جزئیات", "show_hidden_addresses": "نمایش آدرس‌های مخفی", "show_keys": "نمایش عبارت بازیابی/کلیدها", @@ -1107,6 +1135,7 @@ "swap_providers": "ارائه‌دهندگان سواپ", "sweeping_wallet": "در حال انتقال موجودی کیف پول", "sweeping_wallet_alert": "این کار نباید طول بکشد.\nاین صفحه را ترک نکنید، وگرنه ممکن است وجوه انتقال‌یافته از دست برود.", + "swipe_to_bridge": "برای پل‌زدن، انگشت خود را بکشید", "swipe_to_send": "برای ارسال، انگشت خود را بکشید", "switch_wallet": "تعویض کیف پول", "switchToETHWallet": "لطفاً به کیف پول اتریوم تغییر دهید و دوباره تلاش کنید", @@ -1147,6 +1176,7 @@ "testnet_coins_no_value": "کوین‌های تست‌نت هیچ ارزشی ندارند", "third_intro_content": "Yatها خارج از Cake Wallet هم وجود دارند.\nهر آدرس کیف پولی در دنیا می‌تواند با یک Yat جایگزین شود!", "third_intro_title": "Yat با دیگران به‌خوبی کار می‌کند", + "this_can_take_few_seconds": "این ممکن است چند ثانیه طول بکشد", "this_pair_is_not_supported_warning": "این جفت‌ارز با صرافی(های) انتخاب‌شده در حال حاضر پشتیبانی نمی‌شود.\nلطفاً صرافی دیگری را انتخاب کنید.", "thorchain_contract_address_not_supported": "THORChain از ارسال به آدرس قرارداد پشتیبانی نمی‌کند", "thorchain_taproot_address_not_supported": "ارائه‌دهنده ThorChain از آدرس‌های Taproot پشتیبانی نمی‌کند.\nلطفاً آدرس را تغییر دهید یا ارائه‌دهنده دیگری را انتخاب کنید.", @@ -1160,6 +1190,7 @@ "token_decimal": "اعشار توکن (مثلاً: ۶ برای USDT)", "token_name": "نام توکن (مثلاً: Tether)", "token_symbol": "نماد توکن (مثلاً: USDT)", + "token_verified_on_jupiter": "این توکن در Jupiter تأیید شده است", "tokenID": "شناسه", "tokens": "توکن‌ها", "tokens_strong_warning": "هرگز توکن‌ها را به این آدرس ارسال نکنید!", @@ -1251,6 +1282,7 @@ "tx_rejected_dust_output": "تراکنش به‌دلیل قوانین شبکه رد شد؛ مقدار خروجی کم است (داست).\nلطفاً مقدار را افزایش دهید.", "tx_rejected_dust_output_send_all": "تراکنش طبق قوانین شبکه رد شد؛ مقدار خروجی کم است (داست).\nلطفاً موجودی کوین‌های انتخاب‌شده در Coin Control را بررسی کنید.", "tx_rejected_vout_negative": "موجودی کافی برای پرداخت کارمزدهای این تراکنش وجود ندارد.\nلطفاً موجودی کوین‌ها را در بخش Coin Control بررسی کنید.", + "tx_retry_message": "هنگام پردازش تراکنش خطایی رخ داد. لطفاً تراکنش را دوباره تلاش کنید.", "tx_wrong_balance_exception": "شما به اندازه کافی ${currency} برای ارسال این مقدار ندارید.", "tx_wrong_balance_with_amount_exception": "شما به اندازه کافی ${currency} برای ارسال مبلغ کل ${amount} ندارید", "tx_zero_fee_exception": "نمی‌توان تراکنشی با کارمزد ۰ ارسال کرد.\nسعی کنید نرخ را افزایش دهید یا برای دریافت آخرین برآوردها اتصال خود را بررسی کنید.", @@ -1275,6 +1307,7 @@ "upto": "تا ${value}", "usb": "USB", "use": "تغییر به ", + "use_blink_protection": "استفاده از محافظت Blink", "use_card_info_three": "از کارت دیجیتال به‌صورت آنلاین یا با روش‌های پرداخت بدون تماس استفاده کنید.", "use_card_info_two": "وجوه زمانی که در حساب پیش‌پرداخت نگهداری می‌شوند به دلار آمریکا (USD) تبدیل می‌شوند، نه به ارزهای دیجیتال.", "use_device_theme": "استفاده از تم دستگاه", @@ -1286,6 +1319,7 @@ "username": "نام کاربری", "username_available": "نام کاربری در دسترس است", "username_character_error": "نام‌های کاربری فقط باید شامل", + "username_check_your_network": "بررسی نام کاربری امکان‌پذیر نیست. لطفاً اتصال شبکهٔ خود را بررسی کنید.", "username_length_error": "نام‌های کاربری باید شامل ۶ تا ۳۲ کاراکتر حرفی-عددی باشند.", "username_length_error_1_64": "نام‌های کاربری باید شامل ۱ تا ۶۴ نویسهٔ حرفی-عددی باشند.", "username_not_available": "این نام کاربری در دسترس نیست.", @@ -1296,6 +1330,7 @@ "verify_message": "تأیید پیام", "verify_seed": "تأیید عبارت بازیابی", "verify_with_2fa": "تأیید با Cake 2FA", + "verifying_code": "در حال تأیید کد", "version": "نسخه ${currentVersion}", "view_all": "مشاهده همه", "view_in_block_explorer": "مشاهده در بلاک اکسپلورر", @@ -1307,6 +1342,7 @@ "waitFewSecondForTxUpdate": "لطفاً چند ثانیه صبر کنید تا تراکنش در تاریخچه تراکنش‌ها نمایش داده شود", "wallet": "کیف پول", "wallet_accounts": "حساب‌های کیف پول", + "wallet_balance": "موجودی کیف پول", "wallet_group": "گروه کیف پول", "wallet_group_description_existing_seed": "شما انتخاب کرده‌اید که از یک سید موجود برای این کیف پول استفاده کنید.\nاگر لازم است آن را تأیید کنید یا یادداشتش کنید، می‌توانید سید را دوباره بررسی کنید.", "wallet_group_description_four": "برای ایجاد یک کیف پول با سید کاملاً جدید.", @@ -1348,6 +1384,7 @@ "wc_approve_request_title": "درخواست را تایید کنید", "wc_connect_request_title": "درخواست اتصال", "wc_connected_to": "متصل به ${name}", + "wc_desc": "به‌راحتی به dAppها متصل شوید", "wc_max_network_fee": "حداکثر هزینه شبکه", "wc_message_to_sign": "برای امضا پیام دهید", "wc_network_fee": "هزینه شبکه", @@ -1398,6 +1435,7 @@ "yat_popup_content": "اکنون می‌توانید در Cake Wallet با Yat خود — یک نام کاربری کوتاه مبتنی بر ایموجی — رمزارز ارسال و دریافت کنید.\nYatها را هر زمان از صفحه تنظیمات مدیریت کنید", "yat_popup_title": "آدرس کیف پول شما می‌تواند به ایموجی تبدیل شود.", "yes": "بله", + "yes_exit": "بله. خروج", "yesterday": "دیروز", "you_now_have_debit_card": "شما اکنون یک کارت دبیت دارید", "you_pay": "شما پرداخت می‌کنید", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 397529fb1..dd01db39e 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -76,6 +76,7 @@ "approve_tokens": "Approuver les tokens", "apps": "Apps", "arbiscan_history": "Historique ArbiScan", + "are_you_sure_exit": "Êtes-vous sûr de vouloir quitter ?", "arrive_in_this_address": "${currency} ${tag}arriveront à cette adresse", "ascending": "Croissant", "ask_each_time": "Demander à chaque fois", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Générer automatiquement des adresses", "auto_generate_subaddresses": "Générer automatiquement des sous-adresses", "automatic": "Automatique", + "available": "Disponible", "available_balance": "Solde disponible", "available_balance_description": "Le « Solde disponible » ou le « Solde confirmé » correspond aux fonds que vous pouvez dépenser immédiatement. Si des fonds apparaissent dans le solde inférieur mais pas dans le solde supérieur, vous devez attendre quelques minutes pour que les fonds entrants obtiennent davantage de confirmations sur le réseau. Une fois qu’ils auront reçu plus de confirmations, ils pourront être dépensés.", "avg_savings": "Économies moy.", @@ -125,6 +127,7 @@ "block_remaining": "1 bloc restant", "Blocks_remaining": "${status} blocs restants", "bluetooth": "Bluetooth", + "bridging": "Transfert inter-chaînes", "bright_theme": "Clair", "bscscan_history": "Historique BSCScan", "bump_fee": "Augmenter les frais", @@ -216,6 +219,8 @@ "color_theme": "Thème de couleur", "coming_soon_tag": "Bientôt disponible", "commit_transaction_amount_fee": "Confirmer la transaction\nMontant : ${amount}\nFrais : ${fee}", + "compatible_services": "Services compatibles", + "compatible_services_desc": "Utilisez l'outil Scan pour lire les types de codes QR suivants pris en charge par Cake Wallet :", "configure": "Configurer", "confirm": "Confirmer", "confirm_delete_template": "Cette action supprimera ce modèle. Souhaitez-vous continuer ?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Création d'un nouveau portefeuille", "creating_new_wallet_error": "Erreur : ${description}", "creation_date": "Date de création", + "crypto_addresses": "Adresses crypto", "csv_nothing_to_export": "Nothing to export", "current_swap": "Swap en cours", "current_wallet": "Portefeuille actuel", @@ -301,6 +307,7 @@ "default_sell_provider": "Fournisseur de vente par défaut", "delete": "Supprimer", "delete_account": "Supprimer le compte", + "delete_this_node": "Supprimer ce nœud", "delete_wallet": "Supprimer le portefeuille", "delete_wallet_confirm_message": "Êtes-vous sûr de vouloir supprimer le portefeuille ${wallet_name} ?", "deleteConnectionConfirmationPrompt": "Êtes-vous sûr de vouloir supprimer la connexion à", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO est un stablecoin entièrement décentralisé et surcollatéralisé, indexé sur l’euro — sécurisé, polyvalent et résistant à la censure, sans avoir à dépendre d’oracles. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Pour activer dEURO, vous devez avoir de l'ETH dans votre portefeuille.", "deuro_tx_commited_content": "La transaction peut prendre quelques secondes à être confirmée et à s'afficher à l'écran", + "device_confirmation": "Confirmation sur l'appareil", "device_is_signing": "L'appareil signe", "dfx_option_description": "Achetez des cryptos avec EUR & CHF. Pour les clients particuliers et entreprises en Europe", "did_you_back_up_seeds": "Avez-vous sauvegardé toutes vos phrases de récupération ?", @@ -466,6 +474,8 @@ "extracted_address_content": "Vous allez envoyer des fonds à\n${recipient_name}", "failed_authentication": "Échec de l'authentification. ${state_error}", "faq": "FAQ", + "favorite_token": "Jeton favori", + "favorite_token_desc": "Le solde du jeton favori s'affichera sur la carte de solde.", "features": "Fonctionnalités", "fee": "Frais", "fee_less_than_min": "Les frais sélectionnés sont inférieurs au minimum. Veuillez augmenter les frais afin de pouvoir envoyer la transaction.", @@ -491,6 +501,7 @@ "frozen": "Gelé", "frozen_balance": "Solde gelé", "full_balance": "Solde total", + "gallery": "Galerie", "gas_exceeds_allowance": "Le gas requis par la transaction dépasse l'allocation.", "gas_price": "Prix du gas", "general": "Général", @@ -526,6 +537,7 @@ "how_to_connect": "Comment se connecter", "how_to_use": "Comment utiliser", "how_to_use_card": "Comment utiliser cette carte", + "hww_exit_desc": "Cela mettra fin au processus de jumelage en cours avec votre appareil matériel", "i_understand": "Je comprends", "icon_style": "Style d'icône", "id": "ID : ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Votre adresse de réception changera à chaque fois que vous recevrez une transaction", "infobox_multichain": "Utilisez cette adresse pour recevoir n'importe quel jeton ou objet de collection sur", "infobox_rotation": "Votre adresse de réception sera renouvelée à chaque fois que vous fermerez et rouvrirez cet écran", + "input": "Entrée", "inputs": "Entrées", "insufficient_funds_for_tx": "Fonds insuffisants pour exécuter la transaction avec succès.", "insufficient_lamport_for_tx": "Vous n'avez pas assez de SOL pour couvrir la transaction et ses frais. Veuillez ajouter du SOL à votre portefeuille ou réduire le montant de SOL que vous envoyez.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Gérer les nœuds PoW", "manage_providers": "Gérer les prestataires", "manage_yats": "Gérer les Yats", + "manual_input": "Saisie manuelle", "mark_as_redeemed": "Marquer comme utilisé", "market_place": "Marketplace", "mask": "Masquer", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Tous les modèles les plus récents (GPT-5.3, Claude 4.6).\nPas d'abonnement, payez en crypto.", "narrow": "Étroit", "network": "Réseau", + "networks": "Réseaux", "new_first_wallet_text": "Garder vos cryptos en sécurité, c'est du gâteau", "new_node_testing": "Test d’un nouveau nœud", "new_subaddress_create": "Créer", @@ -678,8 +693,10 @@ "node_new": "Nouveau nœud", "node_port": "Port du nœud", "node_reset_settings_title": "Réinitialiser les paramètres", + "node_share_desc": "Scannez ce code QR depuis l'écran Scan pour importer ce nœud.", "node_test": "Test", "nodes": "Nœuds", + "nodes_desc": "Gérez les nœuds existants ou ajoutez-en un personnalisé.", "nodes_list_reset_to_default_message": "Êtes-vous sûr de vouloir réinitialiser les paramètres par défaut ?", "none_of_selected_providers_can_exchange": "Aucun des fournisseurs sélectionnés ne peut effectuer ce swap", "noNFTYet": "Aucun NFT pour le moment", @@ -689,6 +706,7 @@ "note_tap_to_change": "Note (appuyez pour modifier)", "notification_permission_denied": "L'autorisation des notifications a été refusée de manière permanente. Veuillez l'activer manuellement dans les paramètres.", "nullURIError": "L'URI est null", + "ocp_desc": "Payez avec des cryptos en magasin", "offer_expires_in": "L'offre expire dans : ", "offline": "Hors ligne", "ok": "OK", @@ -715,8 +733,13 @@ "outputs": "Sorties", "overshot": "Dépassement", "overwrite_amount": "Écraser le montant", + "pairing_code": "Code de jumelage", + "pairing_code_desc_1": "Votre appareil affichera un code de jumelage.", + "pairing_code_desc_2": "Saisissez-le ici pour continuer", + "pairing_error": "Erreur de jumelage", "pairingInvalidEvent": "Événement de jumelage non valide", "passphrase": "Phrase secrète (facultatif)", + "passphrase_view_keys": "Phrase secrète", "passphrases_doesnt_match": "Les phrases secrètes ne correspondent pas, veuillez réessayer", "password": "Mot de passe", "paste": "Coller", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "La réception d'une transaction Payjoin nécessite que vous ayez des bitcoins disponibles.\n\nDès que votre portefeuille sera approvisionné, Payjoin sera automatiquement activé.", "payjoin_unavailable_sheet_title": "Pourquoi Payjoin est-il indisponible ?", "payment_id": "ID de paiement : ", + "payment_invoices": "Factures de paiement", "payment_made_easy": "Paiements simplifiés", "payment_was_received": "Votre paiement a été reçu.", "payments": "Paiements", @@ -887,6 +911,7 @@ "save": "Enregistrer", "save_backup_password": "Veuillez vous assurer d'avoir bien enregistré votre mot de passe de sauvegarde. Vous ne pourrez pas importer vos fichiers de sauvegarde sans celui-ci.", "save_backup_password_alert": "Enregistrer le mot de passe de sauvegarde", + "save_contact": "Enregistrer le contact", "save_to_downloads": "Enregistrer dans Téléchargements", "saved_the_trade_id": "J'ai enregistré l'ID de la transaction", "savings": "Épargne", @@ -1036,6 +1061,7 @@ "setup_your_debit_card": "Configurez votre carte de débit", "share": "Partager", "share_address": "Partager l’adresse", + "share_this_node": "Partager ce nœud", "shared_seed_wallet_groups": "Groupes de portefeuilles à phrase de récupération partagée", "shared_seed_wallets": "Portefeuilles à phrase de récupération partagée", "show": "Afficher", @@ -1043,6 +1069,7 @@ "show_balance": "Appuyez longuement pour afficher le solde", "show_balance_send_page": "Appuyez pour afficher", "show_balance_toast": "Appuyez longuement pour masquer ou afficher le solde", + "show_combined_balance": "Afficher le solde combiné", "show_details": "Afficher les détails", "show_hidden_addresses": "Afficher les adresses masquées", "show_keys": "Afficher la phrase de récupération/les clés", @@ -1108,6 +1135,7 @@ "swap_providers": "Fournisseurs de swap", "sweeping_wallet": "Balayage du portefeuille", "sweeping_wallet_alert": "Cela ne devrait pas prendre longtemps. NE QUITTEZ PAS CET ÉCRAN, SINON LES FONDS BALAYÉS RISQUENT D’ÊTRE PERDUS.", + "swipe_to_bridge": "Glissez pour transférer (bridge)", "swipe_to_send": "Faites glisser pour envoyer", "switch_wallet": "Changer de portefeuille", "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer", @@ -1148,6 +1176,7 @@ "testnet_coins_no_value": "Les coins de testnet n'ont aucune valeur", "third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. N'importe quelle adresse de portefeuille peut être remplacée par un Yat !", "third_intro_title": "Yat s'entend bien avec les autres", + "this_can_take_few_seconds": "Cela peut prendre quelques secondes", "this_pair_is_not_supported_warning": "Cette paire n'est pas prise en charge avec le(s) échange(s) actuellement sélectionné(s). Veuillez sélectionner un autre échange.", "thorchain_contract_address_not_supported": "THORChain ne prend pas en charge l'envoi vers une adresse de contrat", "thorchain_taproot_address_not_supported": "Le fournisseur ThorChain ne prend pas en charge les adresses Taproot. Veuillez modifier l'adresse ou sélectionner un autre fournisseur.", @@ -1161,6 +1190,7 @@ "token_decimal": "Décimales du token (ex. : USDT)", "token_name": "Nom du jeton (ex. : Tether)", "token_symbol": "Symbole du jeton (ex. : USDT)", + "token_verified_on_jupiter": "Ce jeton est vérifié sur Jupiter", "tokenID": "ID", "tokens": "Jetons", "tokens_strong_warning": "N'envoyez jamais de jetons à cette adresse !", @@ -1289,6 +1319,7 @@ "username": "Nom d'utilisateur", "username_available": "Nom d'utilisateur disponible", "username_character_error": "Les noms d'utilisateur ne doivent contenir que", + "username_check_your_network": "Impossible de vérifier le nom d'utilisateur. Veuillez vérifier votre connexion réseau.", "username_length_error": "Les noms d'utilisateur doivent contenir entre 6 et 32 caractères alphanumériques.", "username_length_error_1_64": "Les noms d'utilisateur doivent contenir entre 1 et 64 caractères alphanumériques.", "username_not_available": "Ce nom d'utilisateur n'est pas disponible.", @@ -1299,6 +1330,7 @@ "verify_message": "Vérifier le message", "verify_seed": "Vérifier la phrase de récupération", "verify_with_2fa": "Vérifier avec Cake 2FA", + "verifying_code": "Vérification du code", "version": "Version ${currentVersion}", "view_all": "Voir tout", "view_in_block_explorer": "Voir dans l'explorateur de blocs", @@ -1310,6 +1342,7 @@ "waitFewSecondForTxUpdate": "Veuillez patienter quelques secondes pour que la transaction apparaisse dans l'historique des transactions.", "wallet": "Portefeuille", "wallet_accounts": "Comptes du portefeuille", + "wallet_balance": "Solde du portefeuille", "wallet_group": "Groupe de portefeuilles", "wallet_group_description_existing_seed": "Vous avez choisi d'utiliser une seed existante pour ce portefeuille. Vous pouvez la vérifier à nouveau si vous devez la confirmer ou la noter.", "wallet_group_description_four": "pour créer un portefeuille avec une nouvelle phrase mnémonique.", @@ -1351,6 +1384,7 @@ "wc_approve_request_title": "Approuver la demande", "wc_connect_request_title": "Demande de connexion", "wc_connected_to": "Connecté à ${name}", + "wc_desc": "Connectez-vous facilement aux dApps", "wc_max_network_fee": "Frais de réseau maximum", "wc_message_to_sign": "Message à signer", "wc_network_fee": "Frais de réseau", @@ -1401,6 +1435,7 @@ "yat_popup_content": "Vous pouvez désormais envoyer et recevoir des cryptos dans Cake Wallet avec votre Yat — un nom d'utilisateur court basé sur des emojis. Gérez vos Yats à tout moment depuis l'écran des paramètres", "yat_popup_title": "L'adresse de votre portefeuille peut être convertie en emojis.", "yes": "Oui", + "yes_exit": "Oui. Quitter", "yesterday": "Hier", "you_now_have_debit_card": "Vous avez maintenant une carte de débit", "you_pay": "Vous payez", diff --git a/res/values/strings_gn.arb b/res/values/strings_gn.arb index 7cb149af0..e5920374e 100644 --- a/res/values/strings_gn.arb +++ b/res/values/strings_gn.arb @@ -2,6 +2,7 @@ "about": "Marandu", "about_cake_pay": "Cake Pay omoneĩ ndéve reñogua hag̃ua tarjetas de regalo activos virtual reheve, ha ikatu reiporu pya’e hag̃ua hetave 150.000 comerciante-pe.", "about_litecoin_privacy": "Litecoin ñemigua rehegua", + "accent_color": "Sa'y acento", "account": "Cuenta", "account_customizer_desc": "Emoinge ha eity umi tarjeta emohenda hag̃ua umi cuenta.", "account_name": "Téra mba'ete", @@ -21,12 +22,16 @@ "add_fund_to_card": "Emoĩve viru jehepyme'ẽva tarjeta-pe (peve ${value})", "add_new_node": "Embojuaju nodo pyahu", "add_new_word": "Emoĩve ñe'ẽ pyahu", + "add_passphrase": "Embojoapy Passphrase", + "add_passphrase_warning_text": "Emoinge passphrase ramo añoite reipuru ra'ekue peteĩ ko billetera-pe yma. Remoingéramo passphrase hekope'ỹva térã ndereipuruiva'ekue passphrase ko billetera-pe, ndahecha mo'ãi mba'eve nde viru oĩva térã rembiasakue.", "add_receiver": "Embojoapy ambue ohupytýva (poravokuaa)", "add_secret_code": "Térã, embojuaju ko ayvu ñemigua peteĩ tembiporu'i jehechaukaha (authenticator) app-pe", "add_tip": "Emoĩve propína", + "add_token": "Embojoapy Token", "add_token_disclaimer_check": "Amoañetéma pe token contrato dirección ha marandu oúvo peteĩ fuente jeroviaha. Oñemoĩramo marandu ivaíva térã hekope'ỹva, ikatu ogueru viru ñehundi.", "add_token_warning": "Ani remohenda térã remoĩ token kuéra estafadór-kuéra he'íhaicha.\nEhechajey hag̃ua umi token dirección jerovia hag̃uáicha hag̃ua umi fuente jerovia hag̃uáicha!", "add_value": "Embojoapy tepykue", + "added_message_for_ata_error": "Ehecha porãke eguereko hetakue SOL saldo emohu'ã hag̃ua ne transacción.", "address": "Kundaharape", "address_book": "Kuatiañe’ẽ renda", "address_book_menu": "Kuatiajoapy'i kundaharape", @@ -47,7 +52,9 @@ "agree": "Aime", "agree_and_continue": "Amoneĩ ha Eku’e", "agree_to": "Emoheñóivo peteĩ kuenta, remoneĩ ", + "alert_notice": "Marandu", "all": "OPA", + "all_coins": "Opaite Moneda", "all_trades": "Opavave ñemuguata", "all_transactions": "Opavave ñembohasa", "alphabetical": "Alfabéticamente", @@ -63,8 +70,13 @@ "anonpay_description": "Ejapo ${type}. Pe ohupytýva ikatu ${method} oipurúvo oimeraẽva criptomoneda oipytyvõva, ha rehupytýta umi viru ko billetera-pe.", "apk_update": "APK ñembohekopyahu", "app_settings": "Aplikasión ñemboheko", + "appearance": "Jehechaha", "approve": "Moneĩ", + "approve_request": "Emoneĩ Jerure", + "approve_tokens": "Emoneĩ token-kuéra", "apps": "Apps", + "arbiscan_history": "ArbiScan rembiasakue", + "are_you_sure_exit": "¿Reime añetehápe resẽse?", "arrive_in_this_address": "${currency} ${tag} og̃uahẽta ko dirección-pe", "ascending": "Ojupíva", "ask_each_time": "Eporandu hag̃ua peteĩteĩ jey", @@ -78,12 +90,18 @@ "auto_generate_addresses": "Emoheñói hag̃ua dirección-kuera ijehegui", "auto_generate_subaddresses": "Heñoĩ ijehegui umi subdirección", "automatic": "Automático", + "available": "Oĩva", "available_balance": "Saldo ojepurukuaáva", "available_balance_description": "Pe “Available Balance” térã “Confirmed Balance” ha'e umi fondo ikatúva reipuru pya'e. Umi fondo ojehecháramo pe saldo yvýpe ha ndaha'éi pe saldo yvate gotyo, upéicharõ eha'arõ sapy'ami hag̃ua umi fondo og̃uahẽva ohupytyve hag̃ua confirmación de red. Oguerekóvo hetave confirmación, ikatúta reipuru.", "avg_savings": "Ñongatu mbytegua", "awaitDAppProcessing": "Eha'arõmi pe dApp omohu'ã hag̃ua hembiapo.", "awaiting_payment_confirmation": "Oha’arõ hína ñemoañete jehepyme’ẽ", + "background_sync": "Ñembojuehe tapykuegua", "background_sync_mode": "Modo de sincronización en segundo plano", + "background_sync_on_battery_low": "Embojuehe batería sa'ív>ramo", + "background_sync_on_charging": "Embojuehe oñembohyru jave añoite", + "background_sync_on_device_idle": "Embojuehe pe mba'e'oka ojepuru'ỹrõ añoite", + "background_sync_on_unmetered_network": "Oñeikotevẽ ñanduti ndojehepyme'ẽiva (unmetered)", "backup": "Ñongatu hag̃ua", "backup_file": "Marandurenda ñongatuha", "backup_password": "Ñe’ẽñemi ñongatuhápe g̃uarã", @@ -93,6 +111,7 @@ "balance_confirmation_desc_2": "Ojejapopa rire opaite ñemoañete, umi fondo oĩta eipuru hag̃ua.", "balance_confirmation_desc_3": "Ikatu rehecha hetave detalle repoko hag̃ua transacción oĩva omoañetéva hag̃ua tembiasápe.", "balance_page": "Balance rehegua kuatia", + "basescan_history": "BaseScan rembiasakue", "best_rate": "Tasa iporãvéva", "best_rate_mixed": "Tarifa iporãvéva (mezclada)", "bill_amount": "Kuatiañemuhague repy", @@ -101,10 +120,14 @@ "bitcoin_amount_display": "Bitcoin cantidad jehechauka", "bitcoin_dark_theme": "Tema ypytũ Bitcoin rehegua", "bitcoin_light_theme": "Tema sa'y Bitcoin rehegua", + "bitcoin_lightning_deposit": "Depósito", + "bitcoin_lightning_withdraw": "Ñeguenohẽ", "bitcoin_payments_require_1_confirmation": "Umi jehepyme’ẽ Bitcoin-pe oikotevẽ 1 ñemoneĩ, ikatúva hi’are 20 aravo’i térã hetave. Aguyje nde py’aguapýre! Oñemondóta ndéve peteĩ marandu correo rupive pe jehepyme’ẽ oñemoneĩ vove.", + "block_height": "Bloque yvate (block height)", "block_remaining": "Opyta 1 bloque", "Blocks_remaining": "${status} Bloque hembýva", "bluetooth": "Bluetooth", + "bridging": "Bridging", "bright_theme": "Tesakã", "bscscan_history": "Historial de BSCScan", "bump_fee": "Embohetave mba’erepy", @@ -114,17 +137,25 @@ "buy_bitcoin": "Ejogua Bitcoin", "buy_now": "Ejogua ko’ág̃a", "buy_provider_unavailable": "Pe proveedor ndaipóri ko’ág̃a.", + "buy_sell_pair_is_not_supported_warning": "Ko par moneda rehegua ndojepytyvõi mavave me'ẽhágui pe jehepyme'ẽrã ojeporavóvape. Eiporavo ambue par térã eha'ã emoambue pe jehepyme'ẽrã.", "buy_with": "Ejogua hag̃ua", "by_cake_pay": "Cake Pay rupive", "cake_2fa_preset": "Cake 2FA ñemboheko ypykue", "cake_dark_theme": "Tema pytũ Cake", "cake_pay_account_note": "Eñemboheraguapy peteĩ correo electrónico rupive añoite rehecha hag̃ua ha rejogua hag̃ua tarjeta. ¡Oĩ avei umi oĩva descuento-pe!", + "cake_pay_card_email_delivered_message": "Ne tarjeta regalo og̃uahẽta correo rupive umi ñemoañete tekotevẽva rire.", "cake_pay_learn_more": "Ejogua ha emboguejy hag̃ua tarjeta regálo pya’ete app rupive!\nEmbohasa nde kuã asúpe guive akatúape hag̃ua reikuaave.", "cake_pay_save_order": "Pe tarjeta oñemondóta nde correo electrónico-pe peteĩ ára hag̃ua (ára hag̃ua oñemba’apóva)\nEñongatu nde Order ID:", "cake_pay_subtitle": "Ejogua tarjeta prepagada ha tarjeta regalo opa tetã rupi.", "cake_pay_web_cards_subtitle": "Ejogua tarjeta prepagada ha tarjeta regalo opa tetã rupi.", "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_seeds_save_disclaimer": "Eñongatúke ko'ã ñe'ẽ peteĩ tenda hekorosãvape! Reikotevẽta ko'ã ñe'ẽ emoĩporã jey hag̃ua ne billetera peteĩ mba'e'oka pyahúpe.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Amoneĩ ndaipuruiha Proxy térã VPN", + "cakepay_confirm_purchase": "Emoneĩ Jejogua", + "cakepay_confirm_terms_agreed": "Amoneĩ umi término ha condición ojehechaukáva ko'ápe:", + "cakepay_confirm_voided_refund": "Aikũmby umi ñeha'ã reñemboguevi hag̃ua peteĩ tetã jejokopyrégui omboguéta oimeraẽ reembolso", + "cakepay_ios_not_available": "Ñembyasy, ko tarjeta regalo ndaipóri iOS-pe. Ikatu rejogua Android-pe térã ore web rupive.", "cakepay_prepaid_card": "Tarjeta de débito prepagada CakePay", "camera_consent": "Ojepurúta nde cámara ojapyhy hag̃ua ta’ãngamýi hag̃ua nde jehechakuaa hag̃ua ${provider} rupive. Eporandu hag̃ua mba’evéichapa omba’apo hag̃ua, ehecha hag̃ua i Política de Privacidad.", "camera_permission_is_required": "Oikotevẽ permiso hag̃ua ojepuru cámara. \nEmyandy hag̃ua app ñemohendápe.", @@ -136,6 +167,7 @@ "cardholder_agreement": "Acuerdo del titular de la tarjeta", "cards": "Tarjetas", "centralized": "Centralizado", + "chain_id": "Chain ID", "chains": "Cadenas", "change": "Moambue", "change_backup_password_alert": "Nde marandu ñongatupyre ymaveguare ndaikatumo’ãi ojegueru hag̃ua pe ñe’ẽñemi ñongatupyre pyahu reheve. Pe ñe’ẽñemi ñongatupyre pyahu ojepurúta añoite marandu ñongatupyre pyahúpe g̃uarã. Añetehápepa remoambue hag̃ua pe ñe’ẽñemi ñongatupyre rehegua?", @@ -153,19 +185,26 @@ "change_rep": "Emoambue pe Representante", "change_rep_message": "¿Reime añetehápe reipota emoambue umi representante?", "change_rep_successful": "Oñemoambue porãma pe representante", + "change_selected_exchanges": "Emoambue umi Intercambio Ojeporavóva", + "change_selected_pair": "Emoambue Par Ojeporavóva", "change_username": "Emoambue puruhára réra", "change_wallet_alert_content": "¿Reipotápa emoambue ko'ág̃a pe billetera hag̃ua ${wallet_name}?", "change_wallet_alert_title": "Emoambue billetera ko'ágãgua", "check_receiver_forms": "Ikatúpa, ehecha umi formulario receptor rehegua.", + "choose_a_payment_method": "Eiporavo peteĩ jehepyme'ẽrã", + "choose_a_provider": "Eiporavo peteĩ me'ẽha", "choose_account": "Eiporavo cuenta", "choose_address": "\n\nEiporavo hag̃ua pe dirección:", "choose_card_value": "Eiporavo peteĩ tarjeta repykue", "choose_derivation": "Eiporavo pe derivación pe billeterápe g̃uarã", "choose_from_available_options": "Eiporavo umi poravokuaa ojeguerekóva apytégui:", "choose_one": "Eiporavo peteĩ", + "choose_qr_code_format": "Eiporavo QR Code Formáto", + "choose_qr_code_format_note": "Eiporavo pe formáto hekopegua ne hardware wallet-pe g̃uarã:", "choose_relay": "Eiporavo peteĩ rele reipuru hag̃ua", "choose_wallet": "Eiporavo wallet", "choose_wallet_currency": "Eiporavo por favor pe moneda pe billetera-pe g̃uarã:", + "choose_wallet_group": "Eiporavo Billetera Atyrã (Wallet Group)", "clear": "Mopotĩ", "clearnet_link": "Joaju clearnet", "close": "Mboty", @@ -173,26 +212,41 @@ "coin_control_desc": "Embogua hag̃ua umi outputs ko transacción-pe guarã. Umi ñemoambue rejapóva ko’ápe ojehechaukáta pe transacción ko’ág̃aguáre añoite.", "coin_control_load_failed": "Ndojekargai umi moneda ndojeporúiva .", "cold_or_recover_wallet": "Embojoapy peteĩ cold wallet air-gapped térã emboykeréi peteĩ paper wallet.", + "collection_address": "Colección Kundaharape", + "collection_description": "Colección Ñemombe'u", + "collection_name": "Colección Téra", "color": "Sa'y", "color_theme": "Téma sa'y", + "coming_soon_tag": "Og̃uahẽ pototáma", "commit_transaction_amount_fee": "Emoneĩ ñembohasa\nMboheta: ${amount}\nHepyme’ẽ: ${fee}", + "compatible_services": "Servicio-kuéra Ojokupytýva", + "compatible_services_desc": "Eipuru pe Scan tembiporu emoñe'ẽ hag̃ua ko'ã QR código Cake Wallet oipytyvõva:", "configure": "Configurar", "confirm": "Moneĩ", "confirm_delete_template": "Ko tembiapo omboguepáta ko plantilla. ¿Reipotápa reku’ejey hag̃ua?", "confirm_delete_wallet": "Ko tembiapo omboguepáta ko billetera. ¿Reipota hag̃ua jajapo hag̃ua hag̃ua?", "confirm_fee_deduction": "Emoañete comisión jeipe'a", "confirm_fee_deduction_content": "¿Reime’ẽpa hag̃ua ojepe’a hag̃ua pe comisión pe salida-gui?", + "confirm_passphrase": "Emoneĩ passphrase", "confirm_sending": "Emoañete emondo hag̃ua", "confirm_silent_payments_switch_node": "Nde nodo ko'ágagua ndoipytyvõi Silent Payments.\n\nCake Wallet omoambuéta peteĩ nodo oikóva hag̃ua hag̃uaicha ojehechajey hag̃ua (escaneo) aja.", + "confirm_transaction": "Emoneĩ transacción", "confirmations": "Moneĩ", "confirmed": "Saldo confirmado", "confirmed_tx": "Omoañetepyréva", "confirming": "Oñemoneĩhína", "congratulations": "¡Vy'apavẽ!", "connect_an_existing_yat": "Embojoaju peteĩ Yat oĩmavare", + "connect_hw_info_step_1": "Ehecha porã ne mba'e'oka hendyha (ON).", + "connect_hw_info_step_2": "Emyendy Bluetooth mokõive mba'e'okápe ha embojoaju pe teléfono guive, TÉRÃ embojoaju ne mba'e'okakuéra peteĩ cable USB rupive.", + "connect_hw_info_step_3": "Eipe'a ne mba'e'oka ha eho pe cripto app reipotávape.", + "connect_hw_info_step_4": "Eiporavo ne mba'e'oka Cake Wallet-pe ha eku'ejey pe ñembosako'i ndive.", "connect_yats": "Embojoaju Yats", "connect_your_hardware_wallet": "Embojoaju nde billetera hardware Bluetooth térã USB rupive", + "connect_your_hardware_wallet_ble": "Embojoaju ne hardware wallet Bluetooth rupive", "connect_your_hardware_wallet_ios": "Embojoaju nde billetera hardware Bluetooth ndive", + "connect_your_hardware_wallet_usb": "Embojoaju ne hardware wallet USB rupive", + "connected": "Oñembojoaju", "connection_sync": "Joaju ha ñembojuehe", "connections": "Jeikeha", "connections_desc": "Emohenda joaju umi servicio ha API mbohapýha rehegua.", @@ -201,9 +255,11 @@ "contact_list_contacts": "Ñe'ẽngára", "contact_list_wallets": "Che Billeterakuéra", "contact_name": "Téra rera", + "contact_name_exists": "Oĩma peteĩ contacto ko téra reheve. Eiporavo ambue téra.", "contact_support": "Eñe’ẽ Support ndive", "contacts": "Contactos", "continue_text": "Eku'e", + "contract_address": "Contrato Kundaharape", "contract_warning": "Ko contrato dirección ojehechakuaa hag̃ua ikatuha haʼe peteĩ ñembotavy térã mba’e vai. Eñangareko porãke.", "contractName": "Contrato réra", "contractSymbol": "Símbolo del contrato", @@ -213,7 +269,10 @@ "copy": "Kopia", "copy_address": "Kopia dirección", "copy_id": "Emonguatia ID", + "copy_payjoin_address": "Emonguatia Payjoin Kundaharape", + "copy_payjoin_url": "Emonguatia Payjoin URL", "copyWalletConnectLink": "Emokopia dApp-gui pe juaju WalletConnect ha emboja ko'ápe", + "corrupted_seed_notice": "Ko billetera marandurenda oñembyai ha ndaikatúi ojepe'a. Ehecha pe seed, eñongatu, ha emoĩporã jey pe billetera.\n\nPe tepykue nandíramo, pe seed ndaikatúi oñemoĩporã hekopete.", "countries": "Tetãnguéra", "create_account": "Emoheñói cuenta", "create_backup": "Emoheñói peteĩ backup", @@ -221,10 +280,12 @@ "create_invoice": "Ejapo kuatiañemuhã", "create_new": "Emoheñói Billetera Pyahu", "create_new_account": "Emoheñói peteĩ cuenta pyahu", + "create_new_seed": "Emoheñói Seed Pyahu", "creating_backup": "Ojejapohína backup", "creating_new_wallet": "Omoheñóvo billetera pyahu", "creating_new_wallet_error": "Jejavy: ${description}", "creation_date": "Arange ojejapo hague", + "crypto_addresses": "Cripto Kundaharape-kuéra", "csv_nothing_to_export": "Nothing to export", "current_swap": "Intercambio ko'ág̃a", "current_wallet": "Billetera actual", @@ -233,6 +294,7 @@ "custom_fee": "Comisión personalizada", "custom_redeem_amount": "Hetakue jererepy'ỹva reñemboguevi hag̃ua", "custom_value": "Tepykue ñemomba'epyre", + "customBackgroundDescription": "Eguerekóma peteĩ background ne mba'éva.\\nReipota emyengovia térã embogue?", "dark_theme": "Pytũ", "debit_card": "Tarjeta de débito", "debit_card_terms": "Pe ñeñongatu ha jeiporu nde kuatia’atã ñemuhã papapy (ha umi credencial oñembojoajúva upe papapy rehe) ko billetera digital-pe oĩ ipoguýpe umi Término ha Condición oĩva pe kuatia’atã ñemuhã jára ñe’ẽme’ẽme, pe kuatia’atã ome’ẽva ndive, oĩ hag̃uáicha sapy’ánte.", @@ -240,10 +302,13 @@ "decentralized_only": "Descentralizado añoite hag̃ua", "decimal_places_error": "Hetaite tenda decimal", "decimals_cannot_be_zero": "Pe token decimal ndaikatúi haʼe cero (0).", + "decred_info_card_details": "Decred oipuru peteĩ ñembojuehe descentralizado ha oñangarekóva tekoñemíre, 'SPV' hérava, ohóva hi'are vyterei peteĩ Bitcoin billetera tee-gui. Reikuaave hag̃ua, eikutu iguýpe.", + "decred_info_title": "Ñembojuehe Decred-pe", "default_buy_provider": "Me’ẽhára ijypykuéva hag̃ua ojogua", "default_sell_provider": "Ñeme’ẽhára ñemu hag̃ua ijypykuéva", "delete": "Embogue", "delete_account": "Embogue hag̃ua", + "delete_this_node": "Embogue ko nodo", "delete_wallet": "Embogue billetera", "delete_wallet_confirm_message": "¿Reime añete rembogueseha ${wallet_name} billetera?", "deleteConnectionConfirmationPrompt": "¿Reime añete rembogueseha pe joaju hag̃ua?", @@ -254,19 +319,44 @@ "destination_tag": "Teramoĩha hag̃ua:", "destination_tag_optional": "Etiqueta destino rehegua (opcional) .", "destination_tag_swap_disclaimer": "Ojeruréva receptor oacredita haguã nde fondo. Etiqueta ofaltáva térã ojavýva he'ise fondo okañýva.", + "deuro_about_deuro": "dEURO rehegua", + "deuro_collect_interest": "Embyaty", + "deuro_reinvest_interest": "Einvertí jey", + "deuro_savings": "dEuro Ñongatu", + "deuro_savings_add": "Depósito", + "deuro_savings_approve_app": "Emoneĩ App", + "deuro_savings_approve_app_description": "Eheja pe dEURO smart contract oñangareko ne dEURO token-kuérare ñongatúpe g̃uarã, ha katu ndaikatumo'ãi omondo térã ohupyty ne dEURO.", + "deuro_savings_available_to_add": "Ojepurukuaáva embojoapy hag̃ua", + "deuro_savings_available_to_remove": "Ojepurukuaáva eipe'a hag̃ua", + "deuro_savings_balance": "Ñongatu Saldo", + "deuro_savings_balance_tooltip": "Kóva ohechauka ne ñongatu saldo ko'ag̃agua, ohupytýva interés ára ohasávo. Ikatu redepositá térã reguenohẽ ne dEURO oimeraẽ ára.", + "deuro_savings_collect_interest": "Embyaty interés", + "deuro_savings_collect_interest_tooltip": "Kóva ohechauka ne interés rehupytýmava, ikatúva embyaty ne dEURO saldo-pe oimeraẽ ára.", + "deuro_savings_remove": "Ñeguenohẽ", + "deuro_savings_set_approval": "Emoĩ ñemoneĩ", + "deuro_savings_subtitle": "Eg̃ana 10% peve interés ne dEuro Stablecoin rehe", + "deuro_savings_welcome_description": "dEURO ha'e peteĩ stablecoin descentralizado ha colateralizado, ojoajúva Euro-re — hekorosã, ojepuruporãva, ha noñembyaikuaáiva oraculo-re ojejerovia'ỹre. 1 dEURO = 1 EURO.", + "deuro_tooltip_no_eth": "Emboguata hag̃ua dEURO, tekotevẽ ereko ETH ne billetera-pe.", + "deuro_tx_commited_content": "Ikatu ohasa mokõi-mbohapy segundo pe transacción oñemoneĩ ha ojehechauka hag̃ua pantalla-pe", + "device_confirmation": "Mba'e'oka Ñemoneĩ", + "device_is_signing": "Pe mba'e'oka oñemboheraguapýhína", "dfx_option_description": "Ejogua cripto EUR ha CHF reheve. Oipurukuaa hag̃ua ñemuhára michĩ ha mba’apohaguasu Europape.", "did_you_back_up_seeds": "¿Rejapo raʼe backup opaite nde seed rehegua?", "didnt_get_code": "¿Nererejapýi kódigo?", "digit_pin": "PIN -dígito", "digital_and_physical_card": "Tarjeta de débito prepago digital y física", "disable": "Mbogue", + "disable_automatic_exchange_status_updates": "Embogue Intercambio Tekotee Ñembohekopyahu Ijeheguíva", "disable_bulletin": "Embogue pe marandu hag̃ua mba’éichapa oĩ pe servicio", "disable_buy": "Eipe'a hag̃ua jejogua", "disable_cake_2fa": "Embogue Cake 2FA", "disable_exchange": "Eipe'a hag̃ua ñembohasa", + "disable_exchange_option": "Embogue Intercambio jeporavorã", "disable_fee_api_warning": "Embogue hag̃ua péva, umi tarifa comisión ikatu ndoikoporãi heta hendápe, upévare ikatu rembojehepyme’ẽ hetave térã sa’ive pe comisión ne transaksiónpe g̃uarã.", "disable_fiat": "Eipe'a fiat", "disable_sell": "Eipe'a hag̃ua ñemu hag̃ua", + "disable_tor": "Embogue Tor", + "disable_trade_option": "Embogue ñemu jeporavorã", "disableBatteryOptimization": "Eipe'a hag̃ua ñemopotĩ batería rehegua", "disableBatteryOptimizationDescription": "¿Reipe’asépa batería ñemoporã hag̃ua pe ñembojoaju tapykuepeguá oiko hag̃ua isãso ha iporãve hag̃ua?", "disabled": "Ojeipe'a", @@ -284,6 +374,7 @@ "domain_looks_up": "Jeheka dominio", "donation": "Me’ẽ", "donation_link_details": "Mba’ekuaarã juajuha ñeme’ẽrei rehegua", + "done": "Oĩmbáma", "duress_pin_description": "Kóva omoĩta peteĩ PIN duress rehegua, peteĩ tembiapoite iñambuéva ndaha’éiva ojepuru hag̃uarã hetavéva puruhára. Ko PIN ojepuruva’erã reime ramo peligro-pe añoite. Reipuru rire ko PIN, opaite ne billetera oñemboguéta, upévare eñangareko opaite ne seed oñeñongatúma hag̃ua reipuru mboyve.", "durres_PIN": "Duress PIN", "durres_PIN_set_up_successfully": "Oñemboheko porãma Duress PIN.", @@ -297,7 +388,12 @@ "edit_token": "Editar token", "electrum_address_disclaimer": "Romoheñói dirección pyahu peteĩteĩ reipuru vove peteĩ, ha katu umi dirección ymaguare gueteri omba'apo.", "email_address": "Dirección de correo electrónico", + "enable": "Emboguata", + "enable_auto_node_switching": "Emboguata Nodo Ñemoambue Ijeheguíva", + "enable_builtin_tor": "Emboguata Tor oñembojoajupyréva", + "enable_for_auto_switching": "Emboguata Ñemoambue Ijehegui-rã", "enable_lightning": "Emboguata Lightning", + "enable_mempool_api": "Mempool API hepyme'ẽ ha arange hekopeguáva g̃uarã", "enable_replace_by_fee": "Embojuruja Replace-By-Fee", "enable_silent_payments_scanning": "Eñepyrũ eheka hag̃ua umi transaksión oñemondo hag̃ua nde Silent Payment kundaharape hag̃ua.", "enabled": "Myandy", @@ -337,15 +433,21 @@ "error_text_template": "Pe téra ha dirección plantilla rehegua ndaikatúi oguereko umi símbolo ` , ' \"\nha oguerekova’erã 1 guive 106 peve tai ipukukue", "error_text_wallet_name": "Pe billetera réra ikatu oguereko tai, papapy ha umi ta’ãnga _ - añoite\nha oĩva’erã 1 ha 33 tai pukukue", "error_text_xmr": "Pe valor XMR ndaikatúi ohasa pe saldo eiporukuaa hag̃.\nPe papapy dígito fraccionario rehegua va'erã sa'ive térã peteĩcha 12", + "error_while_processing": "Oiko peteĩ jejavy oñeprocesa aja", "errorGettingCredentials": "Ojavy: jejavy ojejuhúvo credenciales", "errorSigningTransaction": "Oiko jejavy oñemboheraguapývo pe transacción.", + "establishing_tor_connection": "Oñemboheko hína Tor jeikeha", "estimated": "Jehaipyre", "estimated_new_fee": "Mba’erepy pyahu jehaipyre", "estimated_receive_amount": "Mbohetapy ñemog̃uahẽ hag̃ua jehaipyre", + "eta": "ETA", + "ethereum_ecosystem": "Ethereum Ecosistema", "etherscan_history": "Etherscan rembiasakue", "event": "Tembiaporã", "events": "Tembiaporã", + "evm_ecosystem_description": "Tekotevẽramo, emoambue pe red ha token reipuruséva ko jehepyme'ẽme g̃uarã.", "exchange": "Mbojopyru", + "exchange_extra_info": "Anike nde resarái emombe'u hag̃ua pe Memo térã Extra ID emondóvo ko transacción intercambio-rã", "exchange_incorrect_current_wallet_for_xmr": "Embojopyruse hag̃ua XMR nde saldo Monero Cake Wallet-pe guive, emoambue raẽ nde Monero wallet-pe.", "exchange_new_template": "Plantilla nueva", "exchange_provider_unsupported": "¡${providerName} ndaikatúi ojepuruvé!", @@ -356,6 +458,7 @@ "exchange_result_write_down_ID": "*Ekopiáke térã ehaíke nde ID ojehechaukáva yvate.", "exchange_result_write_down_trade_id": "Ikatúramo, ekopia térã rehai pe trade ID hag̃ua resegí hag̃ua.", "exchange_sync_alert_content": "Eha'arõ ikatu hag̃uáicha nde billetera oñembojuehe hag̃ua.", + "exchange_trade_result_confirm": "Eikutúvo emondo Cake Wallet guive, remondóta ${fetchingLabel} ${from} ne billetera hérava ${walletName} guive pe kundaharape ojehechaukáva yvýpe. Térã ikatu remondo ne billetera okapegua guive pe kundaharape/QR código oĩva 'send from external wallet' kuatiarogue-pe.\n\nEikutúke oimeraẽ botõ resegí hag̃ua térã ejevy emoambue hag̃ua umi monto.", "expired": "Opa", "expires": "Opa hag̃ua", "expiresOn": "Opa hag̃ua", @@ -363,20 +466,28 @@ "export_backup": "Emondo hag̃ua backup", "export_csv": "Export CSV", "export_lightning_logs": "Emondo Lightning rembiapokue", + "export_logs": "Emondo registro-kuéra", + "export_outputs": "Emondo outputs", "export_payjoin_logs": "Emondo okápe Payjoin registro-kuéra", + "extend_session": "Embotuichave Sesión", "external": "Okápegua", "external_wallet": "Billetera externa", "extra_id": "ID extra:", "extracted_address_content": "Emondo hag̃ua viru\n${recipient_name}-pe", "failed_authentication": "Ojejavy hag̃ua jehechajey. ${state_error}", "faq": "FAQ", + "favorite_token": "Token ojehayhúva", + "favorite_token_desc": "Pe token ojehayhúva saldo ojehechaukáta pe saldo tarjeta-pe.", "features": "Tembiapoite", "fee": "Comisión", + "fee_less_than_min": "Pe hepyme'ẽ ojeporavóva michĩve pe mínimo-gui; embohetave pe hepyme'ẽ ikatu hag̃ua remondo pe transacción", + "fee_rate": "Hepyme'ẽ tasa", "fees": "Comisión", "fetching": "Oñembyatyhína", "fiat_api": "API Fiat", "fiat_balance": "Fiat saldo", "field_required": "Ko kora tekotevẽva", + "file_saved": "Marandurenda oñeñongatúma", "fill_code": "Ikatúpiko emyenyhẽ pe ayvu ñemi jehechaukaha oñemondóva nde korreópe.", "filter_by": "Mboguaha rupi", "filters": "Filtro-kuéra rehegua", @@ -388,12 +499,18 @@ "forgot_password": "Nderesarái ñe’ẽñemi", "freeze": "Mbo’y", "frequently_asked_questions": "Porandu ha mbohovái ojeporuvéva", + "from": "Guive", "frozen": "Congelado", + "frozen_balance": "Saldo Oñembotýva", "full_balance": "Saldo completo", + "gallery": "Galería", + "gas_exceeds_allowance": "Pe gas oikotevẽva transacción rupi ohasa pe ñemoneĩ (allowance).", + "gas_price": "Gas repy", "general": "Mba'eichagua", "generate_name": "Emoheñói Téra", "generating_csv": "Generating CSV...", "generating_gift_card": "Oñemoheñói hína tarjeta jopói", + "generating_transaction": "Oñemoheñói hína transacción", "get_a": "Ereko peteĩ ", "get_card_note": "Ikatu emyenyhẽjey viru digital rupive. Ndoikotevẽi ambue marandu!", "get_your_yat": "Eguereko nde Yat", @@ -410,36 +527,47 @@ "haven_app": "Haven by Cake Wallet", "haven_app_wallet_text": "Ñangarekoha iporãiterei Haven-pe g̃uarã", "help": "Pytyvõ", + "hidden_addresses": "Kundaharape Kañymby-kuéra", "hidden_balance": "Saldo ñemi", + "hide": "Mokañy", "hide_address": "Eñomi dirección", "hide_details": "Mokañy Detalles", "high_contrast_theme": "Téma Kontráste Yvate", "history": "Tembiasakue", "home": "Ñepyrũ", "home_screen_settings": "Ñemboheko pe pantalla ñepyrũme", + "how_to_connect": "Mba'éichapa Oñembojoaju", "how_to_use": "Mba’éichapa ojepuru", "how_to_use_card": "Mba’éichapa ojeiporu ko tarjeta", + "hww_exit_desc": "Kóva omboty pe joaju oikóva ne hardware mba'e'oka ndive", "i_understand": "Aikũmby", "icon_style": "Estilo icono rehegua", "id": "ID: ", + "if_you_dont_see_your_device": "Ndehecháiramo ne mba'e'oka yvate, ehecha porãke ne Ledger hesãi ha ipe'apyre!", "ignor": "Eheja", "import": "Embohasa", "importNFTs": "Embogueru NFTs", "in_store": "Ñemuhápe", "incoming": "Oikeva", "incorrect_seed": "Pe jehaipyre emoingeva ndoikói.", + "incorrect_seed_option": "Hekope'ỹ. Eha'ã jey", + "incorrect_seed_option_back": "Hekope'ỹ. Ehecha porãke ne seed oñeñongatu hekopete ha eha'ã jey.", "infobox_auto_address": "Nde dirección de recepción ojere va’erã opaite jey rehupytývo peteĩ transacción.", "infobox_multichain": "Eipuru ko dirección rehe hag̃ua rehepytyvõ hag̃ua oimeraẽva token térã coleccionable.", "infobox_rotation": "Nde dirección rehegua hag̃ua reñemog̃uahẽta ojere hag̃ua opaite jey remboty ha reike jey vove ko pantalla-pe.", + "input": "Jeikeha (input)", "inputs": "Jeikeha", + "insufficient_funds_for_tx": "Ndaipóri viru he'íva emohu'ã hag̃ua pe transacción.", "insufficient_lamport_for_tx": "Ndaipóri ndéve heta SOL ohepyme’ẽ hag̃ua pe transacción ha hepyme’ẽ hag̃ua avei pe comisión. Ikatu remoĩve SOL nde billetera-pe térã remomichĩve pe SOL remondoséva.", "insufficient_lamports": "Ndaipóri ndéve heta SOL hag̃ua ecoveri hag̃ua pe transacción ha pe hepykue transacción rehegua. Reikotevẽ hag̃ua michĩmi ${solValueNeeded} SOL. Ikatúpa embojoapyve SOL nde billetera-pe térã emomichĩve pe SOL remondoséva.", "insufficientFundsForRentError": "Ndaipóri ndéve SOL hembýva hag̃ua rehepyme’ẽ pe transacción ha pe renta hag̃ua pe cuenta. Ikatúpa remoĩve SOL nde billetera-pe térã remomichĩve pe SOL remondoséva.", + "insufficientFundsForRentErrorReceiver": "Pe ohupytýva cuenta ndoguerekói SOL he'íva ohepyme'ẽ hag̃ua pe renta. Ejerure pe ohupytývape ombojoapy hetave SOL icuenta-pe.", "introducing_cake_pay": "¡Roikuaauka Cake Pay!", "invalid_input": "Jeikeha ndoikóiva", "invalid_password": "Ñe'ẽñemi ndoikói", "invoice_details": "Factura rehegua marandu", "is_percentage": "ha'e", + "keys": "Llave-kuéra", "label": "Teramoĩ", "label_address": "Emboheramo dirección", "last_30_days": "Umi 30 ára ohasáva", @@ -449,6 +577,7 @@ "ledger_error_tx_rejected_by_user": "Pe transacción oñemboyke pe dispositívo-pe.", "ledger_error_wrong_app": "Ikatúpa ehecha porã reipeʼa hague pe app hekopete nde Ledger-pe.", "ledger_please_enable_bluetooth": "Emyandy Bluetooth ikatu hag̃ja ehecha nde Ledger", + "legacy": "Legacy", "light_theme": "Tesakã", "lightning_address_desc": "Pago pya'e, comisión michĩva.", "lightning_deposit_desc": "Edepositávo Lightning-pe, reintercambia hína nde Bitcoin on-chain ko billetera-gui nde cuenta Lightning-pe.", @@ -459,7 +588,24 @@ "lightning_username_setup_later": "Eheja hag̃ramo ko’ág̃a, ikatúta remohenda upéi hag̃ua Settings-pe.", "lightning_withdraw_desc": "Reipe'a jave Lightning-gui, remongu'e hína peteĩva térã opaite nde saldo Lightning-gua Bitcoin on-chain-pe.", "lightning_withdraw_disclaimer": "Pe saldo pyahu Bitcoin-pe ndojeguerekomo'ãi pe transacción oñemoañetepa peve.", + "litecoin_enable_mweb_sync": "Emboguata MWEB jeheka (scanning)", + "litecoin_mweb": "MWEB", + "litecoin_mweb_allow_coins": "Eheja MWEB moneda-kuéra", + "litecoin_mweb_always_scan": "Emoĩ MWEB ojeheka katuete hag̃ua", + "litecoin_mweb_description": "MWEB ha'e peteĩ protocolo pyahu ogerúva transacción ipya'eve, hepyve'ỹva ha tekoñemívéva Litecoin-pe", + "litecoin_mweb_dismiss": "Mboyke", "litecoin_mweb_display": "Ehechauka MWEB pantalla ñepyrũme", + "litecoin_mweb_display_card": "Ehechauka MWEB tarjeta", + "litecoin_mweb_enable": "Emboguata MWEB", + "litecoin_mweb_enable_later": "Ikatu eiporavo emboguata jey MWEB Display Settings guýpe.", + "litecoin_mweb_logs": "MWEB Logs", + "litecoin_mweb_node": "MWEB Nodo", + "litecoin_mweb_pegin": "Peg In", + "litecoin_mweb_pegout": "Peg Out", + "litecoin_mweb_scanning": "MWEB Jeheka", + "litecoin_mweb_settings": "MWEB ñemboheko", + "litecoin_mweb_warning": "MWEB jeporu ñepyrũrã omboguejýta ~600MB datos, ha ikatu ohupyty 30 aravo'i peve ñanduti pya'ekue heuti. Ko datos ñepyrũrã omboguejy peteĩ jeýnte ha oĩta opaite Litecoin billetera-pe g̃uarã", + "litecoin_what_is_mweb": "¿Mba'épa MWEB?", "live_fee_rates": "Tasa hepyme’ẽ rehegua hag̃uaicha hag̃ua API rupive", "load_more": "Hupi hetave", "loading": "Oñemyanyhẽhína", @@ -470,10 +616,12 @@ "long_press_show_balance": "Tarjeta de prensa puku ohechauka haguã equilibrio", "low_fee": "Jehepyme’ẽ michĩva", "low_fee_alert": "Koʼág̃a reiporu hína peteĩ prioridad jehepymeʼẽ ñanduti rehegua imbeguéva. Kóva ikatu omoheñói ñehaʼãro puku, tasa iñambuéva térã ñemurã ñembotove. Roñeʼẽporã emoĩ hag̃ua jehepymeʼẽ yvateve hag̃ua reiko porãve hag̃ua.", + "made_easy": "hasy'ỹre", "manage_nodes": "Eñangareko nodo-kuérare", "manage_pow_nodes": "Eñangareko nodo-kuéra PoW rehe", "manage_providers": "Eñangareko umi proveedor-kuéra rehe", "manage_yats": "Eñangareko Yats", + "manual_input": "Jeikeha pópe (manual)", "mark_as_redeemed": "Emoĩ hag̃ua ojehepyme’ẽmava", "market_place": "Ñemuhaguasu", "mask": "Mask", @@ -487,10 +635,13 @@ "memo_swap_disclaimer": "Ojeruréva receptor oacredita haguã nde fondo. Memo ofaltáva térã ojavýva he'ise fondo okañýva.", "message": "Marandu", "message_verified": "Pe marandu ojehechajey porã", + "messages": "Marandu-kuéra", + "method": "Mba'éichapa", "methods": "Mba’éichapa", "min_amount": "Michĩvéva: ${value}", "min_value": "Michĩ: ${value} ${currency}", "mining": "Minería", + "mint_address": "Mint Kundaharape", "minutes_to_pin_code": "${minute} aravo'i", "mm": "MM", "modify_2fa": "Emoambue Cake 2FA", @@ -499,12 +650,16 @@ "monero_dark_theme": "Tema iñypytũva Monero rehegua", "monero_light_theme": "Monero tema sa'y", "moonpay_alert_text": "Pe monto repy tekotevẽ tuichave térã ojoja ${minAmount} ${fiatCurrency}-re.", + "moralis_nft_error": "Oiko peteĩ jejavy oñembyaty aja umi NFT. Ehecha porãke ne ñanduti joaju ha eha'ã jey.", "more_details": "Detallesve", "more_options": "Hetave jeporavorã", + "multiple_addresses_detected": "Heta kundaharape ojejuhu", "mweb_ad": "Emboguata MWEB, pe capa ñemigua Litecoin-pe g̃uarã omoĩva anonimato extra nde viru'ikuérape", + "mweb_confirmed": "MWEB Oñemoañetéva", "mweb_help_desc_1": "MWEB ha’e peteĩ capa privacidad opcional Litecoin-pe g̃uarã, ohejáva puruhárape omokañy umi transacción monto ha omoporãve iprivacidad.", "mweb_help_desc_2": "Umi Litecoin oĩva cadena principal-pe opyta transparente, ha umi moneda oñemomýiva capa MWEB-pe ogana anonimato extra.", "mweb_help_disclaimer": "Ikatu remongu’e pya’e umi moneda mokõi capa apytépe emaskarávo ha demaskarávo rupive.", + "mweb_unconfirmed": "MWEB Noñemoañetéiva", "name": "Téra", "nano_current_rep": "Omyakãva ko'ág̃a", "nano_gpt_thanks_message": "Aguyje reiporu hag̃ua NanoGPT! Nemandu'áke reho jey kundahárape gotyo oĩmba rire ne transacción.", @@ -512,19 +667,24 @@ "nanogpt_subtitle": "Opaite umi modelo ipyahuvéva (GPT-5.3, Claude 4.6).\nNdaipóri suscripción, ehepyme’ẽ cripto rupive.", "narrow": "Poʼi", "network": "Red", + "networks": "Red-kuéra", "new_first_wallet_text": "Eñangareko hag̃ua nde criptomoneda rehe ha'e peteĩ mba'e ndahasýiva", "new_node_testing": "Ñeha’ã nodo pyahu", "new_subaddress_create": "Moheñói", "new_subaddress_label_name": "Téra etiqueta", "new_subaddress_title": "Kundaharape pyahu", + "new_tag": "Pyahu", "new_template": "Plantilla Pyahu", + "new_transactions_notifications": "Emondo marandu'i umi transacción pyahúre", "new_wallet": "Billetera pyahu", "newConnection": "Jeike pyahu", "nfts": "NFTs", "no": "Nahániri", "no_cards_found": "Ndojejuhúi kuatia'atã", + "no_extra_detail": "Ndaipóri mba'ekuaarã adicional", "no_id_needed": "Ndoikotevẽi ID!", "no_id_required": "Ndoikotevẽi ID. Embohetave ha eipuru reñemuhápe mamove", + "no_providers_available": "Ndaipóri me'ẽha oĩva", "no_relay_on_domain": "Ndaipóri peteĩ relé poruhára dominio hag̃ua, térã pe relé ndojepurukuaái. Ikatúpiko eiporavo peteĩ relé reipuru hag̃ua.", "no_relays": "Ndaipóri relays", "no_relays_message": "Rojuhu peteĩ registro Nostr NIP-05 ko usuario-pe g̃uarã, ha ndoguerekói mba’eveichagua relays. Ikatúpiko ere pe ohupytysévape ombojoapy hag̃ua relays iregistro Nostr-pe.", @@ -536,8 +696,10 @@ "node_new": "Nodo Pyahu", "node_port": "Nodo hag̃ua", "node_reset_settings_title": "Emoñepyrũjey ñemohenda", + "node_share_desc": "Emoñe'ẽ ko QR código pe Scan kuatiarogue-gui egueru hag̃ua ko nodo.", "node_test": "Ñeha'ã", "nodes": "Nodo-kuéra", + "nodes_desc": "Emohenda umi nodo oĩva térã embojoapy peteĩ ne mba'éva.", "nodes_list_reset_to_default_message": "¿Reime añetete remoĩjeyseha umi ñemboheko ijypykuévaramo?", "none_of_selected_providers_can_exchange": "Ndaipóri umi proveedor ojeiporavóva apytépe ikatúva ojapo ko swap.", "noNFTYet": "Ndaipóri NFT gueteri", @@ -545,15 +707,19 @@ "note": "Haipy", "note_optional": "Jehaipy (opcional)", "note_tap_to_change": "Jehaipy (eikutu emoambue hag̃ua)", + "notification_permission_denied": "Pe marandu'i ñemoneĩ oñemboty opaite g̃uarãma; emboguata po rupi ñembohekópe", "nullURIError": "URI nulo", + "ocp_desc": "Ehepyme'ẽ cripto-pe ñemuhakuérape", "offer_expires_in": "Ñemurã opáta hag̃ua:", "offline": "ndaipóri", "ok": "OK", "old_fee": "Tembiapo repy ymaguare", + "oled_mode": "OLED modo", "onion_link": "Onion link", "online": "En línea", "onramper_option_description": "Ejogua pyaʼe cripto heta hag̃ua rehepymeʼẽ hag̃ua. Ojeguereko hetave tetãme. Umi joavy ha mbaʼerepy iñambue.", "open_gift_card": "Eipeʼa kuatia'atã meʼẽrã", + "open_wallet": "Eipe'a Billetera", "optional_description": "Ñemombe’u opcional", "optional_email_hint": "Ñandutípe ñemomarandu optional pe ohupytýtavape", "optional_name": "Téra opcional pe ohupytýtavape g̃uarã", @@ -568,14 +734,34 @@ "outdated_electrum_wallet_receive_warning": "Ko billetera oguerekóramo peteĩ seed 12 ñe’ẽgui ha ojejapo Cake-pe, ANI REMOINGE Bitcoin ko billeterápe. Oimeraẽ BTC oñembohasáva ko billeterápe ikatu okañy. Emoheñói peteĩ billetera pyahu 24 ñe’ẽgui (epoko pe menú yvate akatúa gotyo, eiporavo Wallets, eiporavo Create New Wallet, ha upéi eiporavo Bitcoin) ha pya’eterei emongu’e nde BTC upépe. Umi billetera pyahu BTC (24 ñe’ẽ) ojapóva Cake-gui ha’e hekorosã", "outgoing": "Oñemondo", "outputs": "Osẽha", + "overshot": "Ohasa hetave (overshot)", "overwrite_amount": "Embyekovia hetakue", + "pairing_code": "Pairing Código", + "pairing_code_desc_1": "Ne mba'e'oka ohechaukáta peteĩ pairing código.", + "pairing_code_desc_2": "Emoinge ko'ápe resegí hag̃ua", + "pairing_error": "Pairing Jejavy", "pairingInvalidEvent": "Mba'e oiko ndoikóiva pe joaju hag̃ua", "passphrase": "Ñe’ẽñemi (Opcional)", + "passphrase_view_keys": "Passphrase", + "passphrases_doesnt_match": "Umi passphrase ndojojái, eha'ã jey", "password": "Ñe’ẽñemi", "paste": "Mboja", "pause_wallet_creation": "Ko'ág̃a ojejoko sapy'aitemi pe ikatu hag̃a ojejapo Haven Wallet.", + "payjoin_card_content": "Payjoin ha'e peteĩ tembiapoite pyahu oñangarekóva tekoñemíre ha oñongatúva hepyme'ẽ Bitcoin-pe.", + "payjoin_details": "Payjoin mba'ekuaarã", + "payjoin_enabled": "Payjoin oñemboguatáva", + "payjoin_enabling_popup_content": "Ikatu emyendy/embogue Payjoin Menú → Privacy → Use Payjoin guýpe upéi.", + "payjoin_enabling_popup_title": "Payjoin Ñemboguata", + "payjoin_request_awaiting_tx": "Oha'arõ Transacción", + "payjoin_request_in_progress": "Oikohína", + "payjoin_unavailable": "Payjoin ndojepurukuaái", + "payjoin_unavailable_sheet_content": "Peteĩ Payjoin transacción ohupyty hag̃ua tekotevẽ ereko Bitcoin oĩmbáva reipuru hag̃ua.\n\nNe billetera oguerekóvo viru, Payjoin oñemboguatáta ijeheguíva.", + "payjoin_unavailable_sheet_title": "¿Mba'érepa Payjoin ndojepurukuaái?", "payment_id": "ID jehepyme’ẽ rehegua: ", + "payment_invoices": "Jehepyme'ẽ Kuatiañemuhã-kuéra", + "payment_made_easy": "Jehepyme'ẽ hasy'ỹre", "payment_was_received": "Nde pago oñemog̃uahẽma.", + "payments": "Jehepyme'ẽ-kuéra", "pending": " (oĩhína oñehaʼãrõme)", "percentageOf": "rehe ${amount}", "personalizado": "Ojeiporavokuaava", @@ -600,6 +786,7 @@ "pin_number": "PIN papapy", "placeholder_contacts": "Nde contacto kuéra ojehechaukáta koʼápe.", "placeholder_transactions": "Nde transacción-kuéra ojehechaukáta koʼápe.", + "please_choose_one": "Eiporavo peteĩ", "please_fill_totp": "Emoinge pe kódigo 8 dígito oĩva nde ambue tembipurupe.", "please_make_selection": "Eiporavo koʼágui hag̃ua emoheñói térã erujey nde billetera.", "please_reference_document": "Ehecha umi kuatia oĩva iguýpe reikuaave hag̃ua.", @@ -608,6 +795,7 @@ "please_try_to_connect_to_another_node": "Ikatúpa eñeha'ã eñembojoaju ambue nodo rehe", "please_wait": "Eha'ãmi", "polygonscan_history": "PolygonScan rembiasakue", + "potential_scam": "Ñembotavyrã (Potential Scam)", "powered_by": "Oñemombarete ${title} rupive", "pre_seed_button_text": "Aikuaa. Ehechauka chéve che ñe’ẽñemi", "pre_seed_description": "Pe kuatiarogue oúvape rehecháta peteĩ aty ñeʼẽ. Péva haʼe nde seed ijojahaʼỹva ha ñemigua, ha péva añoite hína tape ikatu hag̃a rehejuhu jey nde wallet reñehundi térã ndoikói ramo. Nde rembiapo hína rehai hag̃ua ha reñongatu hag̃ua peteĩ tenda hekorosãvape, okápe Cake Wallet app-gui.", @@ -615,6 +803,7 @@ "preference": "Jerohoryvéva", "prepaid_cards": "Kárta jehepyme’ẽva", "prevent_screenshots": "Ani ejapo hag̃ua ta'angajapyhy térã pantalla grabación", + "primary_address": "Kundaharape Mba'eguasu (primary)", "privacy": "Ñemigua", "privacy_and_security": "Privasida ha Tekorosã", "privacy_and_security_desc": "Emohenda jehechajey ha tekorosã ñemboheko ha emboheko Cake 2FA.", @@ -627,6 +816,8 @@ "proceed_after_one_minute": "Pe pantalla ndohoiramo tenonde 1 aravo’i rire, ehecha nde correo.", "proceed_on_device": "Eku’ejey nde mba’e’okápe.", "proceed_on_device_description": "Eikuaa hag̃ua, ejapo umi mba’e he’íva nde hardware wallet-pe", + "processing": "Oñeprocesahína", + "processing_signed_tx": "Oñeprocesahína transacción oñemboheraguapýva", "profile": "Perfil", "provider": "Proveedor", "provider_error": "Jejavy ${provider}", @@ -634,7 +825,11 @@ "public_key": "Clave pública", "purchase_gift_card": "Ehepyme Tarjeta Regalo", "purple_dark_theme": "Téma pytãũ ypytũva", + "qr_code_format": "QR Code Formáto", + "qr_code_format_body": "BCUR (Blockchain Commons Uniform Resources) ha'e pe estándar industria-pegua, ha ojokupyty hetave Bitcoin hardware wallet-kuéra ndive, ha ojeporavova'erã hetavéva puruhárape g̃uarã. BBQR (Better Bitcoin QR) ha'e peteĩ formáto ojepurúva COLDCARD hardware wallet-kuérape añoite, imodelo Q guive.", + "qr_code_format_note": "Hardware wallet-kuéra iñambuéva oipuru QR código formáto iñambuéva Bitcoin ñe'ãme", "qr_fullscreen": "Eikutu hag̃ua eipe'a hag̃ua QR ayvu tuichakuépe", + "qr_instruction": "Eipuru ko kundaharape ehupyty hag̃ua oimeraẽ token térã coleccionable ko'ápe:", "qr_payment_amount": "Ko QR oguereko peteĩ monto jehepyme’ẽ rehegua. Reipotápa rehai jey pe valor ko’ag̃agua ári?", "quantity": "Hetakue", "question_to_disable_2fa": "¿Añetehápepa remboguese Cake 2FA? Upeicháramo, ndaikotevẽvéima peteĩ kódigo 2FA reike hag̃ua pe wallet-pe ha umi tembiapo hag̃uaicha.", @@ -648,6 +843,7 @@ "recipient_address": "Ojapyhýva kundaharape", "reconnect": "Eñembojoaju jey", "reconnect_alert_text": "¿Reime añetehápe reñembojoaju jeyse?", + "reconnect_your_hardware_wallet": "Embojoaju jey ne Hardware Wallet", "reconnection": "Jeike jey", "red_dark_theme": "Tema pytã pytũ", "red_light_theme": "Tema pytã sa'yju", @@ -663,6 +859,8 @@ "rep_warning_sub": "Nde moha'angáva ndojekuaái oĩha hag̃ua iporã hag̃aicha. Epoko ko'ápe reiporavo hag̃ua peteĩ pyahu", "repeat_wallet_password": "Ehai jey billetera ñe’ẽñemi", "repeated_password_is_incorrect": "Pe ñe’ẽñemi ojehai jeyva ndoikói. Ikatúpiko ehaijey pe billetera ñe’ẽñemi.", + "replace": "Emyengovia", + "requested": "Ojejeruréva", "require_for_adding_contacts": "Oñeikotevẽva oñemoinge hag̃ua contacto-kuéra", "require_for_all_security_and_backup_settings": "Oñeikotevẽ opaite ñemboheko tekorosã ha backup hag̃ua.", "require_for_assessing_wallet": "Ejerure hag̃ua eike hag̃ua wallet-pe", @@ -673,20 +871,24 @@ "require_for_sends_to_internal_wallets": "Oñeikotevẽ hag̃ua oñembohasa billetera ryepýpe", "require_for_sends_to_non_contacts": "Oñeikotevẽ hag̃ua oñembohasa umi ndaha'éiva ne contacto-pe", "require_pin_after": "Oñeikotevẽ PIN upéi", + "required_passphrase": "Passphrase", "rescan": "Eescanea jey", "resend_code": "Emondo jey, ikatúpa emondo jey.", "reset": "Moĩjey", "reset_password": "Emoĩ jey ñe’ẽñemi", + "restore": "Emoĩporã jey", "restore_active_seed": "Seed aktívo", "restore_address": "Dirección", "restore_bitcoin_description_from_keys": "Emoheñói jey nde billetera peteĩ WIF joajuhágui, heñóiva nde clave privada-gui.", "restore_bitcoin_description_from_seed": "Emoheñói jey nde billetera pe kódigo ñembojuehegua 24 ñe’ẽgui.", "restore_bitcoin_title_from_keys": "Emboguejy WIF-gui", "restore_description_from_backup": "Emoĩporã jey Cake Wallet hína chagüe oĩva'ekue rami, emoĩporã jey ñongatupyre archivo-gui.", + "restore_description_from_cupcake": "Embojoaju ore irũ app air-gapped ndive, oñemohendáva ambue teléfono-pe.", "restore_description_from_hardware_wallet": "Embojuaju ne hardware wallet mba’e’oka heta hag̃ua fabricante-gui.", "restore_description_from_keys": "Emoĩporã jey nde billetera umi teclakuéra heñóiva rehegua, oñeñongatúva nde clave privada-gui.", "restore_description_from_seed": "Emoheñói jey nde billetera pe kódigo ñembojoaju 25 térã 13 ñe’ẽgui.", "restore_description_from_seed_keys": "Emoĩporã jey ne billetera ñe'ẽñemi seed-gui térã mba'ekuaarepy oñongatúvagui.", + "restore_existing_wallet": "Emoĩporã jey Billetera Oĩmava", "restore_from_date_or_blockheight": "Ikatúpiko emoinge peteĩ arange ko billetera emoheñói mboyve heta’ẽmi ára. Térã reikuaáramo pe blockheight, emoinge upéva hendaguépe.", "restore_from_seed_placeholder": "Emoinge térã emboja nde seed ko’ápe.", "restore_new_seed": "Seed pyahu", @@ -696,6 +898,7 @@ "restore_seed_keys_restore": "Ñemoĩporã jey Seed/Keys", "restore_spend_key_private": "Spend key (ñemigua)", "restore_title_from_backup": "Archivo de backup", + "restore_title_from_cupcake": "Cupcake App", "restore_title_from_hardware_wallet": "Hardware wallet ", "restore_title_from_keys": "Emboguejy hag̃ua clave-kuéra guive", "restore_title_from_seed": "Emboguyjey ñe’ẽñemigua guive", @@ -712,6 +915,7 @@ "save": "Ñongatu", "save_backup_password": "Ehechajey reñongatúma hague nde backup ñe’ẽñemi. Ndaikatumo’ãi remoinge jey nde backup marandurenda’ỹre upeva.", "save_backup_password_alert": "Eñongatu ñe’ẽñemi backup hag̃ua", + "save_contact": "Eñongatu Contacto", "save_to_downloads": "Ñongatu Ñemboguejy hag̃ua", "saved_the_trade_id": "Añongatu trade ID", "savings": "Ahorro", @@ -728,6 +932,7 @@ "search_or_enter": "Eheka térã emoinge", "second_intro_content": "Nde Yat ha'e peteĩ dirección emoji ijojaha'ỹva ha peteĩnte, omyengoviáva opaite nde dirección hexadecimal ipukúva opaite nde moneda hag̃ua.", "second_intro_title": "Peteĩ dirección emoji hag̃ua omanda hag̃ua opavavépe", + "security": "Tekorosã", "security_and_backup": "Tekorosã ha backup", "seed_alert_back": "Ejevy", "seed_alert_content": "Pe seed ha’eñoite pe tape ikatu hag̃ hag̃ rehupyty jey nde billetera. ¿Rehaíma hag̃ua?", @@ -735,6 +940,7 @@ "seed_alert_yes": "Hêe, aguereko", "seed_and_keys": "Seed ha Llave kuéra", "seed_choose": "Eiporavo seed ñe'ẽ", + "seed_display_path": "Menú → Security and Backup → Show key/seeds", "seed_hex_form": "Billetera seed (hex form)", "seed_key": "Seed key", "seed_language": "Seed ñe'ẽ", @@ -753,12 +959,19 @@ "seed_language_russian": "Ruso", "seed_language_spanish": "Español", "seed_phrase_length": "Seed pukukue", + "seed_position_question_one": "¿Mba'épa pe", + "seed_position_question_two": "ñe'ẽ ne seed-gui?", "seed_reminder": "Ehai koʼãva ikatu hag̃ua ojehu ramo ndehegui nde teléfono okañy térã oñembogue.", "seed_share": "Emoherakuã seed", "seed_title": "Seed", + "seed_verified": "Seed Ojehechajeýva", + "seed_verified_subtext": "Ikatu reipuru ne seed oñeñongatúva upéi emoĩporã jey hag̃ua ko billetera oñembyai térã ne mba'e'oka okañy ramo.\n\nIkatu rehecha jey ko seed ko'águi:", "seedtype": "Mba'eichagua seed", + "seedtype_alert_content": "Seed ñembohasa ambue billetera ndive ikatúnte BIP39 SeedType reheve.", + "seedtype_alert_title": "SeedType Marandu", "seedtype_legacy": "Temimondo (25 ñe’ẽ)", "seedtype_polyseed": "Polieta (16 ñe’ẽ)", + "select_a_wallet": "Eiporavo peteĩ billetera", "select_address_to_copy": "Eiporavo dirección emokopia hag̃ua", "select_all": "Eiporavo opaite", "select_asset": "Eiporavo Activo", @@ -766,17 +979,24 @@ "select_buy_provider_notice": "Eiporavo peteĩ jogua-me’ẽha yvate. Ikatu rehasapa ko pantalla emoĩvo nde jogua-me’ẽha ijypykuéramo ñembohekorã aplicación-pe.", "select_destination": "Eiporavo moõpa oñeñongatúta marandurenda backup.", "select_fiat_currency_title": "Eiporavo Moneda", + "select_hw_account_below": "Eiporavo mávapa cuenta emoĩporã jeýta iguýpe:", + "select_manufacturer_title": "Eiporavo Fabricante", + "select_network": "Eiporavo Red", "select_network_subtitle": "Ko activo oime presente heta red-pe. Eiporavo pe reiporuséva", "select_network_title": "Eiporavo Red", "select_other_wallet": "Eiporavo ambue billetera", "select_receiver": "Eiporavo Mbyhyha", "select_sell_provider_notice": "Eiporavo yvate peteĩ ñemuha. Ikatu rehasa hag̃ua ko pantalla emoĩvo nde ñemuha ijypykuéramo umi ñemboheko hag̃ua aplicación-pe.", + "select_token": "Eiporavo Token", + "select_your_country": "Eiporavo ne tetã", + "selected_trocador_provider": "Trocador me'ẽha ojeporavóva", "sell": "Vende", "sell_alert_content": "Ko’ág̃a rupi roipytyvõ venta Bitcoin, Ethereum ha Litecoin-pe añoite. Ikatúpiko emoheñói térã emoambue nde billetera Bitcoin, Ethereum térã Litecoin-pe.", "sell_monero_com_alert_content": "Ndaikatúi gueteri reñemu Monero.", "send": "Emondo", "send_address": "Dirección ${cryptoCurrency} rehegua", "send_amount": "Hetakue:", + "send_change_to_you": "Ñemoambue, ndéve:", "send_creating_transaction": "Ojejapo hag̃ua ñembohasa", "send_error_currency": "Pe moneda ikatu oguereko papapy añoite.", "send_error_minimum_value": "Pe tepykue michĩvéva hag̃ua pe monto ha’e 0,01", @@ -785,9 +1005,12 @@ "send_external_desc": "Ani remboty ko página rehegua pe emondo hag̃ua umi fondo, ndaha'éiramo upéicha pe depósito ndohóimo'ãi hag̃ua.", "send_fee": "Hepyme’ẽ:", "send_from": "Emondo guive", + "send_from_cake_wallet": "Emondo Cake Wallet guive", "send_from_external": "Emondo Okápe", + "send_from_external_wallet": "Emondo Billetera Okapegua guive", "send_name": "Téra", "send_new": "Pyahu", + "send_payjoin": "Emondo Payjoin", "send_payment_id": "Payment ID (opcional)", "send_priority": "Ko’ánga, pe comisión oñemohenda ${transactionPriority} prioridad-pe.\nPe transacción prioridad ikatu oñemboheko hag̃ua umi ñemboheko hag̃ua.", "send_sending": "Oñemondo...", @@ -803,11 +1026,13 @@ "sent_the_funds": "Amondo umi fondo.", "service_health_disabled": "Pe Marandu Tesãi Mba’apo rehegua oĩ ñemboguepyre.", "service_health_disabled_message": "Kóva ha’e kuatiarogue marandu’i Tesãi Mba’apohágui; ikatu remyendy ko kuatiarogue Ñemboheko → Ñemigua-pe.", + "set_a_pin": "Emoĩ peteĩ PIN", "set_amount": "Emoĩ hetakue", "set_fees": "Emohenda umi tarifa", "set_fees_desc": "Odepende pe monto de comisión rehe, pe depósito ohasáta pyaʼeve.", "set_label": "Establecer etiqueta", "set_refund_address": "Emoĩ Dirección de reembolso", + "set_up_a_wallet": "Embosako'i peteĩ Billetera", "settings": "Ñemboheko", "settings_all": "OPA", "settings_allow_biometrical_authentication": "Eheja jehechakuaa biométrika rupive", @@ -842,15 +1067,24 @@ "setup_your_debit_card": "Emoĩporã nde tarjeta débito", "share": "Mbohasa", "share_address": "Emoherakuã dirección", + "share_this_node": "Emoherakuã ko nodo", + "shared_seed_wallet_groups": "Billetera Atyrã Seed Ojoja'ekuéva", "shared_seed_wallets": "Billetera kuéra seed compartida rehegua", + "show": "Hechauka", + "show_address_book_popup": "Ehechauka Address Book popup", + "show_balance": "Eipoko Puku Ehechauka hag̃ua Saldo", "show_balance_send_page": "Eikutu ehechauka hag̃ua", + "show_balance_toast": "Eipoko puku emokañy térã ehechauka hag̃ua saldo", + "show_combined_balance": "Ehechauka saldo ojembyatypyréva", "show_details": "Ehechauka mba’emimi", "show_hidden_addresses": "Ehechauka umi dirección kañymby.", "show_keys": "Hechauka seed/keys", "show_market_place": "Hechauka Ñemuha Renda", "show_seed": "Hechauka seed", "show_zcash_card": "Ohechauka zcash tarjeta umi viru oĩ'ỹva rehegua.", + "sign_all": "Emboheraguapy Opaite", "sign_message": "Emoheraguapy marandu", + "sign_one": "Emboheraguapy Peteĩ", "sign_up": "Eñemboheraguapy", "sign_verify_message": "Emboheraguapy / Ehechajey", "sign_verify_message_sub": "Emboheraguapy térã ehechajey peteĩ marandu reipuruvo nde clave privada", @@ -861,28 +1095,38 @@ "signTransaction": "Emoheraguapy Transacción", "signup_for_card_accept_terms": "Eñemboheraguapy hag̃ua pe tarjeta ha emoneĩ umi término.", "silent_address_desc": "Dirección estática omomba’eporãva tekoñemi hag̃ua", + "silent_payment": "Silent Payment", "silent_payments": "Jehepyme'ẽ Kirirĩ", "silent_payments_always_scan": "Emoĩ Silent Payments jehechaha (scan) katuete hag̃ua.", "silent_payments_disclaimer": "Umi dirección pyahu ndaha’éi identidad pyahu. Ha’e peteĩ identidad oĩmavavoi ojepurujeyva peteĩ teratee ambuéva ndive.", "silent_payments_display_card": "Ehechauka Silent Payments tarjeta.", + "silent_payments_logs": "Silent Payment Logs", "silent_payments_scan_from_date": "Eñepyrũ je-escaneo arange guive", "silent_payments_scan_from_date_or_blockheight": "Emoinge pe bloque yvate térã pe arange reipuru hag̃uáicha reñepyrũ hag̃ua re-escanea hag̃ua umi Silent Payments oikéva. Ikatu reiporavo pe billetera ocontinua hag̃ua oescanea bloque peteĩteĩva, térã ohecha hag̃ua pe yvate añoite oñemohendáva.", "silent_payments_scan_from_height": "Ehecha hag̃ua yvatekuéra bloque guive", "silent_payments_scanned_tip": "Ojeescanea hag̃ua pe ipahaite peve! (${tip})", "silent_payments_scanning": "Jeheka Silent Payments rehegua", "silent_payments_settings": "Ñemboheko Silent Payments rehegua", + "single_seed_wallets_group": "Billetera Seed Peteĩva", "skip": "Eheja", "skip_set_later": "Eheja hag̃ua térã emohenda ag̃ave", "slidable": "Oñemongu'e hag̃ hag̃ hag̃ua", + "solana_create_associated_token_account_exception": "Jejavy oñemoheñói aja pe associated token account pe ohupytýva kundaharapépe.", "solana_invalid_data_message": "Jejavy eñemoñe'ẽ hag̃ua pe cuenta token asociada hag̃ua pe token-pe. Ikatúpiko ehechajey pe dirección de recepción ha eñeha'ã jey.", + "solana_no_associated_token_account_exception": "Ndaipóri associated token account ko kundaharapépe.", + "solana_sign_native_transaction_rent_exception": "Ndaikatúi oñemohu'ã pe transacción. Ndaipóri SOL hembýva pe renta-rã pe transacción rire. Embohetave ne SOL saldo térã emomichĩ pe SOL remondóva.", + "solana_sign_spl_token_transaction_rent_exception": "Ndaikatúi oñemohu'ã pe transacción. Ndaipóri SOL hembýva pe renta-rã pe transacción rire. Embohetave ne SOL saldo.", "sort_by": "Mohenda hag̃ua", "spend_key_private": "Clave de gasto (privada)", "spend_key_public": "Mba’eñemi hag̃ua (público)", + "starting_tor_proxy": "Oñepyrũhína Tor proxy", "status": "Teko: ", + "step": "Pa'ũ (step)", "string_default": "Ijypykue", "subaddress_title": "Subdirección rysýi", "subaddresses": "Subdirección-kuéra", "submit_request": "Emondo peteĩ jerure", + "success": "Oiko porã", "successful": "Oiko porã", "support_description_guides": "Kuatiahaipyre ha pytyvõ mba’e apañuãi hag̃ua hag̃ua jepigua rehegua", "support_description_live_chat": "¡Rehepyme’ẽ’ỹ ha pya’e! Umi pytyvõhára katupyry oĩ hag̃uaicha ndepytyvõ hag̃ua", @@ -890,12 +1134,16 @@ "support_title_guides": "Kuatiaite Cake Wallet rehegua", "support_title_live_chat": "Pytyvõ hag̃ua hag̃uaicha", "support_title_other_links": "Ambue juaju pytyvõ rehegua", + "supported": "Ojepytyvõva", + "swap": "Swap", "swap_id": "ID ñemoambue rehegua", "swap_provider_initial_desc": "Eiporavo mba’eichagua swap puruhára reipuruséva rembojopyru hag̃ua swap jave.", "swap_providers": "Proveedor-kuéra intercambio rehegua", "sweeping_wallet": "Billetera ñemopotĩ", "sweeping_wallet_alert": "Kóva ndoguerahámo’ãi heta aravo. ANI REHEJA KO PANTALLA, térã umi fondo oñemopotĩva ikatu okañy.", + "swipe_to_bridge": "Embosyryry embridge hag̃ua", "swipe_to_send": "Emoinge hag̃ua emondo hag̃ua.", + "switch_wallet": "Emoambue Billetera", "switchToETHWallet": "Ikatúpa emoambue peteĩ billetera Ethereum-pe ha eha’ãjey.", "switchToWCCompatibleWallet": "Embohasa peteĩ billetera WalletConnect ndive ha eñeha’ã jey (${chains}).", "symbol": "Ta'ãnga’i", @@ -907,9 +1155,13 @@ "sync_not_connected": "Ndojeikói conectádo", "sync_offline": "Offline", "sync_starting_scan": "Oñepyrũvo escaneo", + "sync_status_attempting_scan": "OÑEHA'Ã ESCANEO", "sync_status_attempting_sync": "Oñeha’ã ojesinkronisa", "sync_status_connected": "OÑEMBOJOAJU", "sync_status_connecting": "OÑEMBOJOAJUHÍNA", + "sync_status_display_mode": "Ñembojuehe Tekotee Jehechauka", + "sync_status_display_mode_blocks": "Ehechauka Bloque Hembýva", + "sync_status_display_mode_eta": "Ehechauka ETA", "sync_status_failed_connect": "OJEIÑE'Ĩ", "sync_status_not_connected": "NDOJOAJÚI", "sync_status_starting_scan": "Oñepyrũhína escaneo (guive ${height})", @@ -921,6 +1173,7 @@ "sync_syncing": "Oñembojuehe", "sync_timed_out": "Sincronización ohasáma aravo", "sync_unsupported_node": "Nodo ndojehechaukáiva", + "synchronizing": "Oñembojuehehína", "syncing_wallet_alert_content": "Ne saldo ha ne transacción rysýi ikatu ndoĩporãmbái he’í peve “SYNCHRONIZED” yvate gotyo. Ehecha/ejopy térã epoko reikuaave hag̃ua.", "syncing_wallet_alert_title": "Nde billetera oñembojuehehína", "tap_to_copy": "Eikutu hag̃ua ekopia", @@ -929,20 +1182,28 @@ "testnet_coins_no_value": "Umi testnet moneda ndorekói mba’e repy.", "third_intro_content": "Umi Yat oiko avei okápe Cake Wallet-gui. Oimeraẽva billetera kundaharape ko yvy ape ári ikatu oñemyengovia peteĩ Yat rehe!", "third_intro_title": "Yat ojapo porã ambuekuéra ndive.", + "this_can_take_few_seconds": "Kóva ikatu ohupyty mbovymi segundo", + "this_pair_is_not_supported_warning": "Ko par ndojokupytýi umi intercambio ojeporavóva ko'ag̃agua ndive. Eiporavo ambue intercambio.", "thorchain_contract_address_not_supported": "THORChain ndohejáiva oñemondo hag̃ua peteĩ contrato dirección-pe.", "thorchain_taproot_address_not_supported": "Pe ThorChain me’ẽha ndoipytyvõi Taproot kundaharape. Ikatúpa emoambue pe kundaharape térã eiporavo ambue me’ẽha.", "time": "${minutes}m ${seconds}s", "tip": "Ñemoñe’ẽ:", + "to": "Peve (To)", "to_lightning": "a Lightning", "to_on_chain": "ha on-chain", "today": "Kóina", + "token_already_exists": "Pe token oĩma", "token_contract_address": "Pe dirección contrato token rehegua", "token_decimal": "Token decimal (techapyrã: USDT)", "token_name": "Token réra (techapyrã: Tether)", "token_symbol": "Token ra'ãnga'i (techapyrã: USDT)", + "token_verified_on_jupiter": "Ko token ojeverifika Jupiter rehe", "tokenID": "ID", "tokens": "Tokens", + "tokens_strong_warning": "¡Anive remondo token ko kundaharapépe!", "tor_connection": "Tor jeikeha", + "tor_connection_timeout": "Tor jeikeha ohasáma aravo", + "tor_experimental": "Kóva ha'e peteĩ tembiapoite experimental, ndaha'éi opaite joaju Cake Wallet guive oipytyvõ Tor ruteo — oĩ joaju oipurúva clearnet; ruteo hag̃ua opaite app tráfico eipuru Tor VPN modo ndive.", "tor_only": "Tor añoite hag̃", "total": "Total", "total_saving": "Ñongatu total", @@ -985,6 +1246,7 @@ "trades": "Ñemuha", "transaction": "Transacción rehegua", "transaction_commited": "Transacción ojejapóma.", + "transaction_cost": "Transacción Repykue", "transaction_details_amount": "Hetakue", "transaction_details_copied": "${title} ojekopia portapapélpe", "transaction_details_date": "Arange", @@ -1009,13 +1271,16 @@ "transactions_by_date": "Ñembohasa kuéra arange rupi", "transactions_will_appear_here": "Ko’ápe ojehechaukáta ne transacción-kuéra.", "transparent_secret_key": "Clave Secreta Transparente", + "transport_type": "Transporte Mba'eichagua", "trocador_desc": "ha'e peteĩ agregador de intercambio oiporúva heta intercambio subyacente ojuhú hag̃ua tasa competitiva.", "trocador_desc_kyc": "Pe proveedor réra ykére, ojehechauka peteĩ calificación KYC rehegua. Péva omoĩ Trocador ha oñemopyenda ijehegui hag̃uaichaite hag̃ua.", "trongrid_history": "TronGrid rembiasakue", "trusted": "Jeroviaha", + "try_again": "Eha'ã jey", "trying_to_spend_locked_funds": "Transacción oñembotove reñeha’ãgui reipuru umi fondo orekóva bloqueo de tiempo relativo; eha’arõ ha eñeha’ã jey ag̃ave, térã embogue umi fondo bloqueado coin control-pe", "tx_commit_exception_no_dust_on_change": "Oñemboyke pe transacción ko monto reheve. Ko’ã moneda rupive ikatu remondo ${min} ndorekóiva ñemoambue térã ${max} ome’ẽva ñemoambue.", "tx_commit_failed": "Ndoikói transacción ñemoneĩ. Eñe’ẽ soporte ndive.", + "tx_commit_failed_no_peers": "Pe transacción ndaikatúi oñemyasãi, eha'ã jey peteĩ segundo-pe", "tx_invalid_input": "Reipuru hag̃ua peteĩchagua jeike hekope’ỹva koichagua jehepyme’ẽ hag̃ua.", "tx_no_dust_exception": "Ko transacción oñemboyke oñemondóramo peteĩ monto michĩeterei. Ikatúpiko eha’ã embohetave pe monto.", "tx_not_enough_inputs_exception": "Ndaipóri jeikeha he'íva. Ikatúpa eiporavo hetave Coin Control-pe.", @@ -1038,6 +1303,8 @@ "unlock": "Eipe’a", "unmask": "Mokañy'ỹ", "unmatched_currencies": "Pe moneda ndebilletera ko’agagua ndojoajúi pe QR escaneado ndive", + "unrestricted_background_service": "Servicio tapykuegua ñemboaty'ỹ (unrestricted)", + "unrestricted_background_service_notice": "Emboguata hag̃ua ñembojuehe tapykuegua tekotevẽ emboguata servicio tapykuegua ñemboaty'ỹ", "unselect_all": "Eipe'a opaite jeporavo", "unspent_change": "Ñemoambue", "unspent_coins_details_title": "Marandu viru ndojepurukuaáiva rehegua", @@ -1050,12 +1317,16 @@ "use_blink_protection": "Eipuru Blink Protection", "use_card_info_three": "Eipuru tarjeta dijitálva ñandutípe térã jehepyme’ẽ hag̃ua tapicha’ỹre (contactless).", "use_card_info_two": "Pe viru oñemoambue USD-pe oñeñongatúramo pe cuenta prepaga-pe, ndaha’éi moneda digital-pe.", + "use_device_theme": "Eipuru Mba'e'oka Téma", + "use_payjoin": "Eipuru Payjoin", "use_ssl": "Eipuru SSL", "use_suggested": "Eipuru je'epyréva", "use_testnet": "Eipuru Testnet", + "user_rejected_method": "Puruhára ombotove pe método", "username": "Puruhára réra", "username_available": "Tembipuru réra ojepuru hag̃ua", "username_character_error": "Umi puruhára réra oguerekova’erãnte", + "username_check_your_network": "Ndaikatúi ojehechajey pe puruhára réra. Ehecha ne ñanduti joaju.", "username_length_error": "Umi puruhára réra oguerekova’erã 6-32 tai ha papapy (alfanumérico).", "username_length_error_1_64": "Umi puruhára réra oguerekova’erã 1-64 tai alfanumérico.", "username_not_available": "Ko puruhára réra ndojepurukuaái.", @@ -1064,7 +1335,9 @@ "variable_pair_not_supported": "Ko par iñambuekuáva ndojokupytýi umi ñembohasa ojeporavóva ndive.", "verification": "Jehechajey", "verify_message": "Marandu jehechajey", + "verify_seed": "Ehechajey Seed", "verify_with_2fa": "Jehechajey Cake 2FA ndive", + "verifying_code": "Oñehechajeýhína Código", "version": "Versión ${currentVersion}", "view_all": "Hecha opaite", "view_in_block_explorer": "Ehecha Block Explorer-pe", @@ -1074,10 +1347,24 @@ "view_transaction_on": "Ehecha transacción rehegua hag̃ua", "voting_weight": "Pohýi votación rehegua", "waitFewSecondForTxUpdate": "Eha’ãro sapy’ami hag̃ua pe transacción ojehecha hag̃ua ñembohasa rembiasakue-pe.", + "wallet": "Billetera", "wallet_accounts": "Mba'ete Billetera-pe", + "wallet_balance": "Billetera Saldo", + "wallet_group": "Billetera Atyrã (Wallet Group)", + "wallet_group_description_existing_seed": "Reiporavo reipuru hag̃ua peteĩ seed oĩmava ko billetera-pe. Ikatu rehechajey jey pe seed reikotevẽrõ emoneĩ térã rehai.", + "wallet_group_description_four": "emoheñói hag̃ua peteĩ billetera seed ipyahúva reheve.", + "wallet_group_description_one": "Cake Wallet-pe, ikatu emoheñói peteĩ", + "wallet_group_description_open_wallet": "Ndaupéichairõ, ikatu eku'ejey eipe'a hag̃ua pe billetera", + "wallet_group_description_three": "ehecha hag̃ua umi billetera ha/térã billetera atyrã kuatiarogue. Térã eiporavo", + "wallet_group_description_two": "eiporavóvo peteĩ billetera oĩmava emoherakuã hag̃ua peteĩ seed hendive. Peteĩteĩ billetera atyrã ikatu oguereko peteĩ billetera moneda mba'eichagua-pe.\n\nIkatu eiporavo", + "wallet_group_description_view_seed": "Ikatu rehecha jey ko seed ko'águi", + "wallet_group_empty_state_text_one": "Ndereguerekóiramoguáicha mavave billetera atyrã ojokupytýva.\n\nEikutu", + "wallet_group_empty_state_text_two": "iguýpe emoheñói hag̃ua peteĩ pyahu.", + "wallet_has_passphrase": "Ko billetera oguereko peteĩ passphrase", "wallet_is_syncing": "Pe billetera oĩ hína oñembojuehe hag̃ua", "wallet_keys": "Billetera seed/clave", "wallet_list_create_new_wallet": "Emoheñói billetera pyahu", + "wallet_list_edit_group_name": "Embosako'i Atyrã Téra", "wallet_list_edit_wallet": "Embosako’i wallet", "wallet_list_failed_to_load": "Ndaikatúi ojehupi la billetera ${wallet_name}. ${error}", "wallet_list_failed_to_remove": "Ndoikói emboguete hag̃ua billetera ${wallet_name}. ${error}", @@ -1104,6 +1391,7 @@ "wc_approve_request_title": "Omoneĩ mba’ejerure", "wc_connect_request_title": "Ombojoaju mba’ejerure", "wc_connected_to": "Oñembojoaju ${name} ndive.", + "wc_desc": "Embojoaju hasy'ỹre DApp-kuérandi", "wc_max_network_fee": "Max cuota red rehegua", "wc_message_to_sign": "Marandu ofirma haguã", "wc_network_fee": "Cuota de red rehegua", @@ -1125,8 +1413,12 @@ "wc_verified": "Ojehecháma", "wc_would_like_to_connect_to": "${name} oñembojoajuse", "wc_would_like_to_sign": "${name} ofirmase", + "website": "Website", "welcome": "Tapeguahẽ porãite", + "welcome_subtitle_new_wallet": "Reñepyrũségui pyahúgui, eikutu Create New Wallet iguýpe ha reñepyrũta.", + "welcome_subtitle_restore_wallet": "Ereko ramo peteĩ billetera oĩmava regueruséva Cake-pe, eiporavónte Restore Existing Wallet ha rohechaukáta ndéve mba'éichapa.", "welcome_to_cakepay": "¡Eg̃uahẽporãite Cake Pay-pe!", + "what_is_payjoin": "¿Mba'épa Payjoin?", "what_is_silent_payments": "¿Mbaʼépa hína Jehepymeʼẽ Kirirĩva?", "whats_new": "Mba’e pyahu", "widgets_address": "Dirección", @@ -1152,11 +1444,15 @@ "yat_popup_content": "Ko’ág̃a ikatu remondo ha rehupyty cripto Cake Wallet-pe nde Yat rupive, peteĩ poruhára réra mbykymi, emoji rehe oñemopyendáva. Eñangareko ha emohenda ne Yat oimeraẽ ára hag̃ua pe ñemboheko hag̃ua hag̃ua.", "yat_popup_title": "Ikatu emoambue nde wallet kundaharape emoji-pe.", "yes": "Hẽe", + "yes_exit": "Hẽe. Esẽ", "yesterday": "Kuehe", "you_now_have_debit_card": "Koʼág̃a reguereko peteĩ tarjeta débito.", "you_pay": "Nde rehepy", "you_will_get": "Emoambue hag̃ua", + "you_will_receive_estimated_amount": "Rehupytýta (jehaipyre)", "you_will_send": "Emoambue guive", + "youCanGoBackToYourDapp": "Ikatúma rejevy ne dApp-pe", + "your": "Nde", "yy": "YY", "zcash_card_description": "Ndohecháiramo nde saldo completo, Cake Wallet ikatu oñeha’ã ombyaty (sweep) umi fondo umi dirección de cambio interno-gui oiporúva heta billetera.", "zcash_card_dismiss": "Mboyke", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index db0b67879..66f1df52f 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -76,6 +76,7 @@ "approve_tokens": "Amince token", "apps": "Manhajoji", "arbiscan_history": "Tarihin ArbiScan", + "are_you_sure_exit": "Kun tabbata kuna so ku fita?", "arrive_in_this_address": "${currency} ${tag} za su iso a wannan adireshin", "ascending": "Hawa", "ask_each_time": "Tambaya kowane lokaci", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Samar da adireshi ta atomatik", "auto_generate_subaddresses": "Ƙirƙiri ƙananan adireshi ta atomatik", "automatic": "Atomatik", + "available": "Akwai", "available_balance": "Ma’aunin da ake da shi", "available_balance_description": "“Ma'aunin da ake da shi” ko “Tabbataccen Ma'auni” su ne kuɗaɗen da za a iya kashewa nan take. Idan kuɗaɗe sun bayyana a ƙananan ma'auni amma ba a babban ma'auni ba, to dole ne ku jira 'yan mintoci kaɗan domin kuɗaɗen da ke shigowa su sami ƙarin tabbaci daga hanyar sadarwa. Bayan sun sami ƙarin tabbaci, za a iya kashe su.", "avg_savings": "Matsakaitan Ajiya", @@ -125,6 +127,7 @@ "block_remaining": "Toshe 1 ya rage", "Blocks_remaining": "${status} Tubalan da suka rage", "bluetooth": "Bluetooth", + "bridging": "Ana gada", "bright_theme": "Haske", "bscscan_history": "Tarihin BSCScan", "bump_fee": "Ƙara kuɗin ma'amala", @@ -216,6 +219,8 @@ "color_theme": "Jigon launi", "coming_soon_tag": "Zai zo nan ba da jimawa ba", "commit_transaction_amount_fee": "Tabbatar da ma'amala\nAdadi: ${amount}\nKuɗi: ${fee}", + "compatible_services": "Sabis masu jituwa", + "compatible_services_desc": "Yi amfani da kayan aikin Scan don karanta nau'ikan QR code masu zuwa da Cake Wallet ke goyon baya:", "configure": "Saita", "confirm": "Tabbatar", "confirm_delete_template": "Wannan aikin zai goge wannan samfuri. Kuna so ku ci gaba?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Ana ƙirƙirar sabon walat", "creating_new_wallet_error": "Kuskure: ${description}", "creation_date": "Ranar ƙirƙira", + "crypto_addresses": "Adiresoshin crypto", "csv_nothing_to_export": "Babu abin da za a fitar", "current_swap": "Musayar Yanzu", "current_wallet": "Walit na yanzu", @@ -301,6 +307,7 @@ "default_sell_provider": "Mai Ba da Sabis na Siyarwa na Tsoho", "delete": "Sharewa", "delete_account": "Share Account", + "delete_this_node": "Share wannan node", "delete_wallet": "Share walat", "delete_wallet_confirm_message": "Shin kun tabbata cewa kuna son goge walat ɗin ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Shin kun tabbata kuna son share haɗin zuwa", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO stablecoin ne mai cikakken rarrabawa (decentralized) kuma mai jingina (collateralized) da aka daure shi da Yuro — amintacce, mai sassauci, kuma mai jurewa takunkumi ba tare da dogaro da oracles ba. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Don kunna dEURO, dole ne ka kasance da ETH a cikin walat ɗinka.", "deuro_tx_commited_content": "Yana iya ɗaukar 'yan daƙiƙu kaɗan kafin ma'amalar ta tabbatar kuma ta bayyana a allon", + "device_confirmation": "Tabbatarwa ta na'ura", "device_is_signing": "Na'urar tana sa hannu", "dfx_option_description": "Sayi crypto da EUR & CHF. Don abokan cinikin dillalai da na kamfanoni a Turai", "did_you_back_up_seeds": "Ka adana dukkan seed ɗinka?", @@ -466,6 +474,8 @@ "extracted_address_content": "Za ka tura kuɗi zuwa\n${recipient_name}", "failed_authentication": "An kasa tantancewa. ${state_error}", "faq": "FAQ", + "favorite_token": "Token da aka fi so", + "favorite_token_desc": "Ma'aunin token da aka fi so zai bayyana a katin ma'auni.", "features": "Fasali", "fee": "Kuɗi", "fee_less_than_min": "Kudin da aka zaɓa ya yi ƙasa da mafi ƙarancin kuɗin ma'amala, don Allah ƙara kuɗin ma'amala domin a iya aika ma'amalar.", @@ -491,6 +501,7 @@ "frozen": "Daskare", "frozen_balance": "Ma'aunin da aka daskare", "full_balance": "Cikakken Ma’auni", + "gallery": "Hoton gallery", "gas_exceeds_allowance": "Gas da ake buƙata don ma'amalar ya wuce adadin da aka amince.", "gas_price": "Farashin gas", "general": "Gabaɗaya", @@ -526,6 +537,7 @@ "how_to_connect": "Yadda ake Haɗawa", "how_to_use": "Yadda ake amfani da shi", "how_to_use_card": "Yadda ake amfani da wannan kati", + "hww_exit_desc": "Wannan zai kawo ƙarshen aikin haɗawa (pairing) da ke gudana da na'urarka ta hardware", "i_understand": "Na fahimta", "icon_style": "Salon icon", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Adireshin karɓar ku zai canza duk lokacin da kuka karɓi ma'amala", "infobox_multichain": "Yi amfani da wannan adireshin don karɓar kowace token ko collectible a", "infobox_rotation": "Adireshin karɓar ku zai canza duk lokacin da kuka rufe sannan ku sake buɗe wannan allon", + "input": "Shigarwa", "inputs": "Shigarwa", "insufficient_funds_for_tx": "Ba a da isasshen kuɗi don kammala ma'amala cikin nasara.", "insufficient_lamport_for_tx": "Ba ku da isasshen SOL don rufe ma'amalar da kuɗin ma'amalarta. Da fatan za ku ƙara SOL a walat ɗinku ko ku rage adadin SOL da kuke aikawa.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Sarrafa nododin PoW", "manage_providers": "Sarrafa masu ba da sabis", "manage_yats": "Sarrafa Yats ɗinka", + "manual_input": "Shigarwa da hannu", "mark_as_redeemed": "Yi Alama a Matsayin An Fansa", "market_place": "Kasuwa", "mask": "Ɓoye", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Duk sabbin samfura (GPT-5.3, Claude 4.6).\nBabu biyan kuɗin rajista, biya da crypto.", "narrow": "Kunkuntar", "network": "Hanyar sadarwa", + "networks": "Hanyoyin sadarwa", "new_first_wallet_text": "Kare kuɗin crypto ɗinka cikin aminci abu ne mai sauƙi", "new_node_testing": "Gwajin sabon node", "new_subaddress_create": "Ƙirƙira", @@ -678,8 +693,10 @@ "node_new": "Sabon Node", "node_port": "Tashar node", "node_reset_settings_title": "Sake saiti", + "node_share_desc": "Duba wannan QR code daga allon Scan don shigo da wannan node.", "node_test": "Gwaji", "nodes": "Nododi", + "nodes_desc": "Sarrafa nododi da ke akwai ko ƙara naka na musamman.", "nodes_list_reset_to_default_message": "Kuna da tabbacin kuna so ku mayar da saituna zuwa tsoho?", "none_of_selected_providers_can_exchange": "Babu ɗaya daga cikin masu ba da sabis da aka zaɓa da zai iya yin wannan musayar", "noNFTYet": "Babu NFT tukuna", @@ -689,6 +706,7 @@ "note_tap_to_change": "Bayanan kula (taɓa don canjawa)", "notification_permission_denied": "An ƙi ba da izinin sanarwa har abada, don Allah ka kunna shi da hannu a cikin saituna", "nullURIError": "URI ba shi da komai", + "ocp_desc": "Biya da crypto a shaguna", "offer_expires_in": "Tayin zai ƙare a: ", "offline": "Ba ya kan layi", "ok": "OK", @@ -717,8 +735,13 @@ "outputs": "Fitarwa", "overshot": "Overshot", "overwrite_amount": "Maye gurbin adadi", + "pairing_code": "Lambar haɗawa (pairing)", + "pairing_code_desc_1": "Na'urarka za ta nuna lambar haɗawa (pairing).", + "pairing_code_desc_2": "Shigar da ita a nan don ci gaba", + "pairing_error": "Kuskuren haɗawa (pairing)", "pairingInvalidEvent": "Taron Haɗawa mara inganci", "passphrase": "Passphrase (Zaɓi)", + "passphrase_view_keys": "Passphrase", "passphrases_doesnt_match": "Passphrases ba su dace ba, don Allah a sake gwadawa", "password": "Kalmar sirri", "paste": "Manna", @@ -734,6 +757,7 @@ "payjoin_unavailable_sheet_content": "Karɓar ma'amalar Payjoin yana buƙatar ka/ki kasance da Bitcoin a shirye don amfani.\n\nDa zarar walat ɗinka/ɗinki yana da kuɗi, Payjoin za a kunna ta atomatik.", "payjoin_unavailable_sheet_title": "Me yasa Payjoin ba ya samuwa?", "payment_id": "ID na biyan kuɗi: ", + "payment_invoices": "Daftarin biyan kuɗi", "payment_made_easy": "An sauƙaƙa biyan kuɗi", "payment_was_received": "An karɓi biyan ku.", "payments": "Biyan kuɗi", @@ -889,6 +913,7 @@ "save": "Ajiye", "save_backup_password": "Da fatan a tabbatar kun adana kalmar sirrin ajiyar ku. Ba za ku iya shigo da fayilolin ajiyar ku ba tare da ita ba.", "save_backup_password_alert": "Ajiye kalmar sirrin ajiyar baya", + "save_contact": "Ajiye Tuntuɓa", "save_to_downloads": "Ajiye zuwa Fayilolin da aka zazzage", "saved_the_trade_id": "Na ajiye ID na ciniki", "savings": "Ajiya", @@ -1038,6 +1063,7 @@ "setup_your_debit_card": "Saita katin cire kuɗinka", "share": "Raba", "share_address": "Raba adireshi", + "share_this_node": "Raba wannan node", "shared_seed_wallet_groups": "Ƙungiyoyin Walat na Iri ɗaya da aka Raba", "shared_seed_wallets": "Wallets Masu Seed da Aka Raba", "show": "Nuna", @@ -1045,6 +1071,7 @@ "show_balance": "Danna ka riƙe don nuna ma'auni", "show_balance_send_page": "Taɓa don bayyana", "show_balance_toast": "Danna ka riƙe don ɓoye ko nuna ma'auni", + "show_combined_balance": "Nuna haɗaɗɗen ma'auni", "show_details": "Nuna Cikakkun Bayani", "show_hidden_addresses": "Nuna adiresoshin da aka ɓoye", "show_keys": "Nuna seed/maɓallai", @@ -1110,6 +1137,7 @@ "swap_providers": "Masu samar da Swap", "sweeping_wallet": "Ana kwashe kuɗi daga walat", "sweeping_wallet_alert": "Wannan bai kamata ya ɗauki lokaci mai tsawo ba. KADA KA BAR WANNAN ALLON KO KUDADEN DA AKA KWASO NA IYA ɓACEWA.", + "swipe_to_bridge": "Zame don gada", "swipe_to_send": "Zame don aikawa", "switch_wallet": "Canja Wallet", "switchToETHWallet": "Da fatan za a koma zuwa walat ɗin Ethereum kuma a sake gwadawa", @@ -1150,6 +1178,7 @@ "testnet_coins_no_value": "Tsabar kuɗin Testnet ba su da daraja", "third_intro_content": "Yats suna aiki a wajen Cake Wallet ma. Ana iya maye gurbin kowane adireshin walat a duniya da Yat!", "third_intro_title": "Yat yana aiki da kyau tare da wasu", + "this_can_take_few_seconds": "Wannan na iya ɗaukar 'yan daƙiƙu kaɗan", "this_pair_is_not_supported_warning": "Ba a tallafa wa wannan ma'aurata a musayar(ori) da aka zaɓa a yanzu ba. Da fatan za a zaɓi wata musaya.", "thorchain_contract_address_not_supported": "THORChain ba ya goyon bayan aika zuwa adireshin kwangila", "thorchain_taproot_address_not_supported": "Mai ba da sabis na ThorChain ba ya goyon bayan adiresoshin Taproot. Da fatan za a canza adireshin ko a zaɓi wani mai ba da sabis daban.", @@ -1163,6 +1192,7 @@ "token_decimal": "Adadin decimal na token (misali: USDT)", "token_name": "Sunan token (misali: Tether)", "token_symbol": "Alamar token (misali: USDT)", + "token_verified_on_jupiter": "An tabbatar da wannan alamar akan Jupiter", "tokenID": "ID", "tokens": "Token", "tokens_strong_warning": "Kada ka taɓa aika token zuwa wannan adireshin!", @@ -1291,6 +1321,7 @@ "username": "Sunan mai amfani", "username_available": "Sunan mai amfani yana samuwa", "username_character_error": "Sunayen masu amfani dole ne su ƙunshi kawai", + "username_check_your_network": "An kasa duba sunan mai amfani. Da fatan za a duba haɗin cibiyar sadarwarka.", "username_length_error": "Dole sunayen masu amfani su ƙunshi haruffa da lambobi 6-32.", "username_length_error_1_64": "Dole ne sunayen masu amfani su ƙunshi haruffa da lambobi 1-64.", "username_not_available": "Wannan sunan mai amfani ba ya samuwa.", @@ -1301,6 +1332,7 @@ "verify_message": "Tabbatar da Saƙo", "verify_seed": "Tabbatar da Seed", "verify_with_2fa": "Tabbatar da Cake 2FA", + "verifying_code": "Ana tabbatar da lamba", "version": "Sigar ${currentVersion}", "view_all": "Duba duk", "view_in_block_explorer": "Duba a Block Explorer", @@ -1312,6 +1344,7 @@ "waitFewSecondForTxUpdate": "Da fatan za a jira ƴan daƙiƙa kaɗan domin ma'amalar ta bayyana a tarihin ma'amaloli", "wallet": "Walati", "wallet_accounts": "Asusun Walat", + "wallet_balance": "Ma'aunin walat", "wallet_group": "Rukunin Wallet", "wallet_group_description_existing_seed": "Ka zaɓi amfani da seed da ke akwai don wannan Wallet. Za ka iya sake tabbatar da seed ɗin idan kana buƙatar tabbatarwa ko rubuta shi.", "wallet_group_description_four": "don ƙirƙirar walat tare da sabon iri gaba ɗaya.", @@ -1353,6 +1386,7 @@ "wc_approve_request_title": "Amincewa da buƙata", "wc_connect_request_title": "Buƙatar haɗin kai", "wc_connected_to": "An haɗa zuwa ${name}", + "wc_desc": "Haɗa da DApps cikin sauƙi", "wc_max_network_fee": "Matsakaicin kuɗin hanyar sadarwa", "wc_message_to_sign": "Saƙo don sa hannu", "wc_network_fee": "Kudin hanyar sadarwa", @@ -1404,6 +1438,7 @@ "yat_popup_content": "Yanzu za ku iya aikawa da karɓar crypto a cikin Cake Wallet ta amfani da Yat ɗinku — gajeren sunan mai amfani na emoji. Kuna iya sarrafa Yats a kowane lokaci a allon saituna", "yat_popup_title": "Ana iya mayar da adireshin walat ɗinka zuwa emojis.", "yes": "Eh", + "yes_exit": "Eh. Fita", "yesterday": "Jiya", "you_now_have_debit_card": "Yanzu kana da katin zare kudi", "you_pay": "Ka Biya", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 413a19131..08a42cecc 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -76,6 +76,7 @@ "approve_tokens": "टोकन अनुमोदित करें", "apps": "ऐप्स", "arbiscan_history": "ArbiScan इतिहास", + "are_you_sure_exit": "क्या आप वाकई बाहर निकलना चाहते हैं?", "arrive_in_this_address": "${currency} ${tag} इस पते पर आएंगे", "ascending": "आरोही क्रम", "ask_each_time": "हर बार पूछें", @@ -89,6 +90,7 @@ "auto_generate_addresses": "पते स्वतः जनरेट करें", "auto_generate_subaddresses": "उप-पते स्वतः जनरेट करें", "automatic": "स्वचालित", + "available": "उपलब्ध", "available_balance": "उपलब्ध शेष राशि", "available_balance_description": "“Available Balance” या “Confirmed Balance” वे धनराशि हैं जिन्हें तुरंत खर्च किया जा सकता है। यदि फंड नीचे वाले बैलेंस में दिखाई देते हैं, लेकिन ऊपर वाले बैलेंस में नहीं, तो आने वाले फंड को नेटवर्क पर और अधिक पुष्टिकरण मिलने के लिए आपको कुछ मिनट इंतज़ार करना होगा। अधिक पुष्टिकरण मिलने के बाद, वे खर्च करने योग्य हो जाएंगे।", "avg_savings": "औसत बचत", @@ -125,6 +127,7 @@ "block_remaining": "1 ब्लॉक शेष", "Blocks_remaining": "${status} ब्लॉक शेष", "bluetooth": "ब्लूटूथ", + "bridging": "ब्रिजिंग", "bright_theme": "उज्ज्वल", "bscscan_history": "BSCScan इतिहास", "bump_fee": "फीस बढ़ाएँ", @@ -216,6 +219,8 @@ "color_theme": "रंग थीम", "coming_soon_tag": "जल्द आ रहा है", "commit_transaction_amount_fee": "लेन-देन कमिट करें\nराशि: ${amount}\nशुल्क: ${fee}", + "compatible_services": "संगत सेवाएँ", + "compatible_services_desc": "Cake Wallet पर समर्थित निम्न प्रकार के QR कोड पढ़ने के लिए स्कैन टूल का उपयोग करें:", "configure": "कॉन्फ़िगर करें", "confirm": "पुष्टि करें", "confirm_delete_template": "यह कार्रवाई इस टेम्पलेट को हटा देगी। क्या आप जारी रखना चाहते हैं?", @@ -279,6 +284,7 @@ "creating_new_wallet": "नया वॉलेट बनाया जा रहा है", "creating_new_wallet_error": "त्रुटि: ${description}", "creation_date": "निर्माण तिथि", + "crypto_addresses": "क्रिप्टो पते", "csv_nothing_to_export": "निर्यात करने के लिए कुछ नहीं है", "current_swap": "वर्तमान स्वैप", "current_wallet": "वर्तमान वॉलेट", @@ -301,6 +307,7 @@ "default_sell_provider": "डिफ़ॉल्ट सेल प्रदाता", "delete": "हटाएं", "delete_account": "खाता हटाएँ", + "delete_this_node": "इस नोड को हटाएँ", "delete_wallet": "वॉलेट हटाएँ", "delete_wallet_confirm_message": "क्या आप वाकई ${wallet_name} वॉलेट को हटाना चाहते हैं?", "deleteConnectionConfirmationPrompt": "क्या आप वाकई इसके साथ कनेक्शन हटाना चाहते हैं", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO एक पूरी तरह से विकेंद्रीकृत, संपार्श्विक-समर्थित स्टेबलकॉइन है जो यूरो से पेग्ड है — सुरक्षित, बहुमुखी और सेंसरशिप-प्रतिरोधी, और इसके लिए oracles पर निर्भर होने की ज़रूरत नहीं होती। 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "dEURO को सक्षम करने के लिए, आपके वॉलेट में ETH होना चाहिए।", "deuro_tx_commited_content": "लेन-देन की पुष्टि होने और स्क्रीन पर दिखाई देने में कुछ सेकंड लग सकते हैं", + "device_confirmation": "डिवाइस पुष्टिकरण", "device_is_signing": "डिवाइस साइन कर रहा है", "dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए", "did_you_back_up_seeds": "क्या आपने अपने सभी सीड्स का बैकअप ले लिया?", @@ -466,6 +474,8 @@ "extracted_address_content": "आप निम्न को धनराशि भेजेंगे\n${recipient_name}", "failed_authentication": "प्रमाणीकरण विफल रहा। ${state_error}", "faq": "FAQ", + "favorite_token": "पसंदीदा टोकन", + "favorite_token_desc": "पसंदीदा टोकन का बैलेंस बैलेंस कार्ड पर दिखाई देगा।", "features": "विशेषताएँ", "fee": "फीस", "fee_less_than_min": "चयनित शुल्क न्यूनतम से कम है, कृपया लेन-देन भेजने के लिए शुल्क बढ़ाएँ", @@ -491,6 +501,7 @@ "frozen": "फ्रीज़", "frozen_balance": "फ्रीज़ किया गया बैलेंस", "full_balance": "कुल शेष राशि", + "gallery": "गैलरी", "gas_exceeds_allowance": "लेनदेन के लिए आवश्यक गैस अनुमत सीमा से अधिक है।", "gas_price": "गैस मूल्य", "general": "सामान्य", @@ -526,6 +537,7 @@ "how_to_connect": "कनेक्ट कैसे करें", "how_to_use": "कैसे उपयोग करें", "how_to_use_card": "इस कार्ड का उपयोग कैसे करें", + "hww_exit_desc": "इससे आपके हार्डवेयर डिवाइस के साथ चल रही पेयरिंग प्रक्रिया समाप्त हो जाएगी", "i_understand": "मैं समझता/समझती हूँ", "icon_style": "चिह्न शैली", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "हर बार जब आप कोई लेन-देन प्राप्त करेंगे, आपका प्राप्ति पता बदल जाएगा", "infobox_multichain": "किसी भी टोकन या संग्रहणीय वस्तु को प्राप्त करने के लिए इस पते का उपयोग करें", "infobox_rotation": "जब भी आप इस स्क्रीन को बंद करके दोबारा खोलेंगे, आपका प्राप्ति पता बदल जाएगा", + "input": "इनपुट", "inputs": "इनपुट", "insufficient_funds_for_tx": "लेनदेन को सफलतापूर्वक निष्पादित करने के लिए अपर्याप्त धनराशि।", "insufficient_lamport_for_tx": "आपके पास लेनदेन और उसके शुल्क को कवर करने के लिए पर्याप्त SOL नहीं है। कृपया अपने वॉलेट में और SOL जोड़ें या आप जितनी SOL भेज रहे हैं, वह राशि कम करें।", @@ -605,6 +618,7 @@ "manage_pow_nodes": "PoW नोड प्रबंधित करें", "manage_providers": "प्रोवाइडर्स प्रबंधित करें", "manage_yats": "Yats मैनेज करें", + "manual_input": "मैन्युअल इनपुट", "mark_as_redeemed": "रिडीम के रूप में चिह्नित करें", "market_place": "मार्केटप्लेस", "mask": "मास्क", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "सभी नवीनतम मॉडल (GPT-5.3, Claude 4.6)।\nकोई सब्सक्रिप्शन नहीं, क्रिप्टो से भुगतान करें।", "narrow": "संकीर्ण", "network": "नेटवर्क", + "networks": "नेटवर्क", "new_first_wallet_text": "अपने क्रिप्टो को सुरक्षित रखना बहुत आसान है", "new_node_testing": "नए नोड का परीक्षण", "new_subaddress_create": "बनाएँ", @@ -678,8 +693,10 @@ "node_new": "नया नोड", "node_port": "नोड पोर्ट", "node_reset_settings_title": "सेटिंग्स रीसेट करें", + "node_share_desc": "इस नोड को आयात करने के लिए स्कैन स्क्रीन से इस QR कोड को स्कैन करें।", "node_test": "टेस्ट", "nodes": "नोड्स", + "nodes_desc": "मौजूदा नोड्स प्रबंधित करें या एक कस्टम नोड जोड़ें।", "nodes_list_reset_to_default_message": "क्या आप वाकई सेटिंग्स को डिफ़ॉल्ट पर रीसेट करना चाहते हैं?", "none_of_selected_providers_can_exchange": "चयनित प्रदाताओं में से कोई भी यह स्वैप नहीं कर सकता", "noNFTYet": "अभी तक कोई NFT नहीं", @@ -689,6 +706,7 @@ "note_tap_to_change": "नोट (बदलने के लिए टैप करें)", "notification_permission_denied": "अधिसूचना की अनुमति स्थायी रूप से अस्वीकार कर दी गई है, कृपया इसे सेटिंग्स में जाकर मैन्युअल रूप से सक्षम करें", "nullURIError": "URI शून्य है", + "ocp_desc": "स्टोर में क्रिप्टो से भुगतान करें", "offer_expires_in": "ऑफ़र की समय-सीमा समाप्त होने में: ", "offline": "ऑफ़लाइन", "ok": "ठीक है", @@ -715,8 +733,13 @@ "outputs": "आउटपुट", "overshot": "लक्ष्य से अधिक हो गया", "overwrite_amount": "राशि ओवरराइट करें", + "pairing_code": "पेयरिंग कोड", + "pairing_code_desc_1": "आपका डिवाइस एक पेयरिंग कोड दिखाएगा।", + "pairing_code_desc_2": "जारी रखने के लिए यहाँ दर्ज करें", + "pairing_error": "पेयरिंग त्रुटि", "pairingInvalidEvent": "अमान्य पेयरिंग इवेंट", "passphrase": "पासफ़्रेज़ (वैकल्पिक)", + "passphrase_view_keys": "पासफ़्रेज़", "passphrases_doesnt_match": "Passphrase मेल नहीं खाते, कृपया फिर से प्रयास करें", "password": "पासवर्ड", "paste": "पेस्ट करें", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Payjoin लेन-देन प्राप्त करने के लिए आपके पास उपयोग के लिए तैयार Bitcoin होना आवश्यक है।\n\nजैसे ही आपके वॉलेट में फंड होंगे, Payjoin अपने-आप सक्षम हो जाएगा।", "payjoin_unavailable_sheet_title": "Payjoin उपलब्ध क्यों नहीं है?", "payment_id": "भुगतान आईडी: ", + "payment_invoices": "भुगतान इनवॉइस", "payment_made_easy": "भुगतान करना आसान", "payment_was_received": "आपका भुगतान प्राप्त हो गया।", "Payment_was_received": "आपका भुगतान प्राप्त हो गया था।", @@ -889,6 +913,7 @@ "save": "सहेजें", "save_backup_password": "कृपया सुनिश्चित करें कि आपने अपना बैकअप पासवर्ड सहेज लिया है। इसके बिना आप अपनी बैकअप फ़ाइलें आयात नहीं कर पाएंगे।", "save_backup_password_alert": "बैकअप पासवर्ड सहेजें", + "save_contact": "संपर्क सहेजें", "save_to_downloads": "डाउनलोड में सहेजें", "saved_the_trade_id": "मैंने ट्रेड ID सेव कर ली है", "savings": "बचत", @@ -1038,6 +1063,7 @@ "setup_your_debit_card": "अपना डेबिट कार्ड सेट अप करें", "share": "शेयर करें", "share_address": "पता साझा करें", + "share_this_node": "इस नोड को साझा करें", "shared_seed_wallet_groups": "साझा सीड वॉलेट समूह", "shared_seed_wallets": "साझा सीड वॉलेट", "show": "दिखाएँ", @@ -1045,6 +1071,7 @@ "show_balance": "बैलेंस दिखाने के लिए देर तक दबाएँ", "show_balance_send_page": "दिखाने के लिए टैप करें", "show_balance_toast": "बैलेंस छिपाने या दिखाने के लिए लंबे समय तक दबाएं", + "show_combined_balance": "संयुक्त बैलेंस दिखाएँ", "show_details": "विवरण दिखाएँ", "show_hidden_addresses": "छिपे हुए पते दिखाएँ", "show_keys": "सीड/कुंजियाँ दिखाएँ", @@ -1110,6 +1137,7 @@ "swap_providers": "स्वैप प्रदाता", "sweeping_wallet": "वॉलेट स्वीप करना", "sweeping_wallet_alert": "इसमें ज़्यादा समय नहीं लगना चाहिए। इस स्क्रीन को न छोड़ें, वरना स्वीप किए गए फंड खो सकते हैं।", + "swipe_to_bridge": "ब्रिज करने के लिए स्वाइप करें", "swipe_to_send": "भेजने के लिए स्वाइप करें", "switch_wallet": "वॉलेट बदलें", "switchToETHWallet": "कृपया Ethereum वॉलेट पर स्विच करें और फिर से प्रयास करें", @@ -1150,6 +1178,7 @@ "testnet_coins_no_value": "टेस्टनेट कॉइन्स का कोई मूल्य नहीं है", "third_intro_content": "Yats, Cake Wallet के बाहर भी मौजूद हैं। दुनिया के किसी भी वॉलेट पते को Yat से बदला जा सकता है!", "third_intro_title": "Yat दूसरों के साथ अच्छी तरह काम करता है", + "this_can_take_few_seconds": "इसमें कुछ सेकंड लग सकते हैं", "this_pair_is_not_supported_warning": "यह जोड़ी वर्तमान में चयनित एक्सचेंज(ों) के साथ समर्थित नहीं है। कृपया कोई अन्य एक्सचेंज चुनें।", "thorchain_contract_address_not_supported": "THORChain कॉन्ट्रैक्ट पते पर भेजने का समर्थन नहीं करता है", "thorchain_taproot_address_not_supported": "ThorChain प्रदाता Taproot पतों का समर्थन नहीं करता है। कृपया पता बदलें या कोई अन्य प्रदाता चुनें।", @@ -1163,6 +1192,7 @@ "token_decimal": "टोकन दशमलव (उदा: USDT)", "token_name": "टोकन का नाम (उदाहरण: Tether)", "token_symbol": "टोकन प्रतीक (उदा.: USDT)", + "token_verified_on_jupiter": "यह टोकन Jupiter पर सत्यापित है", "tokenID": "आईडी", "tokens": "टोकन", "tokens_strong_warning": "इस पते पर कभी भी टोकन न भेजें!", @@ -1291,6 +1321,7 @@ "username": "उपयोगकर्ता नाम", "username_available": "उपयोगकर्ता नाम उपलब्ध है", "username_character_error": "यूज़रनेम में केवल शामिल हो सकते हैं", + "username_check_your_network": "उपयोगकर्ता नाम जाँचने में असमर्थ। कृपया अपना नेटवर्क कनेक्शन जाँचें।", "username_length_error": "उपयोगकर्ता नाम में 6-32 अल्फ़ान्यूमेरिक वर्ण होने चाहिए।", "username_length_error_1_64": "उपयोगकर्ता नाम में 1-64 अल्फ़ान्यूमेरिक वर्ण होने चाहिए।", "username_not_available": "यह उपयोगकर्ता नाम उपलब्ध नहीं है।", @@ -1301,6 +1332,7 @@ "verify_message": "संदेश सत्यापित करें", "verify_seed": "सीड सत्यापित करें", "verify_with_2fa": "Cake 2FA के साथ सत्यापित करें", + "verifying_code": "कोड सत्यापित किया जा रहा है", "version": "संस्करण ${currentVersion}", "view_all": "सभी देखें", "view_in_block_explorer": "ब्लॉक एक्सप्लोरर में देखें", @@ -1312,6 +1344,7 @@ "waitFewSecondForTxUpdate": "कृपया लेन-देन इतिहास में लेन-देन दिखने के लिए कुछ सेकंड प्रतीक्षा करें", "wallet": "वॉलेट", "wallet_accounts": "वॉलेट खाते", + "wallet_balance": "वॉलेट बैलेंस", "wallet_group": "वॉलेट समूह", "wallet_group_description_existing_seed": "आपने इस वॉलेट के लिए मौजूदा सीड का उपयोग करना चुना है। यदि आपको पुष्टि करने या लिखने के लिए इसकी आवश्यकता हो, तो आप सीड को फिर से सत्यापित कर सकते हैं।", "wallet_group_description_four": "पूरी तरह नए सीड के साथ वॉलेट बनाने के लिए।", @@ -1353,6 +1386,7 @@ "wc_approve_request_title": "अनुरोध स्वीकृत करें", "wc_connect_request_title": "कनेक्ट अनुरोध", "wc_connected_to": "${name} से कनेक्टेड", + "wc_desc": "DApps से आसानी से कनेक्ट करें", "wc_max_network_fee": "अधिकतम नेटवर्क शुल्क", "wc_message_to_sign": "हस्ताक्षर करने के लिए संदेश", "wc_network_fee": "नेटवर्क शुल्क", @@ -1403,6 +1437,7 @@ "yat_popup_content": "अब आप Cake Wallet में अपने Yat—एक छोटा, इमोजी-आधारित उपयोगकर्ता नाम—के साथ क्रिप्टो भेज और प्राप्त कर सकते हैं। सेटिंग्स स्क्रीन पर किसी भी समय Yats को प्रबंधित करें", "yat_popup_title": "आपका वॉलेट पता इमोजी में बदला जा सकता है।", "yes": "हाँ", + "yes_exit": "हाँ। बाहर निकलें", "yesterday": "कल", "you_now_have_debit_card": "अब आपके पास एक डेबिट कार्ड है", "you_pay": "आप भुगतान करते हैं", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 11a9ffe88..6771d0833 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -76,6 +76,7 @@ "approve_tokens": "Odobri tokene", "apps": "Aplikacije", "arbiscan_history": "Povijest na ArbiScanu", + "are_you_sure_exit": "Jeste li sigurni da želite izaći?", "arrive_in_this_address": "${currency} ${tag}će stići na ovu adresu", "ascending": "Uzlazno", "ask_each_time": "Pitaj svaki put", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Automatsko generiranje adresa", "auto_generate_subaddresses": "Automatski generiraj podadrese", "automatic": "Automatski", + "available": "Dostupno", "available_balance": "Raspoloživo stanje", "available_balance_description": "“Dostupno stanje” ili “Potvrđeno stanje” su sredstva koja možete odmah potrošiti. Ako se sredstva prikazuju u donjem stanju, ali ne i u gornjem, morate pričekati nekoliko minuta da dolazna sredstva dobiju više mrežnih potvrda. Nakon što dobiju više potvrda, moći ćete ih potrošiti.", "avg_savings": "Prosj. ušteda", @@ -125,6 +127,7 @@ "block_remaining": "Preostao je 1 blok", "Blocks_remaining": "${status} preostalih blokova", "bluetooth": "Bluetooth", + "bridging": "Premošćivanje", "bright_theme": "Svijetla", "bscscan_history": "Povijest BSCScan-a", "bump_fee": "Povećaj naknadu", @@ -216,6 +219,8 @@ "color_theme": "Tema boja", "coming_soon_tag": "Uskoro", "commit_transaction_amount_fee": "Potvrdi transakciju\nIznos: ${amount}\nNaknada: ${fee}", + "compatible_services": "Kompatibilne usluge", + "compatible_services_desc": "Upotrijebite alat Skeniraj za čitanje sljedećih vrsta QR kodova podržanih u Cake Walletu:", "configure": "Konfiguriraj", "confirm": "Potvrdi", "confirm_delete_template": "Ovom radnjom izbrisat ćete ovaj predložak. Želite li nastaviti?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Stvaranje novog novčanika", "creating_new_wallet_error": "Greška: ${description}", "creation_date": "Datum izrade", + "crypto_addresses": "Kripto adrese", "csv_nothing_to_export": "Nema ničega za izvoz", "current_swap": "Trenutna zamjena", "current_wallet": "Trenutni novčanik", @@ -301,6 +307,7 @@ "default_sell_provider": "Zadani pružatelj usluge prodaje", "delete": "Izbriši", "delete_account": "Izbriši račun", + "delete_this_node": "Izbriši ovaj čvor", "delete_wallet": "Izbriši novčanik", "delete_wallet_confirm_message": "Jeste li sigurni da želite izbrisati novčanik ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Jeste li sigurni da želite izbrisati vezu s", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO je potpuno decentralizirani, kolateralizirani stablecoin vezan uz euro — siguran, svestran i otporan na cenzuru, bez potrebe oslanjanja na orakle. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Da biste omogućili dEURO, morate imati ETH u svom novčaniku.", "deuro_tx_commited_content": "Može potrajati nekoliko sekundi da se transakcija potvrdi i prikaže na zaslonu", + "device_confirmation": "Potvrda uređaja", "device_is_signing": "Uređaj potpisuje", "dfx_option_description": "Kupite kriptovalute uz EUR i CHF. Za maloprodajne i korporativne kupce u Europi", "did_you_back_up_seeds": "Jeste li sigurnosno kopirali sve svoje seed fraze?", @@ -466,6 +474,8 @@ "extracted_address_content": "Poslat ćete sredstva na\n${recipient_name}", "failed_authentication": "Neuspješna autentifikacija. ${state_error}", "faq": "FAQ", + "favorite_token": "Omiljeni token", + "favorite_token_desc": "Stanje omiljenog tokena prikazat će se na kartici stanja.", "features": "Značajke", "fee": "Naknada", "fee_less_than_min": "Odabrana naknada je manja od minimalne, povećajte naknadu kako biste mogli poslati transakciju", @@ -491,6 +501,7 @@ "frozen": "Zamrznuto", "frozen_balance": "Zamrznuto stanje", "full_balance": "Puni saldo", + "gallery": "Galerija", "gas_exceeds_allowance": "Gas potreban za transakciju premašuje dopušteni iznos.", "gas_price": "Cijena gasa", "general": "Općenito", @@ -526,6 +537,7 @@ "how_to_connect": "Kako se povezati", "how_to_use": "Kako koristiti", "how_to_use_card": "Kako koristiti ovu karticu", + "hww_exit_desc": "Ovo će prekinuti tekući postupak uparivanja s vašim hardverskim uređajem", "i_understand": "Razumijem", "icon_style": "Stil ikone", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Vaša adresa za primanje mijenjat će se svaki put kada primite transakciju", "infobox_multichain": "Koristite ovu adresu za primanje bilo kojeg tokena ili kolekcionarskog predmeta na", "infobox_rotation": "Vaša adresa za primanje će se mijenjati svaki put kada zatvorite i ponovno otvorite ovaj zaslon", + "input": "Unos", "inputs": "Ulazi", "insufficient_funds_for_tx": "Nedovoljno sredstava za uspješno izvršenje transakcije.", "insufficient_lamport_for_tx": "Nemate dovoljno SOL-a za pokrivanje transakcije i transakcijske naknade. Dodajte više SOL-a u svoj novčanik ili smanjite iznos SOL-a koji šaljete.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Upravljaj PoW čvorovima", "manage_providers": "Upravljanje pružateljima", "manage_yats": "Upravljanje Yatovima", + "manual_input": "Ručni unos", "mark_as_redeemed": "Označi kao iskorišteno", "market_place": "Tržište", "mask": "Maska", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Svi najnoviji modeli (GPT-5.3, Claude 4.6).\nBez pretplate, plaćajte kriptom.", "narrow": "Usko", "network": "Mreža", + "networks": "Mreže", "new_first_wallet_text": "Čuvanje vaše kriptovalute sigurnom je mačji kašalj", "new_node_testing": "Testiranje novog noda", "new_subaddress_create": "Izradi", @@ -678,8 +693,10 @@ "node_new": "Novi čvor", "node_port": "Port čvora", "node_reset_settings_title": "Ponovno postavi postavke", + "node_share_desc": "Skenirajte ovaj QR kod sa zaslona Skeniraj da biste uvezli ovaj čvor.", "node_test": "Test", "nodes": "Čvorovi", + "nodes_desc": "Upravljajte postojećim čvorovima ili dodajte prilagođeni.", "nodes_list_reset_to_default_message": "Jeste li sigurni da želite vratiti postavke na zadane vrijednosti?", "none_of_selected_providers_can_exchange": "Nijedan od odabranih pružatelja ne može izvršiti ovu zamjenu", "noNFTYet": "Još nema NFT-ova", @@ -689,6 +706,7 @@ "note_tap_to_change": "Napomena (dodirnite za promjenu)", "notification_permission_denied": "Dozvola za obavijesti trajno je odbijena, molimo ručno je omogućite u postavkama", "nullURIError": "URI je null", + "ocp_desc": "Plaćajte kriptovalutom u trgovinama", "offer_expires_in": "Ponuda istječe za: ", "offline": "Izvan mreže", "ok": "OK", @@ -715,8 +733,13 @@ "outputs": "Izlazi", "overshot": "Prekoračeno", "overwrite_amount": "Prepiši iznos", + "pairing_code": "Kod za uparivanje", + "pairing_code_desc_1": "Vaš će uređaj prikazati kod za uparivanje.", + "pairing_code_desc_2": "Unesite ga ovdje za nastavak", + "pairing_error": "Pogreška pri uparivanju", "pairingInvalidEvent": "Nevažeći događaj uparivanja", "passphrase": "Lozinka (neobavezno)", + "passphrase_view_keys": "Lozinka", "passphrases_doesnt_match": "Lozinke se ne podudaraju, pokušajte ponovno", "password": "Lozinka", "paste": "Zalijepi", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Primanje Payjoin transakcije zahtijeva da imate Bitcoin spreman za korištenje.\n\nČim vaš novčanik bude imao sredstva, Payjoin će se automatski omogućiti.", "payjoin_unavailable_sheet_title": "Zašto Payjoin nije dostupan?", "payment_id": "ID plaćanja: ", + "payment_invoices": "Računi za plaćanje", "payment_made_easy": "Plaćanja su jednostavna", "payment_was_received": "Vaša uplata je primljena.", "payments": "Plaćanja", @@ -887,6 +911,7 @@ "save": "Spremi", "save_backup_password": "Molimo provjerite jeste li spremili lozinku za sigurnosnu kopiju. Bez nje nećete moći uvesti svoje datoteke sigurnosne kopije.", "save_backup_password_alert": "Spremi lozinku sigurnosne kopije", + "save_contact": "Spremi kontakt", "save_to_downloads": "Spremi u Preuzimanja", "saved_the_trade_id": "Spremio/la sam ID trgovine", "savings": "Štednja", @@ -1036,6 +1061,7 @@ "setup_your_debit_card": "Postavite svoju debitnu karticu", "share": "Podijeli", "share_address": "Podijeli adresu", + "share_this_node": "Podijeli ovaj čvor", "shared_seed_wallet_groups": "Grupe novčanika sa zajedničkom seed frazom", "shared_seed_wallets": "Novčanici sa zajedničkom seed frazom", "show": "Prikaži", @@ -1043,6 +1069,7 @@ "show_balance": "Dugo pritisnite za prikaz stanja", "show_balance_send_page": "Dodirnite za prikaz", "show_balance_toast": "Dugo pritisnite za skrivanje ili prikaz stanja", + "show_combined_balance": "Prikaži kombinirano stanje", "show_details": "Prikaži detalje", "show_hidden_addresses": "Prikaži skrivene adrese", "show_keys": "Prikaži seed/ključeve", @@ -1108,6 +1135,7 @@ "swap_providers": "Pružatelji usluga zamjene", "sweeping_wallet": "Prebacivanje sredstava u novčanik", "sweeping_wallet_alert": "Ovo ne bi trebalo dugo trajati. NE NAPUŠTAJTE OVAJ ZASLON ILI PREBAČENA SREDSTVA MOGU BITI IZGUBLJENA.", + "swipe_to_bridge": "Prijeđite prstom za premošćivanje", "swipe_to_send": "Prijeđite prstom za slanje", "switch_wallet": "Prebaci novčanik", "switchToETHWallet": "Molimo prebacite se na Ethereum novčanik i pokušajte ponovno", @@ -1148,6 +1176,7 @@ "testnet_coins_no_value": "Testnet kovanice nemaju vrijednost", "third_intro_content": "Yatovi žive i izvan Cake Walleta. Bilo koja adresa novčanika na svijetu može se zamijeniti Yatom!", "third_intro_title": "Yat se dobro slaže s drugima", + "this_can_take_few_seconds": "Ovo može potrajati nekoliko sekundi", "this_pair_is_not_supported_warning": "Ovaj par nije podržan na trenutno odabranoj razmjeni/razmjenama. Molimo odaberite drugu razmjenu.", "thorchain_contract_address_not_supported": "THORChain ne podržava slanje na adresu ugovora", "thorchain_taproot_address_not_supported": "Pružatelj usluge ThorChain ne podržava Taproot adrese. Promijenite adresu ili odaberite drugog pružatelja usluge.", @@ -1161,6 +1190,7 @@ "token_decimal": "Decimalni broj tokena (npr.: USDT)", "token_name": "Naziv tokena (npr.: Tether)", "token_symbol": "Simbol tokena (npr.: USDT)", + "token_verified_on_jupiter": "Ovaj token je verificiran na Jupiteru", "tokenID": "ID", "tokens": "Tokeni", "tokens_strong_warning": "Nikada nemojte slati tokene na ovu adresu!", @@ -1289,6 +1319,7 @@ "username": "Korisničko ime", "username_available": "Korisničko ime je dostupno", "username_character_error": "Korisnička imena smiju sadržavati samo", + "username_check_your_network": "Nije moguće provjeriti korisničko ime. Provjerite mrežnu vezu.", "username_length_error": "Korisnička imena moraju sadržavati 6–32 alfanumerička znaka.", "username_length_error_1_64": "Korisnička imena moraju sadržavati 1–64 alfanumerička znaka.", "username_not_available": "Ovo korisničko ime nije dostupno.", @@ -1299,6 +1330,7 @@ "verify_message": "Potvrdi poruku", "verify_seed": "Potvrdite seed", "verify_with_2fa": "Potvrdite uz Cake 2FA", + "verifying_code": "Provjera koda", "version": "Verzija ${currentVersion}", "view_all": "Prikaži sve", "view_in_block_explorer": "Prikaži u Block Exploreru", @@ -1310,6 +1342,7 @@ "waitFewSecondForTxUpdate": "Pričekajte nekoliko sekundi da se transakcija prikaže u povijesti transakcija.", "wallet": "Novčanik", "wallet_accounts": "Računi u novčaniku", + "wallet_balance": "Stanje novčanika", "wallet_group": "Grupa novčanika", "wallet_group_description_existing_seed": "Odabrali ste koristiti postojeću seed frazu za ovaj novčanik. Možete je ponovno provjeriti ako je trebate potvrditi ili zapisati.", "wallet_group_description_four": "za izradu novčanika s potpuno novom seed frazom.", @@ -1351,6 +1384,7 @@ "wc_approve_request_title": "Odobri zahtjev", "wc_connect_request_title": "Zahtjev za povezivanje", "wc_connected_to": "Povezan s ${name}", + "wc_desc": "Jednostavno se povežite s DApp-ovima", "wc_max_network_fee": "Maksimalna mrežna naknada", "wc_message_to_sign": "Poruka za potpisivanje", "wc_network_fee": "Mrežna naknada", @@ -1401,6 +1435,7 @@ "yat_popup_content": "Sada možete slati i primati kripto u Cake Walletu pomoću svog Yata – kratkog korisničkog imena temeljenog na emojijima. Yatovima možete upravljati u bilo kojem trenutku na zaslonu postavki", "yat_popup_title": "Adresa vašeg novčanika može se pretvoriti u emojije.", "yes": "Da", + "yes_exit": "Da. Izađi", "yesterday": "Jučer", "you_now_have_debit_card": "Sada imate debitnu karticu", "you_pay": "Vi plaćate", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index 0d0c47ef5..34a6fca5d 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -76,6 +76,7 @@ "approve_tokens": "Հաստատել թոքենները", "apps": "Հավելվածներ", "arbiscan_history": "ArbiScan-ի պատմություն", + "are_you_sure_exit": "Վստա՞հ եք, որ ցանկանում եք դուրս գալ։", "arrive_in_this_address": "${currency} ${tag}կհասնի այս հասցեին", "ascending": "Աճման կարգով", "ask_each_time": "Հարցնել ամեն անգամ", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Հասցեների ավտոմատ ստեղծում", "auto_generate_subaddresses": "Ենթահասցեների ավտոմատ ստեղծում", "automatic": "Ավտոմատ", + "available": "Հասանելի", "available_balance": "Հասանելի մնացորդ", "available_balance_description": "«Հասանելի մնացորդը» կամ «Հաստատված մնացորդը» միջոցներ են, որոնք կարելի է անմիջապես ծախսել։ Եթե միջոցները երևում են ստորին մնացորդում, բայց ոչ վերևի մնացորդում, ապա պետք է մի քանի րոպե սպասեք, մինչև մուտքագրվող միջոցները ստանան ավելի շատ ցանցային հաստատումներ։ Ավելի շատ հաստատումներ ստանալուց հետո դրանք հնարավոր կլինի ծախսել։", "avg_savings": "Միջին խնայողություն", @@ -125,6 +127,7 @@ "block_remaining": "Մնացել է 1 բլոկ", "Blocks_remaining": "${status} Բլոկ է մնացել", "bluetooth": "Bluetooth", + "bridging": "Կամրջում", "bright_theme": "Պայծառ", "bscscan_history": "BSCScan-ի պատմություն", "bump_fee": "Բարձրացնել վճարը", @@ -216,6 +219,8 @@ "color_theme": "Գունային թեմա", "coming_soon_tag": "Շուտով", "commit_transaction_amount_fee": "Հաստատել գործարքը\nԳումար՝ ${amount}\nՄիջնորդավճար՝ ${fee}", + "compatible_services": "Համատեղելի ծառայություններ", + "compatible_services_desc": "Օգտագործեք Սկանավորման գործիքը՝ Cake Wallet-ի կողմից աջակցվող QR կոդերի հետևյալ տեսակները կարդալու համար՝", "configure": "Կարգավորել", "confirm": "Հաստատել", "confirm_delete_template": "Այս գործողությունը կջնջի այս ձևանմուշը։ Ցանկանու՞մ եք շարունակել։", @@ -279,6 +284,7 @@ "creating_new_wallet": "Ստեղծվում է նոր դրամապանակ", "creating_new_wallet_error": "Սխալ՝ ${description}", "creation_date": "Ստեղծման ամսաթիվ", + "crypto_addresses": "Կրիպտո հասցեներ", "csv_nothing_to_export": "Արտահանելու ոչինչ չկա", "current_swap": "Ընթացիկ փոխանակում", "current_wallet": "Ընթացիկ դրամապանակ", @@ -301,6 +307,7 @@ "default_sell_provider": "Վաճառքի լռելյայն մատակարար", "delete": "Ջնջել", "delete_account": "Ջնջել հաշիվը", + "delete_this_node": "Ջնջել այս հանգույցը", "delete_wallet": "Ջնջել դրամապանակը", "delete_wallet_confirm_message": "Վստա՞հ եք, որ ցանկանում եք ջնջել ${wallet_name} դրամապանակը։", "deleteConnectionConfirmationPrompt": "Վստա՞հ եք, որ ցանկանում եք ջնջել կապը", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO-ն լիովին ապակենտրոնացված, գրավով ապահովված ստեյբլքոյն է՝ կապված եվրոյին․ անվտանգ, բազմակողմանի և գրաքննության նկատմամբ դիմացկուն՝ առանց օրաքլների վրա հենվելու։ 1 dEURO = 1 EURO։", "deuro_tooltip_no_eth": "dEURO-ն միացնելու համար ձեր դրամապանակում պետք է ունենաք ETH։", "deuro_tx_commited_content": "Գործարքի հաստատման և էկրանին արտացոլվելու համար կարող է պահանջվել մի քանի վայրկյան", + "device_confirmation": "Սարքի հաստատում", "device_is_signing": "Սարքը ստորագրում է", "dfx_option_description": "Գնեք կրիպտոարժույթ EUR և CHF-ով։ Եվրոպայում գործող մանրածախ և կորպորատիվ հաճախորդների համար", "did_you_back_up_seeds": "Դուք պահուստավորե՞լ եք ձեր բոլոր սիդերը։", @@ -466,6 +474,8 @@ "extracted_address_content": "Դուք կուղարկեք միջոցներ\n${recipient_name}-ին", "failed_authentication": "Նույնականացումը ձախողվեց. ${state_error}", "faq": "ՀՏՀ", + "favorite_token": "Նախընտրած թոքեն", + "favorite_token_desc": "Նախընտրած թոքենի մնացորդը կցուցադրվի մնացորդի քարտի վրա։", "features": "Ֆունկցիաներ", "fee": "Միջնորդավճար", "fee_less_than_min": "Ընտրված միջնորդավճարը նվազագույնից պակաս է, խնդրում ենք ավելացնել միջնորդավճարը, որպեսզի կարողանաք ուղարկել գործարքը", @@ -491,6 +501,7 @@ "frozen": "Սառեցված", "frozen_balance": "Սառեցված մնացորդ", "full_balance": "Ամբողջական մնացորդ", + "gallery": "Պատկերասրահ", "gas_exceeds_allowance": "Գործարքի համար պահանջվող գազը գերազանցում է թույլատրելի սահմանաչափը։", "gas_price": "Գազի գին", "general": "Ընդհանուր", @@ -526,6 +537,7 @@ "how_to_connect": "Ինչպես միանալ", "how_to_use": "Ինչպես օգտագործել", "how_to_use_card": "Ինչպես օգտագործել այս քարտը", + "hww_exit_desc": "Սա կդադարեցնի ձեր ապարատային սարքի հետ ընթացիկ զուգակցման գործընթացը", "i_understand": "Հասկացա", "icon_style": "Սրբապատկերների ոճը", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Ձեր ստացման հասցեն կպտտվի ամեն անգամ, երբ դուք ստանաք գործարք", "infobox_multichain": "Օգտագործեք այս հասցեն՝ ցանկացած թոքեն կամ հավաքածու ստանալու համար", "infobox_rotation": "Ձեր ստացման հասցեն կփոխվի ամեն անգամ, երբ փակեք և նորից բացեք այս էկրանը", + "input": "Մուտք", "inputs": "Մուտքեր", "insufficient_funds_for_tx": "Գործարքը հաջողությամբ կատարելու համար բավարար միջոցներ չկան։", "insufficient_lamport_for_tx": "Դուք չունեք բավարար SOL՝ գործարքը և դրա գործարքի վճարը ծածկելու համար։ Խնդրում ենք ավելացնել ավելի շատ SOL ձեր դրամապանակում կամ նվազեցնել ուղարկվող SOL-ի քանակը։", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Կառավարել PoW հանգույցները", "manage_providers": "Կառավարել մատակարարներին", "manage_yats": "Կառավարել Yats-երը", + "manual_input": "Ձեռքով մուտքագրում", "mark_as_redeemed": "Նշել որպես օգտագործված", "market_place": "Շուկա", "mask": "Դիմակ", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Բոլոր ամենանոր մոդելները (GPT-5.3, Claude 4.6).\nԱռանց բաժանորդագրության՝ վճարեք կրիպտոարժույթով։", "narrow": "Նեղ", "network": "Ցանց", + "networks": "Ցանցեր", "new_first_wallet_text": "Ձեր կրիպտոն անվտանգ պահելը շատ հեշտ է", "new_node_testing": "Նոր հանգույցի փորձարկում", "new_subaddress_create": "Ստեղծել", @@ -666,6 +681,7 @@ "no_extra_detail": "Լրացուցիչ մանրամասներ հասանելի չեն", "no_id_needed": "ID չի պահանջվում!", "no_id_required": "Անձը հաստատող փաստաթուղթ չի պահանջվում։ Լրացրեք հաշիվը և ծախսեք ամենուր", + "no_providers_available": "Մատակարարներ չկան", "no_relay_on_domain": "Օգտատիրոջ տիրույթի համար ռելե չկա կամ ռելեն անհասանելի է։ Խնդրում ենք ընտրել օգտագործելու համար ռելե։", "no_relays": "Ռելեներ չկան", "no_relays_message": "Մենք գտել ենք Nostr NIP-05 գրառում այս օգտատիրոջ համար, բայց այն չի պարունակում որևէ relay։ Խնդրում ենք ստացողին տեղեկացնել, որ իր Nostr գրառման մեջ ավելացնի relay-ներ։", @@ -677,8 +693,10 @@ "node_new": "Նոր հանգույց", "node_port": "Հանգույցի պորտ", "node_reset_settings_title": "Կարգավորումների վերակայում", + "node_share_desc": "Սկանավորեք այս QR կոդը Սկանավորման էկրանից՝ այս հանգույցը ներմուծելու համար։", "node_test": "Թեստ", "nodes": "Հանգույցներ", + "nodes_desc": "Կառավարեք առկա հանգույցները կամ ավելացրեք անհատական հանգույց։", "nodes_list_reset_to_default_message": "Վստա՞հ եք, որ ցանկանում եք վերականգնել կարգավորումները լռելյայնին:", "none_of_selected_providers_can_exchange": "Ընտրված մատակարարներից ոչ մեկը չի կարող կատարել այս սվոփը", "noNFTYet": "Դեռևս NFT-ներ չկան", @@ -688,6 +706,7 @@ "note_tap_to_change": "Նշում (հպեք՝ փոխելու համար)", "notification_permission_denied": "Ծանուցումների թույլտվությունը մշտապես մերժվել է, խնդրում ենք այն ձեռքով միացնել կարգավորումներում", "nullURIError": "URI-ն null է", + "ocp_desc": "Վճարեք կրիպտոյով խանութներում", "offer_expires_in": "Առաջարկը կավարտվի՝ ", "offline": "Անցանց", "ok": "Լավ", @@ -714,8 +733,13 @@ "outputs": "Ելքեր", "overshot": "Գերազանցել է", "overwrite_amount": "Վերագրել գումարը", + "pairing_code": "Զուգակցման կոդ", + "pairing_code_desc_1": "Ձեր սարքը ցույց կտա զուգակցման կոդ։", + "pairing_code_desc_2": "Մուտքագրեք այստեղ՝ շարունակելու համար", + "pairing_error": "Զուգակցման սխալ", "pairingInvalidEvent": "Զուգակցման անվավեր իրադարձություն", "passphrase": "Գաղտնաբառային արտահայտություն (Ոչ պարտադիր)", + "passphrase_view_keys": "Գաղտնաբառային արտահայտություն", "passphrases_doesnt_match": "Գաղտնաբառերը չեն համընկնում, խնդրում ենք կրկին փորձել", "password": "Գաղտնաբառ", "paste": "Փակցնել", @@ -731,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Payjoin գործարք ստանալու համար անհրաժեշտ է, որ ձեր դրամապանակում օգտագործման համար պատրաստ Bitcoin ունենաք։\n\nՀենց որ ձեր դրամապանակում միջոցներ լինեն, Payjoin-ը ավտոմատ կերպով կմիանա։", "payjoin_unavailable_sheet_title": "Ինչո՞ւ է Payjoin-ը անհասանելի։", "payment_id": "Վճարման ID՝ ", + "payment_invoices": "Վճարման հաշիվ-ապրանքագրեր", "payment_made_easy": "Վճարումները՝ հեշտ ու արագ", "payment_was_received": "Ձեր վճարումը ստացվել է։", "payments": "Վճարումներ", @@ -886,6 +911,7 @@ "save": "Պահպանել", "save_backup_password": "Խնդրում ենք համոզվել, որ պահպանել եք ձեր կրկնօրինակի գաղտնաբառը։ Առանց դրա դուք չեք կարողանա ներմուծել ձեր կրկնօրինակման ֆայլերը։", "save_backup_password_alert": "Պահպանել պահուստային պատճենման գաղտնաբառը", + "save_contact": "Պահպանել կոնտակտը", "save_to_downloads": "Պահպանել «Ներբեռնումներ» պանակում", "saved_the_trade_id": "Ես պահպանել եմ փոխանակման ID-ն", "savings": "Խնայողություններ", @@ -957,6 +983,7 @@ "select_sell_provider_notice": "Վերևում ընտրեք վաճառքի մատակարար։ Դուք կարող եք բաց թողնել այս էկրանը՝ հավելվածի կարգավորումներում սահմանելով ձեր լռելայն վաճառքի մատակարարին։", "select_token": "Ընտրեք թոքեն", "select_your_country": "Խնդրում ենք ընտրել ձեր երկիրը", + "selected_trocador_provider": "ընտրված Trocador մատակարար", "sell": "Վաճառել", "sell_alert_content": "Մենք ներկայումս աջակցում ենք միայն Bitcoin, Ethereum և Litecoin-ի վաճառքին։ Խնդրում ենք ստեղծել կամ անցնել ձեր Bitcoin, Ethereum կամ Litecoin դրամապանակին։", "sell_monero_com_alert_content": "Monero-ի վաճառքը դեռ չի աջակցվում", @@ -1034,6 +1061,7 @@ "setup_your_debit_card": "Կարգավորել ձեր դեբետային քարտը", "share": "Կիսվել", "share_address": "Կիսվել հասցեով", + "share_this_node": "Կիսվել այս հանգույցով", "shared_seed_wallet_groups": "Համօգտագործվող սիդով դրամապանակների խմբեր", "shared_seed_wallets": "Համօգտագործվող սիդով դրամապանակներ", "show": "Ցուցադրել", @@ -1041,6 +1069,7 @@ "show_balance": "Երկար սեղմեք՝ մնացորդը ցուցադրելու համար", "show_balance_send_page": "Հպեք՝ ցուցադրելու համար", "show_balance_toast": "Երկար սեղմեք՝ մնացորդը թաքցնելու կամ ցույց տալու համար", + "show_combined_balance": "Ցուցադրել համակցված մնացորդը", "show_details": "Ցույց տալ մանրամասները", "show_hidden_addresses": "Ցույց տալ թաքնված հասցեները", "show_keys": "Ցուցադրել seed-ը/բանալիները", @@ -1106,6 +1135,7 @@ "swap_providers": "Փոխանակման մատակարարներ", "sweeping_wallet": "Դրամապանակի սվիպինգ", "sweeping_wallet_alert": "Սա երկար չի տևի։ ՄԻ ԼՔԵՔ ԱՅՍ ԷԿՐԱՆԸ, ՀԱԿԱՌԱԿ ԴԵՊՔՈՒՄ ՄԱՔՐՎՈՂ ՄԻՋՈՑՆԵՐԸ ԿԱՐՈՂ ԵՆ ԿՈՐՉԵԼ։", + "swipe_to_bridge": "Սահեցրեք՝ կամրջելու համար", "swipe_to_send": "Ուղարկելու համար սահեցրեք", "switch_wallet": "Փոխել դրամապանակը", "switchToETHWallet": "Խնդրում ենք անցնել Ethereum դրամապանակի և կրկին փորձել", @@ -1146,6 +1176,7 @@ "testnet_coins_no_value": "Testnet մետաղադրամները արժեք չունեն", "third_intro_content": "Yat-երը գործում են նաև Cake Wallet-ից դուրս։ Աշխարհի ցանկացած դրամապանակի հասցե կարելի է փոխարինել Yat-ով։", "third_intro_title": "Yat-ը լավ է համատեղվում ուրիշների հետ", + "this_can_take_few_seconds": "Սա կարող է տևել մի քանի վայրկյան", "this_pair_is_not_supported_warning": "Այս զույգը չի աջակցվում ներկայումս ընտրված փոխանակման հարթակ(ներ)ում։ Խնդրում ենք ընտրել մեկ այլ փոխանակման հարթակ։", "thorchain_contract_address_not_supported": "THORChain-ը չի աջակցում պայմանագրային հասցե ուղարկելուն", "thorchain_taproot_address_not_supported": "ThorChain մատակարարը չի աջակցում Taproot հասցեներին։ Խնդրում ենք փոխել հասցեն կամ ընտրել այլ մատակարար։", @@ -1159,6 +1190,7 @@ "token_decimal": "Թոքենի տասնորդականներ (օր.՝ USDT)", "token_name": "Թոքենի անունը (օր.՝ Tether)", "token_symbol": "Թոքենի նշան (օր.՝ USDT)", + "token_verified_on_jupiter": "Այս նշանը հաստատված է Jupiter-ի վրա", "tokenID": "ID", "tokens": "Թոքեններ", "tokens_strong_warning": "Երբեք մի ուղարկեք թոքեններ այս հասցեին!", @@ -1287,6 +1319,7 @@ "username": "Օգտատիրոջ անուն", "username_available": "Օգտանունը հասանելի է", "username_character_error": "Օգտվողի անունները պետք է պարունակեն միայն", + "username_check_your_network": "Չհաջողվեց ստուգել օգտանունը։ Խնդրում ենք ստուգել ձեր ցանցային կապը։", "username_length_error": "Օգտվողի անունները պետք է պարունակեն 6-32 այբբենաթվային նիշ։", "username_length_error_1_64": "Օգտվողի անունները պետք է պարունակեն 1-64 այբբենաթվային նիշ։", "username_not_available": "Այս օգտանունը հասանելի չէ։", @@ -1297,6 +1330,7 @@ "verify_message": "Ստուգել հաղորդագրությունը", "verify_seed": "Հաստատել սիդը", "verify_with_2fa": "Հաստատեք Cake 2FA-ով", + "verifying_code": "Կոդի ստուգում", "version": "Տարբերակ ${currentVersion}", "view_all": "Դիտել բոլորը", "view_in_block_explorer": "Դիտել բլոկների դիտարկիչում", @@ -1308,6 +1342,7 @@ "waitFewSecondForTxUpdate": "Խնդրում ենք սպասել մի քանի վայրկյան, որպեսզի գործարքը արտացոլվի գործարքների պատմության մեջ", "wallet": "Դրամապանակ", "wallet_accounts": "Դրամապանակի հաշիվներ", + "wallet_balance": "Դրամապանակի մնացորդ", "wallet_group": "Դրամապանակների խումբ", "wallet_group_description_existing_seed": "Դուք ընտրել եք այս դրամապանակի համար օգտագործել գոյություն ունեցող սիդը։ Անհրաժեշտության դեպքում կարող եք կրկին ստուգել սիդը՝ այն հաստատելու կամ գրի առնելու համար։", "wallet_group_description_four": "ամբողջովին նոր սիդով դրամապանակ ստեղծելու համար։", @@ -1345,9 +1380,11 @@ "walletConnect": "WalletConnect", "wallets": "Դրամապանակներ", "warning": "Զգուշացում", + "wc_action_approve": "Հաստատել", "wc_approve_request_title": "Հաստատել հարցումը", "wc_connect_request_title": "Միացման հարցում", "wc_connected_to": "Միացված է ${name}-ին", + "wc_desc": "Հեշտությամբ միացեք DApps-երին", "wc_max_network_fee": "Ցանցի առավելագույն վճար", "wc_message_to_sign": "Հաղորդագրություն ստորագրելու համար", "wc_network_fee": "Ցանցի վճար", @@ -1398,6 +1435,7 @@ "yat_popup_content": "Այժմ դուք կարող եք ուղարկել և ստանալ կրիպտո Cake Wallet-ում ձեր Yat-ի միջոցով՝ կարճ, էմոջի-ների վրա հիմնված օգտանունով։ Կառավարեք Yat-երը ցանկացած ժամանակ կարգավորումների էկրանին", "yat_popup_title": "Ձեր դրամապանակի հասցեն կարող է էմոջիֆիկացվել։", "yes": "Այո", + "yes_exit": "Այո։ Դուրս գալ", "yesterday": "Երեկ", "you_now_have_debit_card": "Այժմ դուք ունեք դեբետային քարտ", "you_pay": "Դուք վճարում եք", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index ae2e5ca6b..29bed2a16 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -76,6 +76,7 @@ "approve_tokens": "Setujui token", "apps": "Aplikasi", "arbiscan_history": "Riwayat ArbiScan", + "are_you_sure_exit": "Apakah Anda yakin ingin keluar?", "arrive_in_this_address": "${currency} ${tag}akan masuk ke alamat ini", "ascending": "Urut naik", "ask_each_time": "Tanya setiap kali", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Buat alamat secara otomatis", "auto_generate_subaddresses": "Buat subalamat secara otomatis", "automatic": "Otomatis", + "available": "Tersedia", "available_balance": "Saldo Tersedia", "available_balance_description": "“Saldo Tersedia” atau “Saldo Terkonfirmasi” adalah dana yang dapat langsung dibelanjakan. Jika dana muncul di saldo bawah tetapi tidak di saldo atas, maka Anda harus menunggu beberapa menit agar dana masuk mendapatkan konfirmasi jaringan tambahan. Setelah mendapatkan lebih banyak konfirmasi, dana tersebut akan dapat dibelanjakan.", "avg_savings": "Rata-rata Penghematan", @@ -125,6 +127,7 @@ "block_remaining": "1 Blok Tersisa", "Blocks_remaining": "${status} Blok Tersisa", "bluetooth": "Bluetooth", + "bridging": "Menjembatani", "bright_theme": "Terang", "bscscan_history": "Riwayat BSCScan", "bump_fee": "Naikkan biaya", @@ -216,6 +219,8 @@ "color_theme": "Tema warna", "coming_soon_tag": "Segera hadir", "commit_transaction_amount_fee": "Konfirmasi transaksi\nJumlah: ${amount}\nBiaya: ${fee}", + "compatible_services": "Layanan yang Kompatibel", + "compatible_services_desc": "Gunakan alat Pindai untuk membaca jenis kode QR berikut yang didukung di Cake Wallet:", "configure": "Konfigurasi", "confirm": "Konfirmasi", "confirm_delete_template": "Tindakan ini akan menghapus templat ini. Apakah Anda ingin melanjutkan?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Membuat dompet baru", "creating_new_wallet_error": "Kesalahan: ${description}", "creation_date": "Tanggal Pembuatan", + "crypto_addresses": "Alamat Kripto", "csv_nothing_to_export": "Tidak ada yang dapat diekspor", "current_swap": "Swap Saat Ini", "current_wallet": "Dompet saat ini", @@ -301,6 +307,7 @@ "default_sell_provider": "Penyedia Jual Default", "delete": "Hapus", "delete_account": "Hapus Akun", + "delete_this_node": "Hapus node ini", "delete_wallet": "Hapus dompet", "delete_wallet_confirm_message": "Apakah Anda yakin ingin menghapus dompet ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Apakah Anda yakin ingin menghapus koneksi ke", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO adalah stablecoin yang sepenuhnya terdesentralisasi dan dijaminkan, dipatok ke Euro — aman, serbaguna, dan tahan sensor tanpa harus bergantung pada oracle. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Untuk mengaktifkan dEURO, Anda harus memiliki ETH di dompet Anda.", "deuro_tx_commited_content": "Mungkin perlu beberapa detik agar transaksi dikonfirmasi dan ditampilkan di layar", + "device_confirmation": "Konfirmasi Perangkat", "device_is_signing": "Perangkat sedang menandatangani", "dfx_option_description": "Beli kripto dengan EUR & CHF. Untuk pelanggan ritel dan korporat di Eropa", "did_you_back_up_seeds": "Apakah Anda sudah mencadangkan semua seed Anda?", @@ -466,6 +474,8 @@ "extracted_address_content": "Anda akan mengirim dana ke\n${recipient_name}", "failed_authentication": "Autentikasi gagal. ${state_error}", "faq": "FAQ", + "favorite_token": "Token favorit", + "favorite_token_desc": "Saldo token favorit akan ditampilkan di kartu saldo.", "features": "Fitur", "fee": "Biaya", "fee_less_than_min": "Biaya yang dipilih lebih rendah dari minimum, harap tingkatkan biaya agar dapat mengirim transaksi", @@ -491,6 +501,7 @@ "frozen": "Dibekukan", "frozen_balance": "Saldo Dibekukan", "full_balance": "Saldo Penuh", + "gallery": "Galeri", "gas_exceeds_allowance": "Gas yang diperlukan oleh transaksi melebihi batas yang diizinkan.", "gas_price": "Harga gas", "general": "Umum", @@ -526,6 +537,7 @@ "how_to_connect": "Cara Menghubungkan", "how_to_use": "Cara menggunakan", "how_to_use_card": "Cara menggunakan kartu ini", + "hww_exit_desc": "Ini akan mengakhiri proses pairing yang sedang berlangsung dengan perangkat keras Anda", "i_understand": "Saya mengerti", "icon_style": "Gaya ikon", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Alamat penerimaan Anda akan berganti setiap kali Anda menerima transaksi", "infobox_multichain": "Gunakan alamat ini untuk menerima token atau koleksi apa pun di", "infobox_rotation": "Alamat penerimaan Anda akan berubah setiap kali Anda menutup dan membuka kembali layar ini", + "input": "Input", "inputs": "Input", "insufficient_funds_for_tx": "Saldo tidak mencukupi untuk berhasil mengeksekusi transaksi.", "insufficient_lamport_for_tx": "Anda tidak memiliki cukup SOL untuk menutupi transaksi dan biaya transaksinya. Mohon tambahkan lebih banyak SOL ke dompet Anda atau kurangi jumlah SOL yang Anda kirim.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Kelola node PoW", "manage_providers": "Kelola penyedia", "manage_yats": "Kelola Yats", + "manual_input": "Input Manual", "mark_as_redeemed": "Tandai sebagai Ditukarkan", "market_place": "Marketplace", "mask": "Mask", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Semua model terbaru (GPT-5.3, Claude 4.6).\nTanpa langganan, bayar dengan kripto.", "narrow": "Sempit", "network": "Jaringan", + "networks": "Jaringan", "new_first_wallet_text": "Menjaga kripto Anda tetap aman itu semudah membalik telapak tangan", "new_node_testing": "Pengujian node baru", "new_subaddress_create": "Buat", @@ -678,8 +693,10 @@ "node_new": "Node Baru", "node_port": "Port node", "node_reset_settings_title": "Atur ulang pengaturan", + "node_share_desc": "Pindai kode QR ini dari layar Pindai untuk mengimpor node ini.", "node_test": "Uji", "nodes": "Node", + "nodes_desc": "Kelola node yang ada atau tambahkan node kustom.", "nodes_list_reset_to_default_message": "Apakah Anda yakin ingin mengatur ulang pengaturan ke pengaturan bawaan?", "none_of_selected_providers_can_exchange": "Tidak ada penyedia yang dipilih yang dapat melakukan swap ini", "noNFTYet": "Belum ada NFT", @@ -689,6 +706,7 @@ "note_tap_to_change": "Catatan (ketuk untuk mengubah)", "notification_permission_denied": "Izin notifikasi ditolak secara permanen, mohon aktifkan secara manual di pengaturan", "nullURIError": "URI bernilai null", + "ocp_desc": "Bayar dengan kripto di toko", "offer_expires_in": "Penawaran berakhir dalam: ", "offline": "Offline", "ok": "OK", @@ -717,8 +735,13 @@ "outputs": "Output", "overshot": "Melebihi", "overwrite_amount": "Timpa jumlah", + "pairing_code": "Kode Pairing", + "pairing_code_desc_1": "Perangkat Anda akan menampilkan kode pairing.", + "pairing_code_desc_2": "Masukkan di sini untuk melanjutkan", + "pairing_error": "Kesalahan Pairing", "pairingInvalidEvent": "Peristiwa Pairing Tidak Valid", "passphrase": "Frasa sandi (Opsional)", + "passphrase_view_keys": "Frasa sandi", "passphrases_doesnt_match": "Frasa sandi tidak cocok, silakan coba lagi", "password": "Kata Sandi", "paste": "Tempel", @@ -734,6 +757,7 @@ "payjoin_unavailable_sheet_content": "Menerima transaksi Payjoin mengharuskan Anda memiliki Bitcoin yang siap digunakan.\n\nBegitu dompet Anda memiliki dana, Payjoin akan otomatis diaktifkan.", "payjoin_unavailable_sheet_title": "Mengapa Payjoin tidak tersedia?", "payment_id": "ID Pembayaran: ", + "payment_invoices": "Faktur Pembayaran", "payment_made_easy": "Pembayaran jadi mudah", "payment_was_received": "Pembayaran Anda telah diterima.", "payments": "Pembayaran", @@ -890,6 +914,7 @@ "save": "Simpan", "save_backup_password": "Harap pastikan Anda telah menyimpan kata sandi cadangan Anda. Anda tidak akan dapat mengimpor file cadangan Anda tanpanya.", "save_backup_password_alert": "Simpan kata sandi cadangan", + "save_contact": "Simpan Kontak", "save_to_downloads": "Simpan ke Unduhan", "saved_the_trade_id": "Saya telah menyimpan ID transaksi", "savings": "Tabungan", @@ -1039,6 +1064,7 @@ "setup_your_debit_card": "Siapkan kartu debit Anda", "share": "Bagikan", "share_address": "Bagikan alamat", + "share_this_node": "Bagikan node ini", "shared_seed_wallet_groups": "Grup Dompet Seed Bersama", "shared_seed_wallets": "Dompet Seed Bersama", "show": "Tampilkan", @@ -1046,6 +1072,7 @@ "show_balance": "Tekan lama untuk menampilkan saldo", "show_balance_send_page": "Ketuk untuk menampilkan", "show_balance_toast": "Tekan lama untuk menyembunyikan atau menampilkan saldo", + "show_combined_balance": "Tampilkan saldo gabungan", "show_details": "Tampilkan Detail", "show_hidden_addresses": "Tampilkan alamat yang disembunyikan", "show_keys": "Tampilkan seed/kunci", @@ -1111,6 +1138,7 @@ "swap_providers": "Penyedia swap", "sweeping_wallet": "Dompet sweep", "sweeping_wallet_alert": "Ini seharusnya tidak memakan waktu lama. JANGAN TINGGALKAN LAYAR INI ATAU DANA YANG DISAPU DAPAT HILANG.", + "swipe_to_bridge": "Geser untuk menjembatani", "swipe_to_send": "Geser untuk mengirim", "switch_wallet": "Ganti Wallet", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", @@ -1151,6 +1179,7 @@ "testnet_coins_no_value": "Koin testnet tidak memiliki nilai", "third_intro_content": "Yat juga bisa digunakan di luar Cake Wallet. Alamat dompet apa pun di dunia dapat digantikan dengan Yat!", "third_intro_title": "Yat cocok digunakan dengan yang lain", + "this_can_take_few_seconds": "Ini dapat memakan waktu beberapa detik", "this_pair_is_not_supported_warning": "Pasangan ini tidak didukung oleh bursa yang saat ini dipilih. Silakan pilih bursa lain.", "thorchain_contract_address_not_supported": "THORChain tidak mendukung pengiriman ke alamat kontrak", "thorchain_taproot_address_not_supported": "Penyedia ThorChain tidak mendukung alamat Taproot. Harap ubah alamat tersebut atau pilih penyedia lain.", @@ -1164,6 +1193,7 @@ "token_decimal": "Desimal token (mis: USDT)", "token_name": "Nama token (mis: Tether)", "token_symbol": "Simbol token (mis: USDT)", + "token_verified_on_jupiter": "Token ini diverifikasi di Jupiter", "tokenID": "ID", "tokens": "Token", "tokens_strong_warning": "Jangan pernah mengirim token ke alamat ini!", @@ -1292,6 +1322,7 @@ "username": "Nama pengguna", "username_available": "Nama Pengguna Tersedia", "username_character_error": "Nama pengguna hanya boleh berisi", + "username_check_your_network": "Tidak dapat memeriksa nama pengguna. Silakan periksa koneksi jaringan Anda.", "username_length_error": "Nama pengguna harus terdiri dari 6-32 karakter alfanumerik.", "username_length_error_1_64": "Nama pengguna harus terdiri dari 1–64 karakter alfanumerik.", "username_not_available": "Nama pengguna ini tidak tersedia.", @@ -1302,6 +1333,7 @@ "verify_message": "Verifikasi Pesan", "verify_seed": "Verifikasi seed", "verify_with_2fa": "Verifikasi dengan Cake 2FA", + "verifying_code": "Memverifikasi Kode", "version": "Versi ${currentVersion}", "view_all": "Lihat semua", "view_in_block_explorer": "Lihat di Penjelajah Blok", @@ -1313,6 +1345,7 @@ "waitFewSecondForTxUpdate": "Mohon tunggu beberapa detik hingga transaksi muncul di riwayat transaksi", "wallet": "Dompet", "wallet_accounts": "Akun Dompet", + "wallet_balance": "Saldo Dompet", "wallet_group": "Grup Dompet", "wallet_group_description_existing_seed": "Anda telah memilih untuk menggunakan seed yang sudah ada untuk dompet ini. Anda dapat memverifikasi seed lagi jika perlu untuk mengonfirmasi atau mencatatnya.", "wallet_group_description_four": "untuk membuat dompet dengan seed yang sepenuhnya baru.", @@ -1350,9 +1383,11 @@ "walletConnect": "WalletConnect", "wallets": "Dompet", "warning": "Peringatan", + "wc_action_approve": "Setujui", "wc_approve_request_title": "Setujui permintaan", "wc_connect_request_title": "Hubungkan permintaan", "wc_connected_to": "Terhubung ke ${name}", + "wc_desc": "Hubungkan dengan mudah ke DApps", "wc_max_network_fee": "Biaya jaringan maksimal", "wc_message_to_sign": "Pesan untuk ditandatangani", "wc_network_fee": "Biaya jaringan", @@ -1403,6 +1438,7 @@ "yat_popup_content": "Anda kini dapat mengirim dan menerima kripto di Cake Wallet dengan Yat Anda—nama pengguna pendek berbasis emoji. Kelola Yat kapan saja di layar pengaturan", "yat_popup_title": "Alamat dompet Anda dapat diubah menjadi emoji.", "yes": "Ya", + "yes_exit": "Ya. Keluar", "yesterday": "Kemarin", "you_now_have_debit_card": "Anda sekarang memiliki kartu debit", "you_pay": "Anda Bayar", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 7997f91d2..c0e2d1915 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -76,6 +76,7 @@ "approve_tokens": "Approva token", "apps": "App", "arbiscan_history": "Cronologia ArbiScan", + "are_you_sure_exit": "Sei sicuro di voler uscire?", "arrive_in_this_address": "${currency} ${tag}arriverà a questo indirizzo", "ascending": "Crescente", "ask_each_time": "Chiedi ogni volta", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Genera automaticamente gli indirizzi", "auto_generate_subaddresses": "Genera automaticamente sottoindirizzi", "automatic": "Automatico", + "available": "Disponibile", "available_balance": "Saldo disponibile", "available_balance_description": "Il “Saldo disponibile” o “Saldo confermato” sono fondi che possono essere spesi immediatamente. Se i fondi compaiono nel saldo in basso ma non in quello in alto, devi attendere qualche minuto affinché i fondi in arrivo ottengano ulteriori conferme di rete. Dopo aver ricevuto più conferme, saranno spendibili.", "avg_savings": "Risparmio medio", @@ -125,6 +127,7 @@ "block_remaining": "1 blocco rimanente", "Blocks_remaining": "${status} blocchi rimanenti", "bluetooth": "Bluetooth", + "bridging": "Bridging in corso", "bright_theme": "Chiaro", "bscscan_history": "Cronologia BSCScan", "bump_fee": "Aumento commissione", @@ -216,6 +219,8 @@ "color_theme": "Tema colore", "coming_soon_tag": "Prossimamente", "commit_transaction_amount_fee": "Conferma transazione\nImporto: ${amount}\nCommissione: ${fee}", + "compatible_services": "Servizi compatibili", + "compatible_services_desc": "Usa lo strumento Scansione per leggere i seguenti tipi di codici QR supportati su Cake Wallet:", "configure": "Configura", "confirm": "Conferma", "confirm_delete_template": "Questa azione eliminerà questo modello. Desideri continuare?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Creazione di un nuovo portafoglio", "creating_new_wallet_error": "Errore: ${description}", "creation_date": "Data di creazione", + "crypto_addresses": "Indirizzi crypto", "csv_nothing_to_export": "Niente da esportare", "current_swap": "Scambio in corso", "current_wallet": "Portafoglio corrente", @@ -301,6 +307,7 @@ "default_sell_provider": "Provider di vendita predefinito", "delete": "Elimina", "delete_account": "Elimina account", + "delete_this_node": "Elimina questo nodo", "delete_wallet": "Elimina wallet", "delete_wallet_confirm_message": "Sei sicuro di voler eliminare il wallet ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Sei sicuro di voler eliminare la connessione a", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO è una stablecoin completamente decentralizzata e collateralizzata, ancorata all'euro — sicura, versatile e resistente alla censura senza dover fare affidamento su oracoli. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Per abilitare dEURO, devi avere ETH nel tuo wallet.", "deuro_tx_commited_content": "Potrebbero essere necessari un paio di secondi affinché la transazione venga confermata e venga visualizzata sullo schermo", + "device_confirmation": "Conferma sul dispositivo", "device_is_signing": "Il dispositivo sta firmando", "dfx_option_description": "Acquista crypto con EUR e CHF. Per clienti retail e aziendali in Europa", "did_you_back_up_seeds": "Hai eseguito il backup di tutte le seed?", @@ -466,6 +474,8 @@ "extracted_address_content": "Invierai fondi a\n${recipient_name}", "failed_authentication": "Autenticazione non riuscita. ${state_error}", "faq": "FAQ", + "favorite_token": "Token preferito", + "favorite_token_desc": "Il saldo del token preferito verrà mostrato sulla scheda del saldo.", "features": "Funzionalità", "fee": "Commissione", "fee_less_than_min": "La commissione selezionata è inferiore al minimo. Aumenta la commissione per poter inviare la transazione", @@ -491,6 +501,7 @@ "frozen": "Congelato", "frozen_balance": "Saldo congelato", "full_balance": "Saldo totale", + "gallery": "Galleria", "gas_exceeds_allowance": "Il gas richiesto dalla transazione supera il limite consentito.", "gas_price": "Prezzo del gas", "general": "Generale", @@ -526,6 +537,7 @@ "how_to_connect": "Come connettersi", "how_to_use": "Come usare", "how_to_use_card": "Come usare questa carta", + "hww_exit_desc": "Questo terminerà il processo di associazione in corso con il tuo dispositivo hardware", "i_understand": "Ho capito", "icon_style": "Stile dell'icona", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Il tuo indirizzo di ricezione cambierà ogni volta che ricevi una transazione", "infobox_multichain": "Usa questo indirizzo per ricevere qualsiasi token o oggetto da collezione su", "infobox_rotation": "Il tuo indirizzo di ricezione cambierà ogni volta che chiudi e riapri questa schermata", + "input": "Input", "inputs": "Input", "insufficient_funds_for_tx": "Fondi insufficienti per eseguire correttamente la transazione.", "insufficient_lamport_for_tx": "Non hai abbastanza SOL per coprire la transazione e la relativa commissione. Aggiungi più SOL al tuo wallet oppure riduci l'importo di SOL che stai inviando.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Gestisci i nodi PoW", "manage_providers": "Gestisci i provider", "manage_yats": "Gestisci gli Yats", + "manual_input": "Inserimento manuale", "mark_as_redeemed": "Segna come riscattato", "market_place": "Marketplace", "mask": "Maschera", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Tutti i modelli più recenti (GPT-5.3, Claude 4.6).\nNessun abbonamento, paga con cripto.", "narrow": "Stretto", "network": "Rete", + "networks": "Reti", "new_first_wallet_text": "Tenere al sicuro le tue crypto è un gioco da ragazzi", "new_node_testing": "Test di un nuovo nodo", "new_subaddress_create": "Crea", @@ -678,8 +693,10 @@ "node_new": "Nuovo nodo", "node_port": "Porta del nodo", "node_reset_settings_title": "Ripristina le impostazioni", + "node_share_desc": "Scansiona questo codice QR dalla schermata Scansione per importare questo nodo.", "node_test": "Test", "nodes": "Nodi", + "nodes_desc": "Gestisci i nodi esistenti o aggiungine uno personalizzato.", "nodes_list_reset_to_default_message": "Sei sicuro di voler ripristinare le impostazioni predefinite?", "none_of_selected_providers_can_exchange": "Nessuno dei provider selezionati può effettuare questo swap", "noNFTYet": "Nessun NFT ancora", @@ -689,6 +706,7 @@ "note_tap_to_change": "Nota (tocca per cambiare)", "notification_permission_denied": "L'autorizzazione alle notifiche è stata negata in modo permanente, abilitala manualmente nelle impostazioni", "nullURIError": "L'URI è null", + "ocp_desc": "Paga con crypto nei negozi", "offer_expires_in": "L'offerta scade tra: ", "offline": "Offline", "ok": "OK", @@ -716,8 +734,13 @@ "outputs": "Output", "overshot": "Superato", "overwrite_amount": "Sovrascrivi importo", + "pairing_code": "Codice di associazione", + "pairing_code_desc_1": "Il tuo dispositivo mostrerà un codice di associazione.", + "pairing_code_desc_2": "Inseriscilo qui per continuare", + "pairing_error": "Errore di associazione", "pairingInvalidEvent": "Evento di associazione non valido", "passphrase": "Passphrase (Opzionale)", + "passphrase_view_keys": "Passphrase", "passphrases_doesnt_match": "Le passphrase non corrispondono, riprova", "password": "Password", "paste": "Incolla", @@ -733,6 +756,7 @@ "payjoin_unavailable_sheet_content": "Per ricevere una transazione Payjoin è necessario avere Bitcoin pronti all'uso.\n\nNon appena il tuo portafoglio avrà dei fondi, Payjoin verrà abilitato automaticamente.", "payjoin_unavailable_sheet_title": "Perché Payjoin non è disponibile?", "payment_id": "ID pagamento: ", + "payment_invoices": "Fatture di pagamento", "payment_made_easy": "Pagamenti resi semplici", "payment_was_received": "Il tuo pagamento è stato ricevuto.", "payments": "Pagamenti", @@ -812,6 +836,7 @@ "receive_to": "Ricevi su", "received": "Ricevuto", "receiving": "Ricezione", + "recieving": "Ricezione", "recipient_address": "Indirizzo del destinatario", "reconnect": "Riconnetti", "reconnect_alert_text": "Sei sicuro di voler riconnetterti?", @@ -887,6 +912,7 @@ "save": "Salva", "save_backup_password": "Assicurati di aver salvato la password di backup. Senza di essa non potrai importare i tuoi file di backup.", "save_backup_password_alert": "Salva la password di backup", + "save_contact": "Salva contatto", "save_to_downloads": "Salva in Download", "saved_the_trade_id": "Ho salvato l'ID della transazione", "savings": "Risparmi", @@ -1036,6 +1062,7 @@ "setup_your_debit_card": "Configura la tua carta di debito", "share": "Condividi", "share_address": "Condividi indirizzo", + "share_this_node": "Condividi questo nodo", "shared_seed_wallet_groups": "Gruppi di wallet con seed condiviso", "shared_seed_wallets": "Portafogli con seed condiviso", "show": "Mostra", @@ -1043,6 +1070,7 @@ "show_balance": "Tieni premuto per mostrare il saldo", "show_balance_send_page": "Tocca per mostrare", "show_balance_toast": "Tieni premuto per nascondere o mostrare il saldo", + "show_combined_balance": "Mostra saldo combinato", "show_details": "Mostra dettagli", "show_hidden_addresses": "Mostra indirizzi nascosti", "show_keys": "Mostra seed/chiavi", @@ -1108,6 +1136,7 @@ "swap_providers": "Provider di swap", "sweeping_wallet": "Svuotamento del portafoglio", "sweeping_wallet_alert": "Questo non dovrebbe richiedere molto tempo. NON LASCIARE QUESTA SCHERMATA O I FONDI SPOSTATI POTREBBERO ANDARE PERSI.", + "swipe_to_bridge": "Scorri per il bridge", "swipe_to_send": "Scorri per inviare", "switch_wallet": "Cambia wallet", "switchToETHWallet": "Passa a un wallet Ethereum e riprova", @@ -1148,6 +1177,7 @@ "testnet_coins_no_value": "Le monete di testnet non hanno valore", "third_intro_content": "Gli Yat esistono anche al di fuori di Cake Wallet. Qualsiasi indirizzo di portafoglio al mondo può essere sostituito con uno Yat!", "third_intro_title": "Yat va d'accordo con gli altri", + "this_can_take_few_seconds": "Questo può richiedere alcuni secondi", "this_pair_is_not_supported_warning": "Questa coppia non è supportata con l'exchange attualmente selezionato. Seleziona un altro exchange.", "thorchain_contract_address_not_supported": "THORChain non supporta l'invio a un indirizzo di contratto", "thorchain_taproot_address_not_supported": "Il provider ThorChain non supporta gli indirizzi Taproot. Modifica l'indirizzo o seleziona un provider diverso.", @@ -1161,6 +1191,7 @@ "token_decimal": "Decimali del token (es: USDT)", "token_name": "Nome del token (es: Tether)", "token_symbol": "Simbolo del token (es: USDT)", + "token_verified_on_jupiter": "Questo token è verificato su Jupiter", "tokenID": "ID", "tokens": "Token", "tokens_strong_warning": "Non inviare mai token a questo indirizzo!", @@ -1289,6 +1320,7 @@ "username": "Nome utente", "username_available": "Nome utente disponibile", "username_character_error": "I nomi utente devono contenere solo", + "username_check_your_network": "Impossibile verificare il nome utente. Controlla la tua connessione di rete.", "username_length_error": "I nomi utente devono contenere da 6 a 32 caratteri alfanumerici.", "username_length_error_1_64": "I nomi utente devono contenere 1-64 caratteri alfanumerici.", "username_not_available": "Questo nome utente non è disponibile.", @@ -1299,6 +1331,7 @@ "verify_message": "Verifica messaggio", "verify_seed": "Verifica il seed", "verify_with_2fa": "Verifica con Cake 2FA", + "verifying_code": "Verifica del codice in corso", "version": "Versione ${currentVersion}", "view_all": "Visualizza tutti", "view_in_block_explorer": "Visualizza nel Block Explorer", @@ -1311,6 +1344,7 @@ "waiting_payment_confirmation": "In attesa di conferma del pagamento", "wallet": "Wallet", "wallet_accounts": "Account del wallet", + "wallet_balance": "Saldo del wallet", "wallet_group": "Gruppo di wallet", "wallet_group_description_existing_seed": "Hai scelto di utilizzare un seed esistente per questo wallet. Puoi verificare di nuovo il seed se devi confermarlo o annotarlo.", "wallet_group_description_four": "per creare un wallet con un seed completamente nuovo.", @@ -1348,9 +1382,11 @@ "walletConnect": "WalletConnect", "wallets": "Portafogli", "warning": "Attenzione", + "wc_action_approve": "Approva", "wc_approve_request_title": "Approva la richiesta", "wc_connect_request_title": "Richiesta di connessione", "wc_connected_to": "Connesso a ${name}", + "wc_desc": "Connettiti facilmente alle dApp", "wc_max_network_fee": "Tariffa di rete massima", "wc_message_to_sign": "Messaggio da firmare", "wc_network_fee": "Tariffa di rete", @@ -1402,6 +1438,7 @@ "yat_popup_content": "Ora puoi inviare e ricevere criptovalute in Cake Wallet con il tuo Yat, un breve nome utente basato su emoji. Puoi gestire gli Yat in qualsiasi momento nella schermata delle impostazioni", "yat_popup_title": "L'indirizzo del tuo wallet può essere trasformato in emoji.", "yes": "Sì", + "yes_exit": "Sì. Esci", "yesterday": "Ieri", "you_now_have_debit_card": "Ora hai una carta di debito", "you_pay": "Tu paghi", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index f8ab953de..a94ac6931 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -76,6 +76,7 @@ "approve_tokens": "トークンを承認", "apps": "アプリ", "arbiscan_history": "ArbiScan 履歴", + "are_you_sure_exit": "終了してもよろしいですか?", "arrive_in_this_address": "${currency} ${tag}はこのアドレスに着金します", "ascending": "昇順", "ask_each_time": "毎回確認する", @@ -89,6 +90,7 @@ "auto_generate_addresses": "アドレスを自動生成", "auto_generate_subaddresses": "サブアドレスを自動生成", "automatic": "自動", + "available": "利用可能", "available_balance": "利用可能残高", "available_balance_description": "「利用可能な残高」または「承認済み残高」は、すぐに使用できる資金です。下の残高には表示されているのに上の残高に表示されない場合は、受信した資金がネットワークでさらに承認(確認)されるまで数分待つ必要があります。承認数が増えると、使用できるようになります。", "avg_savings": "平均節約額", @@ -125,6 +127,7 @@ "block_remaining": "残り1ブロック", "Blocks_remaining": "${status} ブロック残り", "bluetooth": "Bluetooth", + "bridging": "ブリッジ中", "bright_theme": "明るい", "bscscan_history": "BSCScan履歴", "bump_fee": "手数料を上げる", @@ -216,6 +219,8 @@ "color_theme": "カラーテーマ", "coming_soon_tag": "近日公開", "commit_transaction_amount_fee": "トランザクションを確定\n金額: ${amount}\n手数料: ${fee}", + "compatible_services": "対応サービス", + "compatible_services_desc": "スキャンツールを使用して、Cake Walletで対応している以下の種類のQRコードを読み取れます:", "configure": "設定", "confirm": "確認", "confirm_delete_template": "この操作により、このテンプレートは削除されます。続行しますか?", @@ -279,6 +284,7 @@ "creating_new_wallet": "新しいウォレットを作成中", "creating_new_wallet_error": "エラー: ${description}", "creation_date": "作成日", + "crypto_addresses": "暗号資産アドレス", "csv_nothing_to_export": "エクスポートするものがありません", "current_swap": "現在のスワップ", "current_wallet": "現在のウォレット", @@ -301,6 +307,7 @@ "default_sell_provider": "デフォルトの売却プロバイダー", "delete": "削除", "delete_account": "アカウントを削除", + "delete_this_node": "このノードを削除", "delete_wallet": "ウォレットを削除", "delete_wallet_confirm_message": "${wallet_name} ウォレットを削除してもよろしいですか?", "deleteConnectionConfirmationPrompt": "への接続を削除してもよろしいですか?", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEUROは、オラクルに頼ることなく、ユーロにペッグされた完全分散型の担保型ステーブルコインです。安全で汎用性が高く、検閲耐性を備えています。1 dEURO = 1 EURO。", "deuro_tooltip_no_eth": "dEUROを有効にするには、ウォレットにETHが必要です。", "deuro_tx_commited_content": "トランザクションが承認され、画面に反映されるまでに数秒かかる場合があります", + "device_confirmation": "デバイスでの確認", "device_is_signing": "デバイスが署名中です", "dfx_option_description": "EUR・CHFで暗号資産を購入。ヨーロッパの個人および法人のお客様向け", "did_you_back_up_seeds": "すべてのシードをバックアップしましたか?", @@ -466,6 +474,8 @@ "extracted_address_content": "次の宛先に送金します\n${recipient_name}", "failed_authentication": "認証に失敗しました。${state_error}", "faq": "FAQ", + "favorite_token": "お気に入りのトークン", + "favorite_token_desc": "お気に入りのトークンの残高が残高カードに表示されます。", "features": "機能", "fee": "手数料", "fee_less_than_min": "選択した手数料が最小値を下回っています。トランザクションを送信できるように、手数料を増やしてください", @@ -491,6 +501,7 @@ "frozen": "凍結", "frozen_balance": "凍結残高", "full_balance": "全残高", + "gallery": "ギャラリー", "gas_exceeds_allowance": "取引に必要なガスが許容上限を超えています。", "gas_price": "ガス価格", "general": "一般", @@ -527,6 +538,7 @@ "how_to_connect": "接続方法", "how_to_use": "使い方", "how_to_use_card": "このカードの使い方", + "hww_exit_desc": "ハードウェアデバイスとの進行中のペアリング処理を終了します", "i_understand": "理解しました", "icon_style": "アイコンのスタイル", "id": "ID: ", @@ -541,6 +553,7 @@ "infobox_auto_address": "受信アドレスは、トランザクションを受信するたびに自動的に切り替わります", "infobox_multichain": "このアドレスを使用して、次のネットワーク上で任意のトークンまたはコレクティブルを受け取れます", "infobox_rotation": "この画面を閉じて再度開くたびに、受信アドレスがローテーションされます。", + "input": "入力", "inputs": "入力", "insufficient_funds_for_tx": "トランザクションを正常に実行するための残高が不足しています。", "insufficient_lamport_for_tx": "トランザクションおよびその取引手数料を支払うためのSOLが不足しています。ウォレットにSOLを追加するか、送信するSOLの量を減らしてください。", @@ -606,6 +619,7 @@ "manage_pow_nodes": "PoWノードを管理", "manage_providers": "プロバイダーを管理", "manage_yats": "Yatsを管理", + "manual_input": "手動入力", "mark_as_redeemed": "使用済みとしてマーク", "market_place": "マーケットプレイス", "mask": "マスク", @@ -651,6 +665,7 @@ "nanogpt_subtitle": "すべての最新モデル(GPT-5.3、Claude 4.6)。\nサブスクリプション不要、暗号資産で支払い。", "narrow": "狭い", "network": "ネットワーク", + "networks": "ネットワーク", "new_first_wallet_text": "暗号資産を安全に守るのはお手のものです", "new_node_testing": "新しいノードのテスト", "new_subaddress_create": "作成", @@ -679,8 +694,10 @@ "node_new": "新規ノード", "node_port": "ノードポート", "node_reset_settings_title": "設定をリセット", + "node_share_desc": "このノードをインポートするには、スキャン画面でこのQRコードをスキャンしてください。", "node_test": "テスト", "nodes": "ノード", + "nodes_desc": "既存のノードを管理するか、カスタムノードを追加します。", "nodes_list_reset_to_default_message": "設定をデフォルトにリセットしてもよろしいですか?", "none_of_selected_providers_can_exchange": "選択したプロバイダーはいずれもこのスワップを実行できません", "noNFTYet": "NFTはまだありません", @@ -690,6 +707,7 @@ "note_tap_to_change": "メモ(タップして変更)", "notification_permission_denied": "通知の権限が永久に拒否されました。設定で手動で有効にしてください", "nullURIError": "URIがnullです", + "ocp_desc": "店舗で暗号資産を使って支払う", "offer_expires_in": "オファーの有効期限: ", "offline": "オフライン", "ok": "OK", @@ -716,8 +734,13 @@ "outputs": "アウトプット", "overshot": "オーバーシュート", "overwrite_amount": "金額を上書き", + "pairing_code": "ペアリングコード", + "pairing_code_desc_1": "デバイスにペアリングコードが表示されます。", + "pairing_code_desc_2": "続行するにはここに入力してください", + "pairing_error": "ペアリングエラー", "pairingInvalidEvent": "無効なペアリングイベント", "passphrase": "パスフレーズ(任意)", + "passphrase_view_keys": "パスフレーズ", "passphrases_doesnt_match": "パスフレーズが一致しません。もう一度お試しください", "password": "パスワード", "paste": "貼り付け", @@ -733,6 +756,7 @@ "payjoin_unavailable_sheet_content": "Payjoinトランザクションを受信するには、使用可能なビットコインが必要です。\n\nウォレットに資金が入ると、Payjoinは自動的に有効になります。", "payjoin_unavailable_sheet_title": "Payjoinが利用できないのはなぜですか?", "payment_id": "支払いID: ", + "payment_invoices": "支払い請求書", "payment_made_easy": "支払いが簡単に", "payment_was_received": "お支払いを受領しました。", "payments": "支払い", @@ -812,6 +836,7 @@ "receive_to": "受取先", "received": "受信", "receiving": "受信", + "recieving": "受信中", "recipient_address": "受取人アドレス", "reconnect": "再接続", "reconnect_alert_text": "再接続してもよろしいですか?", @@ -887,6 +912,7 @@ "save": "保存", "save_backup_password": "バックアップパスワードを保存していることを必ず確認してください。これがないとバックアップファイルをインポートできません。", "save_backup_password_alert": "バックアップ用パスワードを保存", + "save_contact": "連絡先を保存", "save_to_downloads": "ダウンロードに保存", "saved_the_trade_id": "取引IDを保存しました", "savings": "貯蓄", @@ -1036,6 +1062,7 @@ "setup_your_debit_card": "デビットカードを設定する", "share": "共有", "share_address": "アドレスを共有", + "share_this_node": "このノードを共有", "shared_seed_wallet_groups": "共有シードのウォレットグループ", "shared_seed_wallets": "共有シードのウォレット", "show": "表示", @@ -1043,6 +1070,7 @@ "show_balance": "長押しして残高を表示", "show_balance_send_page": "タップして表示", "show_balance_toast": "長押しして残高を非表示/表示", + "show_combined_balance": "合計残高を表示", "show_details": "詳細を表示", "show_hidden_addresses": "非表示のアドレスを表示", "show_keys": "シード/キーを表示", @@ -1108,6 +1136,7 @@ "swap_providers": "スワッププロバイダー", "sweeping_wallet": "スイーピングウォレット", "sweeping_wallet_alert": "すぐに完了します。この画面から離れないでください。離れると、スイープした資金が失われる可能性があります。", + "swipe_to_bridge": "スワイプしてブリッジ", "swipe_to_send": "スワイプして送信", "switch_wallet": "ウォレットを切り替える", "switchToETHWallet": "Ethereumウォレットに切り替えて、もう一度お試しください", @@ -1148,6 +1177,7 @@ "testnet_coins_no_value": "テストネットコインには価値がありません", "third_intro_content": "YatはCake Walletの外でも使えます。地球上のどのウォレットアドレスもYatに置き換えられます!", "third_intro_title": "Yatは他のサービスとも相性がいい", + "this_can_take_few_seconds": "数秒かかる場合があります", "this_pair_is_not_supported_warning": "このペアは、現在選択されている取引所ではサポートされていません。別の取引所を選択してください。", "thorchain_contract_address_not_supported": "THORChainはコントラクトアドレスへの送信をサポートしていません", "thorchain_taproot_address_not_supported": "ThorChainプロバイダーはTaprootアドレスをサポートしていません。アドレスを変更するか、別のプロバイダーを選択してください。", @@ -1161,6 +1191,7 @@ "token_decimal": "トークンの小数点以下桁数(例:USDT)", "token_name": "トークン名(例:Tether)", "token_symbol": "トークンシンボル(例:USDT)", + "token_verified_on_jupiter": "このトークンは Jupiter で検証されています", "tokenID": "ID", "tokens": "トークン", "tokens_strong_warning": "このアドレスにトークンを絶対に送信しないでください!", @@ -1289,6 +1320,7 @@ "username": "ユーザー名", "username_available": "ユーザー名は利用可能です", "username_character_error": "ユーザー名には次の文字のみを含める必要があります", + "username_check_your_network": "ユーザー名を確認できません。ネットワーク接続を確認してください。", "username_length_error": "ユーザー名は6~32文字の英数字である必要があります。", "username_length_error_1_64": "ユーザー名は1~64文字の英数字である必要があります。", "username_not_available": "このユーザー名は利用できません。", @@ -1299,6 +1331,7 @@ "verify_message": "メッセージを検証", "verify_seed": "シードを確認", "verify_with_2fa": "Cake 2FAで認証する", + "verifying_code": "コードを確認中", "version": "バージョン ${currentVersion}", "view_all": "すべて表示", "view_in_block_explorer": "ブロックエクスプローラーで表示", @@ -1310,6 +1343,7 @@ "waitFewSecondForTxUpdate": "取引履歴に取引が反映されるまで、数秒お待ちください。", "wallet": "ウォレット", "wallet_accounts": "ウォレットアカウント", + "wallet_balance": "ウォレット残高", "wallet_group": "ウォレットグループ", "wallet_group_description_existing_seed": "このウォレットでは既存のシードを使用することを選択しました。確認したり書き留めたりする必要がある場合は、シードをもう一度確認できます。", "wallet_group_description_four": "まったく新しいシードでウォレットを作成するため。", @@ -1347,9 +1381,11 @@ "walletConnect": "WalletConnect", "wallets": "ウォレット", "warning": "警告", + "wc_action_approve": "承認", "wc_approve_request_title": "リクエストの承認", "wc_connect_request_title": "接続リクエスト", "wc_connected_to": "${name} に接続しました", + "wc_desc": "dApp に簡単に接続", "wc_max_network_fee": "最大ネットワーク料金", "wc_message_to_sign": "署名するメッセージ", "wc_network_fee": "ネットワーク料金", @@ -1400,6 +1436,7 @@ "yat_popup_content": "Yat(短い絵文字ベースのユーザー名)を使って、Cake Walletで暗号資産を送受信できるようになりました。設定画面でいつでもYatを管理できます", "yat_popup_title": "あなたのウォレットアドレスは絵文字化できます。", "yes": "はい", + "yes_exit": "はい。終了する", "yesterday": "昨日", "you_now_have_debit_card": "デビットカードを利用できるようになりました", "you_pay": "支払う金額", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 299814e60..4f74220a5 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -76,6 +76,7 @@ "approve_tokens": "토큰 승인", "apps": "앱", "arbiscan_history": "ArbiScan 기록", + "are_you_sure_exit": "정말 종료하시겠습니까?", "arrive_in_this_address": "${currency} ${tag}은(는) 이 주소로 입금됩니다", "ascending": "오름차순", "ask_each_time": "매번 확인", @@ -89,6 +90,7 @@ "auto_generate_addresses": "주소 자동 생성", "auto_generate_subaddresses": "서브주소 자동 생성", "automatic": "자동", + "available": "사용 가능", "available_balance": "사용 가능 잔액", "available_balance_description": "“사용 가능 잔액” 또는 “확정 잔액”은 즉시 사용할 수 있는 자금입니다. 자금이 아래 잔액에는 표시되지만 위 잔액에는 표시되지 않는 경우, 입금된 자금이 네트워크에서 더 많은 컨펌(확인)을 받을 때까지 몇 분 정도 기다려야 합니다. 더 많은 컨펌을 받은 후에는 사용할 수 있습니다.", "avg_savings": "평균 절감액", @@ -125,6 +127,7 @@ "block_remaining": "1 블록 남음", "Blocks_remaining": "${status}개 블록 남음", "bluetooth": "블루투스", + "bridging": "브리징", "bright_theme": "밝게", "bscscan_history": "BSCScan 기록", "bump_fee": "수수료 올리기", @@ -216,6 +219,8 @@ "color_theme": "색상 테마", "coming_soon_tag": "출시 예정", "commit_transaction_amount_fee": "트랜잭션 제출\n금액: ${amount}\n수수료: ${fee}", + "compatible_services": "호환 서비스", + "compatible_services_desc": "스캔 도구를 사용하여 Cake Wallet에서 지원하는 다음 유형의 QR 코드를 읽으세요:", "configure": "설정", "confirm": "확인", "confirm_delete_template": "이 작업을 수행하면 이 템플릿이 삭제됩니다. 계속하시겠습니까?", @@ -279,6 +284,7 @@ "creating_new_wallet": "새 지갑 생성 중", "creating_new_wallet_error": "오류: ${description}", "creation_date": "생성일", + "crypto_addresses": "암호화폐 주소", "csv_nothing_to_export": "내보낼 항목이 없습니다", "current_swap": "현재 스왑", "current_wallet": "현재 지갑", @@ -301,6 +307,7 @@ "default_sell_provider": "기본 판매 제공업체", "delete": "삭제", "delete_account": "계정 삭제", + "delete_this_node": "이 노드 삭제", "delete_wallet": "지갑 삭제", "delete_wallet_confirm_message": "${wallet_name} 지갑을 삭제하시겠습니까?", "deleteConnectionConfirmationPrompt": "다음에 대한 연결을 삭제하시겠습니까?", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO는 유로에 페그된 완전한 탈중앙화 담보 기반 스테이블코인으로, 오라클에 의존하지 않으면서도 안전하고 다용도로 사용할 수 있으며 검열 저항성이 있습니다. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "dEURO를 활성화하려면 지갑에 ETH가 있어야 합니다.", "deuro_tx_commited_content": "거래가 확인되어 화면에 반영되기까지 몇 초 정도 걸릴 수 있습니다.", + "device_confirmation": "기기 확인", "device_is_signing": "장치가 서명하고 있습니다", "dfx_option_description": "EUR 및 CHF로 암호화폐 구매. 유럽의 개인 및 기업 고객용", "did_you_back_up_seeds": "모든 시드 문구를 백업하셨나요?", @@ -466,6 +474,8 @@ "extracted_address_content": "다음 수신자에게 자금을 전송합니다\n${recipient_name}", "failed_authentication": "인증에 실패했습니다. ${state_error}", "faq": "FAQ", + "favorite_token": "즐겨찾는 토큰", + "favorite_token_desc": "즐겨찾는 토큰의 잔액이 잔액 카드에 표시됩니다.", "features": "기능", "fee": "수수료", "fee_less_than_min": "선택한 수수료가 최소 수수료보다 낮습니다. 거래를 전송하려면 수수료를 높여주세요.", @@ -491,6 +501,7 @@ "frozen": "동결", "frozen_balance": "동결 잔액", "full_balance": "전체 잔액", + "gallery": "갤러리", "gas_exceeds_allowance": "트랜잭션에 필요한 가스가 허용량을 초과합니다.", "gas_price": "가스 가격", "general": "일반", @@ -526,6 +537,7 @@ "how_to_connect": "연결하는 방법", "how_to_use": "사용 방법", "how_to_use_card": "이 카드 사용 방법", + "hww_exit_desc": "하드웨어 기기와 진행 중인 페어링 과정을 종료합니다", "i_understand": "이해했습니다", "icon_style": "아이콘 스타일", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "수신 주소는 거래를 받을 때마다 변경됩니다.", "infobox_multichain": "이 주소를 사용하여 다음에서 어떤 토큰이나 수집품이든 받으세요", "infobox_rotation": "이 화면을 닫았다가 다시 열 때마다 수신 주소가 변경됩니다.", + "input": "입력", "inputs": "입력값", "insufficient_funds_for_tx": "트랜잭션을 성공적으로 실행하기에 잔액이 부족합니다.", "insufficient_lamport_for_tx": "트랜잭션 및 트랜잭션 수수료를 충당할 SOL이 부족합니다. 지갑에 SOL을 더 추가하거나 전송하는 SOL 금액을 줄여 주세요.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "PoW 노드 관리", "manage_providers": "제공업체 관리", "manage_yats": "Yats 관리", + "manual_input": "수동 입력", "mark_as_redeemed": "사용 완료로 표시", "market_place": "마켓플레이스", "mask": "마스크", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "최신 모델 모두(GPT-5.3, Claude 4.6).\n구독 없이 암호화폐로 결제.", "narrow": "좁게", "network": "네트워크", + "networks": "네트워크", "new_first_wallet_text": "암호화폐를 안전하게 지키는 건 식은 죽 먹기예요", "new_node_testing": "새 노드 테스트", "new_subaddress_create": "생성", @@ -678,8 +693,10 @@ "node_new": "새 노드", "node_port": "노드 포트", "node_reset_settings_title": "설정 재설정", + "node_share_desc": "이 노드를 가져오려면 스캔 화면에서 이 QR 코드를 스캔하세요.", "node_test": "테스트", "nodes": "노드", + "nodes_desc": "기존 노드를 관리하거나 사용자 지정 노드를 추가하세요.", "nodes_list_reset_to_default_message": "설정을 기본값으로 재설정하시겠습니까?", "none_of_selected_providers_can_exchange": "선택한 제공업체 중 이 스왑을 지원하는 곳이 없습니다", "noNFTYet": "아직 NFT가 없습니다", @@ -689,6 +706,7 @@ "note_tap_to_change": "메모 (탭하여 변경)", "notification_permission_denied": "알림 권한이 영구적으로 거부되었습니다. 설정에서 수동으로 활성화해 주세요.", "nullURIError": "URI가 null입니다", + "ocp_desc": "매장에서 암호화폐로 결제", "offer_expires_in": "오퍼 만료까지: ", "offline": "오프라인", "ok": "확인", @@ -715,6 +733,10 @@ "outputs": "출력", "overshot": "초과", "overwrite_amount": "금액 덮어쓰기", + "pairing_code": "페어링 코드", + "pairing_code_desc_1": "기기에 페어링 코드가 표시됩니다.", + "pairing_code_desc_2": "계속하려면 여기에 입력하세요", + "pairing_error": "페어링 오류", "pairingInvalidEvent": "유효하지 않은 페어링 이벤트", "passphrase": "패스프레이즈(선택 사항)", "passphrase_view_keys": "패스프레이즈", @@ -733,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Payjoin 트랜잭션을 수신하려면 사용할 수 있는 비트코인이 준비되어 있어야 합니다.\n\n지갑에 자금이 들어오면 Payjoin이 자동으로 활성화됩니다.", "payjoin_unavailable_sheet_title": "Payjoin을 사용할 수 없는 이유는 무엇인가요?", "payment_id": "결제 ID: ", + "payment_invoices": "결제 청구서", "payment_made_easy": "결제를 쉽게", "payment_was_received": "결제가 수신되었습니다.", "payments": "결제", @@ -812,6 +835,7 @@ "receive_to": "받는 주소", "received": "수신됨", "receiving": "수신", + "recieving": "수신 중", "recipient_address": "수신자 주소", "reconnect": "재연결", "reconnect_alert_text": "정말 다시 연결하시겠습니까?", @@ -887,6 +911,7 @@ "save": "저장", "save_backup_password": "백업 비밀번호를 저장했는지 꼭 확인하세요. 비밀번호가 없으면 백업 파일을 가져올 수 없습니다.", "save_backup_password_alert": "백업 비밀번호 저장", + "save_contact": "연락처 저장", "save_to_downloads": "다운로드 폴더에 저장", "saved_the_trade_id": "거래 ID를 저장했어요", "savings": "저축", @@ -1036,6 +1061,7 @@ "setup_your_debit_card": "직불카드 설정", "share": "공유", "share_address": "주소 공유", + "share_this_node": "이 노드 공유", "shared_seed_wallet_groups": "공유 시드 지갑 그룹", "shared_seed_wallets": "공유 시드 지갑", "show": "보기", @@ -1043,6 +1069,7 @@ "show_balance": "길게 눌러 잔액 표시", "show_balance_send_page": "탭하여 표시", "show_balance_toast": "길게 눌러 잔액을 숨기거나 표시하세요", + "show_combined_balance": "합산 잔액 표시", "show_details": "세부 정보 보기", "show_hidden_addresses": "숨겨진 주소 표시", "show_keys": "시드/키 보기", @@ -1108,6 +1135,7 @@ "swap_providers": "스왑 제공업체", "sweeping_wallet": "지갑 스윕", "sweeping_wallet_alert": "오래 걸리지 않습니다. 이 화면을 떠나지 마세요. 그렇지 않으면 스윕된 자금이 손실될 수 있습니다.", + "swipe_to_bridge": "스와이프하여 브리지", "swipe_to_send": "밀어서 보내기", "switch_wallet": "지갑 전환", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도하세요", @@ -1148,6 +1176,7 @@ "testnet_coins_no_value": "테스트넷 코인은 가치가 없습니다", "third_intro_content": "Yat은 Cake Wallet 밖에서도 사용할 수 있어요. 지구상의 어떤 지갑 주소든 Yat으로 대체할 수 있습니다!", "third_intro_title": "Yat은 다른 서비스와도 잘 어울립니다", + "this_can_take_few_seconds": "몇 초 정도 걸릴 수 있습니다", "this_pair_is_not_supported_warning": "현재 선택된 거래소에서는 이 페어가 지원되지 않습니다. 다른 거래소를 선택하세요.", "thorchain_contract_address_not_supported": "THORChain은 컨트랙트 주소로의 전송을 지원하지 않습니다", "thorchain_taproot_address_not_supported": "ThorChain 제공자는 Taproot 주소를 지원하지 않습니다. 주소를 변경하거나 다른 제공자를 선택하세요.", @@ -1161,6 +1190,7 @@ "token_decimal": "토큰 소수점(예: USDT)", "token_name": "토큰 이름(예: 테더)", "token_symbol": "토큰 심볼(예: USDT)", + "token_verified_on_jupiter": "이 토큰은 Jupiter에서 확인되었습니다.", "tokenID": "ID", "tokens": "토큰", "tokens_strong_warning": "절대 이 주소로 토큰을 보내지 마세요!", @@ -1289,6 +1319,7 @@ "username": "사용자명", "username_available": "사용 가능한 사용자 이름", "username_character_error": "사용자 이름에는 다음만 포함될 수 있습니다.", + "username_check_your_network": "사용자 이름을 확인할 수 없습니다. 네트워크 연결을 확인해 주세요.", "username_length_error": "사용자 이름은 6~32자의 영숫자로 구성되어야 합니다.", "username_length_error_1_64": "사용자 이름은 1~64자의 영숫자 문자로 구성되어야 합니다.", "username_not_available": "이 사용자 이름은 사용할 수 없습니다.", @@ -1299,6 +1330,7 @@ "verify_message": "메시지 확인", "verify_seed": "시드 문구 확인", "verify_with_2fa": "Cake 2FA로 인증", + "verifying_code": "코드 확인 중", "version": "버전 ${currentVersion}", "view_all": "모두 보기", "view_in_block_explorer": "블록 탐색기에서 보기", @@ -1310,6 +1342,7 @@ "waitFewSecondForTxUpdate": "트랜잭션이 거래 내역에 반영될 때까지 몇 초간 기다려 주십시오", "wallet": "지갑", "wallet_accounts": "지갑 계정", + "wallet_balance": "지갑 잔액", "wallet_group": "지갑 그룹", "wallet_group_description_existing_seed": "이 지갑에 기존 시드를 사용하도록 선택했습니다. 확인하거나 적어둘 필요가 있다면 시드를 다시 확인할 수 있습니다.", "wallet_group_description_four": "완전히 새로운 시드로 지갑을 생성하려면", @@ -1347,9 +1380,11 @@ "walletConnect": "WalletConnect", "wallets": "지갑", "warning": "경고", + "wc_action_approve": "승인", "wc_approve_request_title": "요청 승인", "wc_connect_request_title": "연결 요청", "wc_connected_to": "${name}에 연결됨", + "wc_desc": "DApp에 손쉽게 연결", "wc_max_network_fee": "최대 네트워크 수수료", "wc_message_to_sign": "서명하라는 메시지", "wc_network_fee": "네트워크 수수료", @@ -1400,6 +1435,7 @@ "yat_popup_content": "이제 짧은 이모지 기반 사용자 이름인 Yat으로 Cake Wallet에서 암호화폐를 보내고 받을 수 있습니다. 설정 화면에서 언제든지 Yat을 관리할 수 있습니다.", "yat_popup_title": "지갑 주소를 이모지로 변환할 수 있습니다.", "yes": "예", + "yes_exit": "예. 종료", "yesterday": "어제", "you_now_have_debit_card": "이제 직불카드가 생겼습니다", "you_pay": "결제 금액", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index d58b1add9..bde9bfa6a 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -76,6 +76,7 @@ "approve_tokens": "တိုကင်များကို အတည်ပြုပါ", "apps": "အက်ပ်များ", "arbiscan_history": "ArbiScan မှတ်တမ်း", + "are_you_sure_exit": "ထွက်လိုသည်မှာ သေချာပါသလား။", "arrive_in_this_address": "${currency} ${tag}သည် ဤလိပ်စာသို့ ရောက်ရှိပါမည်", "ascending": "အတက်", "ask_each_time": "အကြိမ်တိုင်း မေးပါ", @@ -89,6 +90,7 @@ "auto_generate_addresses": "လိပ်စာများကို အလိုအလျောက် ထုတ်ပေးရန်", "auto_generate_subaddresses": "Subaddress များကို အလိုအလျောက် ဖန်တီးပါ", "automatic": "အလိုအလျောက်", + "available": "ရရှိနိုင်သည်", "available_balance": "ရရှိနိုင်သော လက်ကျန်", "available_balance_description": "“Available Balance” သို့မဟုတ် “Confirmed Balance” သည် ချက်ချင်းသုံးစွဲနိုင်သော လက်ကျန်ငွေဖြစ်သည်။ လက်ကျန်အောက်ပိုင်းတွင်သာ ဝင်လာသော်လည်း အပေါ်ပိုင်းလက်ကျန်တွင် မပေါ်သေးပါက ကွန်ယက်အတည်ပြုချက် (network confirmations) ပိုမိုရရှိရန် မိနစ်အနည်းငယ် စောင့်ရပါမည်။ အတည်ပြုချက်များ ပိုမိုရရှိပြီးနောက် ထိုငွေများကို သုံးစွဲနိုင်ပါလိမ့်မည်။", "avg_savings": "ပျမ်းမျှ ချွေတာမှု", @@ -125,6 +127,7 @@ "block_remaining": "Block 1 ခု ကျန်ရှိသေးသည်", "Blocks_remaining": "${status} ဘလောက် ကျန်နေပါသည်", "bluetooth": "ဘလူးတုသ်", + "bridging": "Bridge လုပ်နေသည်", "bright_theme": "တောက်ပ", "bscscan_history": "BSCScan မှတ်တမ်း", "bump_fee": "အခကြေးငွေ တိုးမြှင့်ရန်", @@ -216,6 +219,8 @@ "color_theme": "အရောင်အပြင်အဆင်", "coming_soon_tag": "မကြာမီလာမည်", "commit_transaction_amount_fee": "ငွေလွှဲမှုကို အတည်ပြုပါ\nပမာဏ: ${amount}\nအခကြေးငွေ: ${fee}", + "compatible_services": "တွဲဖက်အသုံးပြုနိုင်သော ဝန်ဆောင်မှုများ", + "compatible_services_desc": "Cake Wallet တွင် ပံ့ပိုးထားသော အောက်ပါ QR ကုဒ်အမျိုးအစားများကို ဖတ်ရန် Scan tool ကို အသုံးပြုပါ:", "configure": "ပြင်ဆင်ရန်", "confirm": "အတည်ပြု", "confirm_delete_template": "ဤလုပ်ဆောင်ချက်သည် ဤတမ်းပလိတ်ကို ဖျက်ပစ်မည်ဖြစ်သည်။ ဆက်လက်လုပ်ဆောင်လိုပါသလား။", @@ -279,6 +284,7 @@ "creating_new_wallet": "ပိုက်ဆံအိတ်အသစ် ဖန်တီးနေသည်", "creating_new_wallet_error": "အမှား: ${description}", "creation_date": "ဖန်တီးသည့်နေ့စွဲ", + "crypto_addresses": "Crypto လိပ်စာများ", "csv_nothing_to_export": "ထုတ်ယူရန် မရှိပါ", "current_swap": "လက်ရှိ Swap", "current_wallet": "လက်ရှိ Wallet", @@ -301,6 +307,7 @@ "default_sell_provider": "မူလရောင်းချဝန်ဆောင်မှုပေးသူ", "delete": "ဖျက်ရန်", "delete_account": "အကောင့်ကို ဖျက်ပါ", + "delete_this_node": "ဤ node ကို ဖျက်ပါ", "delete_wallet": "ပိုက်ဆံအိတ်ကို ဖျက်မည်", "delete_wallet_confirm_message": "${wallet_name} wallet ကို ဖျက်ချင်တာ သေချာပါသလား။", "deleteConnectionConfirmationPrompt": "ဤချိတ်ဆက်မှုကို ဖျက်လိုသည်မှာ သေချာပါသလား", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO သည် ယူရိုနှင့် ချိတ်ဆက်ထားသော အပြည့်အဝ ဗဟိုချုပ်ကိုင်မှုမရှိသော အာမခံပစ္စည်းအခြေပြု stablecoin တစ်ခုဖြစ်ပြီး — လုံခြုံမှုရှိ၊ အသုံးချနိုင်မှုမြင့်ပြီး၊ censorship ကိုခံနိုင်ရည်ရှိကာ oracles များကို မမှီခိုဘဲ လုပ်ဆောင်နိုင်သည်။ 1 dEURO = 1 EURO။", "deuro_tooltip_no_eth": "dEURO ကို enable လုပ်ရန် သင့်ပိုက်ဆံအိတ်ထဲမှာ ETH ရှိရမယ်။", "deuro_tx_commited_content": "ငွေပေးငွေယူကို အတည်ပြုရန်နှင့် မျက်နှာပြင်ပေါ်တွင် ပြသလာရန် စက္ကန့်အနည်းငယ် ကြာနိုင်ပါသည်", + "device_confirmation": "စက်ပစ္စည်း အတည်ပြုခြင်း", "device_is_signing": "ကိရိယာက လက်မှတ်ရေးထိုးနေသည်", "dfx_option_description": "EUR & CHF ဖြင့် crypto ကို ဝယ်ယူပါ။ ဥရောပရှိ လက်လီနှင့် ကော်ပိုရိတ် ဖောက်သည်များအတွက်", "did_you_back_up_seeds": "သင့် Seed စကားလုံးများအားလုံးကို အရန်ကူးယူပြီးပြီလား?", @@ -466,6 +474,8 @@ "extracted_address_content": "သင်သည် ရန်ပုံငွေများကို\n${recipient_name} သို့ ပေးပို့ပါမည်", "failed_authentication": "အထောက်အထားစိစစ်ခြင်း မအောင်မြင်ပါ။ ${state_error}", "faq": "FAQ", + "favorite_token": "အကြိုက်ဆုံး တိုကင်", + "favorite_token_desc": "အကြိုက်ဆုံး တိုကင်၏ လက်ကျန်ကို လက်ကျန် ကတ်ပေါ်တွင် ပြသပါမည်။", "features": "အင်္ဂါရပ်များ", "fee": "အခကြေးငွေ", "fee_less_than_min": "ရွေးချယ်ထားသော အခကြေးငွေသည် အနည်းဆုံးသတ်မှတ်ချက်ထက် နည်းနေပါသည်။ လွှဲပြောင်းမှုကို ပို့နိုင်ရန် အခကြေးငွေကို တိုးမြှင့်ပါ။", @@ -491,6 +501,7 @@ "frozen": "ရပ်ဆိုင်းထားသည်", "frozen_balance": "အေးခဲထားသော လက်ကျန်", "full_balance": "လက်ကျန်ငွေ အပြည့်", + "gallery": "ပြခန်း", "gas_exceeds_allowance": "ငွေပေးငွေယူအတွက် လိုအပ်သော Gas ပမာဏသည် ခွင့်ပြုထားသော ပမာဏကို ကျော်လွန်နေသည်။", "gas_price": "ဂတ်စ်စျေးနှုန်း", "general": "အထွေထွေ", @@ -526,6 +537,7 @@ "how_to_connect": "ချိတ်ဆက်နည်း", "how_to_use": "အသုံးပြုနည်း", "how_to_use_card": "ဒီကတ်ကို ဘယ်လိုသုံးရမလဲ", + "hww_exit_desc": "၎င်းသည် သင့်ဟာ့ဒ်ဝဲ စက်ပစ္စည်းနှင့် ဆက်လက်လုပ်ဆောင်နေသော တွဲချိတ်မှု လုပ်ငန်းစဉ်ကို ရပ်တန့်စေမည်ဖြစ်သည်။", "i_understand": "နားလည်ပါတယ်", "icon_style": "အိုင်ကွန်စတိုင်", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "သင့်လက်ခံရရှိရန် လိပ်စာသည် ငွေပေးငွေယူတစ်ခု လက်ခံရရှိတိုင်း အလိုအလျောက် ပြောင်းလဲသွားမည်ဖြစ်သည်။", "infobox_multichain": "မည်သည့် တိုကင် သို့မဟုတ် စုဆောင်းပစ္စည်းကိုမဆို လက်ခံရန် ဤလိပ်စာကို အသုံးပြုပါ။", "infobox_rotation": "သင် ဤစခရင်ကို ပိတ်ပြီး ပြန်ဖွင့်သည့်အခါတိုင်း သင့်လက်ခံရရှိရန် လိပ်စာသည် ပြောင်းလဲသွားပါမည်။", + "input": "ထည့်သွင်းမှု", "inputs": "အဝင်များ", "insufficient_funds_for_tx": "ငွေပေးငွေယူကို အောင်မြင်စွာ ဆောင်ရွက်ရန် လက်ကျန်ငွေ မလုံလောက်ပါ။", "insufficient_lamport_for_tx": "ငွေပေးငွေယူနှင့် ၎င်း၏ ငွေပေးငွေယူခကို ပေးချေရန် SOL မလုံလောက်ပါ။ ကျေးဇူးပြု၍ သင့် wallet ထဲသို့ SOL ကို ထပ်မံထည့်ပါ သို့မဟုတ် သင်ပို့မည့် SOL ပမာဏကို လျှော့ချပါ။", @@ -605,6 +618,7 @@ "manage_pow_nodes": "PoW node များကို စီမံပါ", "manage_providers": "ဝန်ဆောင်မှုပေးသူများကို စီမံခန့်ခွဲပါ", "manage_yats": "Yats ကို စီမံခန့်ခွဲပါ", + "manual_input": "လက်ဖြင့် ထည့်သွင်းခြင်း", "mark_as_redeemed": "အသုံးပြုပြီးဖြစ်သည်ဟု အမှတ်အသားပြုပါ", "market_place": "စျေးကွက်", "mask": "Mask", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "နောက်ဆုံးပေါ်မော်ဒယ်များအားလုံး (GPT-5.3, Claude 4.6)။\nစာရင်းသွင်းမှုမလို၊ crypto ဖြင့်ပေးချေပါ။", "narrow": "ကျဉ်း", "network": "ကွန်ရက်", + "networks": "ကွန်ရက်များ", "new_first_wallet_text": "သင့်ရဲ့ crypto ကို လုံခြုံအောင် ထိန်းသိမ်းတာက လွယ်လွယ်ကူကူပါပဲ", "new_node_testing": "နိုဒ်အသစ် စမ်းသပ်ခြင်း", "new_subaddress_create": "ဖန်တီးရန်", @@ -678,8 +693,10 @@ "node_new": "နိုဒ်အသစ်", "node_port": "Node ပေါက်", "node_reset_settings_title": "ဆက်တင်များကို ပြန်လည်သတ်မှတ်ပါ", + "node_share_desc": "ဤ node ကို တင်သွင်းရန် Scan စခရင်မှ ဤ QR ကုဒ်ကို စကင်ဖတ်ပါ။", "node_test": "စမ်းသပ်", "nodes": "နိုဒ်များ", + "nodes_desc": "ရှိပြီးသား node များကို စီမံပါ သို့မဟုတ် စိတ်ကြိုက်တစ်ခု ထည့်ပါ။", "nodes_list_reset_to_default_message": "ဆက်တင်များကို မူရင်းအတိုင်း ပြန်လည်သတ်မှတ်လိုသည်မှာ သေချာပါသလား။", "none_of_selected_providers_can_exchange": "ရွေးချယ်ထားသော ပံ့ပိုးပေးသူများထဲမှ မည်သူမျှ ဒီ swap ကို မလုပ်နိုင်ပါ", "noNFTYet": "NFT မရှိသေးပါ", @@ -689,6 +706,7 @@ "note_tap_to_change": "မှတ်ချက် (ပြောင်းလဲရန် နှိပ်ပါ)", "notification_permission_denied": "အသိပေးချက်ခွင့်ပြုချက်ကို အပြီးတိုင် ငြင်းပယ်ထားပါသည်၊ ကျေးဇူးပြု၍ ချိန်ညှိချက်များတွင် လက်ဖြင့် ဖွင့်ပေးပါ", "nullURIError": "URI သည် null ဖြစ်သည်", + "ocp_desc": "ဆိုင်များတွင် crypto ဖြင့် ပေးချေပါ", "offer_expires_in": "ကမ်းလှမ်းချက် သက်တမ်းကုန်ဆုံးမည့်အချိန်: ", "offline": "အော့ဖ်လိုင်း", "ok": "OK", @@ -715,8 +733,13 @@ "outputs": "အထွက်များ", "overshot": "ကျော်လွန်သွားသည်", "overwrite_amount": "ပမာဏကို အစားထိုးရေးပါ", + "pairing_code": "တွဲချိတ်ကုဒ်", + "pairing_code_desc_1": "သင့်စက်ပစ္စည်းသည် တွဲချိတ်ကုဒ်တစ်ခုကို ပြသပါမည်။", + "pairing_code_desc_2": "ဆက်လက်လုပ်ဆောင်ရန် ဤနေရာတွင် ထည့်ပါ", + "pairing_error": "တွဲချိတ်မှု အမှား", "pairingInvalidEvent": "မမှန်ကန်သော တွဲချိတ်မှု ဖြစ်ရပ်", "passphrase": "စကားဝှက်စာစု (မဖြစ်မနေ မလိုအပ်ပါ)", + "passphrase_view_keys": "Passphrase", "passphrases_doesnt_match": "Passphrase များ မကိုက်ညီပါ၊ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ", "password": "စကားဝှက်", "paste": "ကူးထည့်", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Payjoin လွှဲပြောင်းမှုကို လက်ခံရန် သင့်တွင် အသုံးပြုရန် အသင့်ဖြစ်သော Bitcoin ရှိထားရန် လိုအပ်သည်။\n\nသင့်ပိုက်ဆံအိတ်တွင် ရန်ပုံငွေများ ရှိလာသည်နှင့်တပြိုင်နက် Payjoin ကို အလိုအလျောက် ဖွင့်ပေးမည်ဖြစ်သည်။", "payjoin_unavailable_sheet_title": "Payjoin ကို ဘာကြောင့် မရနိုင်တာလဲ။", "payment_id": "Payment ID: ", + "payment_invoices": "ငွေပေးချေမှု ငွေတောင်းခံလွှာများ", "payment_made_easy": "ငွေပေးချေမှုကို လွယ်ကူစေသည်", "payment_was_received": "သင့်ငွေပေးချေမှုကို လက်ခံရရှိပါသည်။", "payments": "ပေးချေမှုများ", @@ -811,6 +835,7 @@ "receive_to": "သို့ လက်ခံရန်", "received": "လက်ခံရရှိ", "receiving": "လက်ခံနေသည်", + "recieving": "လက်ခံနေသည်", "recipient_address": "လက်ခံသူ၏ လိပ်စာ", "reconnect": "ပြန်လည်ချိတ်ဆက်ရန်", "reconnect_alert_text": "ပြန်လည်ချိတ်ဆက်လိုသည်မှာ သေချာပါသလား?", @@ -886,6 +911,7 @@ "save": "သိမ်းဆည်း", "save_backup_password": "သင်၏ အရန်စကားဝှက်ကို သိမ်းဆည်းထားပြီးဖြစ်ကြောင်း သေချာပါစေ။ ၎င်းမရှိပါက သင်၏ အရန်ဖိုင်များကို တင်သွင်းနိုင်မည် မဟုတ်ပါ။", "save_backup_password_alert": "အရန်ကူးယူမှု စကားဝှက်ကို သိမ်းဆည်းပါ", + "save_contact": "အဆက်အသွယ်ကို သိမ်းဆည်းပါ", "save_to_downloads": "ဒေါင်းလုဒ်များသို့ သိမ်းဆည်းပါ", "saved_the_trade_id": "ကုန်သွယ်မှု ID ကို သိမ်းဆည်းထားပြီးပါပြီ။", "savings": "စုဆောင်းငွေ", @@ -1035,6 +1061,7 @@ "setup_your_debit_card": "သင့်ဒက်ဘစ်ကတ်ကို စနစ်ထည့်သွင်းပါ", "share": "မျှဝေ", "share_address": "လိပ်စာကို မျှဝေပါ", + "share_this_node": "ဤ node ကို မျှဝေပါ", "shared_seed_wallet_groups": "မျှဝေထားသော Seed ပိုက်ဆံအိတ်အုပ်စုများ", "shared_seed_wallets": "မျှဝေထားသော Seed Wallet များ", "show": "ပြပါ", @@ -1042,6 +1069,7 @@ "show_balance": "လက်ကျန်ငွေကို ပြရန် ကြာကြာနှိပ်ပါ", "show_balance_send_page": "ဖော်ပြရန် နှိပ်ပါ", "show_balance_toast": "လက်ချောင်းကို ကြာကြာဖိထားပြီး လက်ကျန်ငွေကို ဖျောက်/ပြပါ", + "show_combined_balance": "ပေါင်းစပ်လက်ကျန်ကို ပြပါ", "show_details": "အသေးစိတ်ပြရန်", "show_hidden_addresses": "ဝှက်ထားသောလိပ်စာများကို ပြပါ", "show_keys": "Seed/Key များကို ပြပါ", @@ -1107,6 +1135,7 @@ "swap_providers": "Swap ဝန်ဆောင်မှုပေးသူများ", "sweeping_wallet": "ပိုက်ဆံအိတ် ရှင်းလင်းခြင်း", "sweeping_wallet_alert": "ဒါက ကြာကြာမခံသင့်ပါဘူး။ ဒီစခရင်ကနေ မထွက်ပါနဲ့၊ မဟုတ်ရင် sweep လုပ်ထားတဲ့ ရန်ပုံငွေတွေ ပျောက်ဆုံးနိုင်ပါတယ်။", + "swipe_to_bridge": "Bridge လုပ်ရန် ပွတ်ဆွဲပါ", "swipe_to_send": "ပို့ရန် ပွတ်ဆွဲပါ", "switch_wallet": "ပိုက်ဆံအိတ် ပြောင်းရန်", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်မံကြိုးစားကြည့်ပါ။", @@ -1147,6 +1176,7 @@ "testnet_coins_no_value": "Testnet ဒင်္ဂါးများမှာ တန်ဖိုးမရှိပါ", "third_intro_content": "Yats သည် Cake Wallet အပြင်ဘက်တွင်လည်း အသုံးပြုနိုင်ပါသည်။ ကမ္ဘာပေါ်ရှိ မည်သည့် wallet address မဆို Yat ဖြင့် အစားထိုးနိုင်ပါသည်။", "third_intro_title": "Yat သည် အခြားဝန်ဆောင်မှုများနှင့်လည်း ကောင်းစွာ တွဲဖက်အသုံးပြုနိုင်သည်။", + "this_can_take_few_seconds": "၎င်းသည် စက္ကန့်အနည်းငယ် ကြာနိုင်ပါသည်", "this_pair_is_not_supported_warning": "ဤအတွဲကို လက်ရှိရွေးချယ်ထားသော လဲလှယ်ရေး(များ) ဖြင့် မပံ့ပိုးပါ။ ကျေးဇူးပြု၍ အခြား လဲလှယ်ရေးကို ရွေးချယ်ပါ။", "thorchain_contract_address_not_supported": "THORChain သည် စာချုပ်လိပ်စာသို့ ပို့ခြင်းကို မပံ့ပိုးပါ", "thorchain_taproot_address_not_supported": "ThorChain ပံ့ပိုးပေးသူသည် Taproot လိပ်စာများကို မထောက်ပံ့ပါ။ ကျေးဇူးပြု၍ လိပ်စာကို ပြောင်းလဲပါ သို့မဟုတ် အခြားပံ့ပိုးပေးသူကို ရွေးချယ်ပါ။", @@ -1160,6 +1190,7 @@ "token_decimal": "တိုကင် ဒဿမ (ဥပမာ: USDT)", "token_name": "တိုကင်အမည် (ဥပမာ: Tether)", "token_symbol": "တိုကင်သင်္ကေတ (ဥပမာ: USDT)", + "token_verified_on_jupiter": "ဤတိုကင်ကို Jupiter တွင် အတည်ပြုထားသည်။", "tokenID": "ID", "tokens": "တိုကင်များ", "tokens_strong_warning": "ဒီလိပ်စာသို့ တိုကင်များကို ဘယ်တော့မှ မပို့ပါနဲ့!", @@ -1288,6 +1319,7 @@ "username": "အသုံးပြုသူအမည်", "username_available": "အသုံးပြုသူအမည် ရနိုင်သည်", "username_character_error": "အသုံးပြုသူအမည်များတွင်သာ ပါဝင်ရမည်", + "username_check_your_network": "အသုံးပြုသူအမည်ကို စစ်ဆေး၍ မရပါ။ ကျေးဇူးပြု၍ သင့်ကွန်ရက်ချိတ်ဆက်မှုကို စစ်ဆေးပါ။", "username_length_error": "အသုံးပြုသူအမည်များတွင် အက္ခရာနှင့် ဂဏန်း ၆-၃၂ လုံး ပါဝင်ရပါမည်။", "username_length_error_1_64": "အသုံးပြုသူအမည်များတွင် အက္ခရာနှင့် ဂဏန်း စာလုံး 1-64 လုံး ပါဝင်ရပါမည်။", "username_not_available": "ဤအသုံးပြုသူအမည်ကို မရနိုင်ပါ။", @@ -1298,6 +1330,7 @@ "verify_message": "မက်ဆေ့ချ်ကို အတည်ပြုရန်", "verify_seed": "Seed ကို အတည်ပြုပါ", "verify_with_2fa": "Cake 2FA ဖြင့် အတည်ပြုပါ", + "verifying_code": "ကုဒ်ကို စိစစ်နေသည်", "version": "ဗားရှင်း ${currentVersion}", "view_all": "အားလုံးကြည့်ရန်", "view_in_block_explorer": "Block Explorer တွင် ကြည့်ရှုပါ", @@ -1309,6 +1342,7 @@ "waitFewSecondForTxUpdate": "ငွေပေးငွေယူမှတ်တမ်းတွင် ပြသလာရန် စက္ကန့်အနည်းငယ် စောင့်ပါ။", "wallet": "ပိုက်ဆံအိတ်", "wallet_accounts": "Wallet အကောင့်များ", + "wallet_balance": "ပိုက်ဆံအိတ် လက်ကျန်", "wallet_group": "ပိုက်ဆံအိတ်အုပ်စု", "wallet_group_description_existing_seed": "ဒီပိုက်ဆံအိတ်အတွက် ရှိပြီးသား seed ကို သုံးဖို့ သင်ရွေးချယ်ထားပါတယ်။ အတည်ပြုရန် သို့မဟုတ် မှတ်သားရေးသားရန် လိုအပ်ပါက seed ကို ထပ်မံစစ်ဆေးအတည်ပြုနိုင်ပါတယ်။", "wallet_group_description_four": "လုံးဝအသစ်သော seed ဖြင့် wallet တစ်ခုဖန်တီးရန်။", @@ -1346,9 +1380,11 @@ "walletConnect": "WalletConnect", "wallets": "ဝေါလက်များ", "warning": "သတိပေးချက်", + "wc_action_approve": "အတည်ပြု", "wc_approve_request_title": "တောင်းဆိုချက်ကို အတည်ပြုပါ။", "wc_connect_request_title": "တောင်းဆိုချက်ကို ချိတ်ဆက်ပါ။", "wc_connected_to": "${name} သို့ ချိတ်ဆက်ထားသည်", + "wc_desc": "dApp များသို့ လွယ်ကူစွာ ချိတ်ဆက်ပါ", "wc_max_network_fee": "အများဆုံးကွန်ရက်အခကြေးငွေ", "wc_message_to_sign": "လက်မှတ်ထိုးရန် မက်ဆေ့ချ်", "wc_network_fee": "ကွန်ရက်ကြေး", @@ -1399,6 +1435,7 @@ "yat_popup_content": "သင်၏ Yat — အီမိုဂျီအခြေပြု တိုတောင်းသော အသုံးပြုသူအမည် — ဖြင့် Cake Wallet တွင် crypto ကို ယခု ပေးပို့ခြင်းနှင့် လက်ခံခြင်း ပြုလုပ်နိုင်ပါပြီ။ ဆက်တင်များ စခရင်ပေါ်တွင် Yats ကို အချိန်မရွေး စီမံခန့်ခွဲနိုင်ပါသည်။", "yat_popup_title": "သင့်ပိုက်ဆံအိတ်လိပ်စာကို emoji အဖြစ်ပြောင်းလဲနိုင်ပါသည်။", "yes": "ဟုတ်ကဲ့", + "yes_exit": "ဟုတ်ကဲ့။ ထွက်ပါ", "yesterday": "မနေ့က", "you_now_have_debit_card": "ယခု သင့်တွင် ဒက်ဘစ်ကတ် ရရှိပြီးပါပြီ", "you_pay": "သင်ပေးချေသည်", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index d538ef215..728ca3fc4 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -76,9 +76,11 @@ "approve_tokens": "Tokens goedkeuren", "apps": "Apps", "arbiscan_history": "ArbiScan-geschiedenis", + "are_you_sure_exit": "Weet je zeker dat je wilt afsluiten?", "arrive_in_this_address": "${currency} ${tag}komt aan op dit adres", "ascending": "Stijgend", "ask_each_time": "Vraag het elke keer", + "assets": "Activa", "auth_store_ban_timeout": "Blokkeringstime-out", "auth_store_banned_for": "Geblokkeerd voor ", "auth_store_banned_minutes": " minuten", @@ -88,6 +90,7 @@ "auto_generate_addresses": "Automatisch adressen genereren", "auto_generate_subaddresses": "Automatisch subadressen genereren", "automatic": "Automatisch", + "available": "Beschikbaar", "available_balance": "Beschikbaar saldo", "available_balance_description": "Het “Beschikbare saldo” of “Bevestigde saldo” zijn fondsen die direct kunnen worden uitgegeven. Als fondsen in het lagere saldo verschijnen maar niet in het bovenste saldo, dan moet je een paar minuten wachten tot de inkomende fondsen meer netwerkbevestigingen krijgen. Daarna kan het worden uitgegeven.", "avg_savings": "Gem. besparingen", @@ -124,6 +127,7 @@ "block_remaining": "1 blok resterend", "Blocks_remaining": "${status} resterende blokken", "bluetooth": "Bluetooth", + "bridging": "Bridgen", "bright_theme": "Helder", "bscscan_history": "BscScan-geschiedenis", "bump_fee": "Vergoeding verhogen", @@ -198,6 +202,7 @@ "choose_qr_code_format": "Kies QR-code-formaat", "choose_qr_code_format_note": "Kies het juiste formaat voor je hardware-wallet:", "choose_relay": "Kies een relay die je wilt gebruiken", + "choose_wallet": "Kies wallet", "choose_wallet_currency": "Kies een walletvaluta:", "choose_wallet_group": "Kies walletgroep", "clear": "Wissen", @@ -214,6 +219,8 @@ "color_theme": "Kleurthema", "coming_soon_tag": "Binnenkort", "commit_transaction_amount_fee": "Bevestig transactie\nBedrag: ${amount}\nKosten: ${fee}", + "compatible_services": "Compatibele services", + "compatible_services_desc": "Gebruik de Scan-tool om de volgende soorten QR-codes te lezen die door Cake Wallet worden ondersteund:", "configure": "Configureren", "confirm": "Bevestigen", "confirm_delete_template": "Met deze actie wordt deze sjabloon verwijderd. Wil je doorgaan?", @@ -277,6 +284,7 @@ "creating_new_wallet": "Nieuwe wallet aanmaken", "creating_new_wallet_error": "Fout: ${description}", "creation_date": "Aanmaakdatum", + "crypto_addresses": "Crypto-adressen", "csv_nothing_to_export": "Niets om te exporteren", "current_swap": "Huidige swap", "current_wallet": "Huidige wallet", @@ -299,6 +307,7 @@ "default_sell_provider": "Standaard verkoopprovider", "delete": "Verwijderen", "delete_account": "Account verwijderen", + "delete_this_node": "Deze node verwijderen", "delete_wallet": "Wallet verwijderen", "delete_wallet_confirm_message": "Weet je zeker dat je de wallet ${wallet_name} wilt verwijderen?", "deleteConnectionConfirmationPrompt": "Weet je zeker dat je de verbinding wilt verwijderen met", @@ -328,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO is een volledig gedecentraliseerde, door onderpand gedekte stablecoin gekoppeld aan de euro — beveiligd, veelzijdig en censuurbestendig zonder te moeten vertrouwen op orakels. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Om dEURO in te schakelen, moet je ETH in je wallet hebben.", "deuro_tx_commited_content": "Het kan een paar seconden duren voordat de transactie wordt bevestigd en weerspiegeld op het scherm", + "device_confirmation": "Apparaatbevestiging", "device_is_signing": "Apparaat ondertekent", "dfx_option_description": "Koop crypto met EUR & CHF. Voor retail- en zakelijke klanten in Europa", "did_you_back_up_seeds": "Heb je een back-up gemaakt van al je seeds?", @@ -464,6 +474,8 @@ "extracted_address_content": "Je stuurt fondsen naar\n${recipient_name}", "failed_authentication": "Mislukte authenticatie. ${state_error}", "faq": "FAQ", + "favorite_token": "Favoriete token", + "favorite_token_desc": "Het saldo van de favoriete token wordt op de saldokaart weergegeven.", "features": "Functies", "fee": "Kosten", "fee_less_than_min": "Geselecteerde vergoeding is lager dan het minimum, verhoog de vergoeding om de transactie te kunnen verzenden", @@ -489,6 +501,7 @@ "frozen": "Bevroren", "frozen_balance": "Bevroren saldo", "full_balance": "Volledig saldo", + "gallery": "Galerij", "gas_exceeds_allowance": "Gas vereist door transactie overschrijdt het toegestane maximum.", "gas_price": "Gasprijs", "general": "Algemeen", @@ -524,6 +537,7 @@ "how_to_connect": "Hoe te verbinden", "how_to_use": "Hoe te gebruiken", "how_to_use_card": "Hoe je deze kaart gebruikt", + "hww_exit_desc": "Hiermee wordt het lopende koppelingsproces met je hardware-apparaat beëindigd", "i_understand": "Ik begrijp het", "icon_style": "Pictogramstijl", "id": "ID: ", @@ -538,6 +552,7 @@ "infobox_auto_address": "Je ontvangstadres wisselt elke keer dat je een transactie ontvangt", "infobox_multichain": "Gebruik dit adres om een token of collectible te ontvangen op", "infobox_rotation": "Je ontvangstadres wisselt telkens wanneer je dit scherm sluit en opnieuw opent", + "input": "Invoer", "inputs": "Invoer", "insufficient_funds_for_tx": "Onvoldoende fondsen om de transactie met succes uit te voeren.", "insufficient_lamport_for_tx": "Je hebt niet genoeg SOL om de transactie en de transactiekosten te dekken. Voeg meer SOL toe aan je wallet of verminder de hoeveelheid SOL die je verzendt.", @@ -576,6 +591,7 @@ "litecoin_mweb_always_scan": "Stel MWEB altijd op scannen", "litecoin_mweb_description": "MWEB is een nieuw protocol dat snellere, goedkopere en meer privacy-vriendelijke transacties naar Litecoin brengt", "litecoin_mweb_dismiss": "Afwijzen", + "litecoin_mweb_display": "Toon MWEB op startscherm", "litecoin_mweb_display_card": "Toon MWEB-kaart", "litecoin_mweb_enable": "MWEB inschakelen", "litecoin_mweb_enable_later": "Je kunt ervoor kiezen om MWEB opnieuw in te schakelen onder weergave-instellingen.", @@ -602,6 +618,7 @@ "manage_pow_nodes": "PoW-nodes beheren", "manage_providers": "Providers beheren", "manage_yats": "Yats beheren", + "manual_input": "Handmatige invoer", "mark_as_redeemed": "Markeer als ingewisseld", "market_place": "Marketplace", "mask": "Masker", @@ -647,6 +664,7 @@ "nanogpt_subtitle": "Alle nieuwste modellen (GPT-5.3, Claude 4.6).\nGeen abonnement, betaal met crypto.", "narrow": "Smal", "network": "Netwerk", + "networks": "Netwerken", "new_first_wallet_text": "Je crypto veilig houden is een fluitje van een cent", "new_node_testing": "Nieuwe node testen", "new_subaddress_create": "Creëren", @@ -675,8 +693,10 @@ "node_new": "Nieuwe node", "node_port": "Node-poort", "node_reset_settings_title": "Reset instellingen", + "node_share_desc": "Scan deze QR-code vanaf het Scan-scherm om deze node te importeren.", "node_test": "Test", "nodes": "Nodes", + "nodes_desc": "Beheer bestaande nodes of voeg een aangepaste toe.", "nodes_list_reset_to_default_message": "Weet je zeker dat je de standaardinstellingen wilt herstellen?", "none_of_selected_providers_can_exchange": "Geen van de geselecteerde providers kan deze swap maken", "noNFTYet": "Nog geen NFT's", @@ -686,6 +706,7 @@ "note_tap_to_change": "Notitie (tik om te wijzigen)", "notification_permission_denied": "Meldingstoestemming is permanent geweigerd. Schakel deze handmatig in via de instellingen.", "nullURIError": "URI is null", + "ocp_desc": "Betaal met crypto in winkels", "offer_expires_in": "Aanbieding verloopt over: ", "offline": "Offline", "ok": "OK", @@ -712,8 +733,13 @@ "outputs": "Outputs", "overshot": "Overschreden", "overwrite_amount": "Bedrag overschrijven", + "pairing_code": "Koppelingscode", + "pairing_code_desc_1": "Je apparaat toont een koppelingscode.", + "pairing_code_desc_2": "Voer deze hier in om door te gaan", + "pairing_error": "Koppelingsfout", "pairingInvalidEvent": "Ongeldige koppelingsgebeurtenis", "passphrase": "Wachtwoordzin (optioneel)", + "passphrase_view_keys": "Wachtwoordzin", "passphrases_doesnt_match": "Wachtwoordzinnen komen niet overeen, probeer het opnieuw", "password": "Wachtwoord", "paste": "Plakken", @@ -729,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Het ontvangen van een Payjoin-transactie vereist dat je Bitcoin klaar hebt om te gebruiken.\n\nZodra je wallet fondsen heeft, wordt Payjoin automatisch ingeschakeld.", "payjoin_unavailable_sheet_title": "Waarom is Payjoin niet beschikbaar?", "payment_id": "Betaling ID: ", + "payment_invoices": "Betalingsfacturen", "payment_made_easy": "Betalingen gemakkelijk gemaakt", "payment_was_received": "Je betaling is ontvangen.", "payments": "Betalingen", @@ -808,6 +835,7 @@ "receive_to": "Ontvangen op", "received": "Ontvangen", "receiving": "Bezig met ontvangen", + "recieving": "Bezig met ontvangen", "recipient_address": "Adres ontvanger", "reconnect": "Opnieuw verbinden", "reconnect_alert_text": "Weet je zeker dat je opnieuw verbinding wilt maken?", @@ -883,6 +911,7 @@ "save": "Opslaan", "save_backup_password": "Zorg ervoor dat je je back-upwachtwoord hebt opgeslagen. Zonder dit kun je je back-upbestanden niet importeren.", "save_backup_password_alert": "Bewaar back-upwachtwoord", + "save_contact": "Contact opslaan", "save_to_downloads": "Opslaan in downloads", "saved_the_trade_id": "Ik heb de trade-ID opgeslagen", "savings": "Spaargeld", @@ -1032,6 +1061,7 @@ "setup_your_debit_card": "Stel je debetkaart in", "share": "Deel", "share_address": "Deel adres", + "share_this_node": "Deel deze node", "shared_seed_wallet_groups": "Gedeelde seed-walletgroepen", "shared_seed_wallets": "Gedeelde seed-wallets", "show": "Tonen", @@ -1039,6 +1069,7 @@ "show_balance": "Lang indrukken om saldo te tonen", "show_balance_send_page": "Tik om te tonen", "show_balance_toast": "Lang indrukken om saldo te verbergen of te tonen", + "show_combined_balance": "Toon gecombineerd saldo", "show_details": "Toon details", "show_hidden_addresses": "Verborgen adressen tonen", "show_keys": "Toon seed/sleutels", @@ -1104,6 +1135,7 @@ "swap_providers": "Swapproviders", "sweeping_wallet": "Wallet wordt geveegd", "sweeping_wallet_alert": "Dit duurt niet lang. VERLAAT DIT SCHERM NIET, ANDERS KUNNEN DE FONDSEN VERLOREN GAAN.", + "swipe_to_bridge": "Veeg om te bridgen", "swipe_to_send": "Swipe om te verzenden", "switch_wallet": "Wissel van wallet", "switchToETHWallet": "Schakel over naar een Ethereum-wallet en probeer het opnieuw", @@ -1144,6 +1176,7 @@ "testnet_coins_no_value": "Testnet-munten hebben geen waarde", "third_intro_content": "Yats bestaan ook buiten Cake Wallet. Elk walletadres op aarde kan worden vervangen door een Yat!", "third_intro_title": "Yat werkt goed samen met anderen", + "this_can_take_few_seconds": "Dit kan een paar seconden duren", "this_pair_is_not_supported_warning": "Dit paar wordt niet ondersteund met de momenteel geselecteerde exchange(s). Selecteer een andere exchange.", "thorchain_contract_address_not_supported": "THORChain ondersteunt het verzenden naar een contractadres niet", "thorchain_taproot_address_not_supported": "De THORChain-provider ondersteunt geen Taproot-adressen. Wijzig het adres of selecteer een andere provider.", @@ -1157,6 +1190,7 @@ "token_decimal": "Token decimaal (bijv. 6 voor USDT)", "token_name": "Tokennaam (bijv. Tether)", "token_symbol": "Tokensymbool (bijv. USDT)", + "token_verified_on_jupiter": "Dit token is geverifieerd op Jupiter", "tokenID": "Token-ID", "tokens": "Tokens", "tokens_strong_warning": "Stuur nooit tokens naar dit adres!", @@ -1285,6 +1319,7 @@ "username": "Gebruikersnaam", "username_available": "Gebruikersnaam beschikbaar", "username_character_error": "Gebruikersnamen mogen alleen bevatten", + "username_check_your_network": "Kan gebruikersnaam niet controleren. Controleer je netwerkverbinding.", "username_length_error": "Gebruikersnamen moeten 6-32 alfanumerieke tekens bevatten.", "username_length_error_1_64": "Gebruikersnamen moeten 1-64 alfanumerieke tekens bevatten.", "username_not_available": "Deze gebruikersnaam is niet beschikbaar.", @@ -1295,6 +1330,7 @@ "verify_message": "Verifieer bericht", "verify_seed": "Controleer seed", "verify_with_2fa": "Controleer met Cake 2FA", + "verifying_code": "Code verifiëren", "version": "Versie ${currentVersion}", "view_all": "Alles bekijken", "view_in_block_explorer": "Bekijk in Block Explorer", @@ -1307,6 +1343,7 @@ "waiting_payment_confirmation": "In afwachting van betalingsbevestiging", "wallet": "Wallet", "wallet_accounts": "Walletaccounts", + "wallet_balance": "Walletsaldo", "wallet_group": "Walletgroep", "wallet_group_description_existing_seed": "Je hebt ervoor gekozen om een bestaande seed voor deze wallet te gebruiken. Je kunt de seed opnieuw verifiëren als je het moet bevestigen of opschrijven.", "wallet_group_description_four": "om een wallet te maken met een geheel nieuwe seed.", @@ -1344,9 +1381,11 @@ "walletConnect": "WalletConnect", "wallets": "Wallets", "warning": "Waarschuwing", + "wc_action_approve": "Goedkeuren", "wc_approve_request_title": "Aanvraag goedkeuren", "wc_connect_request_title": "Verbind verzoek", "wc_connected_to": "Verbonden met ${name}", + "wc_desc": "Maak eenvoudig verbinding met dApps", "wc_max_network_fee": "Maximale netwerkkosten", "wc_message_to_sign": "Bericht om te ondertekenen", "wc_network_fee": "Netwerk vergoeding", @@ -1397,6 +1436,7 @@ "yat_popup_content": "Je kunt nu crypto verzenden en ontvangen in Cake Wallet met je Yat - een korte, op emoji gebaseerde gebruikersnaam. Beheer Yats op elk moment op het instellingenscherm", "yat_popup_title": "Je walletadres kan worden omgezet naar emoji's.", "yes": "Ja", + "yes_exit": "Ja. Afsluiten", "yesterday": "Gisteren", "you_now_have_debit_card": "Je hebt nu een debetkaart", "you_pay": "Je betaalt", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 530163022..977141c2a 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -76,6 +76,7 @@ "approve_tokens": "Zatwierdź tokeny", "apps": "Aplikacje", "arbiscan_history": "Historia ArbiScan", + "are_you_sure_exit": "Czy na pewno chcesz wyjść?", "arrive_in_this_address": "${currency} ${tag}dotrze na ten adres", "ascending": "Rosnąco", "ask_each_time": "Pytaj za każdym razem", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Automatyczne generowanie adresów", "auto_generate_subaddresses": "Automatyczne generowanie podadresów", "automatic": "Automatyczny", + "available": "Dostępne", "available_balance": "Dostępne saldo", "available_balance_description": "„Dostępne saldo” lub „Potwierdzone saldo” to środki, które można wydać od razu. Jeśli środki pojawiają się w dolnym saldzie, ale nie w górnym, musisz poczekać kilka minut, aż przychodzące środki uzyskają więcej potwierdzeń sieci. Gdy uzyskają więcej potwierdzeń, będzie można je wydać.", "avg_savings": "Śr. oszczędności", @@ -125,6 +127,7 @@ "block_remaining": "Pozostał 1 blok", "Blocks_remaining": "Pozostało bloków: ${status}", "bluetooth": "Bluetooth", + "bridging": "Mostkowanie", "bright_theme": "Jasny", "bscscan_history": "Historia BSCScan", "bump_fee": "Podbij opłatę", @@ -216,6 +219,8 @@ "color_theme": "Motyw kolorystyczny", "coming_soon_tag": "Wkrótce", "commit_transaction_amount_fee": "Zatwierdź transakcję\nKwota: ${amount}\nOpłata: ${fee}", + "compatible_services": "Zgodne usługi", + "compatible_services_desc": "Użyj narzędzia Skanuj, aby odczytać następujące typy kodów QR obsługiwane w Cake Wallet:", "configure": "Konfiguruj", "confirm": "Potwierdź", "confirm_delete_template": "Ta czynność usunie ten szablon. Czy chcesz kontynuować?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Tworzenie nowego portfela", "creating_new_wallet_error": "Błąd: ${description}", "creation_date": "Data utworzenia", + "crypto_addresses": "Adresy krypto", "csv_nothing_to_export": "Brak danych do eksportu", "current_swap": "Bieżący swap", "current_wallet": "Bieżący portfel", @@ -301,6 +307,7 @@ "default_sell_provider": "Domyślny dostawca sprzedaży", "delete": "Usuń", "delete_account": "Usuń konto", + "delete_this_node": "Usuń ten węzeł", "delete_wallet": "Usuń portfel", "delete_wallet_confirm_message": "Czy na pewno chcesz usunąć portfel ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Czy na pewno chcesz usunąć połączenie z", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO jest w pełni zdecentralizowanym, zabezpieczonym stablecoinem powiązanym z euro — bezpiecznym, wszechstronnym i odpornym na cenzurę, bez konieczności polegania na wyroczniach. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Aby włączyć dEURO, musisz mieć ETH w swoim portfelu.", "deuro_tx_commited_content": "Może to potrwać kilka sekund, zanim transakcja zostanie potwierdzona i pojawi się na ekranie", + "device_confirmation": "Potwierdzenie na urządzeniu", "device_is_signing": "Urządzenie podpisuje", "dfx_option_description": "Kup kryptowaluty za EUR i CHF. Dla klientów detalicznych i firm w Europie", "did_you_back_up_seeds": "Czy wykonałeś kopię zapasową wszystkich fraz seed?", @@ -435,6 +443,7 @@ "etherscan_history": "Historia w Etherscan", "event": "Zdarzenie", "events": "Zdarzenia", + "evm_ecosystem_description": "W razie potrzeby zmień sieć i token, których chcesz użyć do tej płatności.", "exchange": "Wymiana", "exchange_extra_info": "Proszę nie zapomnieć podać Memo lub Extra ID podczas wysyłania tej transakcji do wymiany", "exchange_incorrect_current_wallet_for_xmr": "Jeśli chcesz wymienić XMR z salda Monero w Cake Wallet, najpierw przełącz się na swój portfel Monero.", @@ -465,6 +474,8 @@ "extracted_address_content": "Wyślesz środki do\n${recipient_name}", "failed_authentication": "Nieudane uwierzytelnienie. ${state_error}", "faq": "FAQ", + "favorite_token": "Ulubiony token", + "favorite_token_desc": "Saldo ulubionego tokena będzie wyświetlane na karcie salda.", "features": "Funkcje", "fee": "Opłata", "fee_less_than_min": "Wybrana opłata jest niższa niż minimalna. Zwiększ opłatę, aby móc wysłać transakcję.", @@ -490,6 +501,7 @@ "frozen": "Zamrożone", "frozen_balance": "Zamrożone saldo", "full_balance": "Pełne saldo", + "gallery": "Galeria", "gas_exceeds_allowance": "Gaz wymagany przez transakcję przekracza dozwolony limit.", "gas_price": "Cena gas", "general": "Ogólne", @@ -525,6 +537,7 @@ "how_to_connect": "Jak się połączyć", "how_to_use": "Jak używać", "how_to_use_card": "Jak używać tej karty", + "hww_exit_desc": "Spowoduje to zakończenie trwającego procesu parowania z Twoim urządzeniem sprzętowym", "i_understand": "Rozumiem", "icon_style": "Styl ikony", "id": "ID: ", @@ -539,6 +552,7 @@ "infobox_auto_address": "Twój adres do odbioru będzie się zmieniał za każdym razem, gdy otrzymasz transakcję", "infobox_multichain": "Użyj tego adresu, aby otrzymać dowolny token lub przedmiot kolekcjonerski na", "infobox_rotation": "Twój adres do odbioru będzie się zmieniać za każdym razem, gdy zamkniesz i ponownie otworzysz ten ekran", + "input": "Dane wejściowe", "inputs": "Wejścia", "insufficient_funds_for_tx": "Niewystarczające środki, aby pomyślnie zrealizować transakcję.", "insufficient_lamport_for_tx": "Nie masz wystarczającej ilości SOL, aby pokryć transakcję oraz opłatę transakcyjną. Dodaj więcej SOL do swojego portfela lub zmniejsz kwotę SOL, którą wysyłasz.", @@ -604,6 +618,7 @@ "manage_pow_nodes": "Zarządzaj węzłami PoW", "manage_providers": "Zarządzaj dostawcami", "manage_yats": "Zarządzaj Yats", + "manual_input": "Wprowadzanie ręczne", "mark_as_redeemed": "Oznacz jako zrealizowane", "market_place": "Marketplace", "mask": "Maska", @@ -649,6 +664,7 @@ "nanogpt_subtitle": "Wszystkie najnowsze modele (GPT-5.3, Claude 4.6).\nBez subskrypcji, płać kryptowalutą.", "narrow": "Wąski", "network": "Sieć", + "networks": "Sieci", "new_first_wallet_text": "Bezpieczne przechowywanie Twoich kryptowalut to bułka z masłem", "new_node_testing": "Testowanie nowego węzła", "new_subaddress_create": "Utwórz", @@ -677,8 +693,10 @@ "node_new": "Nowy węzeł", "node_port": "Port węzła", "node_reset_settings_title": "Resetuj ustawienia", + "node_share_desc": "Zeskanuj ten kod QR z ekranu Skanuj, aby zaimportować ten węzeł.", "node_test": "Test", "nodes": "Węzły", + "nodes_desc": "Zarządzaj istniejącymi węzłami lub dodaj własny.", "nodes_list_reset_to_default_message": "Czy na pewno chcesz przywrócić ustawienia domyślne?", "none_of_selected_providers_can_exchange": "Żaden z wybranych dostawców nie może wykonać tej wymiany", "noNFTYet": "Brak NFT", @@ -688,6 +706,7 @@ "note_tap_to_change": "Notatka (stuknij, aby zmienić)", "notification_permission_denied": "Uprawnienie do powiadomień zostało trwale odrzucone. Włącz je ręcznie w ustawieniach.", "nullURIError": "URI ma wartość null", + "ocp_desc": "Płać kryptowalutą w sklepach", "offer_expires_in": "Oferta wygasa za: ", "offline": "Offline", "ok": "OK", @@ -714,8 +733,13 @@ "outputs": "Wyjścia", "overshot": "Przekroczono", "overwrite_amount": "Nadpisz kwotę", + "pairing_code": "Kod parowania", + "pairing_code_desc_1": "Twoje urządzenie wyświetli kod parowania.", + "pairing_code_desc_2": "Wprowadź go tutaj, aby kontynuować", + "pairing_error": "Błąd parowania", "pairingInvalidEvent": "Nieprawidłowe zdarzenie parowania", "passphrase": "Fraza hasła (Opcjonalnie)", + "passphrase_view_keys": "Fraza hasła", "passphrases_doesnt_match": "Hasła nie pasują, spróbuj ponownie", "password": "Hasło", "paste": "Wklej", @@ -731,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Otrzymanie transakcji Payjoin wymaga posiadania gotowych do użycia bitcoinów.\n\nGdy tylko w Twoim portfelu pojawią się środki, Payjoin zostanie automatycznie włączony.", "payjoin_unavailable_sheet_title": "Dlaczego Payjoin jest niedostępny?", "payment_id": "Identyfikator płatności: ", + "payment_invoices": "Faktury płatności", "payment_made_easy": "Płatności są proste", "payment_was_received": "Twoja płatność została otrzymana.", "payments": "Płatności", @@ -810,6 +835,7 @@ "receive_to": "Odbierz na", "received": "Otrzymane", "receiving": "Odbieranie", + "recieving": "Odbieranie", "recipient_address": "Adres odbiorcy", "reconnect": "Połącz ponownie", "reconnect_alert_text": "Czy na pewno chcesz połączyć się ponownie?", @@ -885,6 +911,7 @@ "save": "Zapisz", "save_backup_password": "Upewnij się, że zapisałeś hasło do kopii zapasowej. Bez niego nie będziesz mógł zaimportować plików kopii zapasowej.", "save_backup_password_alert": "Zapisz hasło kopii zapasowej", + "save_contact": "Zapisz kontakt", "save_to_downloads": "Zapisz w folderze Pobrane", "saved_the_trade_id": "Zapisałem identyfikator transakcji", "savings": "Oszczędności", @@ -1034,6 +1061,7 @@ "setup_your_debit_card": "Skonfiguruj swoją kartę debetową", "share": "Udostępnij", "share_address": "Udostępnij adres", + "share_this_node": "Udostępnij ten węzeł", "shared_seed_wallet_groups": "Grupy portfeli ze współdzielonym seedem", "shared_seed_wallets": "Portfele ze współdzieloną frazą seed", "show": "Pokaż", @@ -1041,6 +1069,7 @@ "show_balance": "Naciśnij i przytrzymaj, aby wyświetlić saldo", "show_balance_send_page": "Dotknij, aby odkryć", "show_balance_toast": "Naciśnij i przytrzymaj, aby ukryć lub pokazać saldo", + "show_combined_balance": "Pokaż łączne saldo", "show_details": "Pokaż szczegóły", "show_hidden_addresses": "Pokaż ukryte adresy", "show_keys": "Pokaż seed/klucze", @@ -1106,6 +1135,7 @@ "swap_providers": "Dostawcy wymiany", "sweeping_wallet": "Opróżnianie portfela", "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE OPUSZCZAJ TEGO EKRANU, W PRZECIWNYM RAZIE ZAMIATANE ŚRODKI MOGĄ ZOSTAĆ UTRACONE.", + "swipe_to_bridge": "Przesuń, aby zmostkować", "swipe_to_send": "Przesuń, aby wysłać", "switch_wallet": "Przełącz portfel", "switchToETHWallet": "Przełącz się na portfel Ethereum i spróbuj ponownie", @@ -1146,6 +1176,7 @@ "testnet_coins_no_value": "Monety testnet nie mają wartości", "third_intro_content": "Yaty działają także poza Cake Wallet. Każdy adres portfela na świecie można zastąpić Yatem!", "third_intro_title": "Yat dobrze współpracuje z innymi", + "this_can_take_few_seconds": "To może potrwać kilka sekund", "this_pair_is_not_supported_warning": "Ta para nie jest obsługiwana przez aktualnie wybraną giełdę/wybrane giełdy. Wybierz inną giełdę.", "thorchain_contract_address_not_supported": "THORChain nie obsługuje wysyłania na adres kontraktu", "thorchain_taproot_address_not_supported": "Dostawca ThorChain nie obsługuje adresów Taproot. Zmień adres lub wybierz innego dostawcę.", @@ -1159,6 +1190,7 @@ "token_decimal": "Liczba miejsc dziesiętnych tokena (np. USDT)", "token_name": "Nazwa tokena (np. Tether)", "token_symbol": "Symbol tokenu (np.: USDT)", + "token_verified_on_jupiter": "Token ten jest zweryfikowany na Jupiterze", "tokenID": "ID", "tokens": "Tokeny", "tokens_strong_warning": "Nigdy nie wysyłaj tokenów na ten adres!", @@ -1287,6 +1319,7 @@ "username": "Nazwa użytkownika", "username_available": "Nazwa użytkownika dostępna", "username_character_error": "Nazwy użytkowników mogą zawierać tylko", + "username_check_your_network": "Nie można sprawdzić nazwy użytkownika. Sprawdź połączenie sieciowe.", "username_length_error": "Nazwy użytkowników muszą zawierać 6–32 znaki alfanumeryczne.", "username_length_error_1_64": "Nazwy użytkowników muszą zawierać 1–64 znaki alfanumeryczne.", "username_not_available": "Ta nazwa użytkownika jest niedostępna.", @@ -1297,6 +1330,7 @@ "verify_message": "Zweryfikuj wiadomość", "verify_seed": "Zweryfikuj frazę seed", "verify_with_2fa": "Zweryfikuj za pomocą Cake 2FA", + "verifying_code": "Weryfikowanie kodu", "version": "Wersja ${currentVersion}", "view_all": "Zobacz wszystko", "view_in_block_explorer": "Wyświetl w eksploratorze bloków", @@ -1308,6 +1342,7 @@ "waitFewSecondForTxUpdate": "Proszę poczekać kilka sekund, aż transakcja pojawi się w historii transakcji", "wallet": "Portfel", "wallet_accounts": "Konta portfela", + "wallet_balance": "Saldo portfela", "wallet_group": "Grupa portfeli", "wallet_group_description_existing_seed": "Wybrałeś użycie istniejącego seeda dla tego portfela. Możesz ponownie zweryfikować seed, jeśli potrzebujesz go potwierdzić lub zapisać.", "wallet_group_description_four": "aby utworzyć portfel z całkowicie nowym seedem.", @@ -1345,9 +1380,11 @@ "walletConnect": "WalletConnect", "wallets": "Portfele", "warning": "Ostrzeżenie", + "wc_action_approve": "Zatwierdź", "wc_approve_request_title": "Zatwierdź żądanie", "wc_connect_request_title": "Połącz żądanie", "wc_connected_to": "Połączono z ${name}", + "wc_desc": "Łatwo łącz się z aplikacjami dApp", "wc_max_network_fee": "Maksymalna opłata sieciowa", "wc_message_to_sign": "Wiadomość do podpisania", "wc_network_fee": "Opłata sieciowa", @@ -1398,6 +1435,7 @@ "yat_popup_content": "Możesz teraz wysyłać i odbierać kryptowaluty w Cake Wallet za pomocą swojego Yat — krótkiej, opartej na emoji nazwy użytkownika. Zarządzaj Yatami w dowolnym momencie na ekranie ustawień", "yat_popup_title": "Twój adres portfela może zostać zamieniony na emoji.", "yes": "Tak", + "yes_exit": "Tak. Wyjdź", "yesterday": "Wczoraj", "you_now_have_debit_card": "Masz teraz kartę debetową", "you_pay": "Płacisz", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index e357dc89d..48bd607ec 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -76,6 +76,7 @@ "approve_tokens": "Aprovar tokens", "apps": "Apps", "arbiscan_history": "Histórico do ArbiScan", + "are_you_sure_exit": "Tem a certeza de que pretende sair?", "arrive_in_this_address": "${currency} ${tag}chegará a este endereço", "ascending": "Ascendente", "ask_each_time": "Perguntar sempre", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Gerar endereços automaticamente", "auto_generate_subaddresses": "Gerar subendereços automaticamente", "automatic": "Automático", + "available": "Disponível", "available_balance": "Saldo disponível", "available_balance_description": "O “Saldo Disponível” ou “Saldo Confirmado” são fundos que podem ser gastos imediatamente. Se os fundos aparecerem no saldo inferior, mas não no saldo superior, você deve aguardar alguns minutos para que os fundos recebidos obtenham mais confirmações na rede. Depois que tiverem mais confirmações, eles poderão ser gastos.", "avg_savings": "Poupança média", @@ -125,6 +127,7 @@ "block_remaining": "1 Bloco restante", "Blocks_remaining": "${status} Blocos restantes", "bluetooth": "Bluetooth", + "bridging": "A fazer bridge", "bright_theme": "Claro", "bscscan_history": "Histórico do BSCScan", "bump_fee": "Aumentar taxa", @@ -216,6 +219,8 @@ "color_theme": "Tema de cores", "coming_soon_tag": "Em breve", "commit_transaction_amount_fee": "Confirmar transação\nValor: ${amount}\nTaxa: ${fee}", + "compatible_services": "Serviços compatíveis", + "compatible_services_desc": "Use a ferramenta de digitalização para ler os seguintes tipos de códigos QR suportados na Cake Wallet:", "configure": "Configurar", "confirm": "Confirmar", "confirm_delete_template": "Esta ação excluirá este modelo. Deseja continuar?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Criando nova carteira", "creating_new_wallet_error": "Erro: ${description}", "creation_date": "Data de criação", + "crypto_addresses": "Endereços de cripto", "csv_nothing_to_export": "Nada para exportar", "current_swap": "Troca atual", "current_wallet": "Carteira atual", @@ -301,6 +307,7 @@ "default_sell_provider": "Provedor de venda padrão", "delete": "Excluir", "delete_account": "Excluir conta", + "delete_this_node": "Eliminar este nó", "delete_wallet": "Excluir carteira", "delete_wallet_confirm_message": "Tem certeza de que deseja excluir a carteira ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Tem certeza de que deseja excluir a conexão com", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO é uma stablecoin totalmente descentralizada e colateralizada, atrelada ao euro — segura, versátil e resistente à censura, sem precisar depender de oráculos. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Para ativar dEURO, você deve ter ETH na sua carteira.", "deuro_tx_commited_content": "Pode levar alguns segundos para a transação ser confirmada e aparecer na tela", + "device_confirmation": "Confirmação no dispositivo", "device_is_signing": "O dispositivo está assinando", "dfx_option_description": "Compre cripto com EUR e CHF. Para clientes de varejo e corporativos na Europa", "did_you_back_up_seeds": "Você fez backup de todas as suas seeds?", @@ -466,6 +474,8 @@ "extracted_address_content": "Você enviará fundos para\n${recipient_name}", "failed_authentication": "Falha na autenticação. ${state_error}", "faq": "FAQ", + "favorite_token": "Token favorito", + "favorite_token_desc": "O saldo do token favorito será apresentado no cartão de saldo.", "features": "Recursos", "fee": "Taxa", "fee_less_than_min": "A taxa selecionada é inferior ao mínimo. Aumente a taxa para poder enviar a transação.", @@ -491,6 +501,7 @@ "frozen": "Congelado", "frozen_balance": "Saldo congelado", "full_balance": "Saldo total", + "gallery": "Galeria", "gas_exceeds_allowance": "O gás exigido pela transação excede o limite permitido.", "gas_price": "Preço do gas", "general": "Geral", @@ -526,6 +537,7 @@ "how_to_connect": "Como Conectar", "how_to_use": "Como usar", "how_to_use_card": "Como usar este cartão", + "hww_exit_desc": "Isto irá terminar o processo de emparelhamento em curso com o seu dispositivo de hardware", "i_understand": "Eu entendo", "icon_style": "Estilo do ícone", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Seu endereço de recebimento mudará a cada transação recebida", "infobox_multichain": "Use este endereço para receber qualquer token ou colecionável em", "infobox_rotation": "Seu endereço de recebimento será alterado sempre que você fechar e reabrir esta tela", + "input": "Entrada", "inputs": "Entradas", "insufficient_funds_for_tx": "Fundos insuficientes para executar a transação com sucesso.", "insufficient_lamport_for_tx": "Você não tem SOL suficiente para cobrir a transação e a taxa de transação. Por favor, adicione mais SOL à sua carteira ou reduza a quantidade de SOL que você está enviando.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Gerenciar nós de PoW", "manage_providers": "Gerenciar provedores", "manage_yats": "Gerenciar Yats", + "manual_input": "Introdução manual", "mark_as_redeemed": "Marcar como resgatado", "mark_as_redemed": "Marcar como resgatado", "market_place": "Marketplace", @@ -651,6 +665,7 @@ "nanogpt_subtitle": "Todos os modelos mais recentes (GPT-5.3, Claude 4.6).\nSem assinatura, pague com cripto.", "narrow": "Estreito", "network": "Rede", + "networks": "Redes", "new_first_wallet_text": "Manter suas criptos seguras é moleza", "new_node_testing": "Teste de novo nó", "new_subaddress_create": "Criar", @@ -679,8 +694,10 @@ "node_new": "Novo nó", "node_port": "Porta do nó", "node_reset_settings_title": "Redefinir configurações", + "node_share_desc": "Digitalize este código QR a partir do ecrã de digitalização para importar este nó.", "node_test": "Teste", "nodes": "Nós", + "nodes_desc": "Faça a gestão dos nós existentes ou adicione um personalizado.", "nodes_list_reset_to_default_message": "Tem certeza de que deseja redefinir as configurações para o padrão?", "none_of_selected_providers_can_exchange": "Nenhum dos provedores selecionados pode realizar esta troca", "noNFTYet": "Ainda não há NFTs", @@ -690,6 +707,7 @@ "note_tap_to_change": "Nota (toque para mudar)", "notification_permission_denied": "A permissão de notificações foi negada permanentemente. Ative-a manualmente nas configurações.", "nullURIError": "O URI é nulo", + "ocp_desc": "Pague com cripto em lojas", "offer_expires_in": "A oferta expira em: ", "offline": "Offline", "ok": "OK", @@ -717,8 +735,13 @@ "outputs": "Saídas", "overshot": "Excedido", "overwrite_amount": "Substituir valor", + "pairing_code": "Código de emparelhamento", + "pairing_code_desc_1": "O seu dispositivo irá mostrar um código de emparelhamento.", + "pairing_code_desc_2": "Introduza-o aqui para continuar", + "pairing_error": "Erro de emparelhamento", "pairingInvalidEvent": "Evento de emparelhamento inválido", "passphrase": "Frase-senha (Opcional)", + "passphrase_view_keys": "Frase-senha", "passphrases_doesnt_match": "As frases-passe não correspondem, por favor tente novamente", "password": "Senha", "paste": "Colar", @@ -734,6 +757,7 @@ "payjoin_unavailable_sheet_content": "Receber uma transação Payjoin exige que você tenha Bitcoin pronto para uso.\n\nAssim que sua carteira tiver fundos, o Payjoin será ativado automaticamente.", "payjoin_unavailable_sheet_title": "Por que o Payjoin não está disponível?", "payment_id": "ID do pagamento: ", + "payment_invoices": "Faturas de pagamento", "payment_made_easy": "Pagamentos facilitados", "payment_was_received": "Seu pagamento foi recebido.", "payments": "Pagamentos", @@ -813,6 +837,7 @@ "receive_to": "Receber para", "received": "Recebido", "receiving": "Recebendo", + "recieving": "A receber", "recipient_address": "Endereço do destinatário", "reconnect": "Reconectar", "reconnect_alert_text": "Tem certeza de que deseja reconectar?", @@ -888,6 +913,7 @@ "save": "Salvar", "save_backup_password": "Certifique-se de que salvou a sua senha de backup. Você não poderá importar os seus arquivos de backup sem ela.", "save_backup_password_alert": "Salvar senha do backup", + "save_contact": "Guardar contacto", "save_to_downloads": "Salvar em Downloads", "saved_the_trade_id": "Salvei o ID da troca", "savings": "Poupança", @@ -1037,6 +1063,7 @@ "setup_your_debit_card": "Configure seu cartão de débito", "share": "Compartilhar", "share_address": "Compartilhar endereço", + "share_this_node": "Partilhar este nó", "shared_seed_wallet_groups": "Grupos de carteiras com seed compartilhada", "shared_seed_wallets": "Carteiras com frase-semente compartilhada", "show": "Mostrar", @@ -1044,6 +1071,7 @@ "show_balance": "Pressione e segure para mostrar o saldo", "show_balance_send_page": "Toque para revelar", "show_balance_toast": "Pressione e segure para ocultar ou mostrar o saldo", + "show_combined_balance": "Mostrar saldo combinado", "show_details": "Mostrar detalhes", "show_hidden_addresses": "Mostrar endereços ocultos", "show_keys": "Mostrar seed/chaves", @@ -1109,6 +1137,7 @@ "swap_providers": "Provedores de swap", "sweeping_wallet": "Carteira de varredura", "sweeping_wallet_alert": "Isso não deve demorar muito. NÃO SAIA DESTA TELA OU OS FUNDOS VARRIDOS PODEM SER PERDIDOS.", + "swipe_to_bridge": "Deslize para fazer bridge", "swipe_to_send": "Deslize para enviar", "switch_wallet": "Alternar carteira", "switchToETHWallet": "Por favor, mude para uma carteira Ethereum e tente novamente", @@ -1149,6 +1178,7 @@ "testnet_coins_no_value": "As moedas de testnet não têm valor", "third_intro_content": "Os Yats também existem fora da Cake Wallet. Qualquer endereço de carteira no mundo pode ser substituído por um Yat!", "third_intro_title": "Yat funciona bem com os outros", + "this_can_take_few_seconds": "Isto pode demorar alguns segundos", "this_pair_is_not_supported_warning": "Este par não é suportado com a(s) exchange(s) selecionada(s) atualmente. Selecione outra exchange.", "thorchain_contract_address_not_supported": "A THORChain não suporta envios para um endereço de contrato", "thorchain_taproot_address_not_supported": "O provedor ThorChain não oferece suporte a endereços Taproot. Altere o endereço ou selecione um provedor diferente.", @@ -1162,6 +1192,7 @@ "token_decimal": "Decimal do token (ex: USDT)", "token_name": "Nome do token (ex.: Tether)", "token_symbol": "Símbolo do token (ex.: USDT)", + "token_verified_on_jupiter": "Este token é verificado em Jupiter", "tokenID": "ID", "tokens": "Tokens", "tokens_strong_warning": "Nunca envie tokens para este endereço!", @@ -1290,6 +1321,7 @@ "username": "Nome de usuário", "username_available": "Nome de usuário disponível", "username_character_error": "Os nomes de usuário devem conter apenas", + "username_check_your_network": "Não foi possível verificar o nome de utilizador. Verifique a sua ligação de rede.", "username_length_error": "Os nomes de usuário devem conter de 6 a 32 caracteres alfanuméricos.", "username_length_error_1_64": "Os nomes de usuário devem conter de 1 a 64 caracteres alfanuméricos.", "username_not_available": "Este nome de usuário não está disponível.", @@ -1300,6 +1332,7 @@ "verify_message": "Verificar mensagem", "verify_seed": "Verificar a seed", "verify_with_2fa": "Verificar com o Cake 2FA", + "verifying_code": "A verificar o código", "version": "Versão ${currentVersion}", "view_all": "Ver tudo", "view_in_block_explorer": "Ver no Explorador de Blocos", @@ -1312,6 +1345,7 @@ "waiting_payment_confirmation": "Aguardando confirmação de pagamento", "wallet": "Carteira", "wallet_accounts": "Contas da carteira", + "wallet_balance": "Saldo da carteira", "wallet_group": "Grupo de carteiras", "wallet_group_description_existing_seed": "Você optou por usar uma seed existente para esta carteira. Você pode verificar a seed novamente se precisar confirmar ou anotá-la.", "wallet_group_description_four": "para criar uma carteira com uma semente totalmente nova.", @@ -1349,9 +1383,11 @@ "walletConnect": "WalletConnect", "wallets": "Carteiras", "warning": "Aviso", + "wc_action_approve": "Aprovar", "wc_approve_request_title": "Aprovar solicitação", "wc_connect_request_title": "Solicitação de conexão", "wc_connected_to": "Conectado a ${name}", + "wc_desc": "Ligue-se facilmente a DApps", "wc_max_network_fee": "Taxa máxima de rede", "wc_message_to_sign": "Mensagem para assinar", "wc_network_fee": "Taxa de rede", @@ -1402,6 +1438,7 @@ "yat_popup_content": "Agora você pode enviar e receber cripto na Cake Wallet com seu Yat — um nome de usuário curto baseado em emojis. Gerencie Yats a qualquer momento na tela de configurações", "yat_popup_title": "O endereço da sua carteira pode ser transformado em emojis.", "yes": "Sim", + "yes_exit": "Sim. Sair", "yesterday": "Ontem", "you_now_have_debit_card": "Agora você tem um cartão de débito", "you_pay": "Você paga", diff --git a/res/values/strings_pt_BR.arb b/res/values/strings_pt_BR.arb index 215136300..1398bd905 100644 --- a/res/values/strings_pt_BR.arb +++ b/res/values/strings_pt_BR.arb @@ -1140,6 +1140,7 @@ "token_name": "Nome do token (ex: Tether)", "token_symbol": "Símbolo do token (ex: USDT)", "tokenID": "ID", + "token_verified_on_jupiter": "Este token é verificado em Jupiter", "tokens": "Tokens", "tokens_strong_warning": "Nunca envie tokens para este endereço!", "tor_connection": "Conexão Tor", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 9ce39e077..40e3fca3c 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -76,6 +76,7 @@ "approve_tokens": "Одобрить токены", "apps": "Приложения", "arbiscan_history": "История ArbiScan", + "are_you_sure_exit": "Вы уверены, что хотите выйти?", "arrive_in_this_address": "${currency} ${tag}поступит на этот адрес", "ascending": "По возрастанию", "ask_each_time": "Спрашивать каждый раз", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Автоматически генерировать адреса", "auto_generate_subaddresses": "Автоматически генерировать субадреса", "automatic": "Автоматически", + "available": "Доступно", "available_balance": "Доступный баланс", "available_balance_description": "«Доступный баланс» или «Подтверждённый баланс» — это средства, которые можно потратить сразу. Если средства отображаются в нижнем балансе, но не в верхнем, значит, нужно подождать несколько минут, пока входящие средства получат больше подтверждений сети. После получения дополнительных подтверждений их можно будет потратить.", "avg_savings": "Средняя экономия", @@ -125,6 +127,7 @@ "block_remaining": "Остался 1 блок", "Blocks_remaining": "${status} блоков осталось", "bluetooth": "Bluetooth", + "bridging": "Перенос через мост", "bright_theme": "Светлая", "bscscan_history": "История BSCScan", "bump_fee": "Увеличить комиссию", @@ -216,6 +219,8 @@ "color_theme": "Цветовая тема", "coming_soon_tag": "Скоро", "commit_transaction_amount_fee": "Подтвердить транзакцию\nСумма: ${amount}\nКомиссия: ${fee}", + "compatible_services": "Совместимые сервисы", + "compatible_services_desc": "Используйте инструмент сканирования, чтобы считывать следующие типы QR-кодов, поддерживаемые в Cake Wallet:", "configure": "Настроить", "confirm": "Подтвердить", "confirm_delete_template": "Это действие удалит этот шаблон. Вы хотите продолжить?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Создание нового кошелька", "creating_new_wallet_error": "Ошибка: ${description}", "creation_date": "Дата создания", + "crypto_addresses": "Криптоадреса", "csv_nothing_to_export": "Нечего экспортировать", "current_swap": "Текущий обмен", "current_wallet": "Текущий кошелёк", @@ -301,6 +307,7 @@ "default_sell_provider": "Провайдер продажи по умолчанию", "delete": "Удалить", "delete_account": "Удалить аккаунт", + "delete_this_node": "Удалить этот узел", "delete_wallet": "Удалить кошелек", "delete_wallet_confirm_message": "Вы уверены, что хотите удалить кошелёк ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Вы уверены, что хотите удалить подключение к", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO — полностью децентрализованный обеспеченный стейблкоин, привязанный к евро: безопасный, универсальный и устойчивый к цензуре, без необходимости полагаться на оракулы. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Чтобы включить dEURO, в вашем кошельке должен быть ETH.", "deuro_tx_commited_content": "Подтверждение транзакции и её отображение на экране может занять пару секунд", + "device_confirmation": "Подтверждение на устройстве", "device_is_signing": "Устройство подписывает", "dfx_option_description": "Покупайте криптовалюту за EUR и CHF. Для розничных и корпоративных клиентов в Европе", "did_you_back_up_seeds": "Вы сделали резервную копию всех своих сид-фраз?", @@ -466,6 +474,8 @@ "extracted_address_content": "Вы отправляете средства\n${recipient_name}", "failed_authentication": "Ошибка аутентификации. ${state_error}", "faq": "FAQ", + "favorite_token": "Избранный токен", + "favorite_token_desc": "Баланс избранного токена будет отображаться на карточке баланса.", "features": "Возможности", "fee": "Комиссия", "fee_less_than_min": "Выбранная комиссия ниже минимальной. Пожалуйста, увеличьте комиссию, чтобы отправить транзакцию", @@ -491,6 +501,7 @@ "frozen": "Заморожено", "frozen_balance": "Замороженный баланс", "full_balance": "Полный баланс", + "gallery": "Галерея", "gas_exceeds_allowance": "Требуемый для транзакции газ превышает лимит.", "gas_price": "Цена газа", "general": "Общие", @@ -526,6 +537,7 @@ "how_to_connect": "Как подключиться", "how_to_use": "Как использовать", "how_to_use_card": "Как пользоваться этой картой", + "hww_exit_desc": "Это завершит текущий процесс сопряжения с вашим аппаратным устройством", "i_understand": "Я понимаю", "icon_style": "Стиль иконок", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Ваш адрес для получения будет меняться каждый раз, когда вы получаете транзакцию", "infobox_multichain": "Используйте этот адрес, чтобы получать любые токены или коллекционные предметы в", "infobox_rotation": "Ваш адрес для получения будет меняться каждый раз, когда вы закроете и снова откроете этот экран.", + "input": "Вход", "inputs": "Входы", "insufficient_funds_for_tx": "Недостаточно средств для успешного выполнения транзакции.", "insufficient_lamport_for_tx": "У вас недостаточно SOL, чтобы покрыть транзакцию и комиссию за неё. Пожалуйста, пополните кошелёк SOL или уменьшите сумму SOL, которую вы отправляете.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Управление PoW-узлами", "manage_providers": "Управление провайдерами", "manage_yats": "Управление Yat", + "manual_input": "Ручной ввод", "mark_as_redeemed": "Отметить как использовано", "market_place": "Маркетплейс", "mask": "Замаскировать", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Все новейшие модели (GPT-5.3, Claude 4.6).\nБез подписки, оплата криптовалютой.", "narrow": "Узкий", "network": "Сеть", + "networks": "Сети", "new_first_wallet_text": "Хранить вашу криптовалюту в безопасности — проще простого", "new_node_testing": "Тестирование новой ноды", "new_subaddress_create": "Создать", @@ -678,8 +693,10 @@ "node_new": "Новый узел", "node_port": "Порт узла", "node_reset_settings_title": "Сброс настроек", + "node_share_desc": "Отсканируйте этот QR-код на экране сканирования, чтобы импортировать этот узел.", "node_test": "Тест", "nodes": "Узлы", + "nodes_desc": "Управляйте существующими узлами или добавьте пользовательский.", "nodes_list_reset_to_default_message": "Вы уверены, что хотите сбросить настройки до значений по умолчанию?", "none_of_selected_providers_can_exchange": "Ни один из выбранных провайдеров не может выполнить этот обмен", "noNFTYet": "Пока нет NFT", @@ -689,6 +706,7 @@ "note_tap_to_change": "Примечание (нажмите, чтобы изменить)", "notification_permission_denied": "Разрешение на уведомления было навсегда отклонено, пожалуйста, включите его вручную в настройках", "nullURIError": "URI равен null", + "ocp_desc": "Платите криптовалютой в магазинах", "offer_expires_in": "Предложение истекает через: ", "offline": "Офлайн", "ok": "OK", @@ -716,8 +734,13 @@ "outputs": "Выходы", "overshot": "Превышено", "overwrite_amount": "Перезаписать сумму", + "pairing_code": "Код сопряжения", + "pairing_code_desc_1": "Ваше устройство покажет код сопряжения.", + "pairing_code_desc_2": "Введите его здесь, чтобы продолжить", + "pairing_error": "Ошибка сопряжения", "pairingInvalidEvent": "Недопустимое событие сопряжения", "passphrase": "Пассфраза (необязательно)", + "passphrase_view_keys": "Парольная фраза", "passphrases_doesnt_match": "Пасфразы не совпадают, попробуйте ещё раз", "password": "Пароль", "paste": "Вставить", @@ -733,6 +756,7 @@ "payjoin_unavailable_sheet_content": "Для получения транзакции Payjoin у вас должны быть готовы к использованию BTC.\n\nКак только на вашем кошельке появятся средства, Payjoin будет автоматически включён.", "payjoin_unavailable_sheet_title": "Почему Payjoin недоступен?", "payment_id": "ID платежа: ", + "payment_invoices": "Платёжные счета", "payment_made_easy": "Платежи — это просто", "payment_was_received": "Ваш платеж получен.", "payments": "Платежи", @@ -812,6 +836,7 @@ "receive_to": "Получить на", "received": "Получено", "receiving": "Получение", + "recieving": "Получение", "recipient_address": "Адрес получателя", "reconnect": "Переподключиться", "reconnect_alert_text": "Вы уверены, что хотите переподключиться?", @@ -887,6 +912,7 @@ "save": "Сохранить", "save_backup_password": "Пожалуйста, убедитесь, что вы сохранили пароль для резервной копии. Без него вы не сможете импортировать файлы резервной копии.", "save_backup_password_alert": "Сохранить пароль для резервной копии", + "save_contact": "Сохранить контакт", "save_to_downloads": "Сохранить в папку «Загрузки»", "saved_the_trade_id": "Я сохранил ID обмена", "savings": "Сбережения", @@ -1036,6 +1062,7 @@ "setup_your_debit_card": "Настройте свою дебетовую карту", "share": "Поделиться", "share_address": "Поделиться адресом", + "share_this_node": "Поделиться этим узлом", "shared_seed_wallet_groups": "Группы кошельков с общим сидом", "shared_seed_wallets": "Кошельки с общим сидом", "show": "Показать", @@ -1043,6 +1070,7 @@ "show_balance": "Нажмите и удерживайте, чтобы показать баланс", "show_balance_send_page": "Нажмите, чтобы показать", "show_balance_toast": "Нажмите и удерживайте, чтобы скрыть или показать баланс", + "show_combined_balance": "Показать объединённый баланс", "show_details": "Показать подробности", "show_hidden_addresses": "Показать скрытые адреса", "show_keys": "Показать seed/ключи", @@ -1108,6 +1136,7 @@ "swap_providers": "Провайдеры обмена", "sweeping_wallet": "Сканирование кошелька", "sweeping_wallet_alert": "Это не должно занять много времени. НЕ ПОКИДАЙТЕ ЭТОТ ЭКРАН, ИНАЧЕ ПЕРЕНЕСЁННЫЕ СРЕДСТВА МОГУТ БЫТЬ ПОТЕРЯНЫ.", + "swipe_to_bridge": "Проведите, чтобы выполнить перенос через мост", "swipe_to_send": "Проведите, чтобы отправить", "switch_wallet": "Переключить кошелёк", "switchToETHWallet": "Пожалуйста, переключитесь на кошелёк Ethereum и повторите попытку", @@ -1148,6 +1177,7 @@ "testnet_coins_no_value": "Монеты тестнета не имеют ценности", "third_intro_content": "Yat существуют и за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!", "third_intro_title": "Yat хорошо работает с другими", + "this_can_take_few_seconds": "Это может занять несколько секунд", "this_pair_is_not_supported_warning": "Эта пара не поддерживается выбранной(ыми) биржей(ами). Пожалуйста, выберите другую биржу.", "thorchain_contract_address_not_supported": "THORChain не поддерживает отправку на адрес контракта", "thorchain_taproot_address_not_supported": "Провайдер ThorChain не поддерживает Taproot-адреса. Пожалуйста, измените адрес или выберите другого провайдера.", @@ -1161,6 +1191,7 @@ "token_decimal": "Десятичные знаки токена (например: USDT)", "token_name": "Название токена (например: Tether)", "token_symbol": "Символ токена (например: USDT)", + "token_verified_on_jupiter": "Этот токен проверен на Jupiter", "tokenID": "ID", "tokens": "Токены", "tokens_strong_warning": "Никогда не отправляйте токены на этот адрес!", @@ -1289,6 +1320,7 @@ "username": "Имя пользователя", "username_available": "Имя пользователя доступно", "username_character_error": "Имя пользователя должно содержать только", + "username_check_your_network": "Не удалось проверить имя пользователя. Пожалуйста, проверьте подключение к сети.", "username_length_error": "Имя пользователя должно содержать 6–32 буквенно-цифровых символа.", "username_length_error_1_64": "Имя пользователя должно содержать 1–64 буквенно-цифровых символа.", "username_not_available": "Это имя пользователя недоступно.", @@ -1299,6 +1331,7 @@ "verify_message": "Проверить сообщение", "verify_seed": "Проверьте сид-фразу", "verify_with_2fa": "Подтвердить через Cake 2FA", + "verifying_code": "Проверка кода", "version": "Версия ${currentVersion}", "view_all": "Посмотреть все", "view_in_block_explorer": "Просмотреть в Block Explorer", @@ -1310,6 +1343,7 @@ "waitFewSecondForTxUpdate": "Пожалуйста, подождите несколько секунд, пока транзакция отобразится в истории транзакций.", "wallet": "Кошелек", "wallet_accounts": "Аккаунты кошелька", + "wallet_balance": "Баланс кошелька", "wallet_group": "Группа кошельков", "wallet_group_description_existing_seed": "Вы выбрали использование существующей сид-фразы для этого кошелька. При необходимости вы можете снова проверить сид-фразу, чтобы подтвердить её или записать.", "wallet_group_description_four": "создать кошелек с совершенно новой seed-фразой.", @@ -1347,9 +1381,11 @@ "walletConnect": "WalletConnect", "wallets": "Кошельки", "warning": "Предупреждение", + "wc_action_approve": "Одобрить", "wc_approve_request_title": "Утвердить запрос", "wc_connect_request_title": "Запрос на подключение", "wc_connected_to": "Подключено к ${name}", + "wc_desc": "Легко подключайтесь к dApps", "wc_max_network_fee": "Максимальная плата за сеть", "wc_message_to_sign": "Сообщение для подписи", "wc_network_fee": "Сетевая плата", @@ -1400,6 +1436,7 @@ "yat_popup_content": "Теперь вы можете отправлять и получать криптовалюту в Cake Wallet с помощью Yat — короткого имени пользователя на основе эмодзи. Управляйте Yat в любое время на экране настроек", "yat_popup_title": "Адрес вашего кошелька можно преобразовать в эмодзи.", "yes": "Да", + "yes_exit": "Да. Выйти", "yesterday": "Вчера", "you_now_have_debit_card": "Теперь у вас есть дебетовая карта", "you_pay": "Вы платите", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 9c575933f..dd6ee027e 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -76,6 +76,7 @@ "approve_tokens": "อนุมัติโทเค็น", "apps": "แอป", "arbiscan_history": "ประวัติ ArbiScan", + "are_you_sure_exit": "คุณแน่ใจหรือไม่ว่าต้องการออก?", "arrive_in_this_address": "${currency} ${tag}จะถูกส่งมาที่ที่อยู่นี้", "ascending": "จากน้อยไปมาก", "ask_each_time": "ถามทุกครั้ง", @@ -89,6 +90,7 @@ "auto_generate_addresses": "สร้างที่อยู่อัตโนมัติ", "auto_generate_subaddresses": "สร้างที่อยู่ย่อยอัตโนมัติ", "automatic": "อัตโนมัติ", + "available": "พร้อมใช้งาน", "available_balance": "ยอดคงเหลือที่ใช้ได้", "available_balance_description": "“ยอดคงเหลือที่ใช้ได้” หรือ “ยอดคงเหลือที่ยืนยันแล้ว” คือเงินที่สามารถใช้จ่ายได้ทันที หากเงินปรากฏในยอดคงเหลือด้านล่างแต่ไม่ปรากฏในยอดคงเหลือด้านบน คุณต้องรอสักครู่เพื่อให้เงินที่เข้ามาได้รับการยืนยันจากเครือข่ายเพิ่มขึ้น เมื่อได้รับการยืนยันมากขึ้นแล้ว เงินนั้นจะสามารถใช้จ่ายได้", "avg_savings": "การประหยัดเฉลี่ย", @@ -125,6 +127,7 @@ "block_remaining": "เหลืออีก 1 บล็อก", "Blocks_remaining": "${status} บล็อกที่เหลือ", "bluetooth": "บลูทูธ", + "bridging": "กำลังบริดจ์", "bright_theme": "สว่าง", "bscscan_history": "ประวัติ BSCScan", "bump_fee": "เพิ่มค่าธรรมเนียม", @@ -216,6 +219,8 @@ "color_theme": "ธีมสี", "coming_soon_tag": "เร็ว ๆ นี้", "commit_transaction_amount_fee": "ยืนยันธุรกรรม\nจำนวน: ${amount}\nค่าธรรมเนียม: ${fee}", + "compatible_services": "บริการที่รองรับ", + "compatible_services_desc": "ใช้เครื่องมือสแกนเพื่ออ่าน QR Code ประเภทต่อไปนี้ที่ Cake Wallet รองรับ:", "configure": "ตั้งค่า", "confirm": "ยืนยัน", "confirm_delete_template": "การดำเนินการนี้จะลบเทมเพลตนี้ คุณต้องการดำเนินการต่อหรือไม่?", @@ -279,6 +284,7 @@ "creating_new_wallet": "กำลังสร้างกระเป๋าเงินใหม่", "creating_new_wallet_error": "ข้อผิดพลาด: ${description}", "creation_date": "วันที่สร้าง", + "crypto_addresses": "ที่อยู่คริปโต", "csv_nothing_to_export": "ไม่มีข้อมูลให้ส่งออก", "current_swap": "การสวอปปัจจุบัน", "current_wallet": "กระเป๋าเงินปัจจุบัน", @@ -301,6 +307,7 @@ "default_sell_provider": "ผู้ให้บริการขายเริ่มต้น", "delete": "ลบ", "delete_account": "ลบบัญชี", + "delete_this_node": "ลบโหนดนี้", "delete_wallet": "ลบกระเป๋าเงิน", "delete_wallet_confirm_message": "คุณแน่ใจหรือไม่ว่าต้องการลบกระเป๋าเงิน ${wallet_name}?", "deleteConnectionConfirmationPrompt": "คุณแน่ใจหรือไม่ว่าต้องการลบการเชื่อมต่อกับ", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO เป็นสเตเบิลคอยน์แบบกระจายอำนาจอย่างเต็มรูปแบบ มีหลักประกัน และตรึงมูลค่ากับยูโร — ปลอดภัย อเนกประสงค์ และทนต่อการเซ็นเซอร์ โดยไม่ต้องพึ่งพาออราเคิล 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "หากต้องการเปิดใช้งาน dEURO คุณต้องมี ETH ในกระเป๋าเงินของคุณ", "deuro_tx_commited_content": "อาจใช้เวลาสองสามวินาทีเพื่อให้ธุรกรรมได้รับการยืนยันและแสดงบนหน้าจอ", + "device_confirmation": "การยืนยันบนอุปกรณ์", "device_is_signing": "อุปกรณ์กำลังลงนาม", "dfx_option_description": "ซื้อคริปโตด้วย EUR และ CHF สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป", "did_you_back_up_seeds": "คุณได้สำรอง seed ทั้งหมดของคุณแล้วหรือยัง?", @@ -466,6 +474,8 @@ "extracted_address_content": "คุณกำลังจะส่งเงินทุนไปยัง\n${recipient_name}", "failed_authentication": "การยืนยันตัวตนล้มเหลว ${state_error}", "faq": "คำถามที่พบบ่อย", + "favorite_token": "โทเค็นโปรด", + "favorite_token_desc": "ยอดคงเหลือของโทเค็นโปรดจะแสดงบนการ์ดยอดคงเหลือ", "features": "คุณสมบัติ", "fee": "ค่าธรรมเนียม", "fee_less_than_min": "ค่าธรรมเนียมที่เลือกต่ำกว่าขั้นต่ำ โปรดเพิ่มค่าธรรมเนียมเพื่อให้สามารถส่งธุรกรรมได้", @@ -491,6 +501,7 @@ "frozen": "ถูกระงับ", "frozen_balance": "ยอดคงเหลือที่ถูกระงับ", "full_balance": "ยอดคงเหลือทั้งหมด", + "gallery": "แกลเลอรี", "gas_exceeds_allowance": "Gas ที่ธุรกรรมต้องใช้เกินกว่าค่าเผื่อที่กำหนด", "gas_price": "ราคา Gas", "general": "ทั่วไป", @@ -526,6 +537,7 @@ "how_to_connect": "วิธีเชื่อมต่อ", "how_to_use": "วิธีใช้งาน", "how_to_use_card": "วิธีใช้การ์ดนี้", + "hww_exit_desc": "การดำเนินการนี้จะสิ้นสุดกระบวนการจับคู่กับอุปกรณ์ฮาร์ดแวร์ของคุณที่กำลังดำเนินอยู่", "i_understand": "ฉันเข้าใจ", "icon_style": "สไตล์ไอคอน", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "ที่อยู่สำหรับรับของคุณจะเปลี่ยนทุกครั้งที่คุณได้รับธุรกรรม", "infobox_multichain": "ใช้ที่อยู่นี้เพื่อรับโทเค็นหรือของสะสมใด ๆ บน", "infobox_rotation": "ที่อยู่สำหรับรับของคุณจะเปลี่ยนทุกครั้งที่คุณปิดและเปิดหน้าจอนี้ใหม่", + "input": "อินพุต", "inputs": "อินพุต", "insufficient_funds_for_tx": "ยอดเงินไม่เพียงพอที่จะดำเนินการธุรกรรมให้สำเร็จ", "insufficient_lamport_for_tx": "คุณมี SOL ไม่เพียงพอที่จะครอบคลุมธุรกรรมและค่าธรรมเนียมธุรกรรม กรุณาเพิ่ม SOL ในกระเป๋าเงินของคุณหรือปรับลดจำนวน SOL ที่คุณกำลังส่ง", @@ -605,6 +618,7 @@ "manage_pow_nodes": "จัดการโหนด PoW", "manage_providers": "จัดการผู้ให้บริการ", "manage_yats": "จัดการ Yats", + "manual_input": "ป้อนข้อมูลด้วยตนเอง", "mark_as_redeemed": "ทำเครื่องหมายว่าแลกใช้แล้ว", "market_place": "มาร์เก็ตเพลส", "mask": "มาสก์", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "โมเดลใหม่ล่าสุดทั้งหมด (GPT-5.3, Claude 4.6)\nไม่ต้องสมัครสมาชิก จ่ายด้วยคริปโต", "narrow": "แคบ", "network": "เครือข่าย", + "networks": "เครือข่าย", "new_first_wallet_text": "การเก็บคริปโตของคุณให้ปลอดภัยเป็นเรื่องง่ายเหมือนปอกกล้วยเข้าปาก", "new_node_testing": "การทดสอบโหนดใหม่", "new_subaddress_create": "สร้าง", @@ -678,8 +693,10 @@ "node_new": "โหนดใหม่", "node_port": "พอร์ตโหนด", "node_reset_settings_title": "รีเซ็ตการตั้งค่า", + "node_share_desc": "สแกน QR Code นี้จากหน้าจอสแกนเพื่อนำเข้าโหนดนี้", "node_test": "ทดสอบ", "nodes": "โหนด", + "nodes_desc": "จัดการโหนดที่มีอยู่หรือเพิ่มโหนดแบบกำหนดเอง", "nodes_list_reset_to_default_message": "คุณแน่ใจหรือไม่ว่าต้องการรีเซ็ตการตั้งค่าเป็นค่าเริ่มต้น?", "none_of_selected_providers_can_exchange": "ไม่มีผู้ให้บริการที่เลือกไว้รายใดสามารถทำการสวอปนี้ได้", "noNFTYet": "ยังไม่มี NFT", @@ -689,6 +706,7 @@ "note_tap_to_change": "หมายเหตุ (แตะเพื่อเปลี่ยน)", "notification_permission_denied": "สิทธิ์การแจ้งเตือนถูกปฏิเสธอย่างถาวร โปรดเปิดใช้งานด้วยตนเองในการตั้งค่า", "nullURIError": "URI เป็นค่าว่าง", + "ocp_desc": "ชำระเงินด้วยคริปโตในร้านค้า", "offer_expires_in": "ข้อเสนอจะหมดอายุใน: ", "offline": "ออฟไลน์", "ok": "ตกลง", @@ -715,8 +733,13 @@ "outputs": "เอาต์พุต", "overshot": "เกิน", "overwrite_amount": "เขียนทับจำนวนเงิน", + "pairing_code": "รหัสจับคู่", + "pairing_code_desc_1": "อุปกรณ์ของคุณจะแสดงรหัสจับคู่", + "pairing_code_desc_2": "ป้อนที่นี่เพื่อดำเนินการต่อ", + "pairing_error": "เกิดข้อผิดพลาดในการจับคู่", "pairingInvalidEvent": "เหตุการณ์การจับคู่ไม่ถูกต้อง", "passphrase": "วลีรหัสผ่าน (ไม่บังคับ)", + "passphrase_view_keys": "วลีรหัสผ่าน", "passphrases_doesnt_match": "Passphrase ไม่ตรงกัน โปรดลองอีกครั้ง", "password": "รหัสผ่าน", "paste": "วาง", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "การรับธุรกรรม Payjoin จำเป็นต้องมี Bitcoin พร้อมใช้งาน\n\nเมื่อกระเป๋าเงินของคุณมีเงินแล้ว Payjoin จะถูกเปิดใช้งานโดยอัตโนมัติ", "payjoin_unavailable_sheet_title": "ทำไม Payjoin ถึงใช้งานไม่ได้?", "payment_id": "รหัสการชำระเงิน: ", + "payment_invoices": "ใบแจ้งหนี้การชำระเงิน", "payment_made_easy": "การชำระเงินที่ง่ายขึ้น", "payment_was_received": "ได้รับการชำระเงินของคุณแล้ว", "payments": "การชำระเงิน", @@ -811,6 +835,7 @@ "receive_to": "รับไปยัง", "received": "ได้รับ", "receiving": "กำลังรับ", + "recieving": "กำลังรับ", "recipient_address": "ที่อยู่ผู้รับ", "reconnect": "เชื่อมต่อใหม่", "reconnect_alert_text": "คุณแน่ใจหรือไม่ว่าต้องการเชื่อมต่อใหม่?", @@ -886,6 +911,7 @@ "save": "บันทึก", "save_backup_password": "โปรดตรวจสอบให้แน่ใจว่าคุณได้บันทึกรหัสผ่านสำรองข้อมูลไว้แล้ว คุณจะไม่สามารถนำเข้าไฟล์สำรองข้อมูลของคุณได้หากไม่มีรหัสผ่านดังกล่าว", "save_backup_password_alert": "บันทึกรหัสผ่านสำหรับการสำรองข้อมูล", + "save_contact": "บันทึกผู้ติดต่อ", "save_to_downloads": "บันทึกไปยังโฟลเดอร์ดาวน์โหลด", "saved_the_trade_id": "ฉันได้บันทึก ID การเทรดไว้แล้ว", "savings": "เงินออม", @@ -1035,6 +1061,7 @@ "setup_your_debit_card": "ตั้งค่าบัตรเดบิตของคุณ", "share": "แชร์", "share_address": "แชร์ที่อยู่", + "share_this_node": "แชร์โหนดนี้", "shared_seed_wallet_groups": "กลุ่มกระเป๋าเงินที่ใช้ Seed ร่วมกัน", "shared_seed_wallets": "กระเป๋าเงิน Seed ที่ใช้ร่วมกัน", "show": "แสดง", @@ -1042,6 +1069,7 @@ "show_balance": "กดค้างเพื่อแสดงยอดคงเหลือ", "show_balance_send_page": "แตะเพื่อแสดง", "show_balance_toast": "กดค้างเพื่อซ่อนหรือแสดงยอดคงเหลือ", + "show_combined_balance": "แสดงยอดคงเหลือรวม", "show_details": "แสดงรายละเอียด", "show_hidden_addresses": "แสดงที่อยู่ที่ซ่อนอยู่", "show_keys": "แสดงซีด/คีย์", @@ -1107,6 +1135,7 @@ "swap_providers": "ผู้ให้บริการสวอป", "sweeping_wallet": "กระเป๋าสตางค์สำหรับกวาดเหรียญ", "sweeping_wallet_alert": "การดำเนินการนี้ใช้เวลาไม่นาน ห้ามออกจากหน้าจอนี้ มิฉะนั้นเงินที่กวาดอาจสูญหาย", + "swipe_to_bridge": "ปัดเพื่อบริดจ์", "swipe_to_send": "ปัดเพื่อส่ง", "switch_wallet": "สลับกระเป๋าเงิน", "switchToETHWallet": "โปรดสลับไปยังกระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", @@ -1147,6 +1176,7 @@ "testnet_coins_no_value": "เหรียญ Testnet ไม่มีมูลค่า", "third_intro_content": "Yat ใช้ได้นอก Cake Wallet ด้วย ที่อยู่กระเป๋าเงินใดๆ ทั่วโลกสามารถแทนที่ด้วย Yat ได้!", "third_intro_title": "Yat ทำงานร่วมกับสิ่งอื่นได้อย่างราบรื่น", + "this_can_take_few_seconds": "การดำเนินการนี้อาจใช้เวลาสักครู่", "this_pair_is_not_supported_warning": "คู่นี้ไม่รองรับกับแพลตฟอร์มแลกเปลี่ยนที่เลือกอยู่ในขณะนี้ โปรดเลือกแพลตฟอร์มแลกเปลี่ยนอื่น", "thorchain_contract_address_not_supported": "THORChain ไม่รองรับการส่งไปยังที่อยู่สัญญา", "thorchain_taproot_address_not_supported": "ผู้ให้บริการ ThorChain ไม่รองรับที่อยู่ Taproot โปรดเปลี่ยนที่อยู่หรือเลือกผู้ให้บริการอื่น", @@ -1160,6 +1190,7 @@ "token_decimal": "ทศนิยมของโทเค็น (เช่น: USDT)", "token_name": "ชื่อโทเค็น (เช่น: Tether)", "token_symbol": "สัญลักษณ์โทเค็น (เช่น: USDT)", + "token_verified_on_jupiter": "โทเค็นนี้ได้รับการตรวจสอบบน Jupiter", "tokenID": "ID", "tokens": "โทเค็น", "tokens_strong_warning": "ห้ามส่งโทเค็นไปยังที่อยู่นี้เด็ดขาด!", @@ -1288,6 +1319,7 @@ "username": "ชื่อผู้ใช้", "username_available": "ชื่อผู้ใช้พร้อมใช้งาน", "username_character_error": "ชื่อผู้ใช้ต้องมีเฉพาะ", + "username_check_your_network": "ไม่สามารถตรวจสอบชื่อผู้ใช้ได้ โปรดตรวจสอบการเชื่อมต่อเครือข่ายของคุณ", "username_length_error": "ชื่อผู้ใช้ต้องมีอักขระตัวอักษรและตัวเลข 6-32 ตัว", "username_length_error_1_64": "ชื่อผู้ใช้ต้องมีอักขระตัวอักษรและตัวเลข 1-64 ตัว", "username_not_available": "ชื่อผู้ใช้นี้ไม่พร้อมใช้งาน", @@ -1298,6 +1330,7 @@ "verify_message": "ตรวจสอบข้อความ", "verify_seed": "ยืนยัน Seed", "verify_with_2fa": "ยืนยันด้วย Cake 2FA", + "verifying_code": "กำลังตรวจสอบรหัส", "version": "เวอร์ชัน ${currentVersion}", "view_all": "ดูทั้งหมด", "view_in_block_explorer": "ดูใน Block Explorer", @@ -1309,6 +1342,7 @@ "waitFewSecondForTxUpdate": "กรุณารอสักครู่เพื่อให้ธุรกรรมแสดงในประวัติธุรกรรม", "wallet": "วอลเล็ต", "wallet_accounts": "บัญชีกระเป๋าเงิน", + "wallet_balance": "ยอดคงเหลือในกระเป๋าเงิน", "wallet_group": "กลุ่มวอลเล็ต", "wallet_group_description_existing_seed": "คุณได้เลือกใช้ซีดที่มีอยู่สำหรับกระเป๋าเงินนี้ คุณสามารถตรวจสอบซีดอีกครั้งได้ หากต้องการยืนยันหรือจดบันทึกไว้", "wallet_group_description_four": "เพื่อสร้างกระเป๋าเงินด้วยซีดใหม่ทั้งหมด", @@ -1346,9 +1380,11 @@ "walletConnect": "WalletConnect", "wallets": "กระเป๋าเงิน", "warning": "คำเตือน", + "wc_action_approve": "อนุมัติ", "wc_approve_request_title": "อนุมัติคำขอ", "wc_connect_request_title": "เชื่อมต่อคำขอ", "wc_connected_to": "เชื่อมต่อกับ ${name}", + "wc_desc": "เชื่อมต่อกับ DApps ได้อย่างง่ายดาย", "wc_max_network_fee": "ค่าธรรมเนียมเครือข่ายสูงสุด", "wc_message_to_sign": "ข้อความที่จะลงนาม", "wc_network_fee": "ค่าธรรมเนียมเครือข่าย", @@ -1399,6 +1435,7 @@ "yat_popup_content": "ขณะนี้คุณสามารถส่งและรับคริปโตใน Cake Wallet ด้วย Yat ของคุณ — ชื่อผู้ใช้แบบสั้นที่ใช้ อีโมจิ เป็นหลัก จัดการ Yat ได้ทุกเมื่อบนหน้าจอการตั้งค่า", "yat_popup_title": "ที่อยู่กระเป๋าเงินของคุณสามารถแปลงเป็นอีโมจิได้", "yes": "ใช่", + "yes_exit": "ใช่ ออก", "yesterday": "เมื่อวาน", "you_now_have_debit_card": "ตอนนี้คุณมีบัตรเดบิตแล้ว", "you_pay": "คุณจ่าย", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 91b49c2e8..55cbebb32 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -76,6 +76,7 @@ "approve_tokens": "Aprubahan ang mga token", "apps": "Apps", "arbiscan_history": "Kasaysayan ng ArbiScan", + "are_you_sure_exit": "Sigurado ka bang gusto mong lumabas?", "arrive_in_this_address": "Darating ang ${currency} ${tag} sa address na ito", "ascending": "Pataas", "ask_each_time": "Magtanong sa bawat pagkakataon", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Awtomatikong bumuo ng mga address", "auto_generate_subaddresses": "Awtomatikong bumuo ng mga subaddress", "automatic": "Awtomatiko", + "available": "Available", "available_balance": "Magagamit na Balanse", "available_balance_description": "Ang “Magagamit na Balanse” o “Nakumpirmang Balanse” ay mga pondong maaari nang gastusin kaagad. Kung lumalabas ang mga pondo sa mas mababang balanse ngunit wala sa itaas na balanse, kailangan mong maghintay ng ilang minuto para makakuha ng mas maraming kumpirmasyon sa network ang mga papasok na pondo. Kapag nakakuha na sila ng mas maraming kumpirmasyon, maaari na silang gastusin.", "avg_savings": "Avg. Matitipid", @@ -125,6 +127,7 @@ "block_remaining": "1 Block ang Natitira", "Blocks_remaining": "${status} Natitirang Block", "bluetooth": "Bluetooth", + "bridging": "Bina-bridge", "bright_theme": "Maningning", "bscscan_history": "Kasaysayan ng BSCScan", "bump_fee": "Itaas ang bayarin", @@ -216,6 +219,8 @@ "color_theme": "Tema ng kulay", "coming_soon_tag": "Paparating na", "commit_transaction_amount_fee": "I-commit ang transaksyon\nHalaga: ${amount}\nBayad: ${fee}", + "compatible_services": "Mga Katugmang Serbisyo", + "compatible_services_desc": "Gamitin ang Scan tool upang basahin ang mga sumusunod na uri ng QR code na sinusuportahan sa Cake Wallet:", "configure": "I-configure", "confirm": "Kumpirmahin", "confirm_delete_template": "Ide-delete ng aksyong ito ang template na ito. Gusto mo bang magpatuloy?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Gumagawa ng bagong wallet", "creating_new_wallet_error": "Error: ${description}", "creation_date": "Petsa ng Paglikha", + "crypto_addresses": "Mga Crypto Address", "csv_nothing_to_export": "Walang i-e-export", "current_swap": "Kasalukuyang Swap", "current_wallet": "Kasalukuyang wallet", @@ -301,6 +307,7 @@ "default_sell_provider": "Default na Provider ng Pagbebenta", "delete": "Tanggalin", "delete_account": "I-delete ang Account", + "delete_this_node": "Tanggalin ang node na ito", "delete_wallet": "I-delete ang wallet", "delete_wallet_confirm_message": "Sigurado ka bang gusto mong tanggalin ang wallet na ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Sigurado ka bang gusto mong tanggalin ang koneksyon sa", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "Ang dEURO ay isang ganap na desentralisado at collateralized na stablecoin na naka-peg sa Euro — secure, maraming gamit, at lumalaban sa censorship nang hindi kailangang umasa sa mga oracle. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Upang paganahin ang dEURO, dapat ay may ETH ka sa iyong wallet.", "deuro_tx_commited_content": "Maaaring tumagal ng ilang segundo bago makumpirma ang transaksyon at lumabas sa screen", + "device_confirmation": "Kumpirmasyon sa Device", "device_is_signing": "Pumipirma ang device", "dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Para sa mga retail at corporate na customer sa Europe", "did_you_back_up_seeds": "Na-back up mo na ba ang lahat ng iyong seed?", @@ -466,6 +474,8 @@ "extracted_address_content": "Magpapadala ka ng mga pondo sa\n${recipient_name}", "failed_authentication": "Nabigo ang pag-authenticate. ${state_error}", "faq": "FAQ", + "favorite_token": "Paboritong token", + "favorite_token_desc": "Ipapakita ang balanse ng paboritong token sa balance card.", "features": "Mga Tampok", "fee": "Bayarin", "fee_less_than_min": "Ang napiling bayad ay mas mababa kaysa sa minimum. Mangyaring taasan ang bayad upang maipadala ang transaksyon.", @@ -491,6 +501,7 @@ "frozen": "Naka-freeze", "frozen_balance": "Naka-freeze na balanse", "full_balance": "Buong Balanse", + "gallery": "Gallery", "gas_exceeds_allowance": "Ang gas na kailangan para sa transaksyon ay lumampas sa itinakdang limitasyon.", "gas_price": "Presyo ng gas", "general": "Pangkalahatan", @@ -526,6 +537,7 @@ "how_to_connect": "Paano Kumonekta", "how_to_use": "Paano gamitin", "how_to_use_card": "Paano gamitin ang card na ito", + "hww_exit_desc": "Tatapusin nito ang kasalukuyang proseso ng pagpa-pair sa iyong hardware device", "i_understand": "Naiintindihan ko", "icon_style": "Estilo ng icon", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Iikot ang iyong receive address sa tuwing makakatanggap ka ng transaksyon", "infobox_multichain": "Gamitin ang address na ito para makatanggap ng anumang token o collectible sa", "infobox_rotation": "Ang iyong receive address ay magpapalit sa tuwing isasara mo at muling bubuksan ang screen na ito", + "input": "Input", "inputs": "Mga input", "insufficient_funds_for_tx": "Hindi sapat ang pondo upang matagumpay na maisagawa ang transaksyon.", "insufficient_lamport_for_tx": "Wala kang sapat na SOL upang masakop ang transaksyon at ang bayad sa transaksyon nito. Mangyaring magdagdag pa ng SOL sa iyong wallet o bawasan ang halagang SOL na ipinapadala mo.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Pamahalaan ang mga PoW node", "manage_providers": "Pamahalaan ang mga provider", "manage_yats": "Pamahalaan ang Yats", + "manual_input": "Manu-manong Paglalagay", "mark_as_redeemed": "Markahan bilang Na-redeem", "market_place": "Marketplace", "mask": "Mask", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Lahat ng pinakabagong modelo (GPT-5.3, Claude 4.6).\nWalang subscription, magbayad gamit ang crypto.", "narrow": "Makitid", "network": "Network", + "networks": "Mga Network", "new_first_wallet_text": "Ang pagpapanatiling ligtas ng iyong crypto ay kasingdali ng pagkain ng keyk", "new_node_testing": "Pagsusuri ng bagong node", "new_subaddress_create": "Lumikha", @@ -678,8 +693,10 @@ "node_new": "Bagong Node", "node_port": "Port ng node", "node_reset_settings_title": "I-reset ang mga setting", + "node_share_desc": "I-scan ang QR code na ito mula sa Scan screen upang i-import ang node na ito.", "node_test": "Pagsubok", "nodes": "Mga Node", + "nodes_desc": "Pamahalaan ang mga umiiral na node o magdagdag ng custom.", "nodes_list_reset_to_default_message": "Sigurado ka bang gusto mong i-reset ang mga setting sa default?", "none_of_selected_providers_can_exchange": "Wala sa mga napiling provider ang makakagawa ng swap na ito", "noNFTYet": "Wala pang mga NFT", @@ -689,6 +706,7 @@ "note_tap_to_change": "Tala (i-tap para baguhin)", "notification_permission_denied": "Permanenteng tinanggihan ang pahintulot para sa mga abiso. Pakipaganahin ito nang manu-mano sa mga setting.", "nullURIError": "Null ang URI", + "ocp_desc": "Magbayad gamit ang crypto sa mga tindahan", "offer_expires_in": "Mag-e-expire ang alok sa: ", "offline": "Offline", "ok": "OK", @@ -715,8 +733,13 @@ "outputs": "Mga Output", "overshot": "Lumampas", "overwrite_amount": "Patungan ang halaga", + "pairing_code": "Pairing Code", + "pairing_code_desc_1": "Magpapakita ang iyong device ng isang pairing code.", + "pairing_code_desc_2": "Ilagay dito upang magpatuloy", + "pairing_error": "Error sa Pagpa-pair", "pairingInvalidEvent": "Hindi Wastong Kaganapan sa Pag-pair", "passphrase": "Passphrase (Opsyonal)", + "passphrase_view_keys": "Passphrase", "passphrases_doesnt_match": "Hindi magkatugma ang mga passphrase, pakisubukang muli", "password": "Password", "paste": "I-paste", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Ang pagtanggap ng isang Payjoin na transaksyon ay nangangailangan na mayroon kang Bitcoin na handang gamitin.\n\nKapag may pondo na ang iyong wallet, awtomatikong maa-enable ang Payjoin.", "payjoin_unavailable_sheet_title": "Bakit hindi available ang Payjoin?", "payment_id": "Payment ID: ", + "payment_invoices": "Mga Invoice ng Pagbabayad", "payment_made_easy": "Pinadali ang mga pagbabayad", "payment_was_received": "Natanggap ang iyong pagbabayad.", "payments": "Mga Pagbabayad", @@ -811,6 +835,7 @@ "receive_to": "Tumanggap sa", "received": "Natanggap", "receiving": "Pagtanggap", + "recieving": "Tumatanggap", "recipient_address": "Address ng tatanggap", "reconnect": "Muling kumonekta", "reconnect_alert_text": "Sigurado ka bang gusto mong kumonekta muli?", @@ -886,6 +911,7 @@ "save": "I-save", "save_backup_password": "Pakisigurado na na-save mo ang iyong backup password. Hindi mo mai-import ang iyong mga backup file kung wala ito.", "save_backup_password_alert": "I-save ang password ng backup", + "save_contact": "I-save ang Contact", "save_to_downloads": "I-save sa Downloads", "saved_the_trade_id": "Na-save ko na ang trade ID", "savings": "Ipon", @@ -1035,6 +1061,7 @@ "setup_your_debit_card": "I-set up ang iyong debit card", "share": "Ibahagi", "share_address": "Ibahagi ang address", + "share_this_node": "Ibahagi ang node na ito", "shared_seed_wallet_groups": "Mga Grupo ng Wallet na may Ibinahaging Seed", "shared_seed_wallets": "Mga Wallet na may Shared Seed", "show": "Ipakita", @@ -1042,6 +1069,7 @@ "show_balance": "Pindutin nang matagal para ipakita ang balanse", "show_balance_send_page": "I-tap para ipakita", "show_balance_toast": "Pindutin nang matagal upang itago o ipakita ang balanse", + "show_combined_balance": "Ipakita ang pinagsamang balanse", "show_details": "Ipakita ang mga Detalye", "show_hidden_addresses": "Ipakita ang mga nakatagong address", "show_keys": "Ipakita ang seed/keys", @@ -1107,6 +1135,7 @@ "swap_providers": "Mga provider ng swap", "sweeping_wallet": "Sweeping wallet", "sweeping_wallet_alert": "Hindi ito dapat magtagal. HUWAG UMALIS SA SCREEN NA ITO O MAARING MAWALA ANG MGA NA-SWEEP NA PONDO.", + "swipe_to_bridge": "Mag-swipe para mag-bridge", "swipe_to_send": "I-swipe para magpadala", "switch_wallet": "Lumipat ng Wallet", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", @@ -1147,6 +1176,7 @@ "testnet_coins_no_value": "Walang halaga ang mga testnet coin", "third_intro_content": "Umiiral din ang Yats sa labas ng Cake Wallet. Anumang wallet address sa mundo ay maaaring palitan ng Yat!", "third_intro_title": "Maganda ang pakikisama ng Yat sa iba", + "this_can_take_few_seconds": "Maaaring tumagal ito ng ilang segundo", "this_pair_is_not_supported_warning": "Hindi sinusuportahan ang pares na ito sa kasalukuyang napiling (mga) exchange. Mangyaring pumili ng ibang exchange.", "thorchain_contract_address_not_supported": "Hindi sinusuportahan ng THORChain ang pagpapadala sa isang contract address", "thorchain_taproot_address_not_supported": "Hindi sinusuportahan ng ThorChain provider ang mga Taproot address. Pakibaguhin ang address o pumili ng ibang provider.", @@ -1160,6 +1190,7 @@ "token_decimal": "Desimal ng token (hal: USDT)", "token_name": "Pangalan ng token (hal: Tether)", "token_symbol": "Simbolo ng token (hal: USDT)", + "token_verified_on_jupiter": "Ang token na ito ay na-verify sa Jupiter", "tokenID": "ID", "tokens": "Mga Token", "tokens_strong_warning": "Huwag kailanman magpadala ng mga token sa address na ito!", @@ -1288,6 +1319,7 @@ "username": "Username", "username_available": "Available ang Username", "username_character_error": "Ang mga username ay dapat maglaman lamang ng", + "username_check_your_network": "Hindi ma-check ang username. Pakisuri ang iyong koneksyon sa network.", "username_length_error": "Ang mga username ay dapat maglaman ng 6-32 alphanumeric na karakter.", "username_length_error_1_64": "Dapat maglaman ang mga username ng 1-64 na alphanumeric na character.", "username_not_available": "Hindi available ang username na ito.", @@ -1298,6 +1330,7 @@ "verify_message": "I-verify ang Mensahe", "verify_seed": "I-verify ang Seed", "verify_with_2fa": "I-verify gamit ang Cake 2FA", + "verifying_code": "Vine-verify ang Code", "version": "Bersyon ${currentVersion}", "view_all": "Tingnan lahat", "view_in_block_explorer": "Tingnan sa Block Explorer", @@ -1309,6 +1342,7 @@ "waitFewSecondForTxUpdate": "Mangyaring maghintay ng ilang segundo para lumabas ang transaksyon sa kasaysayan ng mga transaksyon", "wallet": "Wallet", "wallet_accounts": "Mga Account ng Wallet", + "wallet_balance": "Balanse ng Wallet", "wallet_group": "Grupo ng Wallet", "wallet_group_description_existing_seed": "Pinili mong gumamit ng umiiral na seed para sa wallet na ito. Maaari mong i-verify muli ang seed kung kailangan mong kumpirmahin o isulat ito.", "wallet_group_description_four": "upang lumikha ng wallet na may ganap na bagong seed.", @@ -1346,9 +1380,11 @@ "walletConnect": "WalletConnect", "wallets": "Mga Wallet", "warning": "Babala", + "wc_action_approve": "Aprubahan", "wc_approve_request_title": "Aprubahan ang kahilingan", "wc_connect_request_title": "Kahilingan sa pagkonekta", "wc_connected_to": "Nakakonekta sa ${name}", + "wc_desc": "Madaling kumonekta sa mga DApp", "wc_max_network_fee": "Pinakamataas na bayad sa network", "wc_message_to_sign": "Mensahe para pirmahan", "wc_network_fee": "Bayad sa network", @@ -1399,6 +1435,7 @@ "yat_popup_content": "Maaari ka na ngayong magpadala at tumanggap ng crypto sa Cake Wallet gamit ang iyong Yat — isang maikling username na binubuo ng mga emoji. Pamahalaan ang mga Yat anumang oras sa screen ng mga setting", "yat_popup_title": "Maaaring gawing emoji ang address ng iyong wallet.", "yes": "Oo", + "yes_exit": "Oo. Lumabas", "yesterday": "Kahapon", "you_now_have_debit_card": "Mayroon ka na ngayong debit card", "you_pay": "Ikaw ang Magbabayad", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 765fa2f15..5b6dc47ce 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -76,6 +76,7 @@ "approve_tokens": "Tokenları onaylayın", "apps": "Uygulamalar", "arbiscan_history": "ArbiScan Geçmişi", + "are_you_sure_exit": "Çıkmak istediğinizden emin misiniz?", "arrive_in_this_address": "${currency} ${tag}bu adrese ulaşacaktır", "ascending": "Artan", "ask_each_time": "Her seferinde sor", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Adresleri otomatik oluştur", "auto_generate_subaddresses": "Alt adresleri otomatik oluştur", "automatic": "Otomatik", + "available": "Kullanılabilir", "available_balance": "Kullanılabilir Bakiye", "available_balance_description": "“Kullanılabilir Bakiye” veya “Onaylanmış Bakiye”, hemen harcanabilen fonlardır. Fonlar alt bakiyede görünüp üst bakiyede görünmüyorsa, gelen fonların ağda daha fazla onay alması için birkaç dakika beklemeniz gerekir. Daha fazla onay aldıktan sonra harcanabilir olacaktır.", "avg_savings": "Ort. Tasarruf", @@ -125,6 +127,7 @@ "block_remaining": "Kalan 1 Blok", "Blocks_remaining": "${status} Blok Kaldı", "bluetooth": "Bluetooth", + "bridging": "Köprüleniyor", "bright_theme": "Parlak", "bscscan_history": "BSCScan Geçmişi", "bump_fee": "Ücreti artır", @@ -216,6 +219,8 @@ "color_theme": "Renk teması", "coming_soon_tag": "Yakında", "commit_transaction_amount_fee": "İşlemi onayla\nTutar: ${amount}\nÜcret: ${fee}", + "compatible_services": "Uyumlu Hizmetler", + "compatible_services_desc": "Cake Wallet'ta desteklenen aşağıdaki QR kodu türlerini okumak için Tarama aracını kullanın:", "configure": "Yapılandır", "confirm": "Onayla", "confirm_delete_template": "Bu işlem bu şablonu silecek. Devam etmek istiyor musunuz?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Yeni cüzdan oluşturuluyor", "creating_new_wallet_error": "Hata: ${description}", "creation_date": "Oluşturulma Tarihi", + "crypto_addresses": "Kripto Adresleri", "csv_nothing_to_export": "Dışa aktarılacak bir şey yok", "current_swap": "Mevcut Takas", "current_wallet": "Geçerli cüzdan", @@ -301,6 +307,7 @@ "default_sell_provider": "Varsayılan Satış Sağlayıcısı", "delete": "Sil", "delete_account": "Hesabı Sil", + "delete_this_node": "Bu düğümü sil", "delete_wallet": "Cüzdanı sil", "delete_wallet_confirm_message": "${wallet_name} cüzdanını silmek istediğinden emin misin?", "deleteConnectionConfirmationPrompt": "Şuraya olan bağlantıyı silmek istediğinizden emin misiniz:", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO, Euro’ya sabitlenmiş tamamen merkeziyetsiz, teminatlandırılmış bir stablecoin’dir — güvenli, çok yönlü ve oracle’lara güvenmek zorunda kalmadan sansüre dayanıklıdır. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "dEURO'yu etkinleştirmek için cüzdanınızda ETH bulunmalıdır.", "deuro_tx_commited_content": "İşlemin onaylanması ve ekrana yansıması birkaç saniye sürebilir", + "device_confirmation": "Cihaz Onayı", "device_is_signing": "Cihaz imzalıyor", "dfx_option_description": "EUR ve CHF ile kripto satın alın. Avrupa'daki bireysel ve kurumsal müşteriler için", "did_you_back_up_seeds": "Tüm seed'lerinizi yedeklediniz mi?", @@ -466,6 +474,8 @@ "extracted_address_content": "${recipient_name} adresine\nfon göndereceksiniz", "failed_authentication": "Kimlik doğrulama başarısız oldu. ${state_error}", "faq": "SSS", + "favorite_token": "Favori token", + "favorite_token_desc": "Favori token'ın bakiyesi bakiye kartında gösterilecektir.", "features": "Özellikler", "fee": "Ücret", "fee_less_than_min": "Seçilen ücret minimum değerin altındadır, lütfen işlemi gönderebilmek için ücreti artırın", @@ -491,6 +501,7 @@ "frozen": "Dondurulmuş", "frozen_balance": "Dondurulmuş Bakiye", "full_balance": "Toplam Bakiye", + "gallery": "Galeri", "gas_exceeds_allowance": "İşlemin gerektirdiği gas, izin verilen ödeneği aşıyor.", "gas_price": "Gas ücreti", "general": "Genel", @@ -526,6 +537,7 @@ "how_to_connect": "Nasıl Bağlanılır", "how_to_use": "Nasıl kullanılır", "how_to_use_card": "Bu kart nasıl kullanılır", + "hww_exit_desc": "Bu, donanım cihazınızla devam eden eşleştirme işlemini sonlandıracaktır", "i_understand": "Anladım", "icon_style": "Simge stili", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Her işlem aldığınızda alma adresiniz her seferinde değişecektir", "infobox_multichain": "Herhangi bir token veya koleksiyon parçası almak için bu adresi kullanın", "infobox_rotation": "Bu ekranı her kapatıp yeniden açtığınızda alma adresiniz değişecektir", + "input": "Girdi", "inputs": "Girdiler", "insufficient_funds_for_tx": "İşlemi başarıyla gerçekleştirmek için yeterli bakiye yok.", "insufficient_lamport_for_tx": "İşlemi ve işlem ücretini karşılamak için yeterli SOL'unuz yok. Lütfen cüzdanınıza daha fazla SOL ekleyin veya gönderdiğiniz SOL miktarını azaltın.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "PoW düğümlerini yönet", "manage_providers": "Sağlayıcıları yönet", "manage_yats": "Yat'ları yönet", + "manual_input": "Manuel Giriş", "mark_as_redeemed": "Kullanıldı olarak işaretle", "market_place": "Pazar Yeri", "mask": "Maske", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "En yeni modellerin tümü (GPT-5.3, Claude 4.6).\nAbonelik yok, kripto ile ödeyin.", "narrow": "Dar", "network": "Ağ", + "networks": "Ağlar", "new_first_wallet_text": "Kriptonuzu güvende tutmak çocuk oyuncağı", "new_node_testing": "Yeni düğüm testi", "new_subaddress_create": "Oluştur", @@ -678,8 +693,10 @@ "node_new": "Yeni düğüm", "node_port": "Düğüm bağlantı noktası", "node_reset_settings_title": "Ayarları sıfırla", + "node_share_desc": "Bu düğümü içe aktarmak için bu QR kodunu Tarama ekranından tarayın.", "node_test": "Test", "nodes": "Düğümler", + "nodes_desc": "Mevcut düğümleri yönetin veya özel bir düğüm ekleyin.", "nodes_list_reset_to_default_message": "Ayarları varsayılanlara sıfırlamak istediğinizden emin misiniz?", "none_of_selected_providers_can_exchange": "Seçilen sağlayıcıların hiçbiri bu takası gerçekleştiremez", "noNFTYet": "Henüz NFT yok", @@ -689,6 +706,7 @@ "note_tap_to_change": "Not (değiştirmek için dokunun)", "notification_permission_denied": "Bildirim izni kalıcı olarak reddedildi, lütfen ayarlardan manuel olarak etkinleştirin", "nullURIError": "URI null", + "ocp_desc": "Mağazalarda kripto ile ödeme yapın", "offer_expires_in": "Teklifin sona ermesine kalan: ", "offline": "Çevrimdışı", "ok": "Tamam", @@ -715,8 +733,13 @@ "outputs": "Çıktılar", "overshot": "Aşıldı", "overwrite_amount": "Miktarın üzerine yaz", + "pairing_code": "Eşleştirme Kodu", + "pairing_code_desc_1": "Cihazınız bir eşleştirme kodu gösterecektir.", + "pairing_code_desc_2": "Devam etmek için buraya girin", + "pairing_error": "Eşleştirme Hatası", "pairingInvalidEvent": "Geçersiz Eşleştirme Etkinliği", "passphrase": "Parola (İsteğe bağlı)", + "passphrase_view_keys": "Parola", "passphrases_doesnt_match": "Parolalar eşleşmiyor, lütfen tekrar deneyin", "password": "Şifre", "paste": "Yapıştır", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Bir Payjoin işlemi almak için kullanıma hazır Bitcoin’iniz olması gerekir.\n\nCüzdanınızda fonlar olduğu anda Payjoin otomatik olarak etkinleştirilecektir.", "payjoin_unavailable_sheet_title": "Payjoin neden kullanılamıyor?", "payment_id": "Ödeme Kimliği: ", + "payment_invoices": "Ödeme Faturaları", "payment_made_easy": "Ödemeler artık çok kolay", "payment_was_received": "Ödemeniz alındı.", "payments": "Ödemeler", @@ -811,6 +835,7 @@ "receive_to": "Şuraya al", "received": "Alındı", "receiving": "Alma", + "recieving": "Alınıyor", "recipient_address": "Alıcı adresi", "reconnect": "Yeniden bağlan", "reconnect_alert_text": "Yeniden bağlanmak istediğinizden emin misiniz?", @@ -886,6 +911,7 @@ "save": "Kaydet", "save_backup_password": "Lütfen yedekleme parolanı kaydettiğinden emin ol. Bu parola olmadan yedekleme dosyalarını içe aktaramazsın.", "save_backup_password_alert": "Yedekleme parolasını kaydet", + "save_contact": "Kişiyi Kaydet", "save_to_downloads": "İndirilenler'e Kaydet", "saved_the_trade_id": "Takas kimliğini kaydettim", "savings": "Birikimler", @@ -1035,6 +1061,7 @@ "setup_your_debit_card": "Banka kartını ayarla", "share": "Paylaş", "share_address": "Adresi paylaş", + "share_this_node": "Bu düğümü paylaş", "shared_seed_wallet_groups": "Paylaşılan Seed Cüzdan Grupları", "shared_seed_wallets": "Paylaşılan Seed Cüzdanları", "show": "Göster", @@ -1042,6 +1069,7 @@ "show_balance": "Bakiyeyi Görmek İçin Uzun Basın", "show_balance_send_page": "Göstermek için dokunun", "show_balance_toast": "Bakiyeyi gizlemek veya göstermek için uzun basın", + "show_combined_balance": "Birleşik bakiyeyi göster", "show_details": "Detayları Göster", "show_hidden_addresses": "Gizli adresleri göster", "show_keys": "Seed'i/anahtarları göster", @@ -1107,6 +1135,7 @@ "swap_providers": "Takas sağlayıcıları", "sweeping_wallet": "Cüzdan süpürme", "sweeping_wallet_alert": "Bu uzun sürmemeli. BU EKRANDAN AYRILMAYIN, AKSİ TAKDİRDE SÜPÜRÜLEN FONLAR KAYBOLABİLİR.", + "swipe_to_bridge": "Köprülemek için kaydırın", "swipe_to_send": "Göndermek için kaydırın", "switch_wallet": "Cüzdan Değiştir", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", @@ -1147,6 +1176,7 @@ "testnet_coins_no_value": "Testnet coinlerinin değeri yok", "third_intro_content": "Yat'lar Cake Wallet'ın dışında da kullanılabilir. Dünyadaki herhangi bir cüzdan adresi bir Yat ile değiştirilebilir!", "third_intro_title": "Yat başkalarıyla uyum içinde çalışır", + "this_can_take_few_seconds": "Bu birkaç saniye sürebilir", "this_pair_is_not_supported_warning": "Bu parite, şu anda seçili borsa(lar) ile desteklenmiyor. Lütfen başka bir borsa seçin.", "thorchain_contract_address_not_supported": "THORChain, bir sözleşme adresine gönderimi desteklemiyor", "thorchain_taproot_address_not_supported": "ThorChain sağlayıcısı Taproot adreslerini desteklemiyor. Lütfen adresi değiştirin veya farklı bir sağlayıcı seçin.", @@ -1160,6 +1190,7 @@ "token_decimal": "Token ondalığı (örn: USDT)", "token_name": "Token adı (örn: Tether)", "token_symbol": "Token sembolü (örn: USDT)", + "token_verified_on_jupiter": "Bu jeton Jupiter'de doğrulandı", "tokenID": "ID", "tokens": "Tokenlar", "tokens_strong_warning": "Bu adrese asla token göndermeyin!", @@ -1288,6 +1319,7 @@ "username": "Kullanıcı adı", "username_available": "Kullanıcı adı kullanılabilir", "username_character_error": "Kullanıcı adları yalnızca şunları içermelidir", + "username_check_your_network": "Kullanıcı adı kontrol edilemedi. Lütfen ağ bağlantınızı kontrol edin.", "username_length_error": "Kullanıcı adları 6-32 alfanümerik karakterden oluşmalıdır.", "username_length_error_1_64": "Kullanıcı adları 1-64 alfanümerik karakter içermelidir.", "username_not_available": "Bu kullanıcı adı kullanılamıyor.", @@ -1298,6 +1330,7 @@ "verify_message": "Mesajı Doğrula", "verify_seed": "Seed'i Doğrula", "verify_with_2fa": "Cake 2FA ile doğrulayın", + "verifying_code": "Kod doğrulanıyor", "version": "Sürüm ${currentVersion}", "view_all": "Tümünü görüntüle", "view_in_block_explorer": "Blok Gezgini'nde görüntüle", @@ -1309,6 +1342,7 @@ "waitFewSecondForTxUpdate": "İşlemin işlem geçmişine yansıması için lütfen birkaç saniye bekleyin", "wallet": "Cüzdan", "wallet_accounts": "Cüzdan Hesapları", + "wallet_balance": "Cüzdan Bakiyesi", "wallet_group": "Cüzdan Grubu", "wallet_group_description_existing_seed": "Bu cüzdan için mevcut bir seed kullanmayı seçtiniz. Onaylamanız veya not almanız gerekiyorsa seed’i tekrar doğrulayabilirsiniz.", "wallet_group_description_four": "tamamen yeni bir seed ile bir cüzdan oluşturmak için.", @@ -1346,9 +1380,11 @@ "walletConnect": "WalletConnect", "wallets": "Cüzdanlar", "warning": "Uyarı", + "wc_action_approve": "Onayla", "wc_approve_request_title": "İsteği onayla", "wc_connect_request_title": "Bağlantı isteği", "wc_connected_to": "${name} ile bağlantı kuruldu", + "wc_desc": "DApp'lere kolayca bağlanın", "wc_max_network_fee": "Maksimum ağ ücreti", "wc_message_to_sign": "İmzalanacak mesaj", "wc_network_fee": "Ağ ücreti", @@ -1399,6 +1435,7 @@ "yat_popup_content": "Artık Cake Wallet'ta kısa, emoji tabanlı bir kullanıcı adı olan Yat'inizle kripto gönderebilir ve alabilirsiniz. Yat'lerinizi istediğiniz zaman ayarlar ekranından yönetebilirsiniz.", "yat_popup_title": "Cüzdan adresiniz emojileştirilebilir.", "yes": "Evet", + "yes_exit": "Evet. Çık", "yesterday": "Dün", "you_now_have_debit_card": "Artık bir banka kartın var", "you_pay": "Sen Ödersin", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index f9421be02..ca5dbfcb6 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -76,6 +76,7 @@ "approve_tokens": "Схвалити токени", "apps": "Застосунки", "arbiscan_history": "Історія ArbiScan", + "are_you_sure_exit": "Ви впевнені, що хочете вийти?", "arrive_in_this_address": "${currency} ${tag}надійдуть на цю адресу", "ascending": "За зростанням", "ask_each_time": "Запитувати щоразу", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Автоматично генерувати адреси", "auto_generate_subaddresses": "Автоматично генерувати субадреси", "automatic": "Автоматично", + "available": "Доступно", "available_balance": "Доступний баланс", "available_balance_description": "«Доступний баланс» або «Підтверджений баланс» — це кошти, які можна витратити негайно. Якщо кошти відображаються в нижньому балансі, але не у верхньому, потрібно зачекати кілька хвилин, доки вхідні кошти отримають більше підтверджень мережі. Після отримання додаткових підтверджень їх можна буде витратити.", "avg_savings": "Сер. заощадження", @@ -125,6 +127,7 @@ "block_remaining": "Залишився 1 блок", "Blocks_remaining": "${status} блоків залишилось", "bluetooth": "Bluetooth", + "bridging": "Перенесення між мережами", "bright_theme": "Світла", "bscscan_history": "Історія BSCScan", "bump_fee": "Підвищити комісію", @@ -216,6 +219,8 @@ "color_theme": "Колірна тема", "coming_soon_tag": "Скоро", "commit_transaction_amount_fee": "Підтвердити транзакцію\nСума: ${amount}\nКомісія: ${fee}", + "compatible_services": "Сумісні сервіси", + "compatible_services_desc": "Скористайтеся інструментом сканування, щоб зчитати такі типи QR-кодів, які підтримує Cake Wallet:", "configure": "Налаштувати", "confirm": "Підтвердити", "confirm_delete_template": "Ця дія видалить цей шаблон. Бажаєте продовжити?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Створення нового гаманця", "creating_new_wallet_error": "Помилка: ${description}", "creation_date": "Дата створення", + "crypto_addresses": "Криптоадреси", "csv_nothing_to_export": "Nothing to export", "current_swap": "Поточний своп", "current_wallet": "Поточний гаманець", @@ -301,6 +307,7 @@ "default_sell_provider": "Провайдер продажу за замовчуванням", "delete": "Видалити", "delete_account": "Видалити акаунт", + "delete_this_node": "Видалити цей вузол", "delete_wallet": "Видалити гаманець", "delete_wallet_confirm_message": "Ви впевнені, що хочете видалити гаманець ${wallet_name}?", "deleteConnectionConfirmationPrompt": "Ви впевнені, що хочете видалити підключення до", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO — це повністю децентралізований, колатералізований стейблкоїн, прив’язаний до євро — безпечний, універсальний і стійкий до цензури, без необхідності покладатися на оракули. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Щоб увімкнути dEURO, у вашому гаманці має бути ETH.", "deuro_tx_commited_content": "Підтвердження транзакції та її відображення на екрані може зайняти кілька секунд", + "device_confirmation": "Підтвердження на пристрої", "device_is_signing": "Пристрій підписує", "dfx_option_description": "Купуйте криптовалюту за EUR і CHF. Для роздрібних та корпоративних клієнтів у Європі", "did_you_back_up_seeds": "Ви створили резервні копії всіх своїх сід-фраз?", @@ -466,6 +474,8 @@ "extracted_address_content": "Ви надсилатимете кошти\n${recipient_name}", "failed_authentication": "Не вдалося пройти автентифікацію. ${state_error}", "faq": "FAQ", + "favorite_token": "Улюблений токен", + "favorite_token_desc": "Баланс улюбленого токена відображатиметься на картці балансу.", "features": "Функції", "fee": "Комісія", "fee_less_than_min": "Вибрана комісія менша за мінімальну, будь ласка, збільште комісію, щоб мати змогу надіслати транзакцію", @@ -491,6 +501,7 @@ "frozen": "Заморожено", "frozen_balance": "Заморожений баланс", "full_balance": "Повний баланс", + "gallery": "Галерея", "gas_exceeds_allowance": "Газ, необхідний для транзакції, перевищує ліміт.", "gas_price": "Ціна газу", "general": "Загальні", @@ -526,6 +537,7 @@ "how_to_connect": "Як підключитися", "how_to_use": "Як користуватися", "how_to_use_card": "Як користуватися цією карткою", + "hww_exit_desc": "Це завершить поточний процес сполучення з вашим апаратним пристроєм", "i_understand": "Я розумію", "icon_style": "Стиль значка", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "Ваша адреса для отримання змінюватиметься щоразу, коли ви отримаєте транзакцію", "infobox_multichain": "Використовуйте цю адресу, щоб отримати будь-який токен або колекційний предмет на", "infobox_rotation": "Ваша адреса для отримання змінюватиметься щоразу, коли ви закриватимете та знову відкриватимете цей екран", + "input": "Введення", "inputs": "Входи", "insufficient_funds_for_tx": "Недостатньо коштів для успішного виконання транзакції.", "insufficient_lamport_for_tx": "У вас недостатньо SOL, щоб покрити транзакцію та комісію за неї. Будь ласка, додайте до свого гаманця більше SOL або зменшіть суму SOL, яку ви надсилаєте.", @@ -605,6 +618,7 @@ "manage_pow_nodes": "Керувати PoW-вузлами", "manage_providers": "Керувати провайдерами", "manage_yats": "Керувати Yats", + "manual_input": "Ручне введення", "mark_as_redeemed": "Позначити як використане", "market_place": "Маркетплейс", "mask": "Маска", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "Усі найновіші моделі (GPT-5.3, Claude 4.6).\nБез підписки, оплата криптовалютою.", "narrow": "Вузький", "network": "Мережа", + "networks": "Мережі", "new_first_wallet_text": "Зберігати вашу криптовалюту в безпеці — простіше простого", "new_node_testing": "Тестування нового вузла", "new_subaddress_create": "Створити", @@ -678,8 +693,10 @@ "node_new": "Новий вузол", "node_port": "Порт ноди", "node_reset_settings_title": "Скинути налаштування", + "node_share_desc": "Відскануйте цей QR-код на екрані сканування, щоб імпортувати цей вузол.", "node_test": "Тест", "nodes": "Вузли", + "nodes_desc": "Керуйте наявними вузлами або додайте власний.", "nodes_list_reset_to_default_message": "Ви впевнені, що хочете скинути налаштування до значень за замовчуванням?", "none_of_selected_providers_can_exchange": "Жоден із вибраних провайдерів не може виконати цей своп", "noNFTYet": "NFT ще немає", @@ -689,6 +706,7 @@ "note_tap_to_change": "Примітка (натисніть, щоб змінити)", "notification_permission_denied": "Дозвіл на сповіщення було назавжди відхилено, будь ласка, увімкніть його вручну в налаштуваннях", "nullURIError": "URI має значення null", + "ocp_desc": "Розплачуйтеся криптовалютою в магазинах", "offer_expires_in": "Пропозиція діє ще: ", "offline": "Офлайн", "ok": "OK", @@ -715,8 +733,13 @@ "outputs": "Виходи", "overshot": "Перевищено", "overwrite_amount": "Перезаписати суму", + "pairing_code": "Код сполучення", + "pairing_code_desc_1": "Ваш пристрій покаже код сполучення.", + "pairing_code_desc_2": "Введіть його тут, щоб продовжити", + "pairing_error": "Помилка сполучення", "pairingInvalidEvent": "Недійсна подія спарювання", "passphrase": "Парольна фраза (необов’язково)", + "passphrase_view_keys": "Парольна фраза", "passphrases_doesnt_match": "Парольні фрази не збігаються, спробуйте ще раз", "password": "Пароль", "paste": "Вставити", @@ -732,6 +755,7 @@ "payjoin_unavailable_sheet_content": "Для отримання транзакції Payjoin у вас має бути готовий до використання Bitcoin.\n\nЩойно на вашому гаманці з’являться кошти, Payjoin буде автоматично ввімкнено.", "payjoin_unavailable_sheet_title": "Чому Payjoin недоступний?", "payment_id": "ID платежу: ", + "payment_invoices": "Платіжні інвойси", "payment_made_easy": "Платежі стали простішими", "payment_was_received": "Ваш платіж отримано.", "payments": "Платежі", @@ -811,6 +835,7 @@ "receive_to": "Отримати на", "received": "Отримано", "receiving": "Отримання", + "recieving": "Отримання", "recipient_address": "Адреса отримувача", "reconnect": "Перепідключити", "reconnect_alert_text": "Ви впевнені, що хочете перепідключитися?", @@ -887,6 +912,7 @@ "save": "Зберегти", "save_backup_password": "Будь ласка, переконайтеся, що ви зберегли пароль резервної копії. Без нього ви не зможете імпортувати файли резервної копії.", "save_backup_password_alert": "Зберегти пароль резервної копії", + "save_contact": "Зберегти контакт", "save_to_downloads": "Зберегти в «Завантаження»", "saved_the_trade_id": "Я зберіг ID обміну", "savings": "Заощадження", @@ -1036,6 +1062,7 @@ "setup_your_debit_card": "Налаштуйте свою дебетову картку", "share": "Поділитися", "share_address": "Поділитися адресою", + "share_this_node": "Поділитися цим вузлом", "shared_seed_wallet_groups": "Групи гаманців зі спільною seed-фразою", "shared_seed_wallets": "Гаманці зі спільною сід-фразою", "show": "Показати", @@ -1043,6 +1070,7 @@ "show_balance": "Натисніть і утримуйте, щоб показати баланс", "show_balance_send_page": "Торкніться, щоб показати", "show_balance_toast": "Натисніть і утримуйте, щоб приховати або показати баланс", + "show_combined_balance": "Показати сукупний баланс", "show_details": "Показати деталі", "show_hidden_addresses": "Показати приховані адреси", "show_keys": "Показати сід/ключі", @@ -1108,6 +1136,7 @@ "swap_providers": "Провайдери обміну", "sweeping_wallet": "Змітання гаманця", "sweeping_wallet_alert": "Це не повинно зайняти багато часу. НЕ ЗАЛИШАЙТЕ ЦЕЙ ЕКРАН, ІНАКШЕ ЗМЕТЕНІ КОШТИ МОЖУТЬ БУТИ ВТРАЧЕНІ.", + "swipe_to_bridge": "Проведіть, щоб перенести між мережами", "swipe_to_send": "Проведіть, щоб надіслати", "switch_wallet": "Перемкнути гаманець", "switchToETHWallet": "Будь ласка, перемкніться на гаманець Ethereum і спробуйте ще раз", @@ -1148,6 +1177,7 @@ "testnet_coins_no_value": "Тестнет-монети не мають цінності", "third_intro_content": "Yat існують і поза Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!", "third_intro_title": "Yat добре працює з іншими", + "this_can_take_few_seconds": "Це може зайняти кілька секунд", "this_pair_is_not_supported_warning": "Ця пара не підтримується для вибраної(их) біржі(ж). Будь ласка, виберіть іншу біржу.", "thorchain_contract_address_not_supported": "THORChain не підтримує надсилання на адресу контракту", "thorchain_taproot_address_not_supported": "Провайдер ThorChain не підтримує адреси Taproot. Будь ласка, змініть адресу або виберіть іншого провайдера.", @@ -1161,6 +1191,7 @@ "token_decimal": "Десятковий розряд токена (напр.: USDT)", "token_name": "Назва токена (напр.: Tether)", "token_symbol": "Символ токена (напр.: USDT)", + "token_verified_on_jupiter": "Цей токен перевірено на Jupiter", "tokenID": "ID", "tokens": "Токени", "tokens_strong_warning": "Ніколи не надсилайте токени на цю адресу!", @@ -1289,6 +1320,7 @@ "username": "Ім’я користувача", "username_available": "Ім'я користувача доступне", "username_character_error": "Імена користувачів повинні містити лише", + "username_check_your_network": "Не вдалося перевірити ім’я користувача. Будь ласка, перевірте підключення до мережі.", "username_length_error": "Ім'я користувача має містити 6–32 буквено-цифрові символи.", "username_length_error_1_64": "Імена користувачів мають містити 1–64 буквено-цифрових символів.", "username_not_available": "Це ім’я користувача недоступне.", @@ -1299,6 +1331,7 @@ "verify_message": "Перевірити повідомлення", "verify_seed": "Перевірте сід-фразу", "verify_with_2fa": "Підтвердьте за допомогою Cake 2FA", + "verifying_code": "Перевірка коду", "version": "Версія ${currentVersion}", "view_all": "Переглянути всі", "view_in_block_explorer": "Переглянути в Block Explorer", @@ -1310,6 +1343,7 @@ "waitFewSecondForTxUpdate": "Будь ласка, зачекайте кілька секунд, поки транзакція з’явиться в історії транзакцій", "wallet": "Гаманець", "wallet_accounts": "Облікові записи гаманця", + "wallet_balance": "Баланс гаманця", "wallet_group": "Група гаманців", "wallet_group_description_existing_seed": "Ви вирішили використати наявну сід-фразу для цього гаманця. Ви можете ще раз перевірити сід-фразу, якщо потрібно підтвердити її або записати.", "wallet_group_description_four": "щоб створити гаманець із повністю новою сід-фразою.", @@ -1347,9 +1381,11 @@ "walletConnect": "WalletConnect", "wallets": "Гаманці", "warning": "Попередження", + "wc_action_approve": "Схвалити", "wc_approve_request_title": "Підтвердити запит", "wc_connect_request_title": "Запит на підключення", "wc_connected_to": "Підключено до ${name}", + "wc_desc": "Легко підключайтеся до dApp", "wc_max_network_fee": "Максимальна мережева плата", "wc_message_to_sign": "Повідомлення для підпису", "wc_network_fee": "Плата за мережу", @@ -1400,6 +1436,7 @@ "yat_popup_content": "Тепер ви можете надсилати й отримувати криптовалюту в Cake Wallet за допомогою Yat — короткого імені користувача на основі емодзі. Керуйте Yat у будь-який час на екрані налаштувань", "yat_popup_title": "Адресу вашого гаманця можна перетворити на емодзі.", "yes": "Так", + "yes_exit": "Так. Вийти", "yesterday": "Вчора", "you_now_have_debit_card": "Тепер у вас є дебетова картка", "you_pay": "Ви платите", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 89c767ea8..2f09dda0a 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -76,6 +76,7 @@ "approve_tokens": "ٹوکنز کی منظوری دیں", "apps": "ایپس", "arbiscan_history": "ArbiScan ہسٹری", + "are_you_sure_exit": "کیا آپ واقعی باہر جانا چاہتے ہیں؟", "arrive_in_this_address": "${currency} ${tag}اس پتے پر پہنچے گا", "ascending": "صعودی", "ask_each_time": "ہر بار پوچھیں", @@ -89,6 +90,7 @@ "auto_generate_addresses": "پتے خودکار طور پر تیار کریں", "auto_generate_subaddresses": "سب ایڈریس خودکار طور پر بنائیں", "automatic": "خودکار", + "available": "دستیاب", "available_balance": "دستیاب بیلنس", "available_balance_description": "”دستیاب بیلنس” یا ”تصدیق شدہ بیلنس” وہ فنڈز ہیں جنہیں فوراً خرچ کیا جا سکتا ہے۔ اگر فنڈز نیچے والے بیلنس میں نظر آئیں لیکن اوپر والے بیلنس میں نہیں، تو آپ کو آنے والے فنڈز کے مزید نیٹ ورک کنفرمیشنز حاصل ہونے کے لیے چند منٹ انتظار کرنا ہوگا۔ جب انہیں مزید کنفرمیشنز مل جائیں گی تو وہ خرچ کے قابل ہو جائیں گے۔", "avg_savings": "اوسط بچت", @@ -125,6 +127,7 @@ "block_remaining": "1 بلاک باقی ہے", "Blocks_remaining": "${status} بلاکس باقی ہیں", "bluetooth": "بلوٹوتھ", + "bridging": "برجنگ", "bright_theme": "روشن", "bscscan_history": "BSCScan ہسٹری", "bump_fee": "فیس بڑھائیں", @@ -216,6 +219,8 @@ "color_theme": "رنگ تھیم", "coming_soon_tag": "جلد آ رہا ہے", "commit_transaction_amount_fee": "لین دین کی تصدیق کریں\nرقم: ${amount}\nفیس: ${fee}", + "compatible_services": "موافق سروسز", + "compatible_services_desc": "Cake Wallet پر معاون درج ذیل اقسام کے QR کوڈز پڑھنے کے لیے Scan ٹول استعمال کریں:", "configure": "ترتیب دیں", "confirm": "تصدیق کریں", "confirm_delete_template": "یہ عمل اس ٹیمپلیٹ کو حذف کر دے گا۔ کیا آپ جاری رکھنا چاہتے ہیں؟", @@ -279,6 +284,7 @@ "creating_new_wallet": "نیا والیٹ بنایا جا رہا ہے", "creating_new_wallet_error": "خرابی: ${description}", "creation_date": "تخلیق کی تاریخ", + "crypto_addresses": "کرپٹو ایڈریسز", "csv_nothing_to_export": "ایکسپورٹ کرنے کے لیے کچھ نہیں ہے", "current_swap": "موجودہ سواپ", "current_wallet": "موجودہ والیٹ", @@ -301,6 +307,7 @@ "default_sell_provider": "ڈیفالٹ سیل فراہم کنندہ", "delete": "حذف کریں", "delete_account": "اکاؤنٹ حذف کریں", + "delete_this_node": "یہ نوڈ حذف کریں", "delete_wallet": "والیٹ حذف کریں", "delete_wallet_confirm_message": "کیا آپ واقعی ${wallet_name} والیٹ کو حذف کرنا چاہتے ہیں؟", "deleteConnectionConfirmationPrompt": "کیا آپ کو یقین ہے کہ آپ کنکشن کو حذف کرنا چاہتے ہیں", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO ایک مکمل طور پر غیر مرکزی، کولیٹرل سے سپورٹڈ اسٹیبل کوائن ہے جو یورو کے ساتھ پیگڈ ہے — محفوظ، ہمہ گیر اور سنسرشپ کے خلاف مزاحم، اوریکلز پر انحصار کیے بغیر۔ 1 dEURO = 1 EURO۔", "deuro_tooltip_no_eth": "dEURO کو فعال کرنے کے لیے، آپ کے والیٹ میں ETH ہونا ضروری ہے۔", "deuro_tx_commited_content": "ٹرانزیکشن کی تصدیق ہونے اور اسکرین پر ظاہر ہونے میں چند سیکنڈ لگ سکتے ہیں", + "device_confirmation": "ڈیوائس کی تصدیق", "device_is_signing": "ڈیوائس دستخط کر رہی ہے", "dfx_option_description": "یورو اور CHF کے ساتھ کرپٹو خریدیں۔ یورپ میں خوردہ اور کارپوریٹ صارفین کے لیے", "did_you_back_up_seeds": "کیا آپ نے اپنے تمام سیڈز کا بیک اپ لے لیا ہے؟", @@ -466,6 +474,8 @@ "extracted_address_content": "آپ فنڈز بھیج رہے ہیں\n${recipient_name} کو", "failed_authentication": "تصدیق ناکام ہوگئی۔ ${state_error}", "faq": "عمومی سوالات", + "favorite_token": "پسندیدہ ٹوکن", + "favorite_token_desc": "پسندیدہ ٹوکن کا بیلنس بیلنس کارڈ پر دکھایا جائے گا۔", "features": "خصوصیات", "fee": "فیس", "fee_less_than_min": "منتخب فیس کم از کم حد سے کم ہے، براہ کرم ٹرانزیکشن بھیجنے کے قابل ہونے کے لیے فیس میں اضافہ کریں", @@ -491,6 +501,7 @@ "frozen": "منجمد", "frozen_balance": "منجمد بیلنس", "full_balance": "مکمل بیلنس", + "gallery": "گیلری", "gas_exceeds_allowance": "ٹرانزیکشن کے لیے درکار گیس مقررہ الاؤنس سے زیادہ ہے۔", "gas_price": "گیس کی قیمت", "general": "عمومی", @@ -526,6 +537,7 @@ "how_to_connect": "کیسے کنیکٹ کریں", "how_to_use": "استعمال کرنے کا طریقہ", "how_to_use_card": "اس کارڈ کو استعمال کرنے کا طریقہ", + "hww_exit_desc": "اس سے آپ کے ہارڈ ویئر ڈیوائس کے ساتھ جاری پیئرنگ کا عمل ختم ہو جائے گا", "i_understand": "میں سمجھ گیا/گئی ہوں", "icon_style": "آئیکن اسٹائل", "id": "ID: ", @@ -540,6 +552,7 @@ "infobox_auto_address": "جب بھی آپ کو کوئی لین دین موصول ہوگا، آپ کا وصولی ایڈریس تبدیل ہو جائے گا", "infobox_multichain": "کسی بھی ٹوکن یا کلیکٹیبل وصول کرنے کے لیے اس ایڈریس کا استعمال کریں", "infobox_rotation": "جب بھی آپ اس اسکرین کو بند کر کے دوبارہ کھولیں گے، آپ کا وصول کرنے والا پتہ تبدیل ہو جائے گا", + "input": "ان پٹ", "inputs": "ان پٹس", "insufficient_funds_for_tx": "لین دین کو کامیابی سے انجام دینے کے لیے ناکافی فنڈز۔", "insufficient_lamport_for_tx": "آپ کے پاس ٹرانزیکشن اور اس کی فیس ادا کرنے کے لیے کافی SOL نہیں ہے۔ براہِ کرم اپنے والیٹ میں مزید SOL شامل کریں یا بھیجی جانے والی SOL کی مقدار کم کریں۔", @@ -605,6 +618,7 @@ "manage_pow_nodes": "PoW نوڈز کا نظم کریں", "manage_providers": "فراہم کنندگان کا نظم کریں", "manage_yats": "یاٹس کا نظم کریں", + "manual_input": "دستی اندراج", "mark_as_redeemed": "ریڈیم شدہ کے طور پر نشان زد کریں", "market_place": "مارکیٹ پلیس", "mask": "ماسک", @@ -650,6 +664,7 @@ "nanogpt_subtitle": "تمام جدید ترین ماڈلز (GPT-5.3، Claude 4.6)۔\nکوئی سبسکرپشن نہیں، کرپٹو کے ساتھ ادائیگی کریں۔", "narrow": "تنگ", "network": "نیٹ ورک", + "networks": "نیٹ ورکس", "new_first_wallet_text": "اپنے کرپٹو کو محفوظ رکھنا بہت آسان ہے", "new_node_testing": "نئے نوڈ کی جانچ", "new_subaddress_create": "بنائیں", @@ -678,8 +693,10 @@ "node_new": "نیا نوڈ", "node_port": "نوڈ پورٹ", "node_reset_settings_title": "ترتیبات ری سیٹ کریں", + "node_share_desc": "اس نوڈ کو امپورٹ کرنے کے لیے Scan اسکرین سے یہ QR کوڈ اسکین کریں۔", "node_test": "ٹیسٹ", "nodes": "نوڈز", + "nodes_desc": "موجودہ نوڈز کا نظم کریں یا ایک کسٹم نوڈ شامل کریں۔", "nodes_list_reset_to_default_message": "کیا آپ واقعی ترتیبات کو ڈیفالٹ پر ری سیٹ کرنا چاہتے ہیں؟", "none_of_selected_providers_can_exchange": "منتخب کردہ فراہم کنندگان میں سے کوئی بھی یہ سواپ نہیں کر سکتا", "noNFTYet": "ابھی تک کوئی NFTs نہیں", @@ -689,6 +706,7 @@ "note_tap_to_change": "نوٹ (تبدیل کرنے کے لیے ٹیپ کریں)", "notification_permission_denied": "نوٹیفکیشن کی اجازت مستقل طور پر مسترد کر دی گئی ہے، براہِ کرم اسے سیٹنگز میں دستی طور پر فعال کریں", "nullURIError": "URI خالی ہے", + "ocp_desc": "اسٹورز میں کرپٹو سے ادائیگی کریں", "offer_expires_in": "پیشکش کی میعاد ختم ہونے میں: ", "offline": "آف لائن", "ok": "ٹھیک ہے", @@ -717,8 +735,13 @@ "outputs": "آؤٹ پٹس", "overshot": "اوور شوٹ", "overwrite_amount": "رقم کو اوور رائٹ کریں", + "pairing_code": "پیئرنگ کوڈ", + "pairing_code_desc_1": "آپ کا ڈیوائس ایک پیئرنگ کوڈ دکھائے گا۔", + "pairing_code_desc_2": "جاری رکھنے کے لیے یہاں درج کریں", + "pairing_error": "پیئرنگ کی خرابی", "pairingInvalidEvent": "غلط پیئرنگ ایونٹ", "passphrase": "پاس فریز (اختیاری)", + "passphrase_view_keys": "پاس فریز", "passphrases_doesnt_match": "پاس فریزز مماثل نہیں ہیں، براہ کرم دوبارہ کوشش کریں", "password": "پاس ورڈ", "paste": "چسپاں کریں", @@ -734,6 +757,7 @@ "payjoin_unavailable_sheet_content": "Payjoin ٹرانزیکشن وصول کرنے کے لیے آپ کے پاس استعمال کے لیے تیار بٹ کوائن ہونا ضروری ہے۔\n\nجیسے ہی آپ کے والیٹ میں فنڈز ہوں گے، Payjoin خود بخود فعال ہو جائے گا۔", "payjoin_unavailable_sheet_title": "Payjoin دستیاب کیوں نہیں ہے؟", "payment_id": "ادائیگی آئی ڈی: ", + "payment_invoices": "ادائیگی کے انوائسز", "payment_made_easy": "ادائیگیاں آسان بنائیں", "payment_was_received": "آپ کی ادائیگی موصول ہو گئی۔", "payments": "ادائیگیاں", @@ -813,6 +837,7 @@ "receive_to": "کو وصول کریں", "received": "موصول ہوا", "receiving": "وصولی", + "recieving": "وصولی", "recipient_address": "وصول کنندہ کا پتہ", "reconnect": "دوبارہ جڑیں", "reconnect_alert_text": "کیا آپ واقعی دوبارہ کنیکٹ کرنا چاہتے ہیں؟", @@ -888,6 +913,7 @@ "save": "محفوظ کریں", "save_backup_password": "براہ کرم یقینی بنائیں کہ آپ نے اپنا بیک اپ پاس ورڈ محفوظ کر لیا ہے۔ اس کے بغیر آپ اپنی بیک اپ فائلیں امپورٹ نہیں کر سکیں گے۔", "save_backup_password_alert": "بیک اپ پاس ورڈ محفوظ کریں", + "save_contact": "رابطہ محفوظ کریں", "save_to_downloads": "ڈاؤن لوڈز میں محفوظ کریں", "saved_the_trade_id": "میں نے ٹریڈ ID محفوظ کر لی ہے۔", "savings": "بچت", @@ -1037,6 +1063,7 @@ "setup_your_debit_card": "اپنا ڈیبٹ کارڈ سیٹ اپ کریں", "share": "شیئر کریں", "share_address": "ایڈریس شیئر کریں", + "share_this_node": "یہ نوڈ شیئر کریں", "shared_seed_wallet_groups": "مشترکہ سیڈ والیٹ گروپس", "shared_seed_wallets": "مشترکہ سیڈ والیٹس", "show": "دکھائیں", @@ -1044,6 +1071,7 @@ "show_balance": "بیلنس دکھانے کے لیے طویل دبائیں", "show_balance_send_page": "ظاہر کرنے کے لیے ٹیپ کریں", "show_balance_toast": "بیلنس چھپانے یا دکھانے کے لیے دیر تک دبائیں", + "show_combined_balance": "مجموعی بیلنس دکھائیں", "show_details": "تفصیلات دکھائیں", "show_hidden_addresses": "پوشیدہ ایڈریسز دکھائیں", "show_keys": "سیڈ/کیز دکھائیں", @@ -1109,6 +1137,7 @@ "swap_providers": "سویپ فراہم کنندگان", "sweeping_wallet": "والٹ سویپ کرنا", "sweeping_wallet_alert": "اس میں زیادہ وقت نہیں لگنا چاہیے۔ اس اسکرین کو مت چھوڑیں، ورنہ سویپ کیے گئے فنڈز ضائع ہو سکتے ہیں۔", + "swipe_to_bridge": "برج کرنے کے لیے سوائپ کریں", "swipe_to_send": "بھیجنے کے لیے سوائپ کریں", "switch_wallet": "والیٹ تبدیل کریں", "switchToETHWallet": "براہِ کرم Ethereum والیٹ پر سوئچ کریں اور دوبارہ کوشش کریں", @@ -1149,6 +1178,7 @@ "testnet_coins_no_value": "ٹیسٹ نیٹ کے سکوں کی کوئی قدر نہیں ہوتی", "third_intro_content": "Yats Cake Wallet سے باہر بھی موجود ہوتے ہیں۔ دنیا میں کسی بھی والیٹ ایڈریس کو Yat سے تبدیل کیا جا سکتا ہے!", "third_intro_title": "Yat دوسروں کے ساتھ اچھی طرح چلتا ہے", + "this_can_take_few_seconds": "اس میں چند سیکنڈ لگ سکتے ہیں", "this_pair_is_not_supported_warning": "یہ جوڑی فی الحال منتخب کردہ ایکسچینج(ز) کے ساتھ سپورٹ نہیں ہے۔ براہ کرم کوئی دوسرا ایکسچینج منتخب کریں۔", "thorchain_contract_address_not_supported": "THORChain کنٹریکٹ ایڈریس پر بھیجنے کی حمایت نہیں کرتا", "thorchain_taproot_address_not_supported": "ThorChain فراہم کنندہ Taproot ایڈریسز کو سپورٹ نہیں کرتا۔ براہِ کرم ایڈریس تبدیل کریں یا کوئی دوسرا فراہم کنندہ منتخب کریں۔", @@ -1162,6 +1192,7 @@ "token_decimal": "ٹوکن اعشاریہ (مثلاً: USDT)", "token_name": "ٹوکن کا نام (مثلاً: Tether)", "token_symbol": "ٹوکن کی علامت (مثلاً: USDT)", + "token_verified_on_jupiter": "یہ ٹوکن Jupiter پر تصدیق شدہ ہے۔", "tokenID": "ID", "tokens": "ٹوکنز", "tokens_strong_warning": "اس پتے پر کبھی بھی ٹوکن نہ بھیجیں!", @@ -1290,6 +1321,7 @@ "username": "یوزرنیم", "username_available": "صارف نام دستیاب ہے", "username_character_error": "صارف نام میں صرف یہ شامل ہو سکتے ہیں", + "username_check_your_network": "صارف نام چیک کرنے سے قاصر۔ براہِ کرم اپنا نیٹ ورک کنکشن چیک کریں۔", "username_length_error": "صارف ناموں میں 6-32 حروف اور اعداد پر مشتمل حروف ہونے ضروری ہیں۔", "username_length_error_1_64": "صارف ناموں میں 1-64 حروفِ تہجی یا اعداد پر مشتمل حروف ہونا ضروری ہے۔", "username_not_available": "یہ صارف نام دستیاب نہیں ہے۔", @@ -1300,6 +1332,7 @@ "verify_message": "پیغام کی توثیق کریں", "verify_seed": "سیڈ کی تصدیق کریں", "verify_with_2fa": "Cake 2FA کے ساتھ تصدیق کریں", + "verifying_code": "کوڈ کی تصدیق کی جا رہی ہے", "version": "ورژن ${currentVersion}", "view_all": "سب دیکھیں", "view_in_block_explorer": "بلاک ایکسپلورر میں دیکھیں", @@ -1311,6 +1344,7 @@ "waitFewSecondForTxUpdate": "براہِ کرم ٹرانزیکشن کو ٹرانزیکشن ہسٹری میں ظاہر ہونے کے لیے چند سیکنڈ انتظار کریں۔", "wallet": "والیٹ", "wallet_accounts": "والیٹ اکاؤنٹس", + "wallet_balance": "والیٹ بیلنس", "wallet_group": "والیٹ گروپ", "wallet_group_description_existing_seed": "آپ نے اس والٹ کے لیے موجودہ سیڈ استعمال کرنے کا انتخاب کیا ہے۔ اگر آپ کو تصدیق کرنے یا لکھ کر محفوظ کرنے کی ضرورت ہو تو آپ سیڈ کی دوبارہ تصدیق کر سکتے ہیں۔", "wallet_group_description_four": "بالکل نئے سیڈ کے ساتھ ایک نیا والیٹ بنانے کے لیے۔", @@ -1348,9 +1382,11 @@ "walletConnect": "WalletConnect", "wallets": "والٹس", "warning": "انتباہ", + "wc_action_approve": "منظور کریں", "wc_approve_request_title": "درخواست منظور کریں۔", "wc_connect_request_title": "رابطہ کی درخواست", "wc_connected_to": "${name} سے منسلک", + "wc_desc": "DApps سے آسانی سے کنیکٹ کریں", "wc_max_network_fee": "زیادہ سے زیادہ نیٹ ورک فیس", "wc_message_to_sign": "دستخط کرنے کا پیغام", "wc_network_fee": "نیٹ ورک فیس", @@ -1401,6 +1437,7 @@ "yat_popup_content": "اب آپ Cake Wallet میں اپنے Yat کے ساتھ کرپٹو بھیج اور وصول کر سکتے ہیں — ایک مختصر، ایموجی پر مبنی صارف نام۔ ترتیبات کی سکرین پر کسی بھی وقت Yats کا نظم کریں۔", "yat_popup_title": "آپ کے والیٹ کا پتہ ایموجی میں تبدیل کیا جا سکتا ہے۔", "yes": "ہاں", + "yes_exit": "ہاں۔ باہر جائیں", "yesterday": "گزشتہ روز", "you_now_have_debit_card": "اب آپ کے پاس ڈیبٹ کارڈ ہے", "you_pay": "آپ ادا کرتے ہیں", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index 6963c9a44..a6d75d190 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -76,6 +76,7 @@ "approve_tokens": "Phê duyệt token", "apps": "Ứng dụng", "arbiscan_history": "Lịch sử ArbiScan", + "are_you_sure_exit": "Bạn có chắc chắn muốn thoát không?", "arrive_in_this_address": "${currency} ${tag} sẽ được gửi đến địa chỉ này", "ascending": "Tăng dần", "ask_each_time": "Hỏi mỗi lần", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Tự động tạo địa chỉ", "auto_generate_subaddresses": "Tự động tạo địa chỉ phụ", "automatic": "Tự động", + "available": "Khả dụng", "available_balance": "Số dư khả dụng", "available_balance_description": "“Số dư khả dụng” hoặc “Số dư đã xác nhận” là số tiền có thể chi tiêu ngay lập tức. Nếu tiền xuất hiện ở số dư phía dưới nhưng không xuất hiện ở số dư phía trên, thì bạn phải đợi vài phút để khoản tiền đến có thêm xác nhận từ mạng. Sau khi có thêm xác nhận, chúng sẽ có thể chi tiêu.", "avg_savings": "Tiết kiệm TB", @@ -125,6 +127,7 @@ "block_remaining": "Còn lại 1 block", "Blocks_remaining": "${status} khối còn lại", "bluetooth": "Bluetooth", + "bridging": "Đang bắc cầu", "bright_theme": "Sáng", "bscscan_history": "Lịch sử BSCScan", "bump_fee": "Tăng phí giao dịch", @@ -188,6 +191,8 @@ "change_wallet_alert_content": "Bạn có muốn chuyển ví hiện tại sang ${wallet_name} không?", "change_wallet_alert_title": "Thay đổi ví hiện tại", "check_receiver_forms": "Vui lòng kiểm tra thông tin người nhận", + "choose_a_payment_method": "Chọn phương thức thanh toán", + "choose_a_provider": "Chọn nhà cung cấp", "choose_account": "Chọn tài khoản", "choose_address": "\n\nVui lòng chọn địa chỉ:", "choose_card_value": "Chọn mệnh giá thẻ", @@ -214,6 +219,8 @@ "color_theme": "Chủ đề màu", "coming_soon_tag": "Sắp ra mắt", "commit_transaction_amount_fee": "Xác nhận giao dịch\nSố tiền: ${amount}\nPhí: ${fee}", + "compatible_services": "Dịch vụ tương thích", + "compatible_services_desc": "Sử dụng công cụ Quét để đọc các loại mã QR sau được hỗ trợ trên Cake Wallet:", "configure": "Cấu hình", "confirm": "Xác nhận", "confirm_delete_template": "Thao tác này sẽ xóa mẫu này. Bạn có muốn tiếp tục không?", @@ -278,6 +285,7 @@ "creating_new_wallet": "Đang tạo ví mới", "creating_new_wallet_error": "Lỗi: ${description}", "creation_date": "Ngày tạo", + "crypto_addresses": "Địa chỉ tiền điện tử", "csv_nothing_to_export": "Không có gì để xuất", "current_swap": "Hoán đổi hiện tại", "current_wallet": "Ví hiện tại", @@ -300,6 +308,7 @@ "default_sell_provider": "Nhà cung cấp bán mặc định", "delete": "Xóa", "delete_account": "Xóa tài khoản", + "delete_this_node": "Xóa node này", "delete_wallet": "Xóa ví", "delete_wallet_confirm_message": "Bạn có chắc chắn muốn xóa ví ${wallet_name} không?", "deleteConnectionConfirmationPrompt": "Bạn có chắc chắn muốn xóa kết nối tới", @@ -329,6 +338,7 @@ "deuro_savings_welcome_description": "dEURO là một stablecoin phi tập trung hoàn toàn, được thế chấp và neo theo đồng Euro — an toàn, linh hoạt và chống kiểm duyệt mà không cần dựa vào oracle. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Để bật dEURO, bạn phải có ETH trong ví.", "deuro_tx_commited_content": "Có thể mất vài giây để giao dịch được xác nhận và hiển thị trên màn hình", + "device_confirmation": "Xác nhận trên thiết bị", "device_is_signing": "Thiết bị đang ký", "dfx_option_description": "Mua tiền điện tử bằng EUR & CHF. Dành cho khách hàng cá nhân và doanh nghiệp tại Châu Âu", "did_you_back_up_seeds": "Bạn đã sao lưu tất cả cụm từ khôi phục của mình chưa?", @@ -465,6 +475,8 @@ "extracted_address_content": "Bạn sẽ gửi tiền đến\n${recipient_name}", "failed_authentication": "Xác thực thất bại. ${state_error}", "faq": "FAQ", + "favorite_token": "Token yêu thích", + "favorite_token_desc": "Số dư của token yêu thích sẽ hiển thị trên thẻ số dư.", "features": "Tính năng", "fee": "Phí", "fee_less_than_min": "Phí đã chọn thấp hơn mức tối thiểu, vui lòng tăng phí để có thể gửi giao dịch", @@ -490,6 +502,7 @@ "frozen": "Đóng băng", "frozen_balance": "Số dư bị đóng băng", "full_balance": "Toàn bộ số dư", + "gallery": "Thư viện ảnh", "gas_exceeds_allowance": "Gas cần cho giao dịch vượt quá mức cho phép.", "gas_price": "Giá gas", "general": "Chung", @@ -525,6 +538,7 @@ "how_to_connect": "Cách kết nối", "how_to_use": "Cách sử dụng", "how_to_use_card": "Cách sử dụng thẻ này", + "hww_exit_desc": "Thao tác này sẽ kết thúc quá trình ghép nối đang diễn ra với thiết bị phần cứng của bạn", "i_understand": "Tôi hiểu", "icon_style": "Kiểu biểu tượng", "id": "ID: ", @@ -539,6 +553,7 @@ "infobox_auto_address": "Địa chỉ nhận của bạn sẽ thay đổi mỗi khi bạn nhận được một giao dịch", "infobox_multichain": "Sử dụng địa chỉ này để nhận bất kỳ token hoặc vật phẩm sưu tầm nào trên", "infobox_rotation": "Địa chỉ nhận của bạn sẽ thay đổi mỗi khi bạn đóng và mở lại màn hình này", + "input": "Đầu vào", "inputs": "Đầu vào", "insufficient_funds_for_tx": "Không đủ số dư để thực hiện giao dịch thành công.", "insufficient_lamport_for_tx": "Bạn không có đủ SOL để thực hiện giao dịch và thanh toán phí giao dịch. Vui lòng nạp thêm SOL vào ví hoặc giảm số lượng SOL bạn đang gửi.", @@ -604,6 +619,7 @@ "manage_pow_nodes": "Quản lý nút PoW", "manage_providers": "Quản lý nhà cung cấp", "manage_yats": "Quản lý Yats", + "manual_input": "Nhập thủ công", "mark_as_redeemed": "Đánh dấu là đã đổi", "market_place": "Chợ", "mask": "Ẩn", @@ -649,6 +665,7 @@ "nanogpt_subtitle": "Tất cả các mô hình mới nhất (GPT-5.3, Claude 4.6).\nKhông cần đăng ký, thanh toán bằng crypto.", "narrow": "Hẹp", "network": "Mạng", + "networks": "Mạng", "new_first_wallet_text": "Giữ tiền điện tử của bạn an toàn dễ như ăn bánh", "new_node_testing": "Thử nghiệm nút mới", "new_subaddress_create": "Tạo", @@ -665,6 +682,7 @@ "no_extra_detail": "Không có thông tin chi tiết bổ sung", "no_id_needed": "Không cần ID!", "no_id_required": "Không cần ID. Nạp tiền và chi tiêu ở bất kỳ đâu", + "no_providers_available": "Không có nhà cung cấp nào khả dụng", "no_relay_on_domain": "Không có relay cho miền của người dùng hoặc relay không khả dụng. Vui lòng chọn một relay để sử dụng.", "no_relays": "Không có bộ chuyển tiếp", "no_relays_message": "Chúng tôi đã tìm thấy một bản ghi Nostr NIP-05 cho người dùng này, nhưng bản ghi đó không chứa bất kỳ relay nào. Vui lòng hướng dẫn người nhận thêm relay vào bản ghi Nostr của họ.", @@ -676,8 +694,10 @@ "node_new": "Nút mới", "node_port": "Cổng node", "node_reset_settings_title": "Đặt lại cài đặt", + "node_share_desc": "Quét mã QR này từ màn hình Quét để nhập node này.", "node_test": "Thử nghiệm", "nodes": "Các nút", + "nodes_desc": "Quản lý các node hiện có hoặc thêm một node tùy chỉnh.", "nodes_list_reset_to_default_message": "Bạn có chắc chắn muốn đặt lại cài đặt về mặc định không?", "none_of_selected_providers_can_exchange": "Không có nhà cung cấp nào trong số các nhà cung cấp đã chọn có thể thực hiện hoán đổi này", "noNFTYet": "Chưa có NFT nào", @@ -687,6 +707,7 @@ "note_tap_to_change": "Ghi chú (chạm để thay đổi)", "notification_permission_denied": "Quyền thông báo đã bị từ chối vĩnh viễn, vui lòng bật thủ công trong cài đặt", "nullURIError": "URI là rỗng", + "ocp_desc": "Thanh toán bằng tiền điện tử tại cửa hàng", "offer_expires_in": "Ưu đãi hết hạn sau: ", "offline": "Ngoại tuyến", "ok": "OK", @@ -713,8 +734,13 @@ "outputs": "Đầu ra", "overshot": "Vượt quá", "overwrite_amount": "Ghi đè số lượng", + "pairing_code": "Mã ghép nối", + "pairing_code_desc_1": "Thiết bị của bạn sẽ hiển thị một mã ghép nối.", + "pairing_code_desc_2": "Nhập vào đây để tiếp tục", + "pairing_error": "Lỗi ghép nối", "pairingInvalidEvent": "Sự kiện ghép nối không hợp lệ", "passphrase": "Cụm mật khẩu (Tùy chọn)", + "passphrase_view_keys": "Cụm mật khẩu", "passphrases_doesnt_match": "Cụm mật khẩu không khớp, vui lòng thử lại", "password": "Mật khẩu", "paste": "Dán", @@ -730,6 +756,7 @@ "payjoin_unavailable_sheet_content": "Để nhận một giao dịch Payjoin, bạn cần có sẵn Bitcoin để sử dụng.\n\nNgay khi ví của bạn có số dư, Payjoin sẽ tự động được bật.", "payjoin_unavailable_sheet_title": "Tại sao Payjoin không khả dụng?", "payment_id": "ID thanh toán: ", + "payment_invoices": "Hóa đơn thanh toán", "payment_made_easy": "Thanh toán dễ dàng", "payment_was_received": "Khoản thanh toán của bạn đã được nhận.", "payments": "Thanh toán", @@ -809,6 +836,7 @@ "receive_to": "Nhận vào", "received": "Đã nhận", "receiving": "Đang nhận", + "recieving": "Đang nhận", "recipient_address": "Địa chỉ người nhận", "reconnect": "Kết nối lại", "reconnect_alert_text": "Bạn có chắc chắn muốn kết nối lại không?", @@ -884,6 +912,7 @@ "save": "Lưu", "save_backup_password": "Vui lòng đảm bảo rằng bạn đã lưu mật khẩu sao lưu của mình. Bạn sẽ không thể nhập các tệp sao lưu nếu không có mật khẩu này.", "save_backup_password_alert": "Lưu mật khẩu bản sao lưu", + "save_contact": "Lưu liên hệ", "save_to_downloads": "Lưu vào mục Tải xuống", "saved_the_trade_id": "Tôi đã lưu ID giao dịch", "savings": "Tiết kiệm", @@ -955,6 +984,7 @@ "select_sell_provider_notice": "Chọn nhà cung cấp bán ở trên. Bạn có thể bỏ qua màn hình này bằng cách đặt nhà cung cấp bán mặc định trong cài đặt ứng dụng.", "select_token": "Chọn token", "select_your_country": "Vui lòng chọn quốc gia của bạn", + "selected_trocador_provider": "nhà cung cấp Trocador đã chọn", "sell": "Bán", "sell_alert_content": "Hiện tại chúng tôi chỉ hỗ trợ bán Bitcoin, Ethereum và Litecoin. Vui lòng tạo hoặc chuyển sang ví Bitcoin, Ethereum hoặc Litecoin của bạn.", "sell_monero_com_alert_content": "Chưa hỗ trợ bán Monero", @@ -1032,6 +1062,7 @@ "setup_your_debit_card": "Thiết lập thẻ ghi nợ của bạn", "share": "Chia sẻ", "share_address": "Chia sẻ địa chỉ", + "share_this_node": "Chia sẻ node này", "shared_seed_wallet_groups": "Nhóm ví seed được chia sẻ", "shared_seed_wallets": "Ví seed được chia sẻ", "show": "Hiển thị", @@ -1039,6 +1070,7 @@ "show_balance": "Nhấn và giữ để hiển thị số dư", "show_balance_send_page": "Chạm để hiển thị", "show_balance_toast": "Nhấn và giữ để ẩn hoặc hiển thị số dư", + "show_combined_balance": "Hiển thị số dư tổng hợp", "show_details": "Hiển thị chi tiết", "show_hidden_addresses": "Hiển thị các địa chỉ ẩn", "show_keys": "Hiển thị cụm từ khôi phục/khóa", @@ -1104,6 +1136,7 @@ "swap_providers": "Nhà cung cấp hoán đổi", "sweeping_wallet": "Quét ví", "sweeping_wallet_alert": "Việc này sẽ không mất nhiều thời gian. KHÔNG RỜI KHỎI MÀN HÌNH NÀY, NẾU KHÔNG SỐ TIỀN ĐÃ QUÉT CÓ THỂ BỊ MẤT.", + "swipe_to_bridge": "Vuốt để bắc cầu", "swipe_to_send": "Vuốt để gửi", "switch_wallet": "Chuyển đổi ví", "switchToETHWallet": "Vui lòng chuyển sang ví Ethereum và thử lại", @@ -1144,6 +1177,7 @@ "testnet_coins_no_value": "Coin testnet không có giá trị", "third_intro_content": "Yats cũng tồn tại bên ngoài Cake Wallet. Bất kỳ địa chỉ ví nào trên thế giới cũng có thể được thay thế bằng một Yat!", "third_intro_title": "Yat hoạt động tốt với các nền tảng khác", + "this_can_take_few_seconds": "Việc này có thể mất vài giây", "this_pair_is_not_supported_warning": "Cặp này không được hỗ trợ với (các) sàn giao dịch hiện được chọn. Vui lòng chọn một sàn giao dịch khác.", "thorchain_contract_address_not_supported": "THORChain không hỗ trợ gửi đến địa chỉ hợp đồng", "thorchain_taproot_address_not_supported": "Nhà cung cấp ThorChain không hỗ trợ địa chỉ Taproot. Vui lòng đổi địa chỉ hoặc chọn nhà cung cấp khác.", @@ -1157,6 +1191,7 @@ "token_decimal": "Số thập phân của token (ví dụ: USDT)", "token_name": "Tên token (ví dụ: Tether)", "token_symbol": "Ký hiệu token (ví dụ: USDT)", + "token_verified_on_jupiter": "Mã thông báo này được xác minh trên Jupiter", "tokenID": "ID", "tokens": "Token", "tokens_strong_warning": "Không bao giờ gửi token đến địa chỉ này!", @@ -1285,6 +1320,7 @@ "username": "Tên người dùng", "username_available": "Tên người dùng khả dụng", "username_character_error": "Tên người dùng chỉ được chứa", + "username_check_your_network": "Không thể kiểm tra tên người dùng. Vui lòng kiểm tra kết nối mạng của bạn.", "username_length_error": "Tên người dùng phải chứa 6-32 ký tự chữ và số.", "username_length_error_1_64": "Tên người dùng phải chứa 1-64 ký tự chữ và số.", "username_not_available": "Tên người dùng này không khả dụng.", @@ -1295,6 +1331,7 @@ "verify_message": "Xác minh tin nhắn", "verify_seed": "Xác minh cụm từ khôi phục", "verify_with_2fa": "Xác minh bằng Cake 2FA", + "verifying_code": "Đang xác minh mã", "version": "Phiên bản ${currentVersion}", "view_all": "Xem tất cả", "view_in_block_explorer": "Xem trong trình khám phá khối", @@ -1306,6 +1343,7 @@ "waitFewSecondForTxUpdate": "Vui lòng đợi vài giây để giao dịch hiển thị trong lịch sử giao dịch", "wallet": "Ví", "wallet_accounts": "Tài khoản ví", + "wallet_balance": "Số dư ví", "wallet_group": "Nhóm ví", "wallet_group_description_existing_seed": "Bạn đã chọn sử dụng seed hiện có cho ví này. Bạn có thể xác minh lại seed nếu cần để xác nhận hoặc ghi lại.", "wallet_group_description_four": "để tạo một ví với một seed hoàn toàn mới.", @@ -1343,9 +1381,11 @@ "walletConnect": "WalletConnect", "wallets": "Ví", "warning": "Cảnh báo", + "wc_action_approve": "Phê duyệt", "wc_approve_request_title": "Phê duyệt yêu cầu", "wc_connect_request_title": "Yêu cầu kết nối", "wc_connected_to": "Đã kết nối với ${name}", + "wc_desc": "Dễ dàng kết nối với các dApp", "wc_max_network_fee": "Phí mạng tối đa", "wc_message_to_sign": "Tin nhắn để ký", "wc_network_fee": "Phí mạng", @@ -1396,6 +1436,7 @@ "yat_popup_content": "Giờ đây bạn có thể gửi và nhận tiền mã hóa trong Cake Wallet bằng Yat của bạn – một tên người dùng ngắn dựa trên emoji. Bạn có thể quản lý Yat bất cứ lúc nào trong màn hình cài đặt", "yat_popup_title": "Địa chỉ ví của bạn có thể được chuyển thành emoji.", "yes": "Có", + "yes_exit": "Có. Thoát", "yesterday": "Hôm qua", "you_now_have_debit_card": "Giờ đây bạn đã có thẻ ghi nợ", "you_pay": "Bạn trả", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 8a073f320..385df6301 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -76,6 +76,7 @@ "approve_tokens": "Fọwọsi àwọn àmi", "apps": "Àwọn Ìṣàfilọ́lẹ̀", "arbiscan_history": "Ìtàn ArbiScan", + "are_you_sure_exit": "Ṣé ó dá ọ lójú pé o fẹ́ jáde?", "arrive_in_this_address": "${currency} ${tag} yóò dé sí àdírẹ́sì yìí", "ascending": "Ni aṣẹ̀kẹ́sẹ̀", "ask_each_time": "Beere ní gbogbo ìgbà", @@ -89,6 +90,7 @@ "auto_generate_addresses": "Ṣẹda àwọn adirẹsi láìfẹ́ ọwọ́", "auto_generate_subaddresses": "Ṣẹda àwọn àdírẹ́sì kékeré láìfọwọ́", "automatic": "Aifọwọyi", + "available": "Ó wà", "available_balance": "Ìwọ̀ntúnwọ̀nsì tó wà", "available_balance_description": "“Iwọntunwọnsi Wa” tabi “Iwọntunwọnsi Ti a Jẹ́rìí” jẹ́ àwọn owó tí o lè na lẹ́sẹ̀kẹsẹ. Bí àwọn owó bá hàn ní iwọntunwọnsi ìsàlẹ̀ ṣùgbọ́n kì í hàn ní iwọntunwọnsi òkè, nígbà náà o gbọdọ̀ dúró fún ìṣẹ́jú díẹ̀ kí àwọn owó tí ń wọlé lè gba ìjẹ́rìí nẹ́tíwọ́ọ̀kì púpọ̀ síi. Lẹ́yìn tí wọ́n bá ti gba ìjẹ́rìí púpọ̀ síi, o lè na wọ́n.", "avg_savings": "Ìpamọ́ àpapọ̀", @@ -125,6 +127,7 @@ "block_remaining": "Bulọọki 1 tó kù", "Blocks_remaining": "${status} Àwọn bulọọki tó kù", "bluetooth": "Bluetooth", + "bridging": "Ríré ìjápọ̀", "bright_theme": "Imọlẹ", "bscscan_history": "Ìtàn BSCScan", "bump_fee": "Gbé ọya ga", @@ -216,6 +219,8 @@ "color_theme": "Àkòrí àwọ̀", "coming_soon_tag": "N bọ laipẹ", "commit_transaction_amount_fee": "Fọwọ́sí ìdúnàdúrà\nIye: ${amount}\nOwó ìdúnàdúrà: ${fee}", + "compatible_services": "Àwọn Iṣẹ́ Tó Bámu", + "compatible_services_desc": "Lo irinṣẹ́ Scan láti ka àwọn irú kóòdù QR wọ̀nyí tí a ṣe àtìlẹ́yìn fún lórí Cake Wallet:", "configure": "Ṣètò", "confirm": "Jẹ́risí", "confirm_delete_template": "Ìṣe yìí máa pa àwòṣe yìí rẹ́. Ṣé o fẹ́ tẹ̀síwájú?", @@ -279,6 +284,7 @@ "creating_new_wallet": "Ń ṣẹ̀dá àpamọ́wọ́ tuntun", "creating_new_wallet_error": "Aṣiṣe: ${description}", "creation_date": "Ọjọ́ ìdásílẹ̀", + "crypto_addresses": "Àwọn Àdírẹ́sì Crypto", "csv_nothing_to_export": "Kò sí ohunkóhun láti gbé jáde", "current_swap": "Swap lọwọlọwọ", "current_wallet": "Apamọwọ lọwọlọwọ", @@ -301,6 +307,7 @@ "default_sell_provider": "Olupese Tita Aiyipada", "delete": "Páàré", "delete_account": "Pa àkántì rẹ́", + "delete_this_node": "Pa nódù yìí rẹ́", "delete_wallet": "Pa àpamọ́wọ́ rẹ́", "delete_wallet_confirm_message": "Ṣé ó dá ẹ lójú pé ẹ fẹ́ pa wálẹ́ẹ̀tì ${wallet_name} rẹ́?", "deleteConnectionConfirmationPrompt": "Ṣé ó dá ọ lójú pé o fẹ́ pa asopọ̀ sí", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO jẹ stablecoin tí a ṣe ní ìpínkiri ní kikun, tí a fi ìdógba (collateral) ṣe àtìlẹ́yìn, tí ó sì so mọ́ Euro — ó láàbò, ó rọrùn láti lò ní ọ̀nà púpọ̀, ó sì kọ̀ láti jẹ́ kí a ṣe ìfọwọ́kàn sí i, láì nílò láti gbẹ́kẹ̀lé àwọn orákù. 1 dEURO = 1 EURO.", "deuro_tooltip_no_eth": "Láti lè mu dEURO ṣiṣẹ́, o gbọ́dọ̀ ní ETH nínú apamọwọ rẹ.", "deuro_tx_commited_content": "Ó lè gba ìṣẹ́jú-aaya díẹ̀ kí ìdúnàdúrà náà lè jẹ́risi, kí ó sì hàn lórí iboju", + "device_confirmation": "Ìjẹ́rìísí Ẹrọ", "device_is_signing": "Ẹrọ ń fọwọ́ sí", "dfx_option_description": "Ra crypto pẹlu EUR & CHF. Fun awọn alabara soobu ati awọn alabara ile-iṣẹ ní Yúróòpù", "did_you_back_up_seeds": "Ṣe o ti ṣe afẹyinti gbogbo àwọn gbolohun ìrùgbìn rẹ?", @@ -467,6 +475,8 @@ "extracted_address_content": "O máa rán owó sí\n${recipient_name}", "failed_authentication": "Ìfàṣẹsí kò ṣàṣeyọrí. ${state_error}", "faq": "FAQ", + "favorite_token": "Tóókẹ́nì àyànfẹ́", + "favorite_token_desc": "Ìwọ̀ntúnwọ̀nsì tóókẹ́nì àyànfẹ́ náà yóò hàn lórí kaadi ìwọ̀ntúnwọ̀nsì.", "features": "Awọn ẹya", "fee": "Ọya", "fee_less_than_min": "Owo ìdúná tí a yàn kere ju iye tó kéré jù lọ; jọwọ pọ̀ sí i kí o lè fi ìdúná náà ránṣẹ́.", @@ -492,6 +502,7 @@ "frozen": "Dídì", "frozen_balance": "Iwontunwonsi tí a dì", "full_balance": "Ìwọ̀ntúnwọ̀nsì kíkún", + "gallery": "Àwòrán-ìkójọ", "gas_exceeds_allowance": "Gaasi tí ìdúnàdúrà náà nílò ti kọjá ìwọ̀n tí a fàyè gba.", "gas_price": "Iye gaasi", "general": "Gbogbogbo", @@ -527,6 +538,7 @@ "how_to_connect": "Bí a ṣe lè sopọ", "how_to_use": "Bí a ṣe lè lò", "how_to_use_card": "Báwo ni a ṣe ń lo káàdì yìí", + "hww_exit_desc": "Eyi yóò parí ìlànà ìsopọ̀ tí ń lọ lọ́wọ́ pẹ̀lú ẹrọ hardware rẹ", "i_understand": "Mo ye mi", "icon_style": "Aami ara", "id": "ID: ", @@ -541,6 +553,7 @@ "infobox_auto_address": "Adirẹsi gbigba rẹ yóò máa yí padà ní gbogbo ìgbà tí o bá gba ìdúnàdúrà kan", "infobox_multichain": "Lo adirẹsi yii lati gba eyikeyi tokini tabi ohun ìkójọpọ̀ lori", "infobox_rotation": "Adirẹsi gbigba rẹ yóò yí padà ní gbogbo ìgbà tí o bá ti iboju yìí, tí o sì tún ṣí i", + "input": "Ìwọlé", "inputs": "Àwọn ìwọlé", "insufficient_funds_for_tx": "Ko si owo to lati ṣe idunadura naa ni aṣeyọri.", "insufficient_lamport_for_tx": "O ko ni SOL to lati bo idunadura naa ati owo-ori idunadura rẹ. Jọwọ fi SOL kun apamọwọ rẹ tabi dinku iye SOL ti o n firanṣẹ.", @@ -606,6 +619,7 @@ "manage_pow_nodes": "Ṣakoso àwọn nódì PoW", "manage_providers": "Ṣàkóso àwọn olùpèsè", "manage_yats": "Ṣàkóso Yats", + "manual_input": "Ìwọlé Pẹ̀lú Ọwọ́", "mark_as_redeemed": "Samisi gẹ́gẹ́ bí a ti rà padà", "market_place": "Ọjà", "mask": "Iboju", @@ -651,6 +665,7 @@ "nanogpt_subtitle": "Gbogbo àwọn àwòṣe tuntun jùlọ (GPT-5.3, Claude 4.6).\nKò sí ìforúkọsílẹ̀, sanwó pẹ̀lú crypto.", "narrow": "Dín", "network": "Nẹ́tíwọ́ọ̀kì", + "networks": "Àwọn Nẹ́tíwọ́ọ̀kì", "new_first_wallet_text": "Mímú kíríptò rẹ láàbò rọrùn bíi akara oyinbo", "new_node_testing": "Ìdánwò node tuntun", "new_subaddress_create": "Ṣẹda", @@ -679,8 +694,10 @@ "node_new": "Nóòdù Tuntun", "node_port": "Pọ́ọ̀tì node", "node_reset_settings_title": "Tun àwọn àtòlẹ́sẹẹsẹ ṣe", + "node_share_desc": "Ṣe àyẹ̀wò kóòdù QR yìí láti ojú Scan láti gbé nódù yìí wọlé.", "node_test": "Ìdánwò", "nodes": "Àwọn nódù", + "nodes_desc": "Ṣàkóso àwọn nódù tó wà tẹ́lẹ̀ tàbí ṣàfikún ọ̀kan tí ara rẹ.", "nodes_list_reset_to_default_message": "Ṣé o dá ọ lójú pé o fẹ́ tún àwọn ààtò ṣe sí àtẹ̀yìnwá?", "none_of_selected_providers_can_exchange": "Ko si ọkan ninu awọn olupese tí a yàn tó lè ṣe paṣipaarọ yìí", "noNFTYet": "Ko si NFT sibẹsibẹ", @@ -690,6 +707,7 @@ "note_tap_to_change": "Akọsilẹ (tẹ lati yí padà)", "notification_permission_denied": "A ti kọ igbanilaaye iwifunni patapata, jọwọ mu un ṣiṣẹ lọ́wọ́ rẹ nínú àwọn eto", "nullURIError": "URI jẹ òfo", + "ocp_desc": "Sanwó pẹ̀lú crypto ní àwọn ilé ìtajà", "offer_expires_in": "Ìpèsè yìí máa parí ní: ", "offline": "Àìlórí ayélujára", "ok": "Ó DÁRA", @@ -716,8 +734,13 @@ "outputs": "Àwọn àbájáde", "overshot": "Ti kọja iye", "overwrite_amount": "Rọ́pò iye", + "pairing_code": "Kóòdù Ìsopọ̀", + "pairing_code_desc_1": "Ẹrọ rẹ yóò ṣàfihàn kóòdù ìsopọ̀ kan.", + "pairing_code_desc_2": "Tẹ̀ ẹ́ sílẹ̀ níbí láti tẹ̀síwájú", + "pairing_error": "Àṣìṣe Ìsopọ̀", "pairingInvalidEvent": "Iṣẹlẹ Pipọpọ Aibojumu", "passphrase": "Gbolohun aṣínà (Aṣayan)", + "passphrase_view_keys": "Gbolóhùn aṣínà", "passphrases_doesnt_match": "Awọn gbolohun aṣínà kò bá ara wọn mu, jọwọ gbìyànjú lẹ́ẹ̀kansi", "password": "Ọ̀rọ̀ ìgbaniwọlé", "paste": "Lẹ́", @@ -733,6 +756,7 @@ "payjoin_unavailable_sheet_content": "Gbigba ìdúnàdúrà Payjoin nìbéèrè pé kí o ní Bitcoin tó ṣetán láti lò.\n\nNí kété tí apamọwọ rẹ bá ní owó, Payjoin yóò ṣiṣẹ́ laifọwọ́yì.", "payjoin_unavailable_sheet_title": "Kí nìdí tí Payjoin kò fi wà?", "payment_id": "ID Ìsanwó: ", + "payment_invoices": "Àwọn Ìwé Ìsanwó", "payment_made_easy": "Ṣíṣe ìsanwó rọrùn", "payment_was_received": "A ti gba ìsanwó rẹ.", "payments": "Awọn ìsanwó", @@ -812,6 +836,7 @@ "receive_to": "Gba sí", "received": "Ti gbà", "receiving": "Gbigba", + "recieving": "Gbigba", "recipient_address": "Àdírẹ́sì olùgbà", "reconnect": "Tun so pọ̀", "reconnect_alert_text": "Ṣé ó dá ẹ lójú pé ẹ fẹ́ tún sopọ̀?", @@ -887,6 +912,7 @@ "save": "Fipamọ́", "save_backup_password": "Jọ̀wọ́ rí i dájú pé ẹ ti fipamọ́ ọ̀rọ̀ aṣínà ìpamọ́ yín. Ẹ kò ní lè wọlé sí àwọn fáìlì ìpamọ́ yín láìsí rẹ̀.", "save_backup_password_alert": "Pamọ́ ọ̀rọ̀ aṣínà afẹ́yinti", + "save_contact": "Fi Olùbáṣepọ̀ Pamọ́", "save_to_downloads": "Fipamọ sí Downloads", "saved_the_trade_id": "Mo ti fipamọ́ ID ìṣòwò náà", "savings": "Ifipamọ", @@ -1036,6 +1062,7 @@ "setup_your_debit_card": "Ṣètò káàdì débítì rẹ", "share": "Pín", "share_address": "Pín àdírẹ́sì", + "share_this_node": "Pín nódù yìí", "shared_seed_wallet_groups": "Awọn ẹgbẹ apamọwọ Irugbin Pín", "shared_seed_wallets": "Àwọn Woleti Irúgbìn Pínpín", "show": "Fi hàn", @@ -1043,6 +1070,7 @@ "show_balance": "Tẹ mọ́lẹ̀ láti ṣàfihàn iwọntúnwọ̀nsì", "show_balance_send_page": "Tẹ lati ṣí hàn", "show_balance_toast": "Tẹ mọ́lẹ̀ láti fi ìwọ̀ntúnwọ̀nsì pamọ́ tàbí ṣàfihàn", + "show_combined_balance": "Ṣàfihàn ìwọ̀ntúnwọ̀nsì àpapọ̀", "show_details": "Fi àwọn àlàyè hàn", "show_hidden_addresses": "Ṣàfihàn àwọn àdírẹ́sì tí a ti fipamọ́", "show_keys": "Ṣàfihàn seed/kọ́kọ́rọ́", @@ -1108,6 +1136,7 @@ "swap_providers": "Awọn olupese swap", "sweeping_wallet": "Wallet ìkó", "sweeping_wallet_alert": "Eyi kò yẹ kí ó pẹ́. MÁ ṢE KÚRÒ LÓRÍ IBÓJÚ YÌÍ TÁBÍ OWÓ TÍ A TI SWEEP LÈ SỌ́NÙ.", + "swipe_to_bridge": "Fà láti so ìjápọ̀", "swipe_to_send": "Ra lati fi ránṣẹ́", "switch_wallet": "Yí apamọwọ padà", "switchToETHWallet": "Jọwọ yipada sí apamọwọ Ethereum kí o sì tún gbìyànjú lẹ́ẹ̀kansi", @@ -1148,6 +1177,7 @@ "testnet_coins_no_value": "Awọn kóìnì testnet kò ní iye", "third_intro_content": "Yats wà níta Cake Wallet pàá. A lè rọ́pò àdírẹ́sì àpamọ́wọ́ kankan níbi gbogbo pẹ̀lú Yat!", "third_intro_title": "Yat bá àwọn míì ṣiṣẹ́ dáadáa", + "this_can_take_few_seconds": "Eyi lè gba ìṣẹ́jú-aaya díẹ̀", "this_pair_is_not_supported_warning": "Akọsopọ yii kò ní ìtìlẹ́yìn pẹ̀lú (àwọn) paṣipaarọ tí a yàn lọ́wọ́lọ́wọ́. Jọwọ yan paṣipaarọ míì.", "thorchain_contract_address_not_supported": "THORChain kò ṣe àtìlẹ́yìn fífi ránṣẹ́ sí àdírẹ́sì contract", "thorchain_taproot_address_not_supported": "Olupese ThorChain ko ṣe atilẹyin fún àwọn àdírẹ́sì Taproot. Jọwọ yí àdírẹ́sì náà padà tàbí yan olupese míì.", @@ -1161,6 +1191,7 @@ "token_decimal": "Token decimal (àpẹẹrẹ: 6 fún USDT)", "token_name": "Orukọ token (eg: Tether)", "token_symbol": "Ami àpẹẹrẹ token (àpẹẹrẹ: USDT)", + "token_verified_on_jupiter": "Aami yii jẹ idaniloju lori Jupiter", "tokenID": "ID", "tokens": "Àwọn tóókẹ́nì", "tokens_strong_warning": "Maṣe fi àwọn tóókẹ́nì ránṣẹ́ sí àdírẹ́sì yìí!", @@ -1289,6 +1320,7 @@ "username": "Orúkọ olumulo", "username_available": "Orúkọ olumulo wà", "username_character_error": "Orúkọ olumulo gbọdọ̀ ní àwọn àmi wọ̀nyí nìkan", + "username_check_your_network": "Kò lè ṣàyẹ̀wò orúkọ olumulo. Jọ̀wọ́ ṣàyẹ̀wò ìsopọ̀ nẹ́tíwọ́ọ̀kì rẹ.", "username_length_error": "Orúkọ olumulo gbọdọ ní àwọn ohun kikọ alphanumeric 6-32.", "username_length_error_1_64": "Orúkọ olumulo gbọ́dọ̀ ní àwọn àmi alphanumeric 1-64.", "username_not_available": "Orukọ olumulo yii ko si.", @@ -1299,6 +1331,7 @@ "verify_message": "Ṣàyẹ̀wò Ifiranṣẹ", "verify_seed": "Jẹ́rìí Seed", "verify_with_2fa": "Jẹ́rìí pẹ̀lú Cake 2FA", + "verifying_code": "Ń ṣàyẹ̀wò Kóòdù", "version": "Ẹ̀dà ${currentVersion}", "view_all": "Wo gbogbo rẹ", "view_in_block_explorer": "Wò ní Block Explorer", @@ -1310,6 +1343,7 @@ "waitFewSecondForTxUpdate": "Jọwọ dúró fún ìṣẹ́jú díẹ̀ kí ìdúnàdúrà náà lè hàn nínú ìtàn ìdúnàdúrà", "wallet": "Apamọwọ", "wallet_accounts": "Àwọn àkántì apamọwọ", + "wallet_balance": "Ìwọ̀ntúnwọ̀nsì Apamọwọ", "wallet_group": "Ẹgbẹ́ Apamọwọ", "wallet_group_description_existing_seed": "O ti yan lati lo irugbin (seed) ti o wa tẹlẹ fun apamọwọ yii. O le tun jẹrisi irugbin naa lẹẹkansi ti o ba nilo lati fidi rẹ múlẹ tàbí kọ ọ sílẹ.", "wallet_group_description_four": "Láti ṣẹ̀dá apamọwọ kan pẹ̀lú seed tuntun pátápátá.", @@ -1347,9 +1381,11 @@ "walletConnect": "WalletConnect", "wallets": "Àwọn wálẹ́ẹ̀tì", "warning": "Ìkìlọ̀", + "wc_action_approve": "Fọwọ́sí", "wc_approve_request_title": "fọwọsi ìbéèrè", "wc_connect_request_title": "Sopọ ìbéèrè", "wc_connected_to": "Sopọ si ${name}", + "wc_desc": "So pọ̀ mọ́ àwọn DApp ní rọrùn", "wc_max_network_fee": "Max owo nẹtiwọki", "wc_message_to_sign": "Ifiranṣẹ lati wole", "wc_network_fee": "Nẹtiwọki ọya", @@ -1400,6 +1436,7 @@ "yat_popup_content": "Ẹ lè ránṣẹ́ àti gba crypto nínú Cake Wallet pẹ̀lú Yat yín — orúkọ olùṣàmúlò kúkurú tí a dá lórí emoji. Ṣàkóso àwọn Yat nígbàkúgbà lórí ojú ìṣètò.", "yat_popup_title": "A lè yí àdírẹ́sì wálẹ́ẹ̀tì rẹ padà sí emoji.", "yes": "Bẹẹni", + "yes_exit": "Bẹ́ẹ̀ni. Jáde", "yesterday": "Àná", "you_now_have_debit_card": "O ti ní káàdì débítì báyìí", "you_pay": "Ìwọ san", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 19a2e9a70..893988b17 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -76,6 +76,7 @@ "approve_tokens": "授权代币", "apps": "应用", "arbiscan_history": "ArbiScan 历史记录", + "are_you_sure_exit": "您确定要退出吗?", "arrive_in_this_address": "${currency} ${tag}将发送到此地址", "ascending": "升序", "ask_each_time": "每次都询问", @@ -89,6 +90,7 @@ "auto_generate_addresses": "自动生成地址", "auto_generate_subaddresses": "自动生成子地址", "automatic": "自动", + "available": "可用", "available_balance": "可用余额", "available_balance_description": "“可用余额”或“确认余额”是指可立即花费的资金。如果资金显示在下方余额中但未显示在上方余额中,则需要等待几分钟,让转入资金获得更多网络确认。获得更多确认后,这些资金即可花费。", "avg_savings": "平均节省", @@ -125,6 +127,7 @@ "block_remaining": "剩余 1 个区块", "Blocks_remaining": "剩余 ${status} 个区块", "bluetooth": "蓝牙", + "bridging": "跨链桥接中", "bright_theme": "明亮", "bscscan_history": "BSCScan 历史记录", "bump_fee": "提高手续费(RBF)", @@ -216,6 +219,8 @@ "color_theme": "颜色主题", "coming_soon_tag": "即将推出", "commit_transaction_amount_fee": "提交交易\n金额:${amount}\n手续费:${fee}", + "compatible_services": "兼容的服务", + "compatible_services_desc": "使用扫描工具读取 Cake Wallet 支持的以下类型二维码:", "configure": "配置", "confirm": "确认", "confirm_delete_template": "此操作将删除此模板。是否继续?", @@ -279,6 +284,7 @@ "creating_new_wallet": "正在创建新钱包", "creating_new_wallet_error": "错误:${description}", "creation_date": "创建日期", + "crypto_addresses": "加密货币地址", "csv_nothing_to_export": "无可导出的内容", "current_swap": "当前兑换", "current_wallet": "当前钱包", @@ -301,6 +307,7 @@ "default_sell_provider": "默认卖出服务商", "delete": "删除", "delete_account": "删除账户", + "delete_this_node": "删除此节点", "delete_wallet": "删除钱包", "delete_wallet_confirm_message": "确定要删除 ${wallet_name} 钱包吗?", "deleteConnectionConfirmationPrompt": "您确定要删除与…的连接吗?", @@ -330,6 +337,7 @@ "deuro_savings_welcome_description": "dEURO 是一种完全去中心化、由抵押品支持的稳定币,与欧元挂钩——安全、多用途且抗审查,无需依赖预言机。1 dEURO = 1 欧元。", "deuro_tooltip_no_eth": "要启用 dEURO,您的钱包中必须有 ETH。", "deuro_tx_commited_content": "交易可能需要几秒钟才能确认,并在屏幕上显示", + "device_confirmation": "设备确认", "device_is_signing": "设备正在签名", "dfx_option_description": "使用 EUR 和 CHF 购买加密货币。面向欧洲的零售和企业客户", "did_you_back_up_seeds": "您已备份所有助记词了吗?", @@ -466,6 +474,8 @@ "extracted_address_content": "您将向\n${recipient_name}\n发送资金", "failed_authentication": "身份验证失败。${state_error}", "faq": "FAQ", + "favorite_token": "收藏的代币", + "favorite_token_desc": "收藏代币的余额将显示在余额卡片上。", "features": "功能", "fee": "手续费", "fee_less_than_min": "所选手续费低于最低值,请提高手续费以便发送交易", @@ -491,6 +501,7 @@ "frozen": "冻结", "frozen_balance": "冻结余额", "full_balance": "全部余额", + "gallery": "相册", "gas_exceeds_allowance": "交易所需的 Gas 超过了允许额度。", "gas_price": "Gas 费", "general": "通用", @@ -526,6 +537,7 @@ "how_to_connect": "如何连接", "how_to_use": "如何使用", "how_to_use_card": "如何使用此卡", + "hww_exit_desc": "这将结束与您的硬件设备正在进行的配对过程", "i_understand": "我明白了", "icon_style": "图标风格", "id": "ID: ", @@ -541,6 +553,7 @@ "infobox_auto_address": "每次收到交易时,您的收款地址都会自动轮换", "infobox_multichain": "使用此地址接收任何代币或收藏品", "infobox_rotation": "每次您关闭并重新打开此页面时,您的接收地址都会更换", + "input": "输入", "inputs": "输入", "insufficient_funds_for_tx": "余额不足,无法成功执行交易。", "insufficient_lamport_for_tx": "您的 SOL 余额不足以支付本次交易及其手续费。请向钱包中充值更多 SOL,或减少要发送的 SOL 数量。", @@ -606,6 +619,7 @@ "manage_pow_nodes": "管理 PoW 节点", "manage_providers": "管理服务提供商", "manage_yats": "管理 Yats", + "manual_input": "手动输入", "mark_as_redeemed": "标记为已兑换", "market_place": "市场", "mask": "掩码", @@ -651,6 +665,7 @@ "nanogpt_subtitle": "所有最新模型(GPT-5.3、Claude 4.6)。\n无需订阅,用加密货币支付。", "narrow": "窄", "network": "网络", + "networks": "网络", "new_first_wallet_text": "让您的加密货币安全无忧,轻而易举", "new_node_testing": "新节点测试", "new_subaddress_create": "创建", @@ -679,8 +694,10 @@ "node_new": "新节点", "node_port": "节点端口", "node_reset_settings_title": "重置设置", + "node_share_desc": "在扫描页面扫描此二维码即可导入此节点。", "node_test": "测试", "nodes": "节点", + "nodes_desc": "管理现有节点或添加自定义节点。", "nodes_list_reset_to_default_message": "您确定要将设置重置为默认值吗?", "none_of_selected_providers_can_exchange": "所选的提供商均无法完成此兑换", "noNFTYet": "暂无 NFT", @@ -690,6 +707,7 @@ "note_tap_to_change": "备注(轻触以更改)", "notification_permission_denied": "通知权限已被永久拒绝,请在设置中手动启用", "nullURIError": "URI 为空", + "ocp_desc": "在商店中使用加密货币支付", "offer_expires_in": "优惠将在以下时间到期:", "offline": "离线", "ok": "确定", @@ -716,8 +734,13 @@ "outputs": "输出", "overshot": "超出", "overwrite_amount": "覆盖金额", + "pairing_code": "配对码", + "pairing_code_desc_1": "您的设备将显示一个配对码。", + "pairing_code_desc_2": "在此处输入以继续", + "pairing_error": "配对错误", "pairingInvalidEvent": "配对无效事件", "passphrase": "密码短语(可选)", + "passphrase_view_keys": "密码短语", "passphrases_doesnt_match": "密语不一致,请重试", "password": "密码", "paste": "粘贴", @@ -733,6 +756,7 @@ "payjoin_unavailable_sheet_content": "接收 Payjoin 交易需要您的钱包中有可用的比特币。\n\n一旦您的钱包有资金,Payjoin 将自动启用。", "payjoin_unavailable_sheet_title": "为什么 Payjoin 不可用?", "payment_id": "支付 ID:", + "payment_invoices": "付款发票", "payment_made_easy": "轻松支付", "payment_was_received": "已收到您的付款。", "payments": "支付", @@ -812,6 +836,7 @@ "receive_to": "接收至", "received": "已接收", "receiving": "接收", + "recieving": "接收中", "recipient_address": "收款地址", "reconnect": "重新连接", "reconnect_alert_text": "您确定要重新连接吗?", @@ -887,6 +912,7 @@ "save": "保存", "save_backup_password": "请确保您已保存备份密码。没有它,您将无法导入备份文件。", "save_backup_password_alert": "保存备份密码", + "save_contact": "保存联系人", "save_to_downloads": "保存到“下载”", "saved_the_trade_id": "我已保存交易 ID", "savings": "储蓄", @@ -1036,6 +1062,7 @@ "setup_your_debit_card": "设置您的借记卡", "share": "分享", "share_address": "分享地址", + "share_this_node": "分享此节点", "shared_seed_wallet_groups": "共享助记词钱包组", "shared_seed_wallets": "共享助记词钱包", "show": "显示", @@ -1043,6 +1070,7 @@ "show_balance": "长按显示余额", "show_balance_send_page": "点击以显示", "show_balance_toast": "长按以隐藏或显示余额", + "show_combined_balance": "显示合并余额", "show_details": "显示详情", "show_hidden_addresses": "显示隐藏的地址", "show_keys": "显示种子短语/密钥", @@ -1108,6 +1136,7 @@ "swap_providers": "兑换服务提供商", "sweeping_wallet": "正在归集钱包", "sweeping_wallet_alert": "这应该不会花很长时间。请勿离开此屏幕,否则被归集的资金可能会丢失。", + "swipe_to_bridge": "滑动以跨链桥接", "swipe_to_send": "滑动以发送", "switch_wallet": "切换钱包", "switchToETHWallet": "请切换到以太坊钱包后重试", @@ -1148,6 +1177,7 @@ "testnet_coins_no_value": "测试网币没有实际价值", "third_intro_content": "Yats 也存在于 Cake Wallet 之外。地球上任何一个钱包地址都可以用一个 Yat 来替代!", "third_intro_title": "Yat 与其他应用兼容良好", + "this_can_take_few_seconds": "这可能需要几秒钟", "this_pair_is_not_supported_warning": "当前所选的交易所不支持该交易对。请选择其他交易所。", "thorchain_contract_address_not_supported": "THORChain 不支持发送到合约地址", "thorchain_taproot_address_not_supported": "ThorChain 提供商不支持 Taproot 地址。请更换地址或选择其他提供商。", @@ -1161,6 +1191,7 @@ "token_decimal": "代币小数位数(例如:USDT)", "token_name": "代币名称(例如:Tether)", "token_symbol": "代币符号(例如:USDT)", + "token_verified_on_jupiter": "该令牌已在 Jupiter 上验证", "tokenID": "ID", "tokens": "代币", "tokens_strong_warning": "切勿将代币发送到此地址!", @@ -1289,6 +1320,7 @@ "username": "用户名", "username_available": "用户名可用", "username_character_error": "用户名只能包含", + "username_check_your_network": "无法检查用户名。请检查您的网络连接。", "username_length_error": "用户名必须包含 6-32 个字母数字字符。", "username_length_error_1_64": "用户名必须包含 1-64 个字母或数字字符。", "username_not_available": "该用户名不可用。", @@ -1299,6 +1331,7 @@ "verify_message": "验证消息", "verify_seed": "验证助记词", "verify_with_2fa": "使用 Cake 2FA 验证", + "verifying_code": "正在验证验证码", "version": "版本 ${currentVersion}", "view_all": "查看全部", "view_in_block_explorer": "在区块浏览器中查看", @@ -1310,6 +1343,7 @@ "waitFewSecondForTxUpdate": "请稍等几秒钟,交易将会显示在交易记录中", "wallet": "钱包", "wallet_accounts": "钱包账户", + "wallet_balance": "钱包余额", "wallet_group": "钱包分组", "wallet_group_description_existing_seed": "您已选择在此钱包中使用现有助记词。如需确认或抄写,您可以再次验证助记词。", "wallet_group_description_four": "创建一个使用全新助记词的钱包。", @@ -1347,9 +1381,11 @@ "walletConnect": "WalletConnect", "wallets": "钱包", "warning": "警告", + "wc_action_approve": "批准", "wc_approve_request_title": "批准请求", "wc_connect_request_title": "连接请求", "wc_connected_to": "连接到${name}", + "wc_desc": "轻松连接到 DApp", "wc_max_network_fee": "最高网络费用", "wc_message_to_sign": "要签名的消息", "wc_network_fee": "网络费", @@ -1400,6 +1436,7 @@ "yat_popup_content": "您现在可以在 Cake Wallet 中使用 Yat 发送和接收加密货币——一种基于表情符号的简短用户名。您可随时在设置页面管理 Yat", "yat_popup_title": "您的钱包地址可以表情符号化。", "yes": "是", + "yes_exit": "是的,退出", "yesterday": "昨天", "you_now_have_debit_card": "您现在已拥有一张借记卡", "you_pay": "您支付", @@ -1414,41 +1451,5 @@ "zcash_card_enable_later": "您随时可以在设置中启用此卡", "zcash_card_missing_funds": "资金不见了?", "zcash_card_scan": "扫描", - "zcash_card_warning": "在该过程完成之前请勿关闭应用程序,否则该过程将需要从头重新开始。", - "are_you_sure_exit": "您确定要退出吗?", - "available": "可用", - "bridging": "跨链桥接中", - "compatible_services": "兼容的服务", - "compatible_services_desc": "使用扫描工具读取 Cake Wallet 支持的以下类型二维码:", - "crypto_addresses": "加密货币地址", - "delete_this_node": "删除此节点", - "device_confirmation": "设备确认", - "favorite_token": "收藏的代币", - "favorite_token_desc": "收藏代币的余额将显示在余额卡片上。", - "gallery": "相册", - "hww_exit_desc": "这将结束与您的硬件设备正在进行的配对过程", - "input": "输入", - "manual_input": "手动输入", - "networks": "网络", - "node_share_desc": "在扫描页面扫描此二维码即可导入此节点。", - "nodes_desc": "管理现有节点或添加自定义节点。", - "ocp_desc": "在商店中使用加密货币支付", - "pairing_code": "配对码", - "pairing_code_desc_1": "您的设备将显示一个配对码。", - "pairing_code_desc_2": "在此处输入以继续", - "pairing_error": "配对错误", - "passphrase_view_keys": "密码短语", - "payment_invoices": "付款发票", - "recieving": "接收中", - "save_contact": "保存联系人", - "share_this_node": "分享此节点", - "show_combined_balance": "显示合并余额", - "swipe_to_bridge": "滑动以跨链桥接", - "this_can_take_few_seconds": "这可能需要几秒钟", - "username_check_your_network": "无法检查用户名。请检查您的网络连接。", - "verifying_code": "正在验证验证码", - "wallet_balance": "钱包余额", - "wc_action_approve": "批准", - "wc_desc": "轻松连接到 DApp", - "yes_exit": "是的,退出" + "zcash_card_warning": "在该过程完成之前请勿关闭应用程序,否则该过程将需要从头重新开始。" } \ No newline at end of file diff --git a/tool/configure.dart b/tool/configure.dart index 022eaa2cd..c0ce610a4 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -983,6 +983,7 @@ abstract class Solana { List getDefaultTokenContractAddresses(); List getDefaultTokenSymbols(); bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress); + Future isTokenVerifiedOnJupiter(WalletBase wallet, String mintAddress); // Jupiter swap transaction handling // Signs and prepares a base64-encoded unsigned transaction for sending From fb790120ed39455ffa915e66a0388107888e201f Mon Sep 17 00:00:00 2001 From: Seth For Privacy <40500387+sethforprivacy@users.noreply.github.com> Date: Thu, 6 Aug 2026 20:20:32 -0400 Subject: [PATCH 09/10] Hide the receive rotation notice for static Zcash address types (#3444) --- lib/new-ui/pages/receive_page.dart | 12 ++++++++++++ .../widgets/receive_page/receive_info_box.dart | 8 +++++++- lib/zcash/cw_zcash.dart | 8 ++++++++ tool/configure.dart | 1 + 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/new-ui/pages/receive_page.dart b/lib/new-ui/pages/receive_page.dart index b5656e9de..2948f9a93 100644 --- a/lib/new-ui/pages/receive_page.dart +++ b/lib/new-ui/pages/receive_page.dart @@ -97,6 +97,10 @@ class _NewReceivePageState extends State { ) as WalletAddressListItem?; reaction((_) => widget.receiveOptionViewModel.selectedReceiveOption, (option) { + // The infobox depends on the selected address type, so the page has to be + // rebuilt when it changes. + if (mounted) setState(() {}); + if (widget.dashboardViewModel.type == WalletType.bitcoin && bitcoin!.isBitcoinReceivePageOption(option)) { widget.addressListViewModel.setAddressType(bitcoin!.getOptionToType(option)); @@ -179,6 +183,7 @@ class _NewReceivePageState extends State { autoGenerateSubaddressStatus: widget.lightningMode ? AutoGenerateSubaddressStatus.disabled : widget.dashboardViewModel.settingsStore.autoGenerateSubaddressStatus, + addressRotates: _selectedAddressRotates, ); return Container( @@ -366,6 +371,13 @@ class _NewReceivePageState extends State { ); } + /// Zcash is the only wallet type that also offers static address types, so + /// the rotation notice must not be shown for it unless the disposable + /// transparent type is the one currently selected. + bool get _selectedAddressRotates => + widget.addressListViewModel.type != WalletType.zcash || + zcash!.isRotatingAddressOption(widget.receiveOptionViewModel.selectedReceiveOption); + void _showLabelModal() { showMaterialModalBottomSheet( context: context, diff --git a/lib/new-ui/widgets/receive_page/receive_info_box.dart b/lib/new-ui/widgets/receive_page/receive_info_box.dart index db34cef16..ac3f1acfd 100644 --- a/lib/new-ui/widgets/receive_page/receive_info_box.dart +++ b/lib/new-ui/widgets/receive_page/receive_info_box.dart @@ -16,10 +16,15 @@ class ReceiveInfoBox extends StatelessWidget { required this.onDismissed, this.bottomWidget}); + /// [addressRotates] tells whether the address type currently selected on the + /// receive page actually rotates. Most wallet types only ever expose rotating + /// address types, so it defaults to true; Zcash also offers static types, for + /// which the rotation notice would be wrong. static ReceiveInfoBox? forWalletType(WalletType type, {required VoidCallback onDismissed, required AutoGenerateSubaddressStatus autoGenerateSubaddressStatus, - List? supportedCurrencies}) { + List? supportedCurrencies, + bool addressRotates = true}) { switch (type) { case WalletType.nano: return null; @@ -43,6 +48,7 @@ class ReceiveInfoBox extends StatelessWidget { )); default: if (autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.disabled) return null; + if (!addressRotates) return null; return ReceiveInfoBox( iconPath: "assets/new-ui/info.svg", message: S.current.infobox_auto_address, diff --git a/lib/zcash/cw_zcash.dart b/lib/zcash/cw_zcash.dart index 51c9dc53e..8abef07dc 100644 --- a/lib/zcash/cw_zcash.dart +++ b/lib/zcash/cw_zcash.dart @@ -176,6 +176,14 @@ class CWZcash extends Zcash { return getSelectedAddressType(wallet) == ZcashReceivePageOption.transparentRotated; } + /// The disposable transparent type is the only Zcash address type that + /// rotates. The public transparent address, both shielded types and the + /// unified address are all derived from the account and stay the same. + @override + bool isRotatingAddressOption(ReceivePageOption option) { + return option == ZcashReceivePageOption.transparentRotated; + } + @override dynamic getZcashAddressType(ReceivePageOption option) { return (option as ZcashReceivePageOption).toType(); diff --git a/tool/configure.dart b/tool/configure.dart index c0ce610a4..19e1521fd 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -1766,6 +1766,7 @@ abstract class Zcash { ReceivePageOption getSelectedAddressType(Object wallet); dynamic getZcashAddressType(ReceivePageOption option); bool hasSelectedTransparentAddress(Object wallet); + bool isRotatingAddressOption(ReceivePageOption option); Future setAddressType(Object wallet, dynamic option); dynamic getOptionToType(ReceivePageOption option); void unlockDatabase(String password); From c93843f3347a0d8f816000eb84190f4fa494f363 Mon Sep 17 00:00:00 2001 From: cyan Date: Fri, 7 Aug 2026 02:28:39 +0200 Subject: [PATCH 10/10] fix: display proper address in zcash transactions (#3457) --- cw_zcash/lib/src/zcash_wallet.dart | 211 ++++++++++++++--------------- cw_zcash/pubspec.yaml | 2 +- 2 files changed, 102 insertions(+), 111 deletions(-) diff --git a/cw_zcash/lib/src/zcash_wallet.dart b/cw_zcash/lib/src/zcash_wallet.dart index 98d4a92b1..6266c6700 100644 --- a/cw_zcash/lib/src/zcash_wallet.dart +++ b/cw_zcash/lib/src/zcash_wallet.dart @@ -521,10 +521,10 @@ abstract class ZcashWalletBase static const _dispPhrase = "Received to disposable address"; - bool _hasExternalOutputs(final ZkoolTx tx) => - tx.outputsWithAddress.any((final o) => !_addressBelongsToWallet(o.address)); + bool _hasExternalOutputs(final ZkoolTx tx, final Set ownedAddresses) => + tx.outputsWithAddress.any((final o) => !_isOwnedAddress(o.address, ownedAddresses)); - bool _isIronwoodMigrationTx(final ZkoolTx tx) { + bool _isIronwoodMigrationTx(final ZkoolTx tx, final Set ownedAddresses) { // zkool classifies migration as selfTransfer with fee-sized net value. if (tx.type != TxType.selfTransfer) { return false; @@ -540,7 +540,7 @@ abstract class ZcashWalletBase return true; } // Orchard → Orchard split step (SD notes created, all outputs are ours). - if (tx.orchardReceived > BigInt.zero && !_hasExternalOutputs(tx)) { + if (tx.orchardReceived > BigInt.zero && !_hasExternalOutputs(tx, ownedAddresses)) { return true; } // Orchard → Ironwood before the IW note is attached to tx details. @@ -577,10 +577,7 @@ abstract class ZcashWalletBase .whereType() .where((final m) => m.isNotEmpty) .firstOrNull; - final recipientAddresses = _recipientAddresses( - accountNotes.map((final n) => n.address).whereType(), - direction, - ); + final recipientAddresses = const []; final info = ZcashTransactionInfo( id: txHash, @@ -608,17 +605,20 @@ abstract class ZcashWalletBase final bool isShieldAction = false, final TransactionDirection? directionOverride, final BigInt? amountOverride, + required final Set ownedAddresses, }) { final confirmations = tx.height > 0 && currentHeight >= tx.height ? currentHeight - tx.height + 1 : 0; final memo = extraMemo != null ? "${tx.memo ?? ''}\n$extraMemo".trim() : tx.memo; - final isMigration = directionOverride == null && _isIronwoodMigrationTx(tx); + final isMigration = directionOverride == null && _isIronwoodMigrationTx(tx, ownedAddresses); final direction = directionOverride ?? (isMigration ? TransactionDirection.outgoing : tx.direction); - final recipientAddresses = _recipientAddresses(_paymentOutputAddresses(tx), direction); final amount = amountOverride ?? (isMigration ? _migrationDisplayAmount(tx) : tx.value); + final recipientAddresses = direction == TransactionDirection.outgoing + ? _outgoingRecipientAddresses(tx, ownedAddresses: ownedAddresses) + : const []; final info = ZcashTransactionInfo( id: tx.txHash, amount: Money(amount, currency), @@ -641,14 +641,18 @@ abstract class ZcashWalletBase return info; } - bool _isShieldActionTx(final ZkoolTx tx, {required final Set rotationSweepHashes}) { + bool _isShieldActionTx( + final ZkoolTx tx, { + required final Set rotationSweepHashes, + required final Set ownedAddresses, + }) { if (ZcashWalletService.isAutoshieldTx(tx.txHash)) { return true; } if (rotationSweepHashes.contains(tx.txHash)) { return true; } - if (_isPayToSelfAutoshield(tx)) { + if (_isPayToSelfAutoshield(tx, ownedAddresses)) { return true; } if (tx.direction == TransactionDirection.outgoing && @@ -658,7 +662,7 @@ abstract class ZcashWalletBase return false; } - bool _isPayToSelfAutoshield(final ZkoolTx tx) { + bool _isPayToSelfAutoshield(final ZkoolTx tx, final Set ownedAddresses) { if (tx.type != TxType.shield && tx.type != TxType.transparentSelfTransfer) { return false; } @@ -669,18 +673,23 @@ abstract class ZcashWalletBase return false; } for (final dest in tx.outputAddresses) { - if (_addressBelongsToWallet(dest)) { + if (_isOwnedAddress(dest, ownedAddresses)) { return true; } } return tx.orchardReceived > BigInt.zero; } - bool _shouldSplitAutoshieldTx(final ZkoolTx tx, {required final bool isShield}) { + bool _shouldSplitAutoshieldTx( + final ZkoolTx tx, { + required final bool isShield, + required final Set ownedAddresses, + }) { if (!isShield) { return false; } - if (ZcashWalletService.isAutoshieldTx(tx.txHash) || _isPayToSelfAutoshield(tx)) { + if (ZcashWalletService.isAutoshieldTx(tx.txHash) || + _isPayToSelfAutoshield(tx, ownedAddresses)) { return tx.transparentOrSaplingSpent > BigInt.zero && tx.orchardReceived > BigInt.zero; } return false; @@ -724,104 +733,57 @@ abstract class ZcashWalletBase } } - bool _addressBelongsToWallet(final String addr) { - final addrs = walletAddresses; - if (addrs.containsAddress(addr) || - addrs.hiddenAddresses.contains(addr) || - addrs.usedAddresses.contains(addr)) { - return true; - } - for (final infos in addrs.addressInfos.values) { - for (final info in infos) { - if (info.address == addr) { - return true; - } - } - } - for (final own in [ - addrs.orchardAddress, - addrs.unifiedAddress, - addrs.saplingAddress, - addrs.transparentAddress, - addrs.address, - ]) { - if (own == null || own.isEmpty || own.startsWith('unknown ')) { + Future> _ownedAddressSet(final zkool_coin.Coin coin) async { + final owned = {}; + for (final address in await zkool_account.listOwnedAddresses(c: coin)) { + if (address.isEmpty) { continue; } - if (addr == own || addr.startsWith(own) || own.startsWith(addr)) { - return true; + owned.add(address); + if (address.startsWith('u')) { + owned.addAll(_uaReceivers(address)); } } - return false; - } - - List _paymentOutputAddresses(final ZkoolTx tx) { - final all = tx.outputsWithAddress.toList(); - final external = all.where((final o) => !_addressBelongsToWallet(o.address)).toList(); - final outputs = external.isNotEmpty ? external : all; - final transparent = outputs.where((final o) => o.pool == NotePool.transparent.index).toList(); - if (transparent.length >= 2) { - return transparent.map((final o) => o.address).toList(); + final addrs = walletAddresses; + for (final infos in addrs.addressInfos.values) { + for (final info in infos) { + owned.add(info.address); + } } - return outputs.map((final o) => o.address).toList(); + owned.addAll(addrs.hiddenAddresses); + owned.addAll(addrs.usedAddresses); + return owned; } - List _recipientAddresses( - final Iterable raw, - final TransactionDirection direction, - ) { + bool _isOwnedAddress(final String addr, final Set ownedAddresses) => + ownedAddresses.contains(addr); + + List _outgoingRecipientAddresses( + final ZkoolTx tx, { + required final Set ownedAddresses, + }) { + var outputs = tx.outputsWithAddress + .where((final o) => !_isOwnedAddress(o.address, ownedAddresses)) + .toList(); + if (outputs.isEmpty) { + return []; + } + + final transparent = + outputs.where((final o) => o.pool == NotePool.transparent.index).toList(); + if (transparent.length >= 2) { + outputs = transparent; + } + + return _dedupeAddresses(outputs.map((final o) => o.address)); + } + + List _dedupeAddresses(final Iterable raw) { final seen = {}; - final addresses = [ + return [ for (final address in raw) if (address.trim().isNotEmpty && seen.add(address.trim())) address.trim(), ]; - if (addresses.isEmpty) { - return []; - } - - final external = direction == TransactionDirection.incoming - ? addresses - : [ - for (final address in addresses) - if (!_addressBelongsToWallet(address)) address, - ]; - final list = external.isNotEmpty ? external : addresses; - if (list.isEmpty) { - return []; - } - - final embedded = { - for (final address in list) - if (address.startsWith('u')) ..._uaReceivers(address), - }; - var result = embedded.isEmpty - ? list - : [ - for (final address in list) - if (address.startsWith('u') || !embedded.contains(address)) address, - ]; - if (result.isEmpty) { - result = list; - } - - final standalone = [ - for (final address in result) - if (!address.startsWith('u') && !embedded.contains(address)) address, - ]; - if (standalone.length >= 2) { - result = standalone; - } - - if (direction == TransactionDirection.incoming) { - return [ - result.firstWhere( - (final a) => a.startsWith('u'), - orElse: () => - result.firstWhere((final a) => a.startsWith('z'), orElse: () => result.first), - ), - ]; - } - return result; } Set _uaReceivers(final String ua) { @@ -839,9 +801,10 @@ abstract class ZcashWalletBase @override Future> fetchTransactions() async { await ZcashWalletService.loadShieldTxs(); - final (txs, currentHeight) = await runWithCoin( + final (txs, currentHeight, ownedAddresses) = await runWithCoin( accountId: accountId, func: (coin) async { + final owned = await _ownedAddressSet(coin); final txsI = await zkool_account.listTxHistory(c: coin); final txsA = await Future.wait( txsI.map((final tx) => zkool_account.getTxDetails(idTx: tx.id, c: coin)), @@ -857,7 +820,7 @@ abstract class ZcashWalletBase } catch (e) { printV("failed to get height: $e"); } - return (txs, currentHeight); + return (txs, currentHeight, owned); }, ); final Map byHash = {}; @@ -871,11 +834,25 @@ abstract class ZcashWalletBase if (tx.direction == TransactionDirection.incoming) { _offerTx( byHash, - _zcashInfoFromZkoolTx(tx, currentHeight, extraMemo: _dispPhrase, isRotationReceive: true), + _zcashInfoFromZkoolTx( + tx, + currentHeight, + extraMemo: _dispPhrase, + isRotationReceive: true, + ownedAddresses: ownedAddresses, + ), ); continue; } - _offerTx(byHash, _zcashInfoFromZkoolTx(tx, currentHeight, isShieldAction: true)); + _offerTx( + byHash, + _zcashInfoFromZkoolTx( + tx, + currentHeight, + isShieldAction: true, + ownedAddresses: ownedAddresses, + ), + ); } final Map splitEntries = {}; @@ -884,8 +861,12 @@ abstract class ZcashWalletBase if (tx.height > 0) { ZcashMempoolService.instance.removeTx(tx.txHash); } - final isShield = _isShieldActionTx(tx, rotationSweepHashes: rotationSweepHashes); - if (_shouldSplitAutoshieldTx(tx, isShield: isShield)) { + final isShield = _isShieldActionTx( + tx, + rotationSweepHashes: rotationSweepHashes, + ownedAddresses: ownedAddresses, + ); + if (_shouldSplitAutoshieldTx(tx, isShield: isShield, ownedAddresses: ownedAddresses)) { byHash.remove(tx.txHash); splitEntries[_txResultKey(tx.txHash, suffix: '_shield')] = _zcashInfoFromZkoolTx( tx, @@ -893,16 +874,26 @@ abstract class ZcashWalletBase isShieldAction: true, directionOverride: TransactionDirection.outgoing, amountOverride: tx.transparentOrSaplingSpent, + ownedAddresses: ownedAddresses, ); splitEntries[_txResultKey(tx.txHash, suffix: '_recv')] = _zcashInfoFromZkoolTx( tx, currentHeight, directionOverride: TransactionDirection.incoming, amountOverride: tx.orchardReceived, + ownedAddresses: ownedAddresses, ); continue; } - _offerTx(byHash, _zcashInfoFromZkoolTx(tx, currentHeight, isShieldAction: isShield)); + _offerTx( + byHash, + _zcashInfoFromZkoolTx( + tx, + currentHeight, + isShieldAction: isShield, + ownedAddresses: ownedAddresses, + ), + ); } final knownHashes = { diff --git a/cw_zcash/pubspec.yaml b/cw_zcash/pubspec.yaml index 40fdd5019..3ae75fbd5 100644 --- a/cw_zcash/pubspec.yaml +++ b/cw_zcash/pubspec.yaml @@ -21,7 +21,7 @@ dependencies: # path: ../../zkool2 git: url: https://github.com/cake-tech/zkool2.git - ref: 6329d4aacb4568ee80ff84baba5ea93b07ae1013 + ref: 16fd3d11575f850939f498c3ea75d391915456d1 path_provider: any sqflite_common_ffi: any