aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2022-02-15 17:45:26 +0100
committerFlorian Dold <florian@dold.me>2022-02-15 17:45:26 +0100
commit465ccdaa06d30a995235fd6438172eb125243321 (patch)
tree1d6eefefd858a491ed36353c504abeecab1f1280
parente6c1294c910e6b54d24d62981632cf5e5f79d33f (diff)
subcommands for i18n tooling, unique message IDs
-rw-r--r--packages/pogen/src/po2ts.ts62
-rw-r--r--packages/pogen/src/pogen.ts21
-rw-r--r--packages/pogen/src/potextract.ts183
-rw-r--r--packages/taler-wallet-webextension/package.json7
-rw-r--r--packages/taler-wallet-webextension/src/i18n/taler-wallet-webex.pot243
5 files changed, 291 insertions, 225 deletions
diff --git a/packages/pogen/src/po2ts.ts b/packages/pogen/src/po2ts.ts
index d0f4ed34d..ac85b9b76 100644
--- a/packages/pogen/src/po2ts.ts
+++ b/packages/pogen/src/po2ts.ts
@@ -23,38 +23,44 @@ import * as po2json from "po2json";
import * as fs from "fs";
import * as path from "path";
-const files = fs
- .readdirSync("./src/i18n")
- .filter((x) => x.endsWith(".po"))
- .map((x) => path.join("./src/i18n/", x));
-
-if (files.length === 0) {
- console.error("no .po files found in src/i18n/");
- process.exit(1);
-}
+export function po2ts(): void {
+ const files = fs
+ .readdirSync("./src/i18n")
+ .filter((x) => x.endsWith(".po"))
+ .map((x) => path.join("./src/i18n/", x));
-console.log(files);
+ if (files.length === 0) {
+ console.error("no .po files found in src/i18n/");
+ process.exit(1);
+ }
-const chunks: string[] = [];
+ console.log(files);
-for (const filename of files) {
- const m = filename.match(/([a-zA-Z0-9-_]+).po/);
+ const chunks: string[] = [];
- if (!m) {
- console.error("error: unexpected filename (expected <lang>.po)");
- process.exit(1);
- }
+ for (const filename of files) {
+ const m = filename.match(/([a-zA-Z0-9-_]+).po/);
- const lang = m[1];
- const pojson = po2json.parseFileSync(filename, {
- format: "jed1.x",
- fuzzy: true,
- });
- const s =
- "strings['" + lang + "'] = " + JSON.stringify(pojson, null, " ") + ";\n\n";
- chunks.push(s);
-}
+ if (!m) {
+ console.error("error: unexpected filename (expected <lang>.po)");
+ process.exit(1);
+ }
+
+ const lang = m[1];
+ const pojson = po2json.parseFileSync(filename, {
+ format: "jed1.x",
+ fuzzy: true,
+ });
+ const s =
+ "strings['" +
+ lang +
+ "'] = " +
+ JSON.stringify(pojson, null, " ") +
+ ";\n\n";
+ chunks.push(s);
+ }
-const tsContents = chunks.join("");
+ const tsContents = chunks.join("");
-fs.writeFileSync("src/i18n/strings.ts", tsContents);
+ fs.writeFileSync("src/i18n/strings.ts", tsContents);
+}
diff --git a/packages/pogen/src/pogen.ts b/packages/pogen/src/pogen.ts
new file mode 100644
index 000000000..7d128ce7a
--- /dev/null
+++ b/packages/pogen/src/pogen.ts
@@ -0,0 +1,21 @@
+import { potextract } from "./potextract.js";
+
+function usage(): never {
+ console.log("usage: pogen <extract|merge|emit>");
+ process.exit(1);
+}
+
+export function main() {
+ const subcommand = process.argv[2];
+ if (process.argv.includes("--help") || !subcommand) {
+ usage();
+ }
+ switch (subcommand) {
+ case "extract":
+ potextract();
+ break;
+ default:
+ console.error(`unknown subcommand '${subcommand}'`);
+ usage();
+ }
+}
diff --git a/packages/pogen/src/potextract.ts b/packages/pogen/src/potextract.ts
index 5999d9e1c..5cc085ef8 100644
--- a/packages/pogen/src/potextract.ts
+++ b/packages/pogen/src/potextract.ts
@@ -14,21 +14,27 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-
/**
* Imports.
*/
import * as ts from "typescript";
+import * as fs from "fs";
+import * as os from "os";
+import path = require("path/posix");
function wordwrap(str: string, width: number = 80): string[] {
var regex = ".{1," + width + "}(\\s|$)|\\S+(\\s|$)";
return str.match(RegExp(regex, "g"));
}
-export function processFile(sourceFile: ts.SourceFile, outChunks: string[]) {
- processNode(sourceFile);
+function processFile(
+ sourceFile: ts.SourceFile,
+ outChunks: string[],
+ knownMessageIds: Set<string>,
+) {
let lastTokLine = 0;
let preLastTokLine = 0;
+ processNode(sourceFile);
function getTemplate(node: ts.Node): string {
switch (node.kind) {
@@ -140,7 +146,8 @@ export function processFile(sourceFile: ts.SourceFile, outChunks: string[]) {
outChunks.push(`#. ${cl}\n`);
}
}
- outChunks.push(`#: ${sourceFile.fileName}:${line + 1}\n`);
+ const fn = path.relative(process.cwd(), sourceFile.fileName);
+ outChunks.push(`#: ${fn}:${line + 1}\n`);
outChunks.push(`#, c-format\n`);
}
@@ -148,7 +155,7 @@ export function processFile(sourceFile: ts.SourceFile, outChunks: string[]) {
// Do escaping, wrap break at newlines
let parts = msg
.match(/(.*\n|.+$)/g)
- .map((x) => x.replace(/\n/g, "\\n"))
+ .map((x) => x.replace(/\n/g, "\\n").replace(/"/g, '\\"'))
.map((p) => wordwrap(p))
.reduce((a, b) => a.concat(b));
if (parts.length == 1) {
@@ -188,7 +195,7 @@ export function processFile(sourceFile: ts.SourceFile, outChunks: string[]) {
}
}
- function trim(s) {
+ function trim(s: string) {
return s.replace(/^[ \n\t]*/, "").replace(/[ \n\t]*$/, "");
}
@@ -284,10 +291,13 @@ export function processFile(sourceFile: ts.SourceFile, outChunks: string[]) {
let content = getJsxContent(node);
let { line } = ts.getLineAndCharacterOfPosition(sourceFile, node.pos);
let comment = getComment(node);
- formatMsgComment(line, comment);
- formatMsgLine("msgid", content);
- outChunks.push(`msgstr ""\n`);
- outChunks.push("\n");
+ if (!knownMessageIds.has(content)) {
+ knownMessageIds.add(content);
+ formatMsgComment(line, comment);
+ formatMsgLine("msgid", content);
+ outChunks.push(`msgstr ""\n`);
+ outChunks.push("\n");
+ }
return;
}
if (arrayEq(path, ["i18n", "TranslateSwitch"])) {
@@ -304,11 +314,14 @@ export function processFile(sourceFile: ts.SourceFile, outChunks: string[]) {
console.error("plural form missing");
process.exit(1);
}
- formatMsgLine("msgid", singularForm);
- formatMsgLine("msgid_plural", pluralForm);
- outChunks.push(`msgstr[0] ""\n`);
- outChunks.push(`msgstr[1] ""\n`);
- outChunks.push(`\n`);
+ if (!knownMessageIds.has(singularForm)) {
+ knownMessageIds.add(singularForm);
+ formatMsgLine("msgid", singularForm);
+ formatMsgLine("msgid_plural", pluralForm);
+ outChunks.push(`msgstr[0] ""\n`);
+ outChunks.push(`msgstr[1] ""\n`);
+ outChunks.push(`\n`);
+ }
return;
}
break;
@@ -333,13 +346,16 @@ export function processFile(sourceFile: ts.SourceFile, outChunks: string[]) {
<ts.TaggedTemplateExpression>ce.arguments[1],
);
let comment = getComment(ce);
-
- formatMsgComment(line, comment);
- formatMsgLine("msgid", t1.template);
- formatMsgLine("msgid_plural", t2.template);
- outChunks.push(`msgstr[0] ""\n`);
- outChunks.push(`msgstr[1] ""\n`);
- outChunks.push("\n");
+ const msgid = t1.template;
+ if (!knownMessageIds.has(msgid)) {
+ knownMessageIds.add(msgid);
+ formatMsgComment(line, comment);
+ formatMsgLine("msgid", t1.template);
+ formatMsgLine("msgid_plural", t2.template);
+ outChunks.push(`msgstr[0] ""\n`);
+ outChunks.push(`msgstr[1] ""\n`);
+ outChunks.push("\n");
+ }
// Important: no processing for child i18n expressions here
return;
@@ -351,10 +367,14 @@ export function processFile(sourceFile: ts.SourceFile, outChunks: string[]) {
if (path[0] != "i18n") {
break;
}
- formatMsgComment(line, comment);
- formatMsgLine("msgid", template);
- outChunks.push(`msgstr ""\n`);
- outChunks.push("\n");
+ const msgid = template;
+ if (!knownMessageIds.has(msgid)) {
+ knownMessageIds.add(msgid);
+ formatMsgComment(line, comment);
+ formatMsgLine("msgid", template);
+ outChunks.push(`msgstr ""\n`);
+ outChunks.push("\n");
+ }
break;
}
}
@@ -363,51 +383,48 @@ export function processFile(sourceFile: ts.SourceFile, outChunks: string[]) {
}
}
-const configPath = ts.findConfigFile(
- /*searchPath*/ "./",
- ts.sys.fileExists,
- "tsconfig.json",
-);
-if (!configPath) {
- throw new Error("Could not find a valid 'tsconfig.json'.");
-}
-
-console.log(configPath);
-
-const cmdline = ts.getParsedCommandLineOfConfigFile(
- configPath,
- {},
- {
- fileExists: ts.sys.fileExists,
- getCurrentDirectory: ts.sys.getCurrentDirectory,
- onUnRecoverableConfigFileDiagnostic: (e) => console.log(e),
- readDirectory: ts.sys.readDirectory,
- readFile: ts.sys.readFile,
- useCaseSensitiveFileNames: true,
- },
-);
-
-console.log(cmdline);
-
-const prog = ts.createProgram({
- options: cmdline.options,
- rootNames: cmdline.fileNames,
-});
-
-const allFiles = prog.getSourceFiles();
-
-const ownFiles = allFiles.filter(
- (x) =>
- !x.isDeclarationFile &&
- !prog.isSourceFileFromExternalLibrary(x) &&
- !prog.isSourceFileDefaultLibrary(x),
-);
-
-console.log(ownFiles.map((x) => x.fileName));
-
-const chunks = [];
+export function potextract() {
+ const configPath = ts.findConfigFile(
+ /*searchPath*/ "./",
+ ts.sys.fileExists,
+ "tsconfig.json",
+ );
+ if (!configPath) {
+ throw new Error("Could not find a valid 'tsconfig.json'.");
+ }
-chunks.push(`# SOME DESCRIPTIVE TITLE.
+ const cmdline = ts.getParsedCommandLineOfConfigFile(
+ configPath,
+ {},
+ {
+ fileExists: ts.sys.fileExists,
+ getCurrentDirectory: ts.sys.getCurrentDirectory,
+ onUnRecoverableConfigFileDiagnostic: (e) => console.log(e),
+ readDirectory: ts.sys.readDirectory,
+ readFile: ts.sys.readFile,
+ useCaseSensitiveFileNames: true,
+ },
+ );
+
+ const prog = ts.createProgram({
+ options: cmdline.options,
+ rootNames: cmdline.fileNames,
+ });
+
+ const allFiles = prog.getSourceFiles();
+
+ const ownFiles = allFiles.filter(
+ (x) =>
+ !x.isDeclarationFile &&
+ !prog.isSourceFileFromExternalLibrary(x) &&
+ !prog.isSourceFileDefaultLibrary(x),
+ );
+
+ //console.log(ownFiles.map((x) => x.fileName));
+
+ const chunks = [];
+
+ chunks.push(`# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
@@ -424,10 +441,26 @@ msgstr ""
"Language: \\n"
"MIME-Version: 1.0\\n"
"Content-Type: text/plain; charset=UTF-8\\n"
-"Content-Transfer-Encoding: 8bit\\n"`);
+"Content-Transfer-Encoding: 8bit\\n"\n\n`);
-for (const f of ownFiles) {
- processFile(f, chunks);
-}
+ const knownMessageIds = new Set<string>();
+
+ for (const f of ownFiles) {
+ processFile(f, chunks, knownMessageIds);
+ }
+
+ const pot = chunks.join("");
-console.log(chunks.join(""));
+ //console.log(pot);
+
+ const packageJson = JSON.parse(
+ fs.readFileSync("./package.json", { encoding: "utf-8" }),
+ );
+
+ const poDomain = packageJson.pogen?.domain;
+ if (!poDomain) {
+ console.error("missing 'pogen.domain' field in package.json");
+ process.exit(1);
+ }
+ fs.writeFileSync(`./src/i18n/${poDomain}.pot`, pot);
+}
diff --git a/packages/taler-wallet-webextension/package.json b/packages/taler-wallet-webextension/package.json
index 3ae98284d..4c6f2a564 100644
--- a/packages/taler-wallet-webextension/package.json
+++ b/packages/taler-wallet-webextension/package.json
@@ -15,7 +15,9 @@
"build-storybook": "build-storybook",
"storybook": "start-storybook -s . -p 6006",
"pretty": "prettier --write src",
- "watch": "tsc --watch & rollup -w -c"
+ "watch": "tsc --watch & rollup -w -c",
+ "i18n:extract": "pogen extract",
+ "i18n:msgmerge": "pogen msgmerge"
},
"dependencies": {
"@gnu-taler/taler-util": "workspace:*",
@@ -71,5 +73,8 @@
"**"
],
"exclude": []
+ },
+ "pogen": {
+ "domain": "taler-wallet-webex"
}
}
diff --git a/packages/taler-wallet-webextension/src/i18n/taler-wallet-webex.pot b/packages/taler-wallet-webextension/src/i18n/taler-wallet-webex.pot
index 67b09de1a..70aa9c708 100644
--- a/packages/taler-wallet-webextension/src/i18n/taler-wallet-webex.pot
+++ b/packages/taler-wallet-webextension/src/i18n/taler-wallet-webex.pot
@@ -1,21 +1,12 @@
-# This file is part of TALER
-# (C) 2016 GNUnet e.V.
-#
-# TALER is free software; you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation; either version 3, or (at your option) any later version.
-#
-# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: Taler Wallet\n"
+"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-11-23 00:00+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
@@ -25,266 +16,276 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: src/util/wire.ts:37
+#: src/NavigationBar.tsx:86
#, c-format
-msgid "Invalid Wire"
+msgid "Balance"
msgstr ""
-#: src/util/wire.ts:42 src/util/wire.ts:45
+#: src/NavigationBar.tsx:87
#, c-format
-msgid "Invalid Test Wire Detail"
+msgid "Pending"
msgstr ""
-#: src/util/wire.ts:47
+#: src/NavigationBar.tsx:88
#, c-format
-msgid "Test Wire Acct #%1$s on %2$s"
+msgid "Backup"
msgstr ""
-#: src/util/wire.ts:49
+#: src/NavigationBar.tsx:89
#, c-format
-msgid "Unknown Wire Detail"
+msgid "Settings"
msgstr ""
-#: src/webex/pages/benchmark.tsx:52
+#: src/NavigationBar.tsx:90
#, c-format
-msgid "Operation"
+msgid "Dev"
msgstr ""
-#: src/webex/pages/benchmark.tsx:53
+#: src/wallet/BackupPage.tsx:127
#, c-format
-msgid "time (ms/op)"
+msgid "Add provider"
msgstr ""
-#: src/webex/pages/pay.tsx:130
+#: src/wallet/BackupPage.tsx:137
#, c-format
-msgid "The merchant %1$s offers you to purchase:"
+msgid "Sync all backups"
msgstr ""
-#: src/webex/pages/pay.tsx:136
+#: src/wallet/BackupPage.tsx:139
#, c-format
-msgid "The total price is %1$s (plus %2$s fees)."
+msgid "Sync now"
msgstr ""
-#: src/webex/pages/pay.tsx:141
+#: src/popup/BalancePage.tsx:79
#, c-format
-msgid "The total price is %1$s."
+msgid "You have no balance to show. Need some %1$s getting started?"
msgstr ""
-#: src/webex/pages/pay.tsx:163
+#: src/wallet/ProviderAddPage.tsx:145
#, c-format
-msgid "Retry"
+msgid "&lt; Back"
msgstr ""
-#: src/webex/pages/pay.tsx:173
+#: src/wallet/ProviderAddPage.tsx:156
#, c-format
-msgid "Confirm payment"
+msgid "Next"
msgstr ""
-#: src/webex/pages/popup.tsx:153
+#: src/wallet/ProviderDetailPage.tsx:57
#, c-format
-msgid "Balance"
+msgid "Loading..."
msgstr ""
-#: src/webex/pages/popup.tsx:154
+#: src/wallet/ProviderDetailPage.tsx:64
#, c-format
-msgid "History"
+msgid "There was an error loading the provider detail for \"%1$s\""
msgstr ""
-#: src/webex/pages/popup.tsx:155
+#: src/wallet/ProviderDetailPage.tsx:75
#, c-format
-msgid "Debug"
+msgid "There is not known provider with url \"%1$s\". Redirecting back..."
msgstr ""
-#: src/webex/pages/popup.tsx:175
+#: src/wallet/ProviderDetailPage.tsx:131
#, c-format
-msgid "You have no balance to show. Need some %1$s getting started?"
+msgid "Back up"
msgstr ""
-#: src/webex/pages/popup.tsx:238
+#: src/wallet/ProviderDetailPage.tsx:142
#, c-format
-msgid "%1$s incoming"
+msgid "Extend"
msgstr ""
-#: src/webex/pages/popup.tsx:250
+#: src/wallet/ProviderDetailPage.tsx:148
#, c-format
-msgid "%1$s being spent"
+msgid ""
+"terms has changed, extending the service will imply accepting the new terms of "
+"service"
msgstr ""
-#: src/webex/pages/popup.tsx:281
+#: src/wallet/ProviderDetailPage.tsx:158
#, c-format
-msgid "Error: could not retrieve balance information."
+msgid "old"
msgstr ""
-#: src/webex/pages/popup.tsx:390
+#: src/wallet/ProviderDetailPage.tsx:162
#, c-format
-msgid "Invalid "
+msgid "new"
msgstr ""
-#: src/webex/pages/popup.tsx:396
+#: src/wallet/ProviderDetailPage.tsx:169
#, c-format
-msgid "Fees "
+msgid "fee"
msgstr ""
-#: src/webex/pages/popup.tsx:434
+#: src/wallet/ProviderDetailPage.tsx:177
#, c-format
-msgid "Refresh sessions has completed"
+msgid "storage"
msgstr ""
-#: src/webex/pages/popup.tsx:451
+#: src/wallet/ProviderDetailPage.tsx:190
#, c-format
-msgid "Order Refused"
+msgid "&lt; back"
msgstr ""
-#: src/webex/pages/popup.tsx:465
+#: src/wallet/ProviderDetailPage.tsx:194
#, c-format
-msgid "Order redirected"
+msgid "remove provider"
msgstr ""
-#: src/webex/pages/popup.tsx:482
+#: src/wallet/ProviderDetailPage.tsx:213
#, c-format
-msgid "Payment aborted"
+msgid "There is conflict with another backup from %1$s"
msgstr ""
-#: src/webex/pages/popup.tsx:512
+#: src/wallet/ProviderDetailPage.tsx:228
#, c-format
-msgid "Payment Sent"
+msgid "Unknown backup problem: %1$s"
msgstr ""
-#: src/webex/pages/popup.tsx:536
+#: src/wallet/ProviderDetailPage.tsx:247
#, c-format
-msgid "Order accepted"
+msgid "service paid"
msgstr ""
-#: src/webex/pages/popup.tsx:547
+#: src/popup/Settings.tsx:46
#, c-format
-msgid "Reserve balance updated"
+msgid "Permissions"
msgstr ""
-#: src/webex/pages/popup.tsx:559
+#: src/cta/TermsOfServiceSection.tsx:37
#, c-format
-msgid "Payment refund"
+msgid "Exchange doesn't have terms of service"
msgstr ""
-#: src/webex/pages/popup.tsx:584
+#: src/cta/TermsOfServiceSection.tsx:56
#, c-format
-msgid "Withdrawn"
+msgid "Review exchange terms of service"
msgstr ""
-#: src/webex/pages/popup.tsx:596
+#: src/cta/TermsOfServiceSection.tsx:63
#, c-format
-msgid "Tip Accepted"
+msgid "Review new version of terms of service"
msgstr ""
-#: src/webex/pages/popup.tsx:606
+#: src/cta/TermsOfServiceSection.tsx:75
#, c-format
-msgid "Tip Declined"
+msgid "Show terms of service"
msgstr ""
-#: src/webex/pages/popup.tsx:615
+#: src/cta/TermsOfServiceSection.tsx:83
#, c-format
-msgid "%1$s"
+msgid "I accept the exchange terms of service"
msgstr ""
-#: src/webex/pages/popup.tsx:707
+#: src/cta/TermsOfServiceSection.tsx:127
#, c-format
-msgid "Your wallet has no events recorded."
+msgid "Hide terms of service"
msgstr ""
-#: src/webex/pages/return-coins.tsx:124
+#: src/wallet/ExchangeAddConfirm.tsx:110
#, c-format
-msgid "Wire to bank account"
+msgid "Cancel"
msgstr ""
-#: src/webex/pages/return-coins.tsx:206
+#: src/wallet/ExchangeAddConfirm.tsx:114
#, c-format
-msgid "Confirm"
+msgid "Loading terms.."
msgstr ""
-#: src/webex/pages/return-coins.tsx:209
+#: src/wallet/ExchangeAddConfirm.tsx:121
#, c-format
-msgid "Cancel"
+msgid "Add exchange"
msgstr ""
-#: src/webex/pages/withdraw.tsx:73
+#: src/wallet/ExchangeAddConfirm.tsx:131
#, c-format
-msgid "Could not get details for withdraw operation:"
+msgid "Add exchange anyway"
msgstr ""
-#: src/webex/pages/withdraw.tsx:89 src/webex/pages/withdraw.tsx:183
+#: src/wallet/Settings.tsx:95
#, c-format
-msgid "Chose different exchange provider"
+msgid "Known exchanges"
msgstr ""
-#: src/webex/pages/withdraw.tsx:109
+#: src/wallet/Transaction.tsx:159
#, c-format
-msgid ""
-"Please select an exchange. You can review the details before after your "
-"selection."
+msgid "retry"
+msgstr ""
+
+#: src/wallet/Transaction.tsx:163
+#, c-format
+msgid "Forget"
msgstr ""
-#: src/webex/pages/withdraw.tsx:121
+#: src/wallet/Transaction.tsx:198
#, c-format
-msgid "Select %1$s"
+msgid "Confirm"
msgstr ""
-#: src/webex/pages/withdraw.tsx:143
+#: src/cta/Pay.tsx:211
#, c-format
-msgid "Select custom exchange"
+msgid "Pay with a mobile phone"
msgstr ""
-#: src/webex/pages/withdraw.tsx:163
+#: src/cta/Pay.tsx:211
#, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgid "Hide QR"
msgstr ""
-#: src/webex/pages/withdraw.tsx:174
+#: src/cta/Pay.tsx:241
#, c-format
-msgid "Accept fees and withdraw"
+msgid "Pay"
msgstr ""
-#: src/webex/pages/withdraw.tsx:192
+#: src/cta/Pay.tsx:265
#, c-format
-msgid "Cancel withdraw operation"
+msgid "Withdraw digital cash"
msgstr ""
-#: src/webex/renderHtml.tsx:249
+#: src/cta/Pay.tsx:295
#, c-format
-msgid "Withdrawal fees:"
+msgid "Digital cash payment"
msgstr ""
-#: src/webex/renderHtml.tsx:252
+#: src/cta/Withdraw.tsx:101
#, c-format
-msgid "Rounding loss:"
+msgid "Digital cash withdrawal"
msgstr ""
-#: src/webex/renderHtml.tsx:254
+#: src/cta/Withdraw.tsx:149
#, c-format
-msgid "Earliest expiration (for deposit): %1$s"
+msgid "Cancel exchange selection"
msgstr ""
-#: src/webex/renderHtml.tsx:262
+#: src/cta/Withdraw.tsx:150
#, c-format
-msgid "# Coins"
+msgid "Confirm exchange selection"
msgstr ""
-#: src/webex/renderHtml.tsx:263
+#: src/cta/Withdraw.tsx:155
#, c-format
-msgid "Value"
+msgid "Switch exchange"
msgstr ""
-#: src/webex/renderHtml.tsx:264
+#: src/cta/Withdraw.tsx:174
#, c-format
-msgid "Withdraw Fee"
+msgid "Confirm withdrawal"
msgstr ""
-#: src/webex/renderHtml.tsx:265
+#: src/cta/Withdraw.tsx:183
#, c-format
-msgid "Refresh Fee"
+msgid "Withdraw anyway"
msgstr ""
-#: src/webex/renderHtml.tsx:266
+#: src/cta/Withdraw.tsx:310
#, c-format
-msgid "Deposit Fee"
+msgid "missing withdraw uri"
msgstr ""
+
+#: src/cta/Deposit.tsx:186
+#, c-format
+msgid "Digital cash deposit"
+msgstr ""
+