add i18n where was missing

This commit is contained in:
Sebastian 2022-02-23 15:18:37 -03:00
parent 7647d077e7
commit 41850c9f14
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
50 changed files with 2104 additions and 1303 deletions

View File

@ -18,17 +18,23 @@
* Popup shown to the user when they click
* the Taler browser action button.
*
* @author Florian Dold
* @author sebasjm
*/
/**
* Imports.
*/
import { i18n } from "@gnu-taler/taler-util";
import { i18n, Translate } from "@gnu-taler/taler-util";
import { VNode, h } from "preact";
import { JustInDevMode } from "./components/JustInDevMode";
import { NavigationHeader, NavigationHeaderHolder } from "./components/styled";
/**
* List of pages used by the wallet
*
* @author sebasjm
*/
export enum Pages {
welcome = "/welcome",
@ -60,17 +66,15 @@ export function PopupNavBar({ path = "" }: { path?: string }): VNode {
: "#";
return (
<NavigationHeader>
<a
href="/balance"
class={path.startsWith("/balance") ? "active" : ""}
>{i18n.str`Balance`}</a>
<a
href="/backup"
class={path.startsWith("/backup") ? "active" : ""}
>{i18n.str`Backup`}</a>
<a href="/balance" class={path.startsWith("/balance") ? "active" : ""}>
<Translate>Balance</Translate>
</a>
<a href="/backup" class={path.startsWith("/backup") ? "active" : ""}>
<Translate>Backup</Translate>
</a>
<a />
<a href={innerUrl} target="_blank" rel="noreferrer">
<div class="settings-icon" title="Settings" />
<div class="settings-icon" title={i18n.str`Settings`} />
</a>
</NavigationHeader>
);
@ -80,20 +84,17 @@ export function WalletNavBar({ path = "" }: { path?: string }): VNode {
return (
<NavigationHeaderHolder>
<NavigationHeader>
<a
href="/balance"
class={path.startsWith("/balance") ? "active" : ""}
>{i18n.str`Balance`}</a>
<a
href="/backup"
class={path.startsWith("/backup") ? "active" : ""}
>{i18n.str`Backup`}</a>
<a href="/balance" class={path.startsWith("/balance") ? "active" : ""}>
<Translate>Balance</Translate>
</a>
<a href="/backup" class={path.startsWith("/backup") ? "active" : ""}>
<Translate>Backup</Translate>
</a>
<JustInDevMode>
<a
href="/dev"
class={path.startsWith("/dev") ? "active" : ""}
>{i18n.str`Dev`}</a>
<a href="/dev" class={path.startsWith("/dev") ? "active" : ""}>
<Translate>Dev</Translate>
</a>
</JustInDevMode>
<a />
@ -101,7 +102,7 @@ export function WalletNavBar({ path = "" }: { path?: string }): VNode {
href="/settings"
class={path.startsWith("/settings") ? "active" : ""}
>
<div class="settings-icon" title="Settings" />
<Translate>Settings</Translate>
</a>
</NavigationHeader>
</NavigationHeaderHolder>

View File

@ -17,7 +17,7 @@
/**
* Entry point for the background page.
*
* @author Florian Dold
* @author sebasjm
*/
/**

View File

@ -1,43 +0,0 @@
"use strict";
/*
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/>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BrowserCryptoWorkerFactory = void 0;
/**
* API to access the Taler crypto worker thread.
* @author Florian Dold
*/
class BrowserCryptoWorkerFactory {
startWorker() {
const workerCtor = Worker;
const workerPath = "/browserWorkerEntry.js";
return new workerCtor(workerPath);
}
getConcurrency() {
let concurrency = 2;
try {
// only works in the browser
// tslint:disable-next-line:no-string-literal
concurrency = navigator["hardwareConcurrency"];
concurrency = Math.max(1, Math.ceil(concurrency / 2));
} catch (e) {
concurrency = 2;
}
return concurrency;
}
}
exports.BrowserCryptoWorkerFactory = BrowserCryptoWorkerFactory;
//# sourceMappingURL=browserCryptoWorkerFactory.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"browserCryptoWorkerFactory.js","sourceRoot":"","sources":["browserCryptoWorkerFactory.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH;;;GAGG;AAEH,MAAa,0BAA0B;IACrC,WAAW;QACT,MAAM,UAAU,GAAG,MAAM,CAAC;QAC1B,MAAM,UAAU,GAAG,wBAAwB,CAAC;QAC5C,OAAO,IAAI,UAAU,CAAC,UAAU,CAAiB,CAAC;IACpD,CAAC;IAED,cAAc;QACZ,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI;YACF,4BAA4B;YAC5B,6CAA6C;YAC7C,WAAW,GAAI,SAAiB,CAAC,qBAAqB,CAAC,CAAC;YACxD,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC;SACvD;QAAC,OAAO,CAAC,EAAE;YACV,WAAW,GAAG,CAAC,CAAC;SACjB;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;CACF;AAnBD,gEAmBC"}

View File

@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { PaytoUri } from "@gnu-taler/taler-util";
import { PaytoUri, Translate } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
import { CopiedIcon, CopyIcon } from "../svg";
@ -34,23 +34,23 @@ export function BankDetailsByPaytoType({
amount,
}: BankDetailsProps): VNode {
const firstPart = !payto ? undefined : !payto.isKnown ? (
<Row name="Account" value={payto.targetPath} />
<Row name={<Translate>Account</Translate>} value={payto.targetPath} />
) : payto.targetType === "x-taler-bank" ? (
<Fragment>
<Row name="Bank host" value={payto.host} />
<Row name="Bank account" value={payto.account} />
<Row name={<Translate>Bank host</Translate>} value={payto.host} />
<Row name={<Translate>Bank account</Translate>} value={payto.account} />
</Fragment>
) : payto.targetType === "iban" ? (
<Row name="IBAN" value={payto.iban} />
<Row name={<Translate>IBAN</Translate>} value={payto.iban} />
) : undefined;
return (
<div style={{ textAlign: "left" }}>
<p>Bank transfer details</p>
<table>
{firstPart}
<Row name="Exchange" value={exchangeBaseUrl} />
<Row name="Chosen amount" value={amount} />
<Row name="Subject" value={subject} literal />
<Row name={<Translate>Exchange</Translate>} value={exchangeBaseUrl} />
<Row name={<Translate>Chosen amount</Translate>} value={amount} />
<Row name={<Translate>Subject</Translate>} value={subject} literal />
</table>
</div>
);
@ -61,7 +61,7 @@ function Row({
value,
literal,
}: {
name: string;
name: VNode;
value: string;
literal?: boolean;
}): VNode {

View File

@ -19,9 +19,9 @@ import { h, VNode } from "preact";
interface Props {
enabled: boolean;
onToggle: () => void;
label: string;
label: VNode;
name: string;
description?: string;
description?: VNode;
}
export function Checkbox({
name,

View File

@ -20,7 +20,7 @@ import { h, VNode } from "preact";
interface Props {
enabled: boolean;
onToggle: () => void;
label: string;
label: VNode;
name: string;
}

View File

@ -14,6 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { Translate } from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
export function DebugCheckbox({
@ -36,7 +37,7 @@ export function DebugCheckbox({
htmlFor="checkbox-perm"
style={{ marginLeft: "0.5em", fontWeight: "bold" }}
>
Automatically open wallet based on page content
<Translate>Automatically open wallet based on page content</Translate>
</label>
<span
style={{
@ -46,8 +47,12 @@ export function DebugCheckbox({
marginLeft: "2em",
}}
>
(Enabling this option below will make using the wallet faster, but
requires more permissions from your browser.)
(
<Translate>
Enabling this option below will make using the wallet faster, but
requires more permissions from your browser.
</Translate>
)
</span>
</div>
);

View File

@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { WalletDiagnostics } from "@gnu-taler/taler-util";
import { Translate, WalletDiagnostics } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { PageLink } from "../renderHtml";
@ -25,7 +25,13 @@ interface Props {
export function Diagnostics({ timedOut, diagnostics }: Props): VNode {
if (timedOut) {
return <p>Diagnostics timed out. Could not talk to the wallet backend.</p>;
return (
<p>
<Translate>
Diagnostics timed out. Could not talk to the wallet backend.
</Translate>
</p>
);
}
if (diagnostics) {
@ -41,7 +47,9 @@ export function Diagnostics({ timedOut, diagnostics }: Props): VNode {
paddingBottom: "0.2em",
}}
>
<p>Problems detected:</p>
<p>
<Translate>Problems detected:</Translate>
</p>
<ol>
{diagnostics.errors.map((errMsg) => (
<li key={errMsg}>{errMsg}</li>
@ -49,22 +57,32 @@ export function Diagnostics({ timedOut, diagnostics }: Props): VNode {
</ol>
{diagnostics.firefoxIdbProblem ? (
<p>
<Translate>
Please check in your <code>about:config</code> settings that you
have IndexedDB enabled (check the preference name{" "}
<code>dom.indexedDB.enabled</code>).
</Translate>
</p>
) : null}
{diagnostics.dbOutdated ? (
<p>
<Translate>
Your wallet database is outdated. Currently automatic migration is
not supported. Please go{" "}
<PageLink pageName="/reset-required">here</PageLink> to reset the
wallet database.
<PageLink pageName="/reset-required">
<Translate>here</Translate>
</PageLink>{" "}
to reset the wallet database.
</Translate>
</p>
) : null}
</div>
);
}
return <p>Running diagnostics ...</p>;
return (
<p>
<Translate>Running diagnostics</Translate> ...
</p>
);
}

View File

@ -14,6 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { Translate } from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import { useRef, useState } from "preact/hooks";
@ -39,7 +40,9 @@ export function EditableText({
return (
<div style={{ display: "flex", justifyContent: "space-between" }}>
<p>{value}</p>
<button onClick={() => setEditing(true)}>edit</button>
<button onClick={() => setEditing(true)}>
<Translate>Edit</Translate>
</button>
</div>
);
};
@ -54,7 +57,7 @@ export function EditableText({
onChange(ref.current.value).then(() => setEditing(false));
}}
>
confirm
<Translate>Confirm</Translate>
</button>
</div>
);

View File

@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { VNode, h } from "preact";
import { VNode, h, ComponentChildren } from "preact";
import { useState } from "preact/hooks";
import arrowDown from "../../static/img/chevron-down.svg";
import { ErrorBox } from "./styled";
@ -22,11 +22,10 @@ export function ErrorMessage({
title,
description,
}: {
title?: string | VNode;
title: VNode;
description?: string;
}): VNode | null {
const [showErrorDetail, setShowErrorDetail] = useState(false);
if (!title) return null;
return (
<ErrorBox style={{ paddingTop: 0, paddingBottom: 0 }}>
<div>

View File

@ -24,7 +24,7 @@ export function ErrorTalerOperation({
title,
error,
}: {
title?: string;
title?: VNode;
error?: TalerErrorDetails;
}): VNode | null {
const { devMode } = useDevContext();

View File

@ -13,8 +13,13 @@
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/>
*/
import { Translate } from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
export function Loading(): VNode {
return <div>Loading...</div>;
return (
<div>
<Translate>Loading</Translate>...
</div>
);
}

View File

@ -19,7 +19,7 @@ import { ErrorMessage } from "./ErrorMessage";
import { ErrorTalerOperation } from "./ErrorTalerOperation";
export interface Props {
title: string;
title: VNode;
error: HookError;
}
export function LoadingError({ title, error }: Props): VNode {

View File

@ -4,7 +4,7 @@ import { ButtonBoxPrimary, ButtonPrimary, ParagraphClickable } from "./styled";
import { useState } from "preact/hooks";
export interface Props {
label: (s: string) => string;
label: (s: string) => VNode;
actions: string[];
onClick: (s: string) => void;
}

View File

@ -15,11 +15,11 @@
*/
import { AmountLike } from "@gnu-taler/taler-util";
import { ExtraLargeText, LargeText, SmallLightText } from "./styled";
import { h } from "preact";
import { h, VNode } from "preact";
export type Kind = "positive" | "negative" | "neutral";
interface Props {
title: string;
title: VNode;
text: AmountLike;
kind: Kind;
big?: boolean;

View File

@ -14,13 +14,14 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { Translate } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { NiceSelect } from "./styled";
interface Props {
value?: string;
onChange: (s: string) => void;
label: string;
label: VNode;
list: {
[label: string]: string;
};
@ -58,7 +59,7 @@ export function SelectList({
{value === undefined ||
(canBeNull && (
<option selected disabled>
Select one option
<Translate>Select one option</Translate>
</option>
// ) : (
// <option selected>{list[value]}</option>

View File

@ -21,6 +21,7 @@ import {
Timestamp,
Transaction,
TransactionType,
Translate,
} from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import imageBank from "../../static/img/ri-bank-line.svg";
@ -133,7 +134,7 @@ function TransactionLayout(props: TransactionLayoutProps): VNode {
</LargeText>
{props.pending && (
<LightText style={{ marginTop: 5, marginBottom: 5 }}>
Waiting for confirmation
<Translate>Waiting for confirmation</Translate>
</LightText>
)}
<SmallLightText style={{ marginTop: 5 }}>
@ -195,7 +196,11 @@ function TransactionAmount(props: TransactionAmountProps): VNode {
{sign}
{Amounts.stringifyValue(props.amount)}
</ExtraLargeText>
{props.pending && <div>PENDING</div>}
{props.pending && (
<div>
<Translate>PENDING</Translate>
</div>
)}
</Column>
);
}

View File

@ -35,6 +35,7 @@ import {
NotificationType,
PreparePayResult,
PreparePayResultType,
Translate,
} from "@gnu-taler/taler-util";
import { OperationFailedError } from "@gnu-taler/taler-wallet-core";
import { Fragment, h, VNode } from "preact";
@ -108,7 +109,11 @@ export function DepositPage({ talerPayUri, goBack }: Props): VNode {
}, [talerPayUri, foundAmountStr]);
if (!talerPayUri) {
return <span>missing pay uri</span>;
return (
<span>
<Translate>missing pay uri</Translate>
</span>
);
}
if (!payStatus) {
@ -116,10 +121,16 @@ export function DepositPage({ talerPayUri, goBack }: Props): VNode {
return (
<WalletAction>
<LogoHeader />
<h2>{i18n.str`Digital cash payment`}</h2>
<h2>
<Translate>Digital cash payment</Translate>
</h2>
<section>
<ErrorTalerOperation
title="Could not get the payment information for this order"
title={
<Translate>
Could not get the payment information for this order
</Translate>
}
error={payErrMsg?.operationError}
/>
</section>
@ -130,15 +141,25 @@ export function DepositPage({ talerPayUri, goBack }: Props): VNode {
return (
<WalletAction>
<LogoHeader />
<h2>{i18n.str`Digital cash payment`}</h2>
<h2>
<Translate>Digital cash payment</Translate>
</h2>
<section>
<p>Could not get the payment information for this order</p>
<p>
<Translate>
Could not get the payment information for this order
</Translate>
</p>
<ErrorBox>{payErrMsg}</ErrorBox>
</section>
</WalletAction>
);
}
return <span>Loading payment information ...</span>;
return (
<span>
<Translate>Loading payment information</Translate> ...
</span>
);
}
const onClick = async (): Promise<void> => {
@ -183,20 +204,32 @@ export function PaymentRequestView({
<WalletAction>
<LogoHeader />
<h2>{i18n.str`Digital cash deposit`}</h2>
<h2>
<Translate>Digital cash deposit</Translate>
</h2>
{payStatus.status === PreparePayResultType.AlreadyConfirmed &&
(payStatus.paid ? (
<SuccessBox> Already paid </SuccessBox>
<SuccessBox>
<Translate>Already paid</Translate>
</SuccessBox>
) : (
<WarningBox> Already claimed </WarningBox>
<WarningBox>
<Translate>Already claimed</Translate>
</WarningBox>
))}
{payResult && payResult.type === ConfirmPayResultType.Done && (
<SuccessBox>
<h3>Payment complete</h3>
<h3>
<Translate>Payment complete</Translate>
</h3>
<p>
{!payResult.contractTerms.fulfillment_message
? "You will now be sent back to the merchant you came from."
: payResult.contractTerms.fulfillment_message}
{!payResult.contractTerms.fulfillment_message ? (
<Translate>
You will now be sent back to the merchant you came from.
</Translate>
) : (
payResult.contractTerms.fulfillment_message
)}
</p>
</SuccessBox>
)}
@ -205,7 +238,7 @@ export function PaymentRequestView({
Amounts.isNonZero(totalFees) && (
<Part
big
title="Total to pay"
title={<Translate>Total to pay</Translate>}
text={amountToPretty(
Amounts.parseOrThrow(payStatus.amountEffective),
)}
@ -214,7 +247,7 @@ export function PaymentRequestView({
)}
<Part
big
title="Purchase amount"
title={<Translate>Purchase amount</Translate>}
text={amountToPretty(Amounts.parseOrThrow(payStatus.amountRaw))}
kind="neutral"
/>
@ -222,21 +255,25 @@ export function PaymentRequestView({
<Fragment>
<Part
big
title="Fee"
title={<Translate>Fee</Translate>}
text={amountToPretty(totalFees)}
kind="negative"
/>
</Fragment>
)}
<Part
title="Merchant"
title={<Translate>Merchant</Translate>}
text={contractTerms.merchant.name}
kind="neutral"
/>
<Part title="Purchase" text={contractTerms.summary} kind="neutral" />
<Part
title={<Translate>Purchase</Translate>}
text={contractTerms.summary}
kind="neutral"
/>
{contractTerms.order_id && (
<Part
title="Receipt"
title={<Translate>Receipt</Translate>}
text={`#${contractTerms.order_id}`}
kind="neutral"
/>

View File

@ -37,10 +37,12 @@ import {
PreparePayResult,
PreparePayResultType,
Product,
Translate,
} from "@gnu-taler/taler-util";
import { OperationFailedError } from "@gnu-taler/taler-wallet-core";
import { Fragment, h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
import { ErrorMessage } from "../components/ErrorMessage";
import { Loading } from "../components/Loading";
import { LoadingError } from "../components/LoadingError";
import { LogoHeader } from "../components/LogoHeader";
@ -106,7 +108,12 @@ export function PayPage({
}
if (hook.hasError) {
return <LoadingError title="Could not load pay status" error={hook} />;
return (
<LoadingError
title={<Translate>Could not load pay status</Translate>}
error={hook}
/>
);
}
const foundBalance = hook.response.balance.balances.find(
@ -178,9 +185,13 @@ export function PaymentRequestView({
if (!contractTerms) {
return (
<span>
Error: did not get contract terms from merchant or wallet backend.
</span>
<ErrorMessage
title={
<Translate>
Could not load contract terms from merchant or wallet backend.
</Translate>
}
/>
);
}
@ -192,13 +203,6 @@ export function PaymentRequestView({
totalFees = Amounts.sub(amountEffective, amountRaw).amount;
}
// let merchantName: VNode;
// if (contractTerms.merchant && contractTerms.merchant.name) {
// merchantName = <strong>{contractTerms.merchant.name}</strong>;
// } else {
// merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>;
// }
function Alternative(): VNode {
const [showQR, setShowQR] = useState<boolean>(false);
const privateUri =
@ -209,12 +213,21 @@ export function PaymentRequestView({
return (
<section>
<LinkSuccess upperCased onClick={() => setShowQR((qr) => !qr)}>
{!showQR ? i18n.str`Pay with a mobile phone` : i18n.str`Hide QR`}
{!showQR ? (
<Translate>Pay with a mobile phone</Translate>
) : (
<Translate>Hide QR</Translate>
)}
</LinkSuccess>
{showQR && (
<div>
<QR text={privateUri} />
Scan the QR code or <a href={privateUri}>click here</a>
<Translate>
Scan the QR code or
<a href={privateUri}>
<Translate>click here</Translate>
</a>
</Translate>
</div>
)}
</section>
@ -227,7 +240,9 @@ export function PaymentRequestView({
return (
<section>
<div>
<p>Processing...</p>
<p>
<Translate>Processing</Translate>...
</p>
</div>
</section>
);
@ -239,7 +254,9 @@ export function PaymentRequestView({
<Fragment>
<section>
<ButtonSuccess upperCased onClick={onClick}>
{i18n.str`Pay`} {amountToString(payStatus.amountEffective)}
<Translate>
Pay {amountToString(payStatus.amountEffective)}
</Translate>
</ButtonSuccess>
</section>
<Alternative />
@ -252,18 +269,22 @@ export function PaymentRequestView({
<section>
{balance ? (
<WarningBox>
<Translate>
Your balance of {amountToString(balance)} is not enough to pay
for this purchase
</Translate>
</WarningBox>
) : (
<WarningBox>
<Translate>
Your balance is not enough to pay for this purchase.
</Translate>
</WarningBox>
)}
</section>
<section>
<ButtonSuccess upperCased onClick={goToWalletManualWithdraw}>
{i18n.str`Withdraw digital cash`}
<Translate>Withdraw digital cash</Translate>
</ButtonSuccess>
</section>
<Alternative />
@ -276,7 +297,7 @@ export function PaymentRequestView({
<section>
{payStatus.paid && contractTerms.fulfillment_message && (
<Part
title="Merchant message"
title={<Translate>Merchant message</Translate>}
text={contractTerms.fulfillment_message}
kind="neutral"
/>
@ -293,31 +314,48 @@ export function PaymentRequestView({
<WalletAction>
<LogoHeader />
<h2>{i18n.str`Digital cash payment`}</h2>
<h2>
<Translate>Digital cash payment</Translate>
</h2>
{payStatus.status === PreparePayResultType.AlreadyConfirmed &&
(payStatus.paid ? (
payStatus.contractTerms.fulfillment_url ? (
<SuccessBox>
<Translate>
Already paid, you are going to be redirected to{" "}
<a href={payStatus.contractTerms.fulfillment_url}>
{payStatus.contractTerms.fulfillment_url}
</a>
</Translate>
</SuccessBox>
) : (
<SuccessBox> Already paid </SuccessBox>
<SuccessBox>
<Translate>Already paid</Translate>
</SuccessBox>
)
) : (
<WarningBox> Already claimed </WarningBox>
<WarningBox>
<Translate>Already claimed</Translate>
</WarningBox>
))}
{payResult && payResult.type === ConfirmPayResultType.Done && (
<SuccessBox>
<h3>Payment complete</h3>
<h3>
<Translate>Payment complete</Translate>
</h3>
<p>
{!payResult.contractTerms.fulfillment_message
? payResult.contractTerms.fulfillment_url
? `You are going to be redirected to ${payResult.contractTerms.fulfillment_url}`
: "You can close this page."
: payResult.contractTerms.fulfillment_message}
{!payResult.contractTerms.fulfillment_message ? (
payResult.contractTerms.fulfillment_url ? (
<Translate>
You are going to be redirected to $
{payResult.contractTerms.fulfillment_url}
</Translate>
) : (
<Translate>You can close this page.</Translate>
)
) : (
payResult.contractTerms.fulfillment_message
)}
</p>
</SuccessBox>
)}
@ -326,14 +364,14 @@ export function PaymentRequestView({
Amounts.isNonZero(totalFees) && (
<Part
big
title="Total to pay"
title={<Translate>Total to pay</Translate>}
text={amountToString(payStatus.amountEffective)}
kind="negative"
/>
)}
<Part
big
title="Purchase amount"
title={<Translate>Purchase amount</Translate>}
text={amountToString(payStatus.amountRaw)}
kind="neutral"
/>
@ -341,21 +379,25 @@ export function PaymentRequestView({
<Fragment>
<Part
big
title="Fee"
title={<Translate>Fee</Translate>}
text={amountToString(totalFees)}
kind="negative"
/>
</Fragment>
)}
<Part
title="Merchant"
title={<Translate>Merchant</Translate>}
text={contractTerms.merchant.name}
kind="neutral"
/>
<Part title="Purchase" text={contractTerms.summary} kind="neutral" />
<Part
title={<Translate>Purchase</Translate>}
text={contractTerms.summary}
kind="neutral"
/>
{contractTerms.order_id && (
<Part
title="Receipt"
title={<Translate>Receipt</Translate>}
text={`#${contractTerms.order_id}`}
kind="neutral"
/>
@ -373,7 +415,7 @@ function ProductList({ products }: { products: Product[] }): VNode {
return (
<Fragment>
<SmallLightText style={{ margin: ".5em" }}>
List of products
<Translate>List of products</Translate>
</SmallLightText>
<dl>
{products.map((p, i) => {
@ -415,15 +457,18 @@ function ProductList({ products }: { products: Product[] }): VNode {
{p.quantity ?? 1} x {p.description}
</dt>
<dd>
Total{` `}
{p.price
? `${Amounts.stringifyValue(
<Translate>Total</Translate>
{` `}
{p.price ? (
`${Amounts.stringifyValue(
Amounts.mult(
Amounts.parseOrThrow(p.price),
p.quantity ?? 1,
).amount,
)} ${p}`
: "free"}
) : (
<Translate>free</Translate>
)}
</dd>
</div>
</div>

View File

@ -17,10 +17,10 @@
/**
* Page that shows refund status for purchases.
*
* @author Florian Dold
* @author sebasjm
*/
import { Amounts, ApplyRefundResponse } from "@gnu-taler/taler-util";
import { Amounts, ApplyRefundResponse, Translate } from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
import { AmountView } from "../renderHtml";
@ -37,20 +37,28 @@ export function View({ applyResult }: ViewProps): VNode {
<section class="main">
<h1>GNU Taler Wallet</h1>
<article class="fade">
<h2>Refund Status</h2>
<h2>
<Translate>Refund Status</Translate>
</h2>
<p>
<Translate>
The product <em>{applyResult.info.summary}</em> has received a total
effective refund of{" "}
</Translate>
<AmountView amount={applyResult.amountRefundGranted} />.
</p>
{applyResult.pendingAtExchange ? (
<p>Refund processing is still in progress.</p>
<p>
<Translate>Refund processing is still in progress.</Translate>
</p>
) : null}
{!Amounts.isZero(applyResult.amountRefundGone) ? (
<p>
<Translate>
The refund amount of{" "}
<AmountView amount={applyResult.amountRefundGone} /> could not be
applied.
</Translate>
</p>
) : null}
</article>
@ -82,15 +90,27 @@ export function RefundPage({ talerRefundUri }: Props): VNode {
console.log("rendering");
if (!talerRefundUri) {
return <span>missing taler refund uri</span>;
return (
<span>
<Translate>missing taler refund uri</Translate>
</span>
);
}
if (errMsg) {
return <span>Error: {errMsg}</span>;
return (
<span>
<Translate>Error: {errMsg}</Translate>
</span>
);
}
if (!applyResult) {
return <span>Updating refund status</span>;
return (
<span>
<Translate>Updating refund status</Translate>
</span>
);
}
return <View applyResult={applyResult} />;

View File

@ -1,4 +1,4 @@
import { i18n } from "@gnu-taler/taler-util";
import { i18n, Translate } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { CheckboxOutlined } from "../components/CheckboxOutlined";
import { ExchangeXmlTos } from "../components/ExchangeToS";
@ -34,7 +34,7 @@ export function TermsOfServiceSection({
{terms.status === "notfound" && (
<section>
<WarningText>
{i18n.str`Exchange doesn't have terms of service`}
<Translate>Exchange doesn't have terms of service</Translate>
</WarningText>
</section>
)}
@ -46,21 +46,21 @@ export function TermsOfServiceSection({
{terms.status === "notfound" && (
<section>
<WarningText>
{i18n.str`Exchange doesn't have terms of service`}
<Translate>Exchange doesn't have terms of service</Translate>
</WarningText>
</section>
)}
{terms.status === "new" && (
<section>
<ButtonSuccess upperCased onClick={() => onReview(true)}>
{i18n.str`Review exchange terms of service`}
<Translate>Review exchange terms of service</Translate>
</ButtonSuccess>
</section>
)}
{terms.status === "changed" && (
<section>
<ButtonWarning upperCased onClick={() => onReview(true)}>
{i18n.str`Review new version of terms of service`}
<Translate>Review new version of terms of service</Translate>
</ButtonWarning>
</section>
)}
@ -72,7 +72,7 @@ export function TermsOfServiceSection({
{onReview && (
<section>
<LinkSuccess upperCased onClick={() => onReview(true)}>
{i18n.str`Show terms of service`}
<Translate>Show terms of service</Translate>
</LinkSuccess>
</section>
)}
@ -80,7 +80,9 @@ export function TermsOfServiceSection({
<CheckboxOutlined
name="terms"
enabled={reviewed}
label={i18n.str`I accept the exchange terms of service`}
label={
<Translate>I accept the exchange terms of service</Translate>
}
onToggle={() => {
onAccept(!reviewed);
if (onReview) onReview(false);
@ -95,7 +97,9 @@ export function TermsOfServiceSection({
{terms.status !== "notfound" && !terms.content && (
<section>
<WarningBox>
<Translate>
The exchange reply with a empty terms of service
</Translate>
</WarningBox>
</section>
)}
@ -116,7 +120,7 @@ export function TermsOfServiceSection({
)}
{terms.content.type === "pdf" && (
<a href={terms.content.location.toString()} download="tos.pdf">
Download Terms of Service
<Translate>Download Terms of Service</Translate>
</a>
)}
</section>
@ -124,7 +128,7 @@ export function TermsOfServiceSection({
{reviewed && onReview && (
<section>
<LinkSuccess upperCased onClick={() => onReview(false)}>
{i18n.str`Hide terms of service`}
<Translate>Hide terms of service</Translate>
</LinkSuccess>
</section>
)}
@ -133,7 +137,9 @@ export function TermsOfServiceSection({
<CheckboxOutlined
name="terms"
enabled={reviewed}
label={i18n.str`I accept the exchange terms of service`}
label={
<Translate>I accept the exchange terms of service</Translate>
}
onToggle={() => {
onAccept(!reviewed);
if (onReview) onReview(false);

View File

@ -17,10 +17,10 @@
/**
* Page shown to the user to accept or ignore a tip from a merchant.
*
* @author Florian Dold <dold@taler.net>
* @author sebasjm <dold@taler.net>
*/
import { PrepareTipResult } from "@gnu-taler/taler-util";
import { PrepareTipResult, Translate } from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
import { Loading } from "../components/Loading";
@ -46,21 +46,29 @@ export function View({
<article class="fade">
{prepareTipResult.accepted ? (
<span>
<Translate>
Tip from <code>{prepareTipResult.merchantBaseUrl}</code> accepted.
Check your transactions list for more details.
</Translate>
</span>
) : (
<div>
<p>
<Translate>
The merchant <code>{prepareTipResult.merchantBaseUrl}</code> is
offering you a tip of{" "}
<strong>
<AmountView amount={prepareTipResult.tipAmountEffective} />
</strong>{" "}
via the exchange <code>{prepareTipResult.exchangeBaseUrl}</code>
</Translate>
</p>
<button onClick={onAccept}>Accept tip</button>
<button onClick={onIgnore}>Ignore</button>
<button onClick={onAccept}>
<Translate>Accept tip</Translate>
</button>
<button onClick={onIgnore}>
<Translate>Ignore</Translate>
</button>
</div>
)}
</article>
@ -98,11 +106,19 @@ export function TipPage({ talerTipUri }: Props): VNode {
};
if (!talerTipUri) {
return <span>missing tip uri</span>;
return (
<span>
<Translate>missing tip uri</Translate>
</span>
);
}
if (tipIgnored) {
return <span>You've ignored the tip.</span>;
return (
<span>
<Translate>You've ignored the tip.</Translate>
</span>
);
}
if (!prepareTipResult) {

View File

@ -18,7 +18,7 @@
* Page shown to the user to confirm creation
* of a reserve, usually requested by the bank.
*
* @author Florian Dold
* @author sebasjm
*/
import {
@ -26,6 +26,7 @@ import {
Amounts,
ExchangeListItem,
i18n,
Translate,
WithdrawUriInfoResponse,
} from "@gnu-taler/taler-util";
import { OperationFailedError } from "@gnu-taler/taler-wallet-core";
@ -117,37 +118,46 @@ export function View({
return (
<WalletAction>
<LogoHeader />
<h2>{i18n.str`Digital cash withdrawal`}</h2>
<h2>
<Translate>Digital cash withdrawal</Translate>
</h2>
{withdrawError && (
<ErrorTalerOperation
title="Could not finish the withdrawal operation"
title={
<Translate>Could not finish the withdrawal operation</Translate>
}
error={withdrawError.operationError}
/>
)}
<section>
<Part
title="Total to withdraw"
title={<Translate>Total to withdraw</Translate>}
text={amountToString(Amounts.sub(amount, withdrawalFee).amount)}
kind="positive"
/>
{Amounts.isNonZero(withdrawalFee) && (
<Fragment>
<Part
title="Chosen amount"
title={<Translate>Chosen amount</Translate>}
text={amountToString(amount)}
kind="neutral"
/>
<Part
title="Exchange fee"
title={<Translate>Exchange fee</Translate>}
text={amountToString(withdrawalFee)}
kind="negative"
/>
</Fragment>
)}
{exchangeBaseUrl && (
<Part title="Exchange" text={exchangeBaseUrl} kind="neutral" big />
<Part
title={<Translate>Exchange</Translate>}
text={exchangeBaseUrl}
kind="neutral"
big
/>
)}
</section>
{!reviewing && (
@ -156,7 +166,7 @@ export function View({
<Fragment>
<div>
<SelectList
label="Known exchanges"
label={<Translate>Known exchanges</Translate>}
list={exchanges}
value={nextExchange}
name="switchingExchange"
@ -172,14 +182,16 @@ export function View({
setSwitchingExchange(false);
}}
>
{nextExchange === undefined
? i18n.str`Cancel exchange selection`
: i18n.str`Confirm exchange selection`}
{nextExchange === undefined ? (
<Translate>Cancel exchange selection</Translate>
) : (
<Translate>Confirm exchange selection</Translate>
)}
</LinkSuccess>
</Fragment>
) : (
<LinkSuccess upperCased onClick={() => setSwitchingExchange(true)}>
{i18n.str`Switch exchange`}
<Translate>Switch exchange</Translate>
</LinkSuccess>
)}
</section>
@ -198,7 +210,7 @@ export function View({
disabled={!exchangeBaseUrl || confirmDisabled}
onClick={doWithdrawAndCheckError}
>
{i18n.str`Confirm withdrawal`}
<Translate>Confirm withdrawal</Translate>
</ButtonSuccess>
)}
{terms.status === "notfound" && (
@ -207,7 +219,7 @@ export function View({
disabled={!exchangeBaseUrl}
onClick={doWithdrawAndCheckError}
>
{i18n.str`Withdraw anyway`}
<Translate>Withdraw anyway</Translate>
</ButtonWarning>
)}
</section>
@ -270,7 +282,7 @@ export function WithdrawPageWithParsedURI({
if (detailsHook.hasError) {
return (
<LoadingError
title="Could not load the withdrawal details"
title={<Translate>Could not load the withdrawal details</Translate>}
error={detailsHook}
/>
);
@ -293,9 +305,7 @@ export function WithdrawPageWithParsedURI({
const onWithdraw = async (): Promise<void> => {
if (!exchange) return;
console.log("accepting exchange", exchange);
const res = await wxApi.acceptWithdrawal(uri, exchange);
console.log("accept withdrawal response", res);
if (res.confirmTransferUrl) {
document.location.href = res.confirmTransferUrl;
}
@ -327,7 +337,7 @@ export function WithdrawPage({ talerWithdrawUri }: Props): VNode {
if (!talerWithdrawUri) {
return (
<span>
<i18n.Translate>missing withdraw uri</i18n.Translate>
<Translate>missing withdraw uri</Translate>
</span>
);
}
@ -337,7 +347,7 @@ export function WithdrawPage({ talerWithdrawUri }: Props): VNode {
if (uriInfoHook.hasError) {
return (
<LoadingError
title="Could not get the info from the URI"
title={<Translate>Could not get the info from the URI</Translate>}
error={uriInfoHook}
/>
);

View File

@ -1,31 +0,0 @@
/*
This file is part of TALER
(C) 2017 Inria
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/>
*/
import { h, VNode } from "preact";
/**
* View and edit auditors.
*
* @author Florian Dold
*/
/**
* Imports.
*/
export function makePaybackPage(): VNode {
return <div>not implemented</div>;
}

View File

@ -17,9 +17,10 @@
/**
* Page to inform the user when a database reset is required.
*
* @author Florian Dold
* @author sebasjm
*/
import { Translate } from "@gnu-taler/taler-util";
import { Component, h, VNode } from "preact";
import * as wxApi from "../wxApi";
@ -49,14 +50,20 @@ class ResetNotification extends Component<any, State> {
if (this.state.resetRequired) {
return (
<div>
<h1>Manual Reset Required</h1>
<h1>
<Translate>Manual Reset Required</Translate>
</h1>
<p>
The wallet&apos;s database in your browser is incompatible with the{" "}
currently installed wallet. Please reset manually.
<Translate>
The wallet&apos;s database in your browser is incompatible with
the currently installed wallet. Please reset manually.
</Translate>
</p>
<p>
<Translate>
Once the database format has stabilized, we will provide automatic
upgrades.
</Translate>
</p>
<input
id="check"
@ -67,7 +74,7 @@ class ResetNotification extends Component<any, State> {
}}
/>{" "}
<label htmlFor="check">
I understand that I will lose all my data
<Translate>I understand that I will lose all my data</Translate>
</label>
<br />
<button
@ -75,15 +82,21 @@ class ResetNotification extends Component<any, State> {
disabled={!this.state.checked}
onClick={() => wxApi.resetDb()}
>
Reset
<Translate>Reset</Translate>
</button>
</div>
);
}
return (
<div>
<h1>Everything is fine!</h1>A reset is not required anymore, you can
close this page.
<h1>
<Translate>Everything is fine!</Translate>
</h1>
<p>
<Translate>
A reset is not required anymore, you can close this page.
</Translate>
</p>
</div>
);
}

View File

@ -14,16 +14,21 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { Translate } from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
/**
* Return coins to own bank account.
*
* @author Florian Dold
* @author sebasjm
*/
/**
* Imports.
*/
export function createReturnCoinsPage(): VNode {
return <span>Not implemented yet.</span>;
return (
<span>
<Translate>Not implemented yet.</Translate>
</span>
);
}

File diff suppressed because it is too large Load Diff

View File

@ -17,275 +17,38 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/NavigationBar.tsx:86
#, c-format
msgid "Balance"
msgstr ""
#: src/NavigationBar.tsx:87
#, c-format
msgid "Pending"
msgstr ""
#: src/NavigationBar.tsx:88
#, c-format
msgid "Backup"
msgstr ""
#: src/NavigationBar.tsx:89
#: src/NavigationBar.tsx:71
#, c-format
msgid "Settings"
msgstr ""
#: src/NavigationBar.tsx:90
#, c-format
msgid "Dev"
msgstr ""
#: src/wallet/BackupPage.tsx:127
#, c-format
msgid "Add provider"
msgstr ""
#: src/wallet/BackupPage.tsx:137
#, c-format
msgid "Sync all backups"
msgstr ""
#: src/wallet/BackupPage.tsx:139
#, c-format
msgid "Sync now"
msgstr ""
#: src/popup/BalancePage.tsx:79
#, c-format
msgid "You have no balance to show. Need some %1$s getting started?"
msgstr ""
#: src/wallet/ProviderAddPage.tsx:145
#, c-format
msgid "&lt; Back"
msgstr ""
#: src/wallet/ProviderAddPage.tsx:156
#, c-format
msgid "Next"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:57
#, c-format
msgid "Loading..."
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:64
#, c-format
msgid "There was an error loading the provider detail for \"%1$s\""
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:75
#, c-format
msgid "There is not known provider with url \"%1$s\". Redirecting back..."
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:131
#, c-format
msgid "Back up"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:142
#, c-format
msgid "Extend"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:148
#: src/popup/DeveloperPage.tsx:377
#, c-format
msgid ""
"terms has changed, extending the service will imply accepting the new terms of "
"service"
"Do you want to IRREVOCABLY DESTROY everything inside your wallet and LOSE ALL "
"YOUR COINS?"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:158
#: src/wallet/CreateManualWithdraw.tsx:102
#, c-format
msgid "old"
msgid "Manual Withdrawal"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:162
#: src/wallet/CreateManualWithdraw.tsx:104
#, c-format
msgid "new"
msgid ""
"Choose a exchange from where the coins will be withdrawn. The exchange\n"
" will send the coins to this wallet after receiving a wire transfer\n"
" with the correct subject."
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:169
#: src/wallet/CreateManualWithdraw.tsx:109
#, c-format
msgid "fee"
msgid "No exchange configured"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:177
#, c-format
msgid "storage"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:190
#, c-format
msgid "&lt; back"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:194
#, c-format
msgid "remove provider"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:213
#, c-format
msgid "There is conflict with another backup from %1$s"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:228
#, c-format
msgid "Unknown backup problem: %1$s"
msgstr ""
#: src/wallet/ProviderDetailPage.tsx:247
#, c-format
msgid "service paid"
msgstr ""
#: src/popup/Settings.tsx:46
#, c-format
msgid "Permissions"
msgstr ""
#: src/cta/TermsOfServiceSection.tsx:37
#, c-format
msgid "Exchange doesn't have terms of service"
msgstr ""
#: src/cta/TermsOfServiceSection.tsx:56
#, c-format
msgid "Review exchange terms of service"
msgstr ""
#: src/cta/TermsOfServiceSection.tsx:63
#, c-format
msgid "Review new version of terms of service"
msgstr ""
#: src/cta/TermsOfServiceSection.tsx:75
#, c-format
msgid "Show terms of service"
msgstr ""
#: src/cta/TermsOfServiceSection.tsx:83
#, c-format
msgid "I accept the exchange terms of service"
msgstr ""
#: src/cta/TermsOfServiceSection.tsx:127
#, c-format
msgid "Hide terms of service"
msgstr ""
#: src/wallet/ExchangeAddConfirm.tsx:110
#, c-format
msgid "Cancel"
msgstr ""
#: src/wallet/ExchangeAddConfirm.tsx:114
#, c-format
msgid "Loading terms.."
msgstr ""
#: src/wallet/ExchangeAddConfirm.tsx:121
#: src/wallet/CreateManualWithdraw.tsx:111
#, c-format
msgid "Add exchange"
msgstr ""
#: src/wallet/ExchangeAddConfirm.tsx:131
#, c-format
msgid "Add exchange anyway"
msgstr ""
#: src/wallet/Settings.tsx:95
#, c-format
msgid "Known exchanges"
msgstr ""
#: src/wallet/Transaction.tsx:159
#, c-format
msgid "retry"
msgstr ""
#: src/wallet/Transaction.tsx:163
#, c-format
msgid "Forget"
msgstr ""
#: src/wallet/Transaction.tsx:198
#, c-format
msgid "Confirm"
msgstr ""
#: src/cta/Pay.tsx:211
#, c-format
msgid "Pay with a mobile phone"
msgstr ""
#: src/cta/Pay.tsx:211
#, c-format
msgid "Hide QR"
msgstr ""
#: src/cta/Pay.tsx:241
#, c-format
msgid "Pay"
msgstr ""
#: src/cta/Pay.tsx:265
#, c-format
msgid "Withdraw digital cash"
msgstr ""
#: src/cta/Pay.tsx:295
#, c-format
msgid "Digital cash payment"
msgstr ""
#: src/cta/Withdraw.tsx:101
#, c-format
msgid "Digital cash withdrawal"
msgstr ""
#: src/cta/Withdraw.tsx:149
#, c-format
msgid "Cancel exchange selection"
msgstr ""
#: src/cta/Withdraw.tsx:150
#, c-format
msgid "Confirm exchange selection"
msgstr ""
#: src/cta/Withdraw.tsx:155
#, c-format
msgid "Switch exchange"
msgstr ""
#: src/cta/Withdraw.tsx:174
#, c-format
msgid "Confirm withdrawal"
msgstr ""
#: src/cta/Withdraw.tsx:183
#, c-format
msgid "Withdraw anyway"
msgstr ""
#: src/cta/Withdraw.tsx:310
#, c-format
msgid "missing withdraw uri"
msgstr ""
#: src/cta/Deposit.tsx:186
#, c-format
msgid "Digital cash deposit"
msgstr ""

View File

@ -14,7 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { Amounts, Balance } from "@gnu-taler/taler-util";
import { Amounts, Balance, Translate } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { BalanceTable } from "../components/BalanceTable";
@ -47,7 +47,12 @@ export function BalancePage({
}
if (state.hasError) {
return <LoadingError title="Could not load balance page" error={state} />;
return (
<LoadingError
title={<Translate>Could not load balance page</Translate>}
error={state}
/>
);
}
if (addingAction) {
@ -99,17 +104,19 @@ export function BalanceView({
</section>
<footer style={{ justifyContent: "space-between" }}>
<ButtonPrimary onClick={goToWalletManualWithdraw}>
Withdraw
<Translate>Withdraw</Translate>
</ButtonPrimary>
{currencyWithNonZeroAmount.length > 0 && (
<MultiActionButton
label={(s) => `Deposit ${s}`}
label={(s) => <Translate>Deposit {s}</Translate>}
actions={currencyWithNonZeroAmount}
onClick={(c) => goToWalletDeposit(c)}
/>
)}
<JustInDevMode>
<ButtonBoxPrimary onClick={goToAddAction}>enter uri</ButtonBoxPrimary>
<ButtonBoxPrimary onClick={goToAddAction}>
<Translate>Enter URI</Translate>
</ButtonBoxPrimary>
</JustInDevMode>
</footer>
</Fragment>

View File

@ -20,6 +20,8 @@ import {
CoinDumpJson,
ExchangeListItem,
NotificationType,
Translate,
i18n,
} from "@gnu-taler/taler-util";
import { PendingTaskInfo } from "@gnu-taler/taler-wallet-core";
import { format } from "date-fns";
@ -31,7 +33,6 @@ import { Time } from "../components/Time";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
import { useDiagnostics } from "../hooks/useDiagnostics";
import * as wxApi from "../wxApi";
import BalanceStories from "./Balance.stories";
export function DeveloperPage(): VNode {
const [status, timedOut] = useDiagnostics();
@ -149,10 +150,16 @@ export function View({
return (
<div>
<p>Debug tools:</p>
<button onClick={confirmReset}>reset</button>
<p>
<Translate>Debug tools</Translate>:
</p>
<button onClick={confirmReset}>
<Translate>reset</Translate>
</button>
<br />
<button onClick={() => fileRef?.current?.click()}>import database</button>
<button onClick={() => fileRef?.current?.click()}>
<Translate>import database</Translate>
</button>
<input
ref={fileRef}
style={{ display: "none" }}
@ -171,9 +178,12 @@ export function View({
}}
/>
<br />
<button onClick={onExportDatabase}>export database</button>
<button onClick={onExportDatabase}>
<Translate>export database</Translate>
</button>
{downloadedDatabase && (
<div>
<Translate>
Database exported at
<Time
timestamp={{ t_ms: downloadedDatabase.time.getTime() }}
@ -188,14 +198,16 @@ export function View({
"yyyy/MM/dd_HH:mm",
)}.json`}
>
{" "}
click here{" "}
<Translate>click here</Translate>
</a>
to download
</Translate>
</div>
)}
<br />
<p>Coins:</p>
<p>
<Translate>Coins</Translate>:
</p>
{Object.keys(money_by_exchange).map((ex) => {
const allcoins = money_by_exchange[ex];
allcoins.sort((a, b) => {
@ -220,7 +232,9 @@ export function View({
<Diagnostics diagnostics={status} timedOut={timedOut} />
{operations && operations.length > 0 && (
<Fragment>
<p>Pending operations</p>
<p>
<Translate>Pending operations</Translate>
</p>
<dl>
{operations.reverse().map((o) => {
return (
@ -257,18 +271,30 @@ function ShowAllCoins({
<b>{ex}</b>: {total} {currencies[ex]}
</p>
<p>
<b>usable coins</b>
<b>
<Translate>usable coins</Translate>
</b>
</p>
{collapsedUnspent ? (
<div onClick={() => setCollapsedUnspent(false)}>click to show</div>
) : (
<table onClick={() => setCollapsedUnspent(true)}>
<tr>
<td>id</td>
<td>denom</td>
<td>value</td>
<td>status</td>
<td>from refresh?</td>
<td>
<Translate>id</Translate>
</td>
<td>
<Translate>denom</Translate>
</td>
<td>
<Translate>value</Translate>
</td>
<td>
<Translate>status</Translate>
</td>
<td>
<Translate>from refresh?</Translate>
</td>
</tr>
{coins.usable.map((c) => {
return (
@ -283,17 +309,31 @@ function ShowAllCoins({
})}
</table>
)}
<p>spent coins</p>
<p>
<Translate>spent coins</Translate>
</p>
{collapsedSpent ? (
<div onClick={() => setCollapsedSpent(false)}>click to show</div>
<div onClick={() => setCollapsedSpent(false)}>
<Translate>click to show</Translate>
</div>
) : (
<table onClick={() => setCollapsedSpent(true)}>
<tr>
<td>id</td>
<td>denom</td>
<td>value</td>
<td>status</td>
<td>refresh?</td>
<td>
<Translate>id</Translate>
</td>
<td>
<Translate>denom</Translate>
</td>
<td>
<Translate>value</Translate>
</td>
<td>
<Translate>status</Translate>
</td>
<td>
<Translate>from refresh?</Translate>
</td>
</tr>
{coins.spent.map((c) => {
return (
@ -335,8 +375,7 @@ function runIntegrationTest() {}
export async function confirmReset(): Promise<void> {
if (
confirm(
"Do you want to IRREVOCABLY DESTROY everything inside your" +
" wallet and LOSE ALL YOUR COINS?",
i18n.str`Do you want to IRREVOCABLY DESTROY everything inside your wallet and LOSE ALL YOUR COINS?`,
)
) {
await wxApi.resetDb();

View File

@ -1,4 +1,4 @@
import { i18n } from "@gnu-taler/taler-util";
import { Translate } from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import { ButtonBoxWarning, WarningBox } from "../components/styled";
@ -11,16 +11,16 @@ export function NoBalanceHelp({
<WarningBox>
<p>
<b>
<i18n.Translate>You have no balance to show.</i18n.Translate>
<Translate>You have no balance to show.</Translate>
</b>
<br />
<i18n.Translate>
<Translate>
To withdraw money you can start from your bank site or click the
"withdraw" button to use a known exchange.
</i18n.Translate>
</Translate>
</p>
<ButtonBoxWarning onClick={() => goToWalletManualWithdraw()}>
Withdraw
<Translate>Withdraw</Translate>
</ButtonBoxWarning>
</WarningBox>
);

View File

@ -19,7 +19,11 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
import {
classifyTalerUri,
TalerUriType,
Translate,
} from "@gnu-taler/taler-util";
import { Fragment, h } from "preact";
import { ButtonPrimary, ButtonSuccess } from "../components/styled";
import { actionForTalerUri } from "../utils/index";
@ -52,46 +56,56 @@ export function TalerActionFound({ url, onDismiss }: Props) {
return (
<Fragment>
<section>
<h1>Taler Action </h1>
<h1>
<Translate>Taler Action</Translate>
</h1>
{uriType === TalerUriType.TalerPay && (
<div>
<p>This page has pay action.</p>
<p>
<Translate>This page has pay action.</Translate>
</p>
<ButtonSuccess
onClick={() => {
navigateTo(actionForTalerUri(uriType, url));
}}
>
Open pay page
<Translate>Open pay page</Translate>
</ButtonSuccess>
</div>
)}
{uriType === TalerUriType.TalerWithdraw && (
<div>
<p>This page has a withdrawal action.</p>
<p>
<Translate>This page has a withdrawal action.</Translate>
</p>
<ButtonSuccess
onClick={() => {
navigateTo(actionForTalerUri(uriType, url));
}}
>
Open withdraw page
<Translate>Open withdraw page</Translate>
</ButtonSuccess>
</div>
)}
{uriType === TalerUriType.TalerTip && (
<div>
<p>This page has a tip action.</p>
<p>
<Translate>This page has a tip action.</Translate>
</p>
<ButtonSuccess
onClick={() => {
navigateTo(actionForTalerUri(uriType, url));
}}
>
Open tip page
<Translate>Open tip page</Translate>
</ButtonSuccess>
</div>
)}
{uriType === TalerUriType.TalerNotifyReserve && (
<div>
<p>This page has a notify reserve action.</p>
<p>
<Translate>This page has a notify reserve action.</Translate>
</p>
<ButtonSuccess
onClick={() => {
navigateTo(actionForTalerUri(uriType, url));
@ -103,26 +117,33 @@ export function TalerActionFound({ url, onDismiss }: Props) {
)}
{uriType === TalerUriType.TalerRefund && (
<div>
<p>This page has a refund action.</p>
<p>
<Translate>This page has a refund action.</Translate>
</p>
<ButtonSuccess
onClick={() => {
navigateTo(actionForTalerUri(uriType, url));
}}
>
Open refund page
<Translate>Open refund page</Translate>
</ButtonSuccess>
</div>
)}
{uriType === TalerUriType.Unknown && (
<div>
<p>This page has a malformed taler uri.</p>
<p>
<Translate>This page has a malformed taler uri.</Translate>
</p>
<p>{url}</p>
</div>
)}
</section>
<footer>
<div />
<ButtonPrimary onClick={() => onDismiss()}> Dismiss </ButtonPrimary>
<ButtonPrimary onClick={() => onDismiss()}>
{" "}
<Translate>Dismiss</Translate>{" "}
</ButtonPrimary>
</footer>
</Fragment>
);

View File

@ -17,10 +17,10 @@
/**
* Main entry point for extension pages.
*
* @author Florian Dold <dold@taler.net>
* @author sebasjm <dold@taler.net>
*/
import { setupI18n } from "@gnu-taler/taler-util";
import { setupI18n, Translate } from "@gnu-taler/taler-util";
import { createHashHistory } from "history";
import { Fragment, h, render, VNode } from "preact";
import Router, { route, Route } from "preact-router";
@ -87,27 +87,20 @@ function Application(): VNode {
<CheckTalerActionComponent />
<PopupBox devMode={devMode}>
<Router history={hash_history}>
<Route path={Pages.dev} component={DeveloperPage} />
<Route
path={Pages.balance}
component={BalancePage}
goToWalletManualWithdraw={() =>
goToWalletPage(
Pages.balance_manual_withdraw.replace(":currency?", ""),
)
route(Pages.balance_manual_withdraw.replace(":currency?", ""))
}
goToWalletDeposit={(currency: string) =>
goToWalletPage(
Pages.balance_deposit.replace(":currency", currency),
)
route(Pages.balance_deposit.replace(":currency", currency))
}
goToWalletHistory={(currency: string) =>
goToWalletPage(
Pages.balance_history.replace(":currency", currency),
)
route(Pages.balance_history.replace(":currency", currency))
}
/>
<Route
path={Pages.cta}
component={function Action({ action }: { action: string }) {
@ -139,21 +132,29 @@ function Application(): VNode {
route(Pages.backup);
}}
/>
<Route
path={Pages.backup_provider_add}
component={ProviderAddPage}
onBack={() => {
route(Pages.backup);
}}
/>
<Route
path={Pages.settings_exchange_add}
component={ExchangeAddPage}
onBack={() => {
route(Pages.balance);
}}
path={Pages.balance_manual_withdraw}
component={RedirectToWalletPage}
/>
<Route
path={Pages.balance_deposit}
component={RedirectToWalletPage}
/>
<Route
path={Pages.balance_history}
component={RedirectToWalletPage}
/>
<Route
path={Pages.backup_provider_add}
component={RedirectToWalletPage}
/>
<Route path={Pages.settings} component={RedirectToWalletPage} />
<Route
path={Pages.settings_exchange_add}
component={RedirectToWalletPage}
/>
<Route path={Pages.dev} component={RedirectToWalletPage} />
<Route default component={Redirect} to={Pages.balance} />
</Router>
@ -165,15 +166,26 @@ function Application(): VNode {
);
}
async function goToWalletPage(page: Pages | string): Promise<void> {
// eslint-disable-next-line no-undef
await chrome.tabs.create({
function RedirectToWalletPage(): VNode {
const page = document.location.hash || "#/";
useEffect(() => {
chrome.tabs
.create({
active: true,
// eslint-disable-next-line no-undef
url: chrome.runtime.getURL(`/static/wallet.html#${page}`),
});
url: chrome.runtime.getURL(`/static/wallet.html${page}`),
})
.then(() => {
window.close();
// return null;
});
});
return (
<span>
<Translate>
this popup is being closed and you are being redirected to {page}
</Translate>
</span>
);
}
function Redirect({ to }: { to: string }): null {

View File

@ -1,4 +1,8 @@
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
import {
classifyTalerUri,
TalerUriType,
Translate,
} from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Button, ButtonSuccess, InputWithLabel } from "../components/styled";
@ -8,20 +12,20 @@ export interface Props {
onCancel: () => void;
}
function buttonLabelByTalerType(type: TalerUriType): string {
function buttonLabelByTalerType(type: TalerUriType): VNode {
switch (type) {
case TalerUriType.TalerNotifyReserve:
return "Open reserve page";
return <Translate>Open reserve page</Translate>;
case TalerUriType.TalerPay:
return "Open pay page";
return <Translate>Open pay page</Translate>;
case TalerUriType.TalerRefund:
return "Open refund page";
return <Translate>Open refund page</Translate>;
case TalerUriType.TalerTip:
return "Open tip page";
return <Translate>Open tip page</Translate>;
case TalerUriType.TalerWithdraw:
return "Open withdraw page";
return <Translate>Open withdraw page</Translate>;
}
return "";
return <Fragment />;
}
export function AddNewActionView({ onCancel }: Props): VNode {
@ -47,7 +51,9 @@ export function AddNewActionView({ onCancel }: Props): VNode {
</InputWithLabel>
</section>
<footer>
<Button onClick={onCancel}>Back</Button>
<Button onClick={onCancel}>
<Translate>Back</Translate>
</Button>
{uriType !== TalerUriType.Unknown && (
<ButtonSuccess
onClick={() => {

View File

@ -14,7 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { i18n, Timestamp } from "@gnu-taler/taler-util";
import { i18n, Timestamp, Translate } from "@gnu-taler/taler-util";
import {
ProviderInfo,
ProviderPaymentPaid,
@ -71,7 +71,10 @@ export function BackupPage({ onAddProvider }: Props): VNode {
}
if (status.hasError) {
return (
<LoadingError title="Could not load backup providers" error={status} />
<LoadingError
title={<Translate>Could not load backup providers</Translate>}
error={status}
/>
);
}
@ -122,9 +125,11 @@ export function BackupView({
))}
{!providers.length && (
<Centered style={{ marginTop: 100 }}>
<BoldLight>No backup providers configured</BoldLight>
<BoldLight>
<Translate>No backup providers configured</Translate>
</BoldLight>
<ButtonSuccess onClick={onAddProvider}>
<i18n.Translate>Add provider</i18n.Translate>
<Translate>Add provider</Translate>
</ButtonSuccess>
</Centered>
)}
@ -135,12 +140,14 @@ export function BackupView({
<div>
<ButtonPrimary onClick={onSyncAll}>
{providers.length > 1 ? (
<i18n.Translate>Sync all backups</i18n.Translate>
<Translate>Sync all backups</Translate>
) : (
<i18n.Translate>Sync now</i18n.Translate>
<Translate>Sync now</Translate>
)}
</ButtonPrimary>
<ButtonSuccess onClick={onAddProvider}>Add provider</ButtonSuccess>
<ButtonSuccess onClick={onAddProvider}>
<Translate>Add provider</Translate>
</ButtonSuccess>
</div>
</footer>
)}
@ -176,10 +183,14 @@ function BackupLayout(props: TransactionLayoutProps): VNode {
</a>
{dateStr && (
<SmallText style={{ marginTop: 5 }}>Last synced: {dateStr}</SmallText>
<SmallText style={{ marginTop: 5 }}>
<Translate>Last synced</Translate>: {dateStr}
</SmallText>
)}
{!dateStr && (
<SmallLightText style={{ marginTop: 5 }}>Not synced</SmallLightText>
<SmallLightText style={{ marginTop: 5 }}>
<Translate>Not synced</Translate>
</SmallLightText>
)}
</div>
<div>
@ -196,7 +207,9 @@ function BackupLayout(props: TransactionLayoutProps): VNode {
function ExpirationText({ until }: { until: Timestamp }): VNode {
return (
<Fragment>
<CenteredText> Expires in </CenteredText>
<CenteredText>
<Translate>Expires in</Translate>
</CenteredText>
<CenteredBoldText {...{ color: colorByTimeToExpire(until) }}>
{" "}
{daysUntil(until)}{" "}

View File

@ -19,7 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
import { AmountJson, Amounts, i18n } from "@gnu-taler/taler-util";
import { AmountJson, Amounts, i18n, Translate } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { ErrorMessage } from "../components/ErrorMessage";
@ -99,16 +99,22 @@ export function CreateManualWithdraw({
if (!initialExchange) {
return (
<section>
<h2>Manual Withdrawal</h2>
<h2>
<Translate>Manual Withdrawal</Translate>
</h2>
<LightText>
Choose a exchange from where the coins will be withdrawn. The exchange
will send the coins to this wallet after receiving a wire transfer
with the correct subject.
<Translate>
Choose a exchange from where the coins will be withdrawn. The
exchange will send the coins to this wallet after receiving a wire
transfer with the correct subject.
</Translate>
</LightText>
<Centered style={{ marginTop: 100 }}>
<BoldLight>No exchange configured</BoldLight>
<BoldLight>
<Translate>No exchange configured</Translate>
</BoldLight>
<ButtonSuccess onClick={onAddExchange}>
<i18n.Translate>Add exchange</i18n.Translate>
<Translate>Add exchange</Translate>
</ButtonSuccess>
</Centered>
</section>
@ -118,20 +124,26 @@ export function CreateManualWithdraw({
return (
<Fragment>
<section>
{error && (
<ErrorMessage
title={error && "Can't create the reserve"}
title={<Translate>Can't create the reserve</Translate>}
description={error}
/>
<h2>Manual Withdrawal</h2>
)}
<h2>
<Translate>Manual Withdrawal</Translate>
</h2>
<LightText>
Choose a exchange from where the coins will be withdrawn. The exchange
will send the coins to this wallet after receiving a wire transfer
with the correct subject.
<Translate>
Choose a exchange from where the coins will be withdrawn. The
exchange will send the coins to this wallet after receiving a wire
transfer with the correct subject.
</Translate>
</LightText>
<p>
<Input>
<SelectList
label="Currency"
label={<Translate>Currency</Translate>}
list={currencyMap}
name="currency"
value={currency}
@ -140,7 +152,7 @@ export function CreateManualWithdraw({
</Input>
<Input>
<SelectList
label="Exchange"
label={<Translate>Exchange</Translate>}
list={exchangeMap}
name="currency"
value={exchange}
@ -149,12 +161,14 @@ export function CreateManualWithdraw({
</Input>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<LinkPrimary onClick={onAddExchange} style={{ marginLeft: "auto" }}>
<i18n.Translate>Add exchange</i18n.Translate>
<Translate>Add Exchange</Translate>
</LinkPrimary>
</div>
{currency && (
<InputWithLabel invalid={!!amount && !parsedAmount}>
<label>Amount</label>
<label>
<Translate>Amount</Translate>
</label>
<div>
<span>{currency}</span>
<input
@ -173,7 +187,7 @@ export function CreateManualWithdraw({
disabled={!parsedAmount || !exchange}
onClick={() => onCreate(exchange, parsedAmount!)}
>
Start withdrawal
<Translate>Start withdrawal</Translate>
</ButtonPrimary>
</footer>
</Fragment>

View File

@ -19,6 +19,7 @@ import {
Amounts,
AmountString,
PaytoUri,
Translate,
} from "@gnu-taler/taler-util";
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
import { Fragment, h, VNode } from "preact";
@ -132,13 +133,21 @@ export function View({
}, [amount]);
if (!balance) {
return <div>no balance</div>;
return (
<div>
<Translate>no balance</Translate>
</div>
);
}
if (!knownBankAccounts || !knownBankAccounts.length) {
return (
<WarningBox>
<p>There is no known bank account to send money to</p>
<ButtonBoxWarning>Withdraw</ButtonBoxWarning>
<p>
<Translate>There is no known bank account to send money to</Translate>
</p>
<ButtonBoxWarning>
<Translate>Withdraw</Translate>
</ButtonBoxWarning>
</WarningBox>
);
}
@ -162,11 +171,13 @@ export function View({
return (
<Fragment>
<h2>Send {currency} to your account</h2>
<h2>
<Translate>Send {currency} to your account</Translate>
</h2>
<section>
<Input>
<SelectList
label="Bank account IBAN number"
label={<Translate>Bank account IBAN number</Translate>}
list={accountMap}
name="account"
value={String(accountIdx)}
@ -174,7 +185,9 @@ export function View({
/>
</Input>
<InputWithLabel invalid={!!error}>
<label>Amount</label>
<label>
<Translate>Amount</Translate>
</label>
<div>
<span>{currency}</span>
<input
@ -196,7 +209,9 @@ export function View({
{
<Fragment>
<InputWithLabel>
<label>Deposit fee</label>
<label>
<Translate>Deposit fee</Translate>
</label>
<div>
<span>{currency}</span>
<input
@ -208,7 +223,9 @@ export function View({
</InputWithLabel>
<InputWithLabel>
<label>Total deposit</label>
<label>
<Translate>Total deposit</Translate>
</label>
<div>
<span>{currency}</span>
<input
@ -224,10 +241,14 @@ export function View({
<footer>
<div />
{unableToDeposit ? (
<ButtonPrimary disabled>Deposit</ButtonPrimary>
<ButtonPrimary disabled>
<Translate>Deposit</Translate>
</ButtonPrimary>
) : (
<ButtonPrimary onClick={() => onSend(accountURI, amountStr)}>
<Translate>
Deposit {Amounts.stringifyValue(totalToDeposit)} {currency}
</Translate>
</ButtonPrimary>
)}
</footer>

View File

@ -1,4 +1,4 @@
import { i18n } from "@gnu-taler/taler-util";
import { i18n, Translate } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Button, ButtonSuccess, ButtonWarning } from "../components/styled";
@ -84,9 +84,11 @@ export function View({
return (
<Fragment>
<section>
<h1>Review terms of service</h1>
<h1>
<Translate>Review terms of service</Translate>
</h1>
<div>
Exchange URL:
<Translate>Exchange URL</Translate>:
<a href={url} target="_blank" rel="noreferrer">
{url}
</a>
@ -107,28 +109,28 @@ export function View({
<footer>
<Button onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate>
<Translate>Cancel</Translate>
</Button>
{!terms && (
<Button disabled>
<i18n.Translate>Loading terms..</i18n.Translate>
<Translate>Loading terms..</Translate>
</Button>
)}
{terms && (
<Fragment>
{needsReview && !reviewed && (
<ButtonSuccess disabled upperCased onClick={onConfirm}>
{i18n.str`Add exchange`}
<Translate>Add exchange</Translate>
</ButtonSuccess>
)}
{(terms.status === "accepted" || (needsReview && reviewed)) && (
<ButtonSuccess upperCased onClick={onConfirm}>
{i18n.str`Add exchange`}
<Translate>Add exchange</Translate>
</ButtonSuccess>
)}
{terms.status === "notfound" && (
<ButtonWarning upperCased onClick={onConfirm}>
{i18n.str`Add exchange anyway`}
<Translate>Add exchange anyway</Translate>
</ButtonWarning>
)}
</Fragment>

View File

@ -2,6 +2,7 @@ import {
canonicalizeBaseUrl,
i18n,
TalerConfigResponse,
Translate,
} from "@gnu-taler/taler-util";
import { Fragment, h } from "preact";
import { useEffect, useState } from "preact/hooks";
@ -91,32 +92,46 @@ export function ExchangeSetUrlPage({
<Fragment>
<section>
{!expectedCurrency ? (
<h1>Add new exchange</h1>
<h1>
<Translate>Add new exchange</Translate>
</h1>
) : (
<h2>Add exchange for {expectedCurrency}</h2>
<h2>
<Translate>Add exchange for {expectedCurrency}</Translate>
</h2>
)}
{!result && (
<LightText>Enter the URL of an exchange you trust.</LightText>
<LightText>
<Translate>Enter the URL of an exchange you trust.</Translate>
</LightText>
)}
{result && (
<LightText>
<Translate>
An exchange has been found! Review the information and click next
</Translate>
</LightText>
)}
{result && expectedCurrency && expectedCurrency !== result.currency && (
<WarningBox>
This exchange doesn't match the expected currency{" "}
<Translate>
This exchange doesn't match the expected currency
<b>{expectedCurrency}</b>
</Translate>
</WarningBox>
)}
{error && (
<ErrorMessage
title={error && "Unable to add this exchange"}
title={<Translate>Unable to verify this exchange</Translate>}
description={error}
/>
)}
{confirmationError && (
<ErrorMessage
title={confirmationError && "Unable to add this exchange"}
title={<Translate>Unable to add this exchange</Translate>}
description={confirmationError}
/>
)}
<p>
<Input invalid={!!error}>
<label>URL</label>
@ -127,15 +142,23 @@ export function ExchangeSetUrlPage({
onInput={(e) => updateEndpoint(e.currentTarget.value)}
/>
</Input>
{loading && <div>loading... </div>}
{loading && (
<div>
<Translate>loading</Translate>...
</div>
)}
{result && !loading && (
<Fragment>
<Input>
<label>Version</label>
<label>
<Translate>Version</Translate>
</label>
<input type="text" disabled value={result.version} />
</Input>
<Input>
<label>Currency</label>
<label>
<Translate>Currency</Translate>
</label>
<input type="text" disabled value={result.currency} />
</Input>
</Fragment>
@ -144,7 +167,7 @@ export function ExchangeSetUrlPage({
</section>
<footer>
<Button onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate>
<Translate>Cancel</Translate>
</Button>
<ButtonPrimary
disabled={
@ -160,7 +183,7 @@ export function ExchangeSetUrlPage({
);
}}
>
<i18n.Translate>Next</i18n.Translate>
<Translate>Next</Translate>
</ButtonPrimary>
</footer>
</Fragment>

View File

@ -19,6 +19,7 @@ import {
Balance,
NotificationType,
Transaction,
Translate,
} from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
@ -66,7 +67,7 @@ export function HistoryPage({
if (transactionQuery.hasError) {
return (
<LoadingError
title="Could not load the list of transactions"
title={<Translate>Could not load the list of transactions</Translate>}
error={transactionQuery}
/>
);
@ -193,21 +194,23 @@ export function HistoryView({
style={{ marginLeft: 0, marginTop: 8 }}
onClick={() => goToWalletManualWithdraw(selectedCurrency)}
>
Withdraw
<Translate>Withdraw</Translate>
</ButtonPrimary>
{currencyAmount && Amounts.isNonZero(currencyAmount) && (
<ButtonBoxPrimary
style={{ marginLeft: 0, marginTop: 8 }}
onClick={() => goToWalletDeposit(selectedCurrency)}
>
Deposit
<Translate>Deposit</Translate>
</ButtonBoxPrimary>
)}
</div>
</div>
</section>
{datesWithTransaction.length === 0 ? (
<section>There is no history for this currency</section>
<section>
<Translate>There is no history for this currency</Translate>
</section>
) : (
<section>
{datesWithTransaction.map((d, i) => {

View File

@ -19,6 +19,7 @@ import {
AmountJson,
Amounts,
NotificationType,
Translate,
} from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
@ -95,7 +96,9 @@ export function ManualWithdrawPage({ currency, onCancel }: Props): VNode {
if (state.hasError) {
return (
<LoadingError
title="Could not load the list of known exchanges"
title={
<Translate>Could not load the list of known exchanges</Translate>
}
error={state}
/>
);

View File

@ -19,6 +19,7 @@ import {
BackupBackupProviderTerms,
canonicalizeBaseUrl,
i18n,
Translate,
} from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
@ -113,15 +114,23 @@ export function SetUrlView({
return (
<Fragment>
<section>
<h1> Add backup provider</h1>
<h1>
<Translate>Add backup provider</Translate>
</h1>
{error && (
<ErrorMessage
title={error && "Could not get provider information"}
title={<Translate>Could not get provider information</Translate>}
description={error}
/>
<LightText> Backup providers may charge for their service</LightText>
)}
<LightText>
<Translate>Backup providers may charge for their service</Translate>
</LightText>
<p>
<Input invalid={urlError}>
<label>URL</label>
<label>
<Translate>URL</Translate>
</label>
<input
type="text"
placeholder="https://"
@ -130,7 +139,9 @@ export function SetUrlView({
/>
</Input>
<Input>
<label>Name</label>
<label>
<Translate>Name</Translate>
</label>
<input
type="text"
disabled={name === undefined}
@ -142,7 +153,7 @@ export function SetUrlView({
</section>
<footer>
<Button onClick={onCancel}>
<i18n.Translate> &lt; Back</i18n.Translate>
&lt; <Translate>Back</Translate>
</Button>
<ButtonPrimary
disabled={!value && !urlError}
@ -153,7 +164,7 @@ export function SetUrlView({
);
}}
>
<i18n.Translate>Next</i18n.Translate>
<Translate>Next</Translate>
</ButtonPrimary>
</footer>
</Fragment>
@ -177,29 +188,41 @@ export function ConfirmProviderView({
return (
<Fragment>
<section>
<h1>Review terms of service</h1>
<h1>
<Translate>Review terms of service</Translate>
</h1>
<div>
Provider URL:{" "}
<Translate>Provider URL</Translate>:{" "}
<a href={url} target="_blank">
{url}
</a>
</div>
<SmallLightText>
<Translate>
Please review and accept this provider's terms of service
</Translate>
</SmallLightText>
<h2>1. Pricing</h2>
<h2>
1. <Translate>Pricing</Translate>
</h2>
<p>
{Amounts.isZero(provider.annual_fee)
? "free of charge"
: `${provider.annual_fee} per year of service`}
{Amounts.isZero(provider.annual_fee) ? (
<Translate>free of charge</Translate>
) : (
<Translate>{provider.annual_fee} per year of service</Translate>
)}
</p>
<h2>2. Storage</h2>
<h2>
2. <Translate>Storage</Translate>
</h2>
<p>
{provider.storage_limit_in_megabytes} megabytes of storage per year of
service
<Translate>
{provider.storage_limit_in_megabytes} megabytes of storage per year
of service
</Translate>
</p>
<Checkbox
label="Accept terms of service"
label={<Translate>Accept terms of service</Translate>}
name="terms"
onToggle={() => setAccepted((old) => !old)}
enabled={accepted}
@ -207,10 +230,10 @@ export function ConfirmProviderView({
</section>
<footer>
<Button onClick={onCancel}>
<i18n.Translate> &lt; Back</i18n.Translate>
&lt; <Translate>Back</Translate>
</Button>
<ButtonPrimary disabled={!accepted} onClick={onConfirm}>
<i18n.Translate>Add provider</i18n.Translate>
<Translate>Add provider</Translate>
</ButtonPrimary>
</footer>
</Fragment>

View File

@ -14,7 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { i18n } from "@gnu-taler/taler-util";
import { Translate } from "@gnu-taler/taler-util";
import {
ProviderInfo,
ProviderPaymentStatus,
@ -22,6 +22,8 @@ import {
} from "@gnu-taler/taler-wallet-core";
import { Fragment, h, VNode } from "preact";
import { ErrorMessage } from "../components/ErrorMessage";
import { Loading } from "../components/Loading";
import { LoadingError } from "../components/LoadingError";
import {
Button,
ButtonDestructive,
@ -52,35 +54,24 @@ export function ProviderDetailPage({ pid: providerURL, onBack }: Props): VNode {
const state = useAsyncAsHook(getProviderInfo);
if (!state) {
return (
<div>
<i18n.Translate>Loading...</i18n.Translate>
</div>
);
return <Loading />;
}
if (state.hasError) {
return (
<div>
<i18n.Translate>
<LoadingError
title={
<Translate>
There was an error loading the provider detail for "{providerURL}"
</i18n.Translate>
</div>
</Translate>
}
error={state}
/>
);
}
if (state.response === null) {
onBack();
return (
<div>
<i18n.Translate>
There is not known provider with url "{providerURL}". Redirecting
back...
</i18n.Translate>
</div>
);
}
return (
<ProviderView
url={providerURL}
info={state.response}
onSync={async () => wxApi.syncOneProvider(providerURL)}
onDelete={async () => wxApi.removeProvider(providerURL).then(onBack)}
@ -93,7 +84,8 @@ export function ProviderDetailPage({ pid: providerURL, onBack }: Props): VNode {
}
export interface ViewProps {
info: ProviderInfo;
url: string;
info: ProviderInfo | null;
onDelete: () => void;
onSync: () => void;
onBack: () => void;
@ -102,12 +94,30 @@ export interface ViewProps {
export function ProviderView({
info,
url,
onDelete,
onSync,
onBack,
onExtend,
}: ViewProps): VNode {
const lb = info?.lastSuccessfulBackupTimestamp;
if (info === null) {
return (
<Fragment>
<section>
<p>
<Translate>There is not known provider with url "{url}".</Translate>
</p>
</section>
<footer>
<Button onClick={onBack}>
&lt; <Translate>Back</Translate>
</Button>
<div />
</footer>
</Fragment>
);
}
const lb = info.lastSuccessfulBackupTimestamp;
const isPaid =
info.paymentStatus.type === ProviderPaymentType.Paid ||
info.paymentStatus.type === ProviderPaymentType.TermsChanged;
@ -125,48 +135,55 @@ export function ProviderView({
</header>
<section>
<p>
<b>Last backup:</b> <Time timestamp={lb} format="dd MMMM yyyy" />
<b>
<Translate>Last backup</Translate>:
</b>{" "}
<Time timestamp={lb} format="dd MMMM yyyy" />
</p>
<ButtonPrimary onClick={onSync}>
<i18n.Translate>Back up</i18n.Translate>
<Translate>Back up</Translate>
</ButtonPrimary>
{info.terms && (
<Fragment>
<p>
<b>Provider fee:</b> {info.terms && info.terms.annualFee} per year
<b>
<Translate>Provider fee</Translate>:
</b>{" "}
{info.terms && info.terms.annualFee}{" "}
<Translate>per year</Translate>
</p>
</Fragment>
)}
<p>{descriptionByStatus(info.paymentStatus)}</p>
<ButtonPrimary disabled onClick={onExtend}>
<i18n.Translate>Extend</i18n.Translate>
<Translate>Extend</Translate>
</ButtonPrimary>
{info.paymentStatus.type === ProviderPaymentType.TermsChanged && (
<div>
<p>
<i18n.Translate>
<Translate>
terms has changed, extending the service will imply accepting
the new terms of service
</i18n.Translate>
</Translate>
</p>
<table>
<thead>
<tr>
<td>&nbsp;</td>
<td>
<i18n.Translate>old</i18n.Translate>
<Translate>old</Translate>
</td>
<td> -&gt;</td>
<td>
<i18n.Translate>new</i18n.Translate>
<Translate>new</Translate>
</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<i18n.Translate>fee</i18n.Translate>
<Translate>fee</Translate>
</td>
<td>{info.paymentStatus.oldTerms.annualFee}</td>
<td>-&gt;</td>
@ -174,7 +191,7 @@ export function ProviderView({
</tr>
<tr>
<td>
<i18n.Translate>storage</i18n.Translate>
<Translate>storage</Translate>
</td>
<td>{info.paymentStatus.oldTerms.storageLimitInMegabytes}</td>
<td>-&gt;</td>
@ -187,11 +204,11 @@ export function ProviderView({
</section>
<footer>
<Button onClick={onBack}>
<i18n.Translate> &lt; back</i18n.Translate>
&lt; <Translate>back</Translate>
</Button>
<div>
<ButtonDestructive onClick={onDelete}>
<i18n.Translate>remove provider</i18n.Translate>
<Translate>Remove provider</Translate>
</ButtonDestructive>
</div>
</footer>
@ -201,7 +218,12 @@ export function ProviderView({
function Error({ info }: { info: ProviderInfo }): VNode {
if (info.lastError) {
return <ErrorMessage title={info.lastError.hint} />;
return (
<ErrorMessage
title={<Translate>This provider has reported an error</Translate>}
description={info.lastError.hint}
/>
);
}
if (info.backupProblem) {
switch (info.backupProblem.type) {
@ -210,24 +232,26 @@ function Error({ info }: { info: ProviderInfo }): VNode {
<ErrorMessage
title={
<Fragment>
<i18n.Translate>
<Translate>
There is conflict with another backup from{" "}
<b>{info.backupProblem.otherDeviceId}</b>
</i18n.Translate>
</Translate>
</Fragment>
}
/>
);
case "backup-unreadable":
return <ErrorMessage title="Backup is not readable" />;
return (
<ErrorMessage title={<Translate>Backup is not readable</Translate>} />
);
default:
return (
<ErrorMessage
title={
<Fragment>
<i18n.Translate>
<Translate>
Unknown backup problem: {JSON.stringify(info.backupProblem)}
</i18n.Translate>
</Translate>
</Fragment>
}
/>
@ -239,16 +263,20 @@ function Error({ info }: { info: ProviderInfo }): VNode {
function descriptionByStatus(status: ProviderPaymentStatus): VNode {
switch (status.type) {
// return i18n.str`no enough balance to make the payment`
// return i18n.str`not paid yet`
case ProviderPaymentType.Paid:
case ProviderPaymentType.TermsChanged:
if (status.paidUntil.t_ms === "never") {
return <span>{i18n.str`service paid`}</span>;
return (
<span>
<Translate>service paid</Translate>
</span>
);
}
return (
<Fragment>
<b>Backup valid until:</b>{" "}
<b>
<Translate>Backup valid until</Translate>:
</b>{" "}
<Time timestamp={status.paidUntil} format="dd MMM yyyy" />
</Fragment>
);

View File

@ -1,4 +1,9 @@
import { AmountJson, Amounts, parsePaytoUri } from "@gnu-taler/taler-util";
import {
AmountJson,
Amounts,
parsePaytoUri,
Translate,
} from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType";
import { QR } from "../components/QR";
@ -22,15 +27,23 @@ export function ReserveCreated({
const paytoURI = parsePaytoUri(payto);
// const url = new URL(paytoURI?.targetPath);
if (!paytoURI) {
return <div>could not parse payto uri from exchange {payto}</div>;
return (
<div>
<Translate>could not parse payto uri from exchange {payto}</Translate>
</div>
);
}
return (
<Fragment>
<section>
<h1>Exchange is ready for withdrawal!</h1>
<h1>
<Translate>Exchange is ready for withdrawal</Translate>
</h1>
<p>
To complete the process you need to wire{" "}
<Translate>
To complete the process you need to wire
<b>{amountToString(amount)}</b> to the exchange bank account
</Translate>
</p>
<BankDetailsByPaytoType
amount={amountToString(amount)}
@ -40,23 +53,27 @@ export function ReserveCreated({
/>
<p>
<WarningBox>
<Translate>
Make sure to use the correct subject, otherwise the money will not
arrive in this wallet.
</Translate>
</WarningBox>
</p>
</section>
<section>
<p>
Alternative, you can also scan this QR code or open{" "}
<a href={payto}>this link</a> if you have a banking app installed that
supports RFC 8905
<Translate>
Alternative, you can also scan this QR code or open
<a href={payto}>this link</a> if you have a banking app installed
that supports RFC 8905
</Translate>
</p>
<QR text={payto} />
</section>
<footer>
<div />
<ButtonDestructive onClick={onCancel}>
Cancel withdrawal
<Translate>Cancel withdrawal</Translate>
</ButtonDestructive>
</footer>
</Fragment>

View File

@ -14,7 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { ExchangeListItem, i18n } from "@gnu-taler/taler-util";
import { ExchangeListItem, i18n, Translate } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { Checkbox } from "../components/Checkbox";
import {
@ -81,29 +81,46 @@ export function SettingsView({
<Fragment>
<section>
<h2>
<i18n.Translate>Permissions</i18n.Translate>
<Translate>Permissions</Translate>
</h2>
<Checkbox
label="Automatically open wallet based on page content"
label={
<Translate>
Automatically open wallet based on page content
</Translate>
}
name="perm"
description="(Enabling this option below will make using the wallet faster, but requires more permissions from your browser.)"
description={
<Translate>
Enabling this option below will make using the wallet faster, but
requires more permissions from your browser.
</Translate>
}
enabled={permissionsEnabled}
onToggle={togglePermissions}
/>
<h2>
<i18n.Translate>Known exchanges</i18n.Translate>
<Translate>Known exchanges</Translate>
</h2>
{!knownExchanges || !knownExchanges.length ? (
<div>No exchange yet!</div>
<div>
<Translate>No exchange yet</Translate>
</div>
) : (
<Fragment>
<table>
<thead>
<tr>
<th>currency</th>
<th>url</th>
<th>term of service</th>
<th>
<Translate>Currency</Translate>
</th>
<th>
<Translate>URL</Translate>
</th>
<th>
<Translate>Term of Service</Translate>
</th>
</tr>
</thead>
<tbody>
@ -116,12 +133,24 @@ export function SettingsView({
);
switch (status) {
case "accepted":
return <SuccessText>ok</SuccessText>;
return (
<SuccessText>
<Translate>ok</Translate>
</SuccessText>
);
case "changed":
return <WarningText>changed!</WarningText>;
return (
<WarningText>
<Translate>changed</Translate>
</WarningText>
);
case "new":
case "notfound":
return <DestructiveText>not accepted</DestructiveText>;
return (
<DestructiveText>
<Translate>not accepted</Translate>
</DestructiveText>
);
}
}
return (
@ -143,15 +172,19 @@ export function SettingsView({
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div />
<LinkPrimary href={Pages.settings_exchange_add}>
Add an exchange
<Translate>Add an exchange</Translate>
</LinkPrimary>
</div>
<h2>Config</h2>
<Checkbox
label="Developer mode"
label={<Translate>Developer mode</Translate>}
name="devMode"
description="(More options and information useful for debugging)"
description={
<Translate>
(More options and information useful for debugging)
</Translate>
}
enabled={developerMode}
onToggle={toggleDeveloperMode}
/>

View File

@ -22,6 +22,7 @@ import {
parsePaytoUri,
Transaction,
TransactionType,
Translate,
WithdrawalType,
} from "@gnu-taler/taler-util";
import { differenceInSeconds } from "date-fns";
@ -47,7 +48,6 @@ import {
} from "../components/styled";
import { Time } from "../components/Time";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
import { Pages } from "../NavigationBar";
import * as wxApi from "../wxApi";
interface Props {
@ -76,7 +76,9 @@ export function TransactionPage({ tid, goToWalletHistory }: Props): VNode {
if (state.hasError) {
return (
<LoadingError
title="Could not load the transaction information"
title={
<Translate>Could not load the transaction information</Translate>
}
error={state}
/>
);
@ -139,11 +141,17 @@ export function TransactionView({
<Fragment>
<section style={{ padding: 8, textAlign: "center" }}>
<ErrorTalerOperation
title="There was an error trying to complete the transaction"
title={
<Translate>
There was an error trying to complete the transaction
</Translate>
}
error={transaction?.error}
/>
{transaction.pending && (
<WarningBox>This transaction is not completed</WarningBox>
<WarningBox>
<Translate>This transaction is not completed</Translate>
</WarningBox>
)}
</section>
<section>
@ -151,16 +159,16 @@ export function TransactionView({
</section>
<footer>
<Button onClick={onBack}>
<i18n.Translate> &lt; Back </i18n.Translate>
&lt; <Translate> Back </Translate>
</Button>
<div>
{showRetry ? (
<ButtonPrimary onClick={onRetry}>
<i18n.Translate>retry</i18n.Translate>
<Translate>Retry</Translate>
</ButtonPrimary>
) : null}
<ButtonDestructive onClick={doCheckBeforeForget}>
<i18n.Translate> Forget </i18n.Translate>
<Translate>Forget</Translate>
</ButtonDestructive>
</div>
</footer>
@ -184,24 +192,30 @@ export function TransactionView({
{confirmBeforeForget ? (
<Overlay>
<CenteredDialog>
<header>Caution!</header>
<header>
<Translate>Caution!</Translate>
</header>
<section>
<Translate>
If you have already wired money to the exchange you will loose
the chance to get the coins form it.
</Translate>
</section>
<footer>
<Button onClick={() => setConfirmBeforeForget(false)}>
<i18n.Translate> Cancel </i18n.Translate>
<Translate>Cancel</Translate>
</Button>
<ButtonDestructive onClick={onDelete}>
<i18n.Translate> Confirm </i18n.Translate>
<Translate>Confirm</Translate>
</ButtonDestructive>
</footer>
</CenteredDialog>
</Overlay>
) : undefined}
<h2>Withdrawal</h2>
<h2>
<Translate>Withdrawal</Translate>
</h2>
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
{transaction.pending ? (
transaction.withdrawalDetails.type ===
@ -217,19 +231,21 @@ export function TransactionView({
/>
<p>
<WarningBox>
Make sure to use the correct subject, otherwise the money will
not arrive in this wallet.
<Translate>
Make sure to use the correct subject, otherwise the money
will not arrive in this wallet.
</Translate>
</WarningBox>
</p>
<Part
big
title="Total withdrawn"
title={<Translate>Total withdrawn</Translate>}
text={amountToString(transaction.amountEffective)}
kind="positive"
/>
<Part
big
title="Exchange fee"
title={<Translate>Exchange fee</Translate>}
text={amountToString(fee)}
kind="negative"
/>
@ -239,34 +255,38 @@ export function TransactionView({
{!transaction.withdrawalDetails.confirmed &&
transaction.withdrawalDetails.bankConfirmationUrl ? (
<InfoBox>
<Translate>
The bank is waiting for confirmation. Go to the
<a
href={transaction.withdrawalDetails.bankConfirmationUrl}
target="_blank"
rel="noreferrer"
>
bank site
<Translate>bank site</Translate>
</a>
</Translate>
</InfoBox>
) : undefined}
{transaction.withdrawalDetails.confirmed && (
<InfoBox>Waiting for the coins to arrive</InfoBox>
<InfoBox>
<Translate>Waiting for the coins to arrive</Translate>
</InfoBox>
)}
<Part
big
title="Total withdrawn"
title={<Translate>Total withdrawn</Translate>}
text={amountToString(transaction.amountEffective)}
kind="positive"
/>
<Part
big
title="Chosen amount"
title={<Translate>Chosen amount</Translate>}
text={amountToString(transaction.amountRaw)}
kind="neutral"
/>
<Part
big
title="Exchange fee"
title={<Translate>Exchange fee</Translate>}
text={amountToString(fee)}
kind="negative"
/>
@ -276,26 +296,26 @@ export function TransactionView({
<Fragment>
<Part
big
title="Total withdrawn"
title={<Translate>Total withdrawn</Translate>}
text={amountToString(transaction.amountEffective)}
kind="positive"
/>
<Part
big
title="Chosen amount"
title={<Translate>Chosen amount</Translate>}
text={amountToString(transaction.amountRaw)}
kind="neutral"
/>
<Part
big
title="Exchange fee"
title={<Translate>Exchange fee</Translate>}
text={amountToString(fee)}
kind="negative"
/>
</Fragment>
)}
<Part
title="Exchange"
title={<Translate>Exchange</Translate>}
text={new URL(transaction.exchangeBaseUrl).hostname}
kind="neutral"
/>
@ -315,30 +335,41 @@ export function TransactionView({
return (
<TransactionTemplate>
<h2>Payment </h2>
<h2>
<Translate>Payment</Translate>
</h2>
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
<br />
<Part
big
title="Total paid"
title={<Translate>Total paid</Translate>}
text={amountToString(transaction.amountEffective)}
kind="negative"
/>
<Part
big
title="Purchase amount"
title={<Translate>Purchase amount</Translate>}
text={amountToString(transaction.amountRaw)}
kind="neutral"
/>
<Part big title="Fee" text={amountToString(fee)} kind="negative" />
<Part
title="Merchant"
big
title={<Translate>Fee</Translate>}
text={amountToString(fee)}
kind="negative"
/>
<Part
title={<Translate>Merchant</Translate>}
text={transaction.info.merchant.name}
kind="neutral"
/>
<Part title="Purchase" text={transaction.info.summary} kind="neutral" />
<Part
title="Receipt"
title={<Translate>Purchase</Translate>}
text={transaction.info.summary}
kind="neutral"
/>
<Part
title={<Translate>Receipt</Translate>}
text={`#${transaction.info.orderId}`}
kind="neutral"
/>
@ -375,22 +406,29 @@ export function TransactionView({
).amount;
return (
<TransactionTemplate>
<h2>Deposit </h2>
<h2>
<Translate>Deposit</Translate>
</h2>
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
<br />
<Part
big
title="Total send"
title={<Translate>Total send</Translate>}
text={amountToString(transaction.amountEffective)}
kind="neutral"
/>
<Part
big
title="Deposit amount"
title={<Translate>Deposit amount</Translate>}
text={amountToString(transaction.amountRaw)}
kind="positive"
/>
<Part big title="Fee" text={amountToString(fee)} kind="negative" />
<Part
big
title={<Translate>Fee</Translate>}
text={amountToString(fee)}
kind="negative"
/>
</TransactionTemplate>
);
}
@ -402,22 +440,29 @@ export function TransactionView({
).amount;
return (
<TransactionTemplate>
<h2>Refresh</h2>
<h2>
<Translate>Refresh</Translate>
</h2>
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
<br />
<Part
big
title="Total refresh"
title={<Translate>Total refresh</Translate>}
text={amountToString(transaction.amountEffective)}
kind="negative"
/>
<Part
big
title="Refresh amount"
title={<Translate>Refresh amount</Translate>}
text={amountToString(transaction.amountRaw)}
kind="neutral"
/>
<Part big title="Fee" text={amountToString(fee)} kind="negative" />
<Part
big
title={<Translate>Fee</Translate>}
text={amountToString(fee)}
kind="negative"
/>
</TransactionTemplate>
);
}
@ -429,22 +474,29 @@ export function TransactionView({
).amount;
return (
<TransactionTemplate>
<h2>Tip</h2>
<h2>
<Translate>Tip</Translate>
</h2>
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
<br />
<Part
big
title="Total tip"
title={<Translate>Total tip</Translate>}
text={amountToString(transaction.amountEffective)}
kind="positive"
/>
<Part
big
title="Received amount"
title={<Translate>Received amount</Translate>}
text={amountToString(transaction.amountRaw)}
kind="neutral"
/>
<Part big title="Fee" text={amountToString(fee)} kind="negative" />
<Part
big
title={<Translate>Fee</Translate>}
text={amountToString(fee)}
kind="negative"
/>
</TransactionTemplate>
);
}
@ -456,30 +508,41 @@ export function TransactionView({
).amount;
return (
<TransactionTemplate>
<h2>Refund</h2>
<h2>
<Translate>Refund</Translate>
</h2>
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
<br />
<Part
big
title="Total refund"
title={<Translate>Total refund</Translate>}
text={amountToString(transaction.amountEffective)}
kind="positive"
/>
<Part
big
title="Refund amount"
title={<Translate>Refund amount</Translate>}
text={amountToString(transaction.amountRaw)}
kind="neutral"
/>
<Part big title="Fee" text={amountToString(fee)} kind="negative" />
<Part
title="Merchant"
big
title={<Translate>Fee</Translate>}
text={amountToString(fee)}
kind="negative"
/>
<Part
title={<Translate>Merchant</Translate>}
text={transaction.info.merchant.name}
kind="neutral"
/>
<Part title="Purchase" text={transaction.info.summary} kind="neutral" />
<Part
title="Receipt"
title={<Translate>Purchase</Translate>}
text={transaction.info.summary}
kind="neutral"
/>
<Part
title={<Translate>Receipt</Translate>}
text={`#${transaction.info.orderId}`}
kind="neutral"
/>

View File

@ -17,10 +17,10 @@
/**
* Welcome page, shown on first installs.
*
* @author Florian Dold
* @author sebasjm
*/
import { WalletDiagnostics } from "@gnu-taler/taler-util";
import { Translate, WalletDiagnostics } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { Checkbox } from "../components/Checkbox";
import { Diagnostics } from "../components/Diagnostics";
@ -54,24 +54,41 @@ export function View({
}: ViewProps): VNode {
return (
<Fragment>
<h1>Browser Extension Installed!</h1>
<h1>
<Translate>Browser Extension Installed!</Translate>
</h1>
<div>
<p>Thank you for installing the wallet.</p>
<p>
<Translate>Thank you for installing the wallet.</Translate>
</p>
<Diagnostics diagnostics={diagnostics} timedOut={timedOut} />
<h2>Permissions</h2>
<h2>
<Translate>Permissions</Translate>
</h2>
<Checkbox
label="Automatically open wallet based on page content"
label={
<Translate>
Automatically open wallet based on page content
</Translate>
}
name="perm"
description="(Enabling this option below will make using the wallet faster, but requires more permissions from your browser.)"
description={
<Translate>
(Enabling this option below will make using the wallet faster, but
requires more permissions from your browser.)
</Translate>
}
enabled={permissionsEnabled}
onToggle={togglePermissions}
/>
<h2>Next Steps</h2>
<h2>
<Translate>Next Steps</Translate>
</h2>
<a href="https://demo.taler.net/" style={{ display: "block" }}>
Try the demo »
<Translate>Try the demo</Translate> »
</a>
<a href="https://demo.taler.net/" style={{ display: "block" }}>
Learn how to top up your wallet balance »
<Translate>Learn how to top up your wallet balance</Translate> »
</a>
</div>
</Fragment>

View File

@ -17,10 +17,10 @@
/**
* Main entry point for extension pages.
*
* @author Florian Dold <dold@taler.net>
* @author sebasjm <dold@taler.net>
*/
import { i18n, setupI18n } from "@gnu-taler/taler-util";
import { i18n, setupI18n, Translate } from "@gnu-taler/taler-util";
import { createHashHistory } from "history";
import { Fragment, h, render, VNode } from "preact";
import Router, { route, Route } from "preact-router";
@ -78,7 +78,7 @@ if (document.readyState === "loading") {
function Application(): VNode {
const [globalNotification, setGlobalNotification] = useState<
string | undefined
VNode | undefined
>(undefined);
const hash_history = createHashHistory();
function clearNotification(): void {
@ -169,7 +169,9 @@ function Application(): VNode {
onSuccess={(currency: string) => {
route(Pages.balance_history.replace(":currency", currency));
setGlobalNotification(
"All done, your transaction is in progress",
<Translate>
All done, your transaction is in progress
</Translate>,
);
}}
/>

View File

@ -41,6 +41,12 @@ import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits
import { ExchangeWithdrawDetails } from "@gnu-taler/taler-wallet-core/src/operations/withdraw";
import { MessageFromBackend } from "./wxBackend";
/**
*
* @autor Florian Dold
* @autor sebasjm
*/
export interface ExtendedPermissionsResponse {
newValue: boolean;
}