Allow Exporting transaction history to a CSV file (#3230)
What changed, and why it matters
This commit adds a feature that lets users export their transaction history to a CSV file. The export includes details such as dates, amounts, transaction IDs, addresses, and notes. It is a normal data-export feature, not a code vulnerability. However, because the exported file can contain sensitive financial information, users should be careful where they save or share it. The commit also includes two small safety fixes: it checks whether a screen can be closed before trying to close it, and it clips the share-dialog position on iOS so it does not go off-screen.
Treat this as a feature addition with routine privacy implications rather than a security defect. Reviewers should verify that: (1) exported CSV does not include private keys or seed material, (2) the temp file is reliably deleted after share/save failures, (3) Android scoped storage / MANAGE_EXTERNAL_STORAGE requirements are correctly declared, and (4) user-facing strings inform users that the export contains sensitive data. No immediate patch is required for the code shown.
Security signals we found
New data-export surface: transaction history can be written to external storage / shared
CSV values are escaped (quote-doubling) before serialization
Temp file is written to application documents directory then copied/deleted
Android export writes to fixed public Downloads path /storage/emulated/0/Download
Share sheet receives file path and filename from app-controlled values
Navigator pop guarded with canPop to prevent exception
iOS share position origin clipped to screen bounds to avoid PlatformException
No input from untrusted sources is parsed or executed
Evidence from the diff
The change introduces CsvExportService, which serializes ActionListItem objects (transactions, trades, orders, anonpay, payjoin) into CSV using RFC 4180-style escaping (quote-doubling). It writes a UTF-8 BOM, creates a temp file in the app documents directory, then either saves to Android Downloads, shares via the platform share sheet, or prompts the user with file_picker on desktop. Two minor hardening changes are included: send_page.dart now checks Navigator.canPop(context) before popping, and share_util.dart validates the RenderBox type and clips sharePositionOrigin to the screen bounds to avoid iOS PlatformException on iPad. No injection, path traversal, or cryptographic weaknesses are visible in the diff, but CSV content is derived from wallet data and could be mishandled by external apps.
Changed components
lib/core/csv_export_service.dartlib/new-ui/pages/send_page.dartlib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dartlib/src/screens/dashboard/pages/transactions_page.dartlib/src/screens/dashboard/widgets/header_row.dartlib/utils/share_util.dartInspect captured patch +538 / −48
diff --git a/lib/core/csv_export_service.dart b/lib/core/csv_export_service.dart
new file mode 100644
index 00000000..ae6fa347
--- /dev/null
+++ b/lib/core/csv_export_service.dart
@@ -0,0 +1,317 @@
+import 'dart:io';
+
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/src/screens/backup/backup_page.dart';
+import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
+import 'package:cake_wallet/utils/share_util.dart';
+import 'package:cake_wallet/utils/show_bar.dart';
+import 'package:cake_wallet/utils/show_pop_up.dart';
+import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
+import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart';
+import 'package:cake_wallet/view_model/dashboard/date_section_item.dart';
+import 'package:cake_wallet/view_model/dashboard/order_list_item.dart';
+import 'package:cake_wallet/view_model/dashboard/payjoin_transaction_list_item.dart';
+import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
+import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
+import 'package:cw_core/transaction_direction.dart';
+import 'package:file_picker/file_picker.dart';
+import 'package:flutter/material.dart';
+import 'package:intl/intl.dart';
+import 'package:path_provider/path_provider.dart';
+
+class CsvExportService {
+ static const _columns = [
+ 'record_type',
+ 'date_time',
+ 'type',
+ 'amount',
+ 'currency',
+ 'fee',
+ 'tx_id',
+ 'address',
+ 'status',
+ 'note',
+ 'from_amount',
+ 'from_currency',
+ 'to_amount',
+ 'to_currency',
+ 'trade_id',
+ 'provider',
+ 'confirmations',
+ ];
+
+ static const _utf8Bom = '';
+
+ String buildCsvContent(List<ActionListItem> items) {
+ final buf = StringBuffer();
+ buf.write(_utf8Bom);
+ buf.writeln(_columns.join(','));
+
+ for (final item in items) {
+ if (item is DateSectionItem) continue;
+
+ final row = _buildRow(item);
+ if (row != null) buf.writeln(row);
+ }
+
+ return buf.toString();
+ }
+
+ String? _buildRow(ActionListItem item) {
+ if (item is TransactionListItem) return _transactionRow(item);
+ if (item is TradeListItem) return _tradeRow(item);
+ if (item is OrderListItem) return _orderRow(item);
+ if (item is AnonpayTransactionListItem) return _anonpayRow(item);
+ if (item is PayjoinTransactionListItem) return _payjoinRow(item);
+ return null;
+ }
+
+ String _transactionRow(TransactionListItem item) {
+ final tx = item.transaction;
+ final type = tx.direction == TransactionDirection.incoming ? 'incoming' : 'outgoing';
+ final status = tx.isPending ? 'pending' : 'confirmed';
+
+ // Prefer tx.to/tx.from; fall back to address lists for chains that don't populate them.
+ final address = tx.direction == TransactionDirection.incoming
+ ? (tx.from?.isNotEmpty == true
+ ? tx.from!
+ : (tx.inputAddresses?.firstOrNull ?? ''))
+ : (tx.to?.isNotEmpty == true
+ ? tx.to!
+ : (tx.outputAddresses?.firstOrNull ?? ''));
+
+ // Split "0.2769 LTC" → amount="0.2769", currency="LTC"
+ final (amount, currency) = _splitAmountCurrency(tx.amountFormatted());
+
+ // fee is stored as (inputAmount - totalOutputAmount) which is negative for incoming
+ // transactions — only include it when the raw value is a sensible positive fee.
+ final fee = tx.fee != null && tx.fee! > 0 ? (tx.feeFormatted() ?? '') : '';
+ final (feeAmount, _) = fee.isNotEmpty ? _splitAmountCurrency(fee) : ('', '');
+
+ return _row([
+ 'transaction',
+ _isoDate(tx.date),
+ type,
+ amount,
+ currency,
+ feeAmount,
+ tx.id,
+ address,
+ status,
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ tx.confirmations.toString(),
+ ]);
+ }
+
+ /// Splits a formatted amount like "0.2769 LTC" into ("0.2769", "LTC").
+ /// If there is no trailing symbol the whole string is returned as the amount.
+ (String, String) _splitAmountCurrency(String formatted) {
+ final trimmed = formatted.trim();
+ final idx = trimmed.lastIndexOf(' ');
+ if (idx == -1) return (trimmed, '');
+ return (trimmed.substring(0, idx), trimmed.substring(idx + 1));
+ }
+
+ String _tradeRow(TradeListItem item) {
+ final trade = item.trade;
+ return _row([
+ 'trade',
+ _isoDate(trade.createdAt ?? DateTime.fromMillisecondsSinceEpoch(0, isUtc: true)),
+ 'swap',
+ '',
+ '',
+ trade.fee?.toString() ?? '',
+ trade.outputTransaction ?? '',
+ trade.payoutAddress ?? '',
+ trade.state.title,
+ trade.memo ?? '',
+ trade.amount,
+ trade.from?.name ?? '',
+ trade.receiveAmount ?? '',
+ trade.to?.name ?? '',
+ trade.id,
+ trade.provider.title,
+ '',
+ ]);
+ }
+
+ String _orderRow(OrderListItem item) {
+ final order = item.order;
+ return _row([
+ 'order',
+ _isoDate(order.createdAt),
+ order.source.title,
+ order.amountFormatted(),
+ order.from ?? '',
+ '',
+ order.transferId,
+ '',
+ order.state.title,
+ '',
+ order.amountFormatted(),
+ order.from ?? '',
+ order.receiveAmount ?? '',
+ order.to ?? '',
+ order.id,
+ order.providerTitle,
+ '',
+ ]);
+ }
+
+ String _anonpayRow(AnonpayTransactionListItem item) {
+ final tx = item.transaction;
+ final amount = tx.fiatAmount?.toString() ?? tx.amountTo?.toString() ?? '';
+ final currency = tx.fiatEquiv ?? tx.coinTo;
+
+ return _row([
+ 'anonpay',
+ _isoDate(tx.createdAt),
+ 'anonymous_payment',
+ amount,
+ currency,
+ '',
+ tx.invoiceId,
+ tx.address,
+ tx.status,
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ tx.provider,
+ '',
+ ]);
+ }
+
+ String _payjoinRow(PayjoinTransactionListItem item) {
+ final session = item.session;
+ final type = session.isSenderSession ? 'send' : 'receive';
+ final amount = session.rawAmount ?? '0';
+
+ return _row([
+ 'payjoin',
+ _isoDate(session.inProgressSince ?? DateTime.fromMillisecondsSinceEpoch(0, isUtc: true)),
+ type,
+ amount,
+ 'BTC',
+ '',
+ session.txId ?? '',
+ '',
+ item.status,
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ ]);
+ }
+
+ String _row(List<String> fields) => fields.map(escapeField).join(',');
+
+ String escapeField(String field) {
+ if (field.contains(',') || field.contains('"') || field.contains('\n')) {
+ return '"${field.replaceAll('"', '""')}"';
+ }
+ return field;
+ }
+
+ String _isoDate(DateTime dt) => dt.toUtc().toIso8601String();
+
+ Future<void> exportToCsv(List<ActionListItem> items, BuildContext context) async {
+ final dataItems = items.whereType<ActionListItem>().where((e) => e is! DateSectionItem).toList();
+
+ if (dataItems.isEmpty) {
+ await showBar<void>(context, S.current.csv_nothing_to_export);
+ return;
+ }
+
+ final now = DateTime.now();
+ final fileName = 'cake_wallet_export_${DateFormat('yyyyMMdd_HHmmss').format(now)}.csv';
+
+ late File csvFile;
+
+ final exportFuture = Future(() async {
+ final content = buildCsvContent(items);
+ csvFile = await _writeTempFile(fileName, content);
+ });
+
+ showPersistentActionOverlay(context, exportFuture, text: S.current.generating_csv);
+ await exportFuture;
+
+ if (!context.mounted) return;
+
+ if (Platform.isAndroid) {
+ _showAndroidExportDialog(context, csvFile, fileName);
+ } else if (Platform.isIOS) {
+ await _shareFile(csvFile, fileName, context);
+ } else {
+ await _saveFileDesktop(csvFile, fileName);
+ }
+ }
+
+ void _showAndroidExportDialog(BuildContext context, File csvFile, String fileName) {
+ showPopUp<void>(
+ context: context,
+ builder: (dialogContext) {
+ return AlertWithTwoActions(
+ alertTitle: S.current.export_csv,
+ alertContent: S.current.select_destination,
+ rightButtonText: S.current.save_to_downloads,
+ leftButtonText: S.current.share,
+ actionRightButton: () async {
+ await _saveToDownloads(fileName, csvFile);
+ Navigator.of(dialogContext).pop();
+ await showBar<void>(context, S.current.file_saved);
+ await csvFile.delete();
+ },
+ actionLeftButton: () async {
+ Navigator.of(dialogContext).pop();
+ await _shareFile(csvFile, fileName, context);
+ },
+ );
+ },
+ );
+ }
+
+ Future<void> _shareFile(File file, String fileName, BuildContext context) async {
+ await ShareUtil.shareFile(filePath: file.path, fileName: fileName, context: context);
+ if (await file.exists()) await file.delete();
+ }
+
+ Future<void> _saveFileDesktop(File csvFile, String fileName) async {
+ final outputPath = await FilePicker.platform.saveFile(
+ dialogTitle: 'Save CSV export',
+ fileName: fileName,
+ lockParentWindow: true,
+ );
+ if (outputPath == null) return;
+ await csvFile.copy(outputPath);
+ await csvFile.delete();
+ }
+
+ Future<File> _writeTempFile(String fileName, String content) async {
+ final dir = await getApplicationDocumentsDirectory();
+ final file = File('${dir.path}/$fileName');
+ if (file.existsSync()) file.deleteSync();
+ await file.writeAsString(content, flush: true);
+ return file;
+ }
+
+ Future<void> _saveToDownloads(String fileName, File file) async {
+ if (!Platform.isAndroid) return;
+ const downloadsPath = '/storage/emulated/0/Download';
+ final dest = File('$downloadsPath/$fileName');
+ if (dest.existsSync()) dest.deleteSync();
+ await file.copy(dest.path);
+ }
+}
diff --git a/lib/new-ui/pages/send_page.dart b/lib/new-ui/pages/send_page.dart
index 1a77db06..1fd28fc9 100644
--- a/lib/new-ui/pages/send_page.dart
+++ b/lib/new-ui/pages/send_page.dart
@@ -763,7 +763,7 @@ class _NewSendPageState extends State<NewSendPage> {
conditionToDetermineIfToUse2FA: check,
onAuthSuccess: (value) async {
if (value) {
- if (!widget.mode.popOnConfirmation) {
+ if (!widget.mode.popOnConfirmation && Navigator.canPop(context)) {
Navigator.of(context, rootNavigator: true).pop();
}
showModalBottomSheet(
diff --git a/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart b/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart
index 9ea80989..3b5d1fde 100644
--- a/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart
+++ b/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart
@@ -1,3 +1,4 @@
+import 'package:cake_wallet/core/csv_export_service.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/new-ui/widgets/line_tab_switcher.dart';
import 'package:cake_wallet/routes.dart';
@@ -24,6 +25,9 @@ class AssetsTopBar extends StatelessWidget {
Widget build(BuildContext context) {
final settingsButtonText = _getSettingsButtonText();
final hasTokenSettingsButton = settingsButtonText != null;
+ // Reuse the exact same detection logic as _getSettingsButtonText so the
+ // export button always matches whether the Filters button is visible.
+ final isHistoryTab = settingsButtonText == S.current.filters;
return SliverToBoxAdapter(
child: Padding(
@@ -39,8 +43,33 @@ class AssetsTopBar extends StatelessWidget {
selectedTab: selectedTab,
)
else SizedBox.shrink(),
- Opacity(
- opacity: hasTokenSettingsButton ? 1 : 0,
+ Row(
+ spacing: 8,
+ children: [
+ if (isHistoryTab)
+ GestureDetector(
+ onTap: () =>
+ CsvExportService().exportToCsv(dashboardViewModel.items, context),
+ child: Semantics(
+ label: S.of(context).export_csv,
+ button: true,
+ child: Container(
+ height: 36,
+ width: 36,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: Theme.of(context).colorScheme.surfaceContainer,
+ ),
+ child: Icon(
+ Icons.file_download_outlined,
+ color: Theme.of(context).colorScheme.onSurface,
+ size: 20,
+ ),
+ ),
+ ),
+ ),
+ Opacity(
+ opacity: hasTokenSettingsButton ? 1 : 0,
child: ElevatedButton(
onPressed: () {
if (tabs[selectedTab] == S.of(context).assets) {
@@ -48,40 +77,41 @@ class AssetsTopBar extends StatelessWidget {
Routes.homeSettings,
arguments: dashboardViewModel.balanceViewModel,
);
- } else if(tabs[selectedTab] == S.of(context).history) {
+ } else if (tabs[selectedTab] == S.of(context).history) {
showPopUp<void>(
context: context,
- builder: (context) => FilterWidget(filterItems: dashboardViewModel.filterItems),
+ builder: (context) =>
+ FilterWidget(filterItems: dashboardViewModel.filterItems),
);
}
},
style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero,
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(999999),
- ),
- backgroundColor: Theme.of(
- context,
- ).colorScheme.surfaceContainer,
- ),
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 12.0),
- child: Row(
- spacing: 6,
- children: [
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(999999),
+ ),
+ backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
+ ),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 12.0),
+ child: Row(
+ spacing: 6,
+ children: [
CakeImageWidget(
imageUrl: "assets/new-ui/options_slider.svg",
colorFilter: ColorFilter.mode(
Theme.of(context).colorScheme.primary, BlendMode.srcIn)),
Text(
- settingsButtonText??"",
- style: TextStyle(color: Theme.of(context).colorScheme.primary),
- )
- ],
- ),
- ),
+ settingsButtonText ?? "",
+ style: TextStyle(color: Theme.of(context).colorScheme.primary),
+ )
+ ],
),
+ ),
),
+ ),
+ ],
+ ),
],
),
),
diff --git a/lib/src/screens/dashboard/pages/transactions_page.dart b/lib/src/screens/dashboard/pages/transactions_page.dart
index 39b0dcc8..87b67f28 100644
--- a/lib/src/screens/dashboard/pages/transactions_page.dart
+++ b/lib/src/screens/dashboard/pages/transactions_page.dart
@@ -1,4 +1,5 @@
import 'package:cake_wallet/bitcoin/bitcoin.dart';
+import 'package:cake_wallet/core/csv_export_service.dart';
import 'package:cake_wallet/entities/balance_display_mode.dart';
import 'package:cake_wallet/order/order_source_description.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/anonpay_transaction_row.dart';
@@ -65,6 +66,8 @@ class TransactionsPage extends StatelessWidget {
}),
HeaderRow(
dashboardViewModel: dashboardViewModel,
+ onExportCsv: () =>
+ CsvExportService().exportToCsv(dashboardViewModel.items, context),
key: ValueKey('transactions_page_header_row_key'),
),
Expanded(
diff --git a/lib/src/screens/dashboard/widgets/header_row.dart b/lib/src/screens/dashboard/widgets/header_row.dart
index f85a2cf6..5b89c0e8 100644
--- a/lib/src/screens/dashboard/widgets/header_row.dart
+++ b/lib/src/screens/dashboard/widgets/header_row.dart
@@ -5,9 +5,10 @@ import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
class HeaderRow extends StatelessWidget {
- HeaderRow({required this.dashboardViewModel, super.key});
+ HeaderRow({required this.dashboardViewModel, this.onExportCsv, super.key});
final DashboardViewModel dashboardViewModel;
+ final VoidCallback? onExportCsv;
@override
Widget build(BuildContext context) {
@@ -28,31 +29,62 @@ class HeaderRow extends StatelessWidget {
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurface),
),
- Semantics(
- container: true,
- child: GestureDetector(
- key: ValueKey('transactions_page_header_row_transaction_filter_button_key'),
- onTap: () {
- showPopUp<void>(
- context: context,
- builder: (context) => FilterWidget(filterItems: dashboardViewModel.filterItems),
- );
- },
- child: Semantics(
- label: 'Transaction Filter',
- button: true,
- enabled: true,
- child: Container(
- height: 36,
- width: 36,
- decoration: BoxDecoration(
- shape: BoxShape.circle,
- color: Theme.of(context).colorScheme.surfaceContainer,
+ Row(
+ children: [
+ if (onExportCsv != null)
+ Padding(
+ padding: const EdgeInsets.only(right: 8),
+ child: GestureDetector(
+ key: ValueKey('transactions_page_header_row_export_csv_button_key'),
+ onTap: onExportCsv,
+ child: Semantics(
+ label: S.of(context).export_csv,
+ button: true,
+ enabled: true,
+ child: Container(
+ height: 36,
+ width: 36,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: Theme.of(context).colorScheme.surfaceContainer,
+ ),
+ child: Icon(
+ Icons.file_download_outlined,
+ color: Theme.of(context).colorScheme.onSurface,
+ size: 20,
+ ),
+ ),
+ ),
+ ),
+ ),
+ Semantics(
+ container: true,
+ child: GestureDetector(
+ key: ValueKey('transactions_page_header_row_transaction_filter_button_key'),
+ onTap: () {
+ showPopUp<void>(
+ context: context,
+ builder: (context) =>
+ FilterWidget(filterItems: dashboardViewModel.filterItems),
+ );
+ },
+ child: Semantics(
+ label: 'Transaction Filter',
+ button: true,
+ enabled: true,
+ child: Container(
+ height: 36,
+ width: 36,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: Theme.of(context).colorScheme.surfaceContainer,
+ ),
+ child: filterIcon,
+ ),
),
- child: filterIcon,
),
),
- ),
+ ],
)
],
),
diff --git a/lib/utils/share_util.dart b/lib/utils/share_util.dart
index cfb9e74a..9fd2c5eb 100644
--- a/lib/utils/share_util.dart
+++ b/lib/utils/share_util.dart
@@ -33,8 +33,20 @@ class ShareUtil {
return Rect.zero;
}
- final box = context.findRenderObject() as RenderBox?;
+ final renderObject = context.findRenderObject();
+ if (renderObject is! RenderBox) {
+ return Rect.zero;
+ }
- return box!.localToGlobal(Offset.zero) & box.size;
+ final rect = renderObject.localToGlobal(Offset.zero) & renderObject.size;
+ // iOS requires sharePositionOrigin to lie fully within the source view's
+ // bounds; clip to the screen so an offset/oversized page rect doesn't spill
+ // past the edge and trigger a PlatformException on iPad.
+ final screen = Offset.zero & MediaQuery.of(context).size;
+ final clipped = rect.intersect(screen);
+ if (clipped.isEmpty) {
+ return Rect.zero;
+ }
+ return clipped;
}
}
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index 2860f09e..8077e97f 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -453,11 +453,14 @@
"expires": "ينتهي",
"expiresOn": "تنتهي في",
"expiry_and_validity": "تاريخ الانتهاء والصلاحية",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "تصدير النسخة الاحتياطية",
+ "export_csv": "Export CSV",
"export_lightning_logs": "تصدير سجلات Lightning",
"export_logs": "تصدير السجلات",
"export_outputs": "تصدير المخرجات",
"export_payjoin_logs": "تصدير سجلات Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "تمديد الجلسة",
"external": "خارجي",
"external_wallet": "محفظة خارجية",
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index 584e8496..9fb31cff 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -453,11 +453,14 @@
"expires": "Изтича",
"expiresOn": "Изтича на",
"expiry_and_validity": "Срок на валидност и валидност",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Експортиране на резервно копие",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Експортиране на Lightning логове",
"export_logs": "Експортиране на логове",
"export_outputs": "Експортиране на изходи",
"export_payjoin_logs": "Експортиране на Payjoin логове",
+ "generating_csv": "Generating CSV...",
"extend_session": "Удължи сесията",
"external": "Външен",
"external_wallet": "Външен портфейл",
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index 65d11438..b8eaafbc 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -453,11 +453,14 @@
"expires": "Vyprší",
"expiresOn": "Vyprší dne",
"expiry_and_validity": "Vypršení platnosti",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Exportovat zálohu",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Exportovat protokoly Lightning",
"export_logs": "Exportovat protokoly",
"export_outputs": "Exportovat výstupy",
"export_payjoin_logs": "Exportovat protokoly Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Prodloužit relaci",
"external": "Externí",
"external_wallet": "Externí peněženka",
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index 9857550a..cf20f6db 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -453,11 +453,14 @@
"expires": "Läuft ab",
"expiresOn": "Läuft ab am",
"expiry_and_validity": "Ablauf und Gültigkeit",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Backup exportieren",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Lightning-Logs exportieren",
"export_logs": "Protokolle exportieren",
"export_outputs": "Outputs exportieren",
"export_payjoin_logs": "Payjoin-Logs exportieren",
+ "generating_csv": "Generating CSV...",
"extend_session": "Sitzung verlängern",
"external": "Extern",
"external_wallet": "Externe Wallet",
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index 1ded5a8e..a4a49797 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -455,11 +455,14 @@
"expires": "Expires",
"expiresOn": "Expires on",
"expiry_and_validity": "Expiry and Validity",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Export backup",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Export Lightning logs",
"export_logs": "Export logs",
"export_outputs": "Export outputs",
"export_payjoin_logs": "Export Payjoin logs",
+ "generating_csv": "Generating CSV...",
"extend_session": "Extend Session",
"external": "External",
"external_wallet": "External wallet",
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index de1489ea..9c9fe3d8 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -453,11 +453,14 @@
"expires": "Caduca",
"expiresOn": "Caduca el",
"expiry_and_validity": "Caducidad y validez",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Exportar copia de seguridad",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Exportar registros de Lightning",
"export_logs": "Exportar registros",
"export_outputs": "Exportar salidas",
"export_payjoin_logs": "Exportar registros de Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Extender sesión",
"external": "Externo",
"external_wallet": "Billetera externa",
diff --git a/res/values/strings_fa.arb b/res/values/strings_fa.arb
index 6fcdc663..167c4fa5 100644
--- a/res/values/strings_fa.arb
+++ b/res/values/strings_fa.arb
@@ -451,11 +451,14 @@
"expires": "منقضی میشود",
"expiresOn": "انقضا در",
"expiry_and_validity": "انقضا و اعتبار",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "صدور نسخه پشتیبان",
+ "export_csv": "Export CSV",
"export_lightning_logs": "خروجی گرفتن از گزارشهای لایتنینگ",
"export_logs": "خروجی گرفتن از گزارشها",
"export_outputs": "برونبرد خروجیها",
"export_payjoin_logs": "گزارشهای Payjoin را صادر کنید",
+ "generating_csv": "Generating CSV...",
"extend_session": "تمدید جلسه",
"external": "خارجی",
"external_wallet": "کیف پول خارجی",
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index dc91f0e5..7fb51b38 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -453,11 +453,14 @@
"expires": "Expire",
"expiresOn": "Expire le",
"expiry_and_validity": "Expiration et validité",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Exporter la sauvegarde",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Exporter les logs Lightning",
"export_logs": "Exporter les journaux",
"export_outputs": "Exporter les sorties",
"export_payjoin_logs": "Exporter les journaux de Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Prolonger la session",
"external": "Externe",
"external_wallet": "Portefeuille externe",
diff --git a/res/values/strings_gn.arb b/res/values/strings_gn.arb
index abf322a1..e17fd274 100644
--- a/res/values/strings_gn.arb
+++ b/res/values/strings_gn.arb
@@ -355,9 +355,12 @@
"expires": "Opa hag̃ua",
"expiresOn": "Opa hag̃ua",
"expiry_and_validity": "Opaha ára ha hekorã",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Emondo hag̃ua backup",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Emondo Lightning rembiapokue",
"export_payjoin_logs": "Emondo okápe Payjoin registro-kuéra",
+ "generating_csv": "Generating CSV...",
"external": "Okápegua",
"external_wallet": "Billetera externa",
"extra_id": "ID extra:",
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index c36af10b..c0a4d515 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -453,11 +453,14 @@
"expires": "Yana ƙarewa",
"expiresOn": "Yana ƙarewa a",
"expiry_and_validity": "Ranar ƙarewa da inganci",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Fitar da ajiyar baya",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Fitar da log ɗin Lightning",
"export_logs": "Fitar da log",
"export_outputs": "Fitar da abubuwan fitarwa",
"export_payjoin_logs": "Fitar da log ɗin Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Tsawaita Zama",
"external": "Na waje",
"external_wallet": "Wallet na waje",
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index d7493f08..a1ce0c33 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -453,11 +453,14 @@
"expires": "समाप्त होता है",
"expiresOn": "इस दिन समाप्त होता है",
"expiry_and_validity": "समाप्ति और वैधता",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "बैकअप निर्यात करें",
+ "export_csv": "Export CSV",
"export_lightning_logs": "लाइटनिंग लॉग्स निर्यात करें",
"export_logs": "लॉग निर्यात करें",
"export_outputs": "आउटपुट निर्यात करें",
"export_payjoin_logs": "Payjoin लॉग एक्सपोर्ट करें",
+ "generating_csv": "Generating CSV...",
"extend_session": "सत्र बढ़ाएँ",
"external": "बाहरी",
"external_wallet": "बाहरी वॉलेट",
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index 615ca219..a8e281b3 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -453,11 +453,14 @@
"expires": "Ističe",
"expiresOn": "Istječe",
"expiry_and_validity": "Istek i valjanost",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Izvezi sigurnosnu kopiju",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Izvezi Lightning zapise",
"export_logs": "Izvezi zapise",
"export_outputs": "Izvoz izlaza",
"export_payjoin_logs": "Izvezi Payjoin zapise",
+ "generating_csv": "Generating CSV...",
"extend_session": "Produži sesiju",
"external": "Vanjski",
"external_wallet": "Vanjski novčanik",
diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb
index b72cc51e..c003dc3b 100644
--- a/res/values/strings_hy.arb
+++ b/res/values/strings_hy.arb
@@ -453,11 +453,14 @@
"expires": "Լրանում է",
"expiresOn": "Լրանում է",
"expiry_and_validity": "Ժամկետ և վավերականություն",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Արտահանել պահուստային պատճենը",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Արտահանել Lightning-ի տեղեկամատյանները",
"export_logs": "Արտահանել տեղեկամատյանները",
"export_outputs": "Արտահանել ելքերը",
"export_payjoin_logs": "Արտահանել Payjoin-ի մատյանները",
+ "generating_csv": "Generating CSV...",
"extend_session": "Երկարացնել սեսիան",
"external": "Արտաքին",
"external_wallet": "Արտաքին դրամապանակ",
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index be26c93b..b89942b1 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -453,11 +453,14 @@
"expires": "Kedaluwarsa",
"expiresOn": "Kedaluwarsa pada",
"expiry_and_validity": "Kedaluwarsa dan Validitas",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Ekspor cadangan",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Ekspor log Lightning",
"export_logs": "Ekspor log",
"export_outputs": "Ekspor keluaran",
"export_payjoin_logs": "Ekspor log Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Perpanjang Sesi",
"external": "Eksternal",
"external_wallet": "Dompet eksternal",
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index 6f0e1ad6..b90718c4 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -453,11 +453,14 @@
"expires": "Scade",
"expiresOn": "Scade il",
"expiry_and_validity": "Scadenza e validità",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Esporta backup",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Esporta i log di Lightning",
"export_logs": "Esporta registri",
"export_outputs": "Esporta output",
"export_payjoin_logs": "Esporta i log Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Estendi la sessione",
"external": "Esterno",
"external_wallet": "Portafoglio esterno",
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index a470e459..0db5a061 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -453,11 +453,14 @@
"expires": "有効期限",
"expiresOn": "有効期限",
"expiry_and_validity": "有効期限と有効性",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "バックアップをエクスポート",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Lightningログをエクスポート",
"export_logs": "ログをエクスポート",
"export_outputs": "アウトプットをエクスポート",
"export_payjoin_logs": "Payjoinログをエクスポート",
+ "generating_csv": "Generating CSV...",
"extend_session": "セッションを延長",
"external": "外部",
"external_wallet": "外部ウォレット",
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index 80f132fe..2cbfd964 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -453,11 +453,14 @@
"expires": "만료됨",
"expiresOn": "만료일",
"expiry_and_validity": "만료 및 유효 기간",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "백업 내보내기",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Lightning 로그 내보내기",
"export_logs": "로그 내보내기",
"export_outputs": "출력 내보내기",
"export_payjoin_logs": "Payjoin 로그 내보내기",
+ "generating_csv": "Generating CSV...",
"extend_session": "세션 연장",
"external": "외부",
"external_wallet": "외부 지갑",
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index 1b619278..288f3dc9 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -453,11 +453,14 @@
"expires": "သက်တမ်းကုန်ဆုံးသည်",
"expiresOn": "သက်တမ်းကုန်ဆုံးမည့်ရက်",
"expiry_and_validity": "သက်တမ်းကုန်ဆုံးရက်နှင့် အကျုံးဝင်မှု",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "အရန်ကူးကို ထုတ်ယူရန်",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Lightning မှတ်တမ်းများကို ထုတ်ယူပါ",
"export_logs": "မှတ်တမ်းများကို ထုတ်ယူရန်",
"export_outputs": "Outputs များကို ထုတ်ယူရန်",
"export_payjoin_logs": "Payjoin မှတ်တမ်းများကို တင်ပို့ပါ",
+ "generating_csv": "Generating CSV...",
"extend_session": "စက်ရှင် သက်တမ်းတိုးရန်",
"external": "ပြင်ပ",
"external_wallet": "ပြင်ပ Wallet",
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index a1a085f0..12d1bb54 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -451,11 +451,14 @@
"expires": "Verloopt",
"expiresOn": "Verloopt op",
"expiry_and_validity": "Vervaldatum en geldigheid",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Back-up exporteren",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Lightning-logboeken exporteren",
"export_logs": "Exporteer logboeken",
"export_outputs": "Outputs exporteren",
"export_payjoin_logs": "Payjoin-logboeken exporteren",
+ "generating_csv": "Generating CSV...",
"extend_session": "Sessie verlengen",
"external": "Extern",
"external_wallet": "Externe wallet",
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index a70d9f72..5389b181 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -452,11 +452,14 @@
"expires": "Wygasa",
"expiresOn": "Wygasa",
"expiry_and_validity": "Termin ważności i ważność",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Eksportuj kopię zapasową",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Eksportuj logi Lightning",
"export_logs": "Eksportuj logi",
"export_outputs": "Eksportuj wyjścia",
"export_payjoin_logs": "Eksportuj logi Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Przedłuż sesję",
"external": "Zewnętrzny",
"external_wallet": "Zewnętrzny portfel",
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index 902b43c9..118cd47d 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -453,11 +453,14 @@
"expires": "Expira",
"expiresOn": "Expira em",
"expiry_and_validity": "Expiração e validade",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Exportar backup",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Exportar logs do Lightning",
"export_logs": "Exportar logs",
"export_outputs": "Exportar saídas",
"export_payjoin_logs": "Exportar logs do Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Estender sessão",
"external": "Externo",
"external_wallet": "Carteira externa",
diff --git a/res/values/strings_pt_BR.arb b/res/values/strings_pt_BR.arb
index 878799ef..2f5e17e3 100644
--- a/res/values/strings_pt_BR.arb
+++ b/res/values/strings_pt_BR.arb
@@ -451,11 +451,14 @@
"expires": "Expira",
"expiresOn": "Expira em",
"expiry_and_validity": "Expiração e Validade",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Exportar backup",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Exportar logs do Lightning",
"export_logs": "Exportar logs",
"export_outputs": "Exportar saídas",
"export_payjoin_logs": "Exportar logs do Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Estender sessão",
"external": "Externo",
"external_wallet": "Carteira externa",
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index d48f52f3..828e899b 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -453,11 +453,14 @@
"expires": "Истекает",
"expiresOn": "Истекает",
"expiry_and_validity": "Срок действия и действительность",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Экспорт резервной копии",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Экспорт логов Lightning",
"export_logs": "Экспорт журналов",
"export_outputs": "Экспорт выходов",
"export_payjoin_logs": "Экспорт журналов Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Продлить сессию",
"external": "Внешний",
"external_wallet": "Внешний кошелёк",
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index cc66b12e..f0abd039 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -453,11 +453,14 @@
"expires": "หมดอายุ",
"expiresOn": "หมดอายุวันที่",
"expiry_and_validity": "วันหมดอายุและระยะเวลาที่มีผล",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "ส่งออกข้อมูลสำรอง",
+ "export_csv": "Export CSV",
"export_lightning_logs": "ส่งออกล็อก Lightning",
"export_logs": "ส่งออกบันทึก",
"export_outputs": "ส่งออกเอาต์พุต",
"export_payjoin_logs": "ส่งออกล็อก Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "ขยายเซสชัน",
"external": "ภายนอก",
"external_wallet": "กระเป๋าเงินภายนอก",
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index ffdd9e49..71a87c25 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -453,11 +453,14 @@
"expires": "Mag-e-expire",
"expiresOn": "Mag-e-expire sa",
"expiry_and_validity": "Pag-expire at Pagiging Balido",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "I-export ang backup",
+ "export_csv": "Export CSV",
"export_lightning_logs": "I-export ang mga log ng Lightning",
"export_logs": "I-export ang mga log",
"export_outputs": "I-export ang mga output",
"export_payjoin_logs": "I-export ang mga Payjoin log",
+ "generating_csv": "Generating CSV...",
"extend_session": "Palawigin ang session",
"external": "Panlabas",
"external_wallet": "Panlabas na wallet",
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index ead93675..346b35d0 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -453,11 +453,14 @@
"expires": "Sona erme tarihi",
"expiresOn": "Şu tarihte sona erer",
"expiry_and_validity": "Son Kullanma ve Geçerlilik",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Yedeklemeyi dışa aktar",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Lightning günlüklerini dışa aktar",
"export_logs": "Günlükleri dışa aktar",
"export_outputs": "Çıktıları dışa aktar",
"export_payjoin_logs": "Payjoin günlüklerini dışa aktar",
+ "generating_csv": "Generating CSV...",
"extend_session": "Oturumu Uzat",
"external": "Harici",
"external_wallet": "Harici cüzdan",
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index 7478683a..76922150 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -453,11 +453,14 @@
"expires": "Термін дії закінчується",
"expiresOn": "Дійсний до",
"expiry_and_validity": "Термін дії та чинність",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Експортувати резервну копію",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Експортувати логи Lightning",
"export_logs": "Експорт журналів",
"export_outputs": "Експорт виходів",
"export_payjoin_logs": "Експорт журналів Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Подовжити сеанс",
"external": "Зовнішній",
"external_wallet": "Зовнішній гаманець",
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index d9607eb8..9285c8e7 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -453,11 +453,14 @@
"expires": "میعاد ختم ہوتا ہے",
"expiresOn": "میعاد ختم ہونے کی تاریخ",
"expiry_and_validity": "میعادِ ختم اور درستگی",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "بیک اپ ایکسپورٹ کریں",
+ "export_csv": "Export CSV",
"export_lightning_logs": "لائٹننگ لاگز برآمد کریں",
"export_logs": "لاگز برآمد کریں",
"export_outputs": "آؤٹ پٹس ایکسپورٹ کریں",
"export_payjoin_logs": "Payjoin لاگز ایکسپورٹ کریں",
+ "generating_csv": "Generating CSV...",
"extend_session": "سیشن میں توسیع کریں",
"external": "بیرونی",
"external_wallet": "بیرونی والیٹ",
diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb
index 3c4d7a4c..5ce21b68 100644
--- a/res/values/strings_vi.arb
+++ b/res/values/strings_vi.arb
@@ -452,11 +452,14 @@
"expires": "Hết hạn",
"expiresOn": "Hết hạn vào",
"expiry_and_validity": "Thời hạn và hiệu lực",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Xuất bản sao lưu",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Xuất nhật ký Lightning",
"export_logs": "Xuất nhật ký",
"export_outputs": "Xuất đầu ra",
"export_payjoin_logs": "Xuất nhật ký Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Gia hạn phiên",
"external": "Bên ngoài",
"external_wallet": "Ví ngoài",
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index d29fd32f..29ebbe6c 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -454,11 +454,14 @@
"expires": "Yóò parí",
"expiresOn": "Yóò parí ní",
"expiry_and_validity": "Ọjọ́ ìparí àti ìmúlò",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "Gbé ẹ̀dà àfipamọ́ jáde",
+ "export_csv": "Export CSV",
"export_lightning_logs": "Gbe àwọn àkọọlẹ Lightning jáde",
"export_logs": "Gbe àwọn ìwé-àkọsílẹ̀ jáde",
"export_outputs": "Gbe àwọn output jáde",
"export_payjoin_logs": "Gbejade àwọn ìkọ̀ọ́lẹ̀ Payjoin",
+ "generating_csv": "Generating CSV...",
"extend_session": "Fa igba iṣẹ́ pọ̀ síi",
"external": "Ita",
"external_wallet": "Apamọwọ ita",
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index 960e29a9..766d7973 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -453,11 +453,14 @@
"expires": "到期",
"expiresOn": "到期于",
"expiry_and_validity": "有效期和有效性",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "导出备份",
+ "export_csv": "Export CSV",
"export_lightning_logs": "导出 Lightning 日志",
"export_logs": "导出日志",
"export_outputs": "导出输出",
"export_payjoin_logs": "导出 Payjoin 日志",
+ "generating_csv": "Generating CSV...",
"extend_session": "延长会话",
"external": "外部",
"external_wallet": "外部钱包",
diff --git a/res/values/strings_zh_tw.arb b/res/values/strings_zh_tw.arb
index cc672e0b..c85a7b64 100644
--- a/res/values/strings_zh_tw.arb
+++ b/res/values/strings_zh_tw.arb
@@ -392,11 +392,14 @@
"expires": "到期",
"expiresOn": "到期日",
"expiry_and_validity": "到期與有效性",
+ "csv_nothing_to_export": "Nothing to export",
"export_backup": "匯出備份",
+ "export_csv": "Export CSV",
"export_lightning_logs": "匯出 Lightning 記錄",
"export_logs": "匯出記錄",
"export_outputs": "匯出輸出項",
"export_payjoin_logs": "匯出 Payjoin 日誌",
+ "generating_csv": "Generating CSV...",
"extend_session": "延長登入階段",
"extra_id": "額外 ID:",
"extracted_address_content": "您將發送資金至\n${recipient_name}",
Why this scored 28/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.