moving strings from wallet-core to web-extension
This commit is contained in:
parent
2e1438eb04
commit
1d55c551bb
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
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/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation helpers for React components and template literals.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imports.
|
|
||||||
*/
|
|
||||||
import { strings } from "./strings";
|
|
||||||
export { strings } from "./strings";
|
|
||||||
|
|
||||||
// @ts-ignore: no type decl for this library
|
|
||||||
import * as jedLib from "jed";
|
|
||||||
import { Logger } from "../util/logging";
|
|
||||||
|
|
||||||
const logger = new Logger("i18n/index.ts");
|
|
||||||
|
|
||||||
export let jed: any = undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up jed library for internationalization,
|
|
||||||
* based on browser language settings.
|
|
||||||
*/
|
|
||||||
export function setupI18n(lang: string): any {
|
|
||||||
lang = lang.replace("_", "-");
|
|
||||||
|
|
||||||
if (!strings[lang]) {
|
|
||||||
lang = "en-US";
|
|
||||||
logger.warn(`language ${lang} not found, defaulting to english`);
|
|
||||||
}
|
|
||||||
jed = new jedLib.Jed(strings[lang]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use different translations for testing. Should not be used outside
|
|
||||||
* of test cases.
|
|
||||||
*/
|
|
||||||
export function internalSetStrings(langStrings: any): void {
|
|
||||||
jed = new jedLib.Jed(langStrings);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert template strings to a msgid
|
|
||||||
*/
|
|
||||||
function toI18nString(stringSeq: ReadonlyArray<string>): string {
|
|
||||||
let s = "";
|
|
||||||
for (let i = 0; i < stringSeq.length; i++) {
|
|
||||||
s += stringSeq[i];
|
|
||||||
if (i < stringSeq.length - 1) {
|
|
||||||
s += `%${i + 1}$s`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internationalize a string template with arbitrary serialized values.
|
|
||||||
*/
|
|
||||||
export function str(stringSeq: TemplateStringsArray, ...values: any[]): string {
|
|
||||||
const s = toI18nString(stringSeq);
|
|
||||||
const tr = jed
|
|
||||||
.translate(s)
|
|
||||||
.ifPlural(1, s)
|
|
||||||
.fetch(...values);
|
|
||||||
return tr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an internationalized string (based on the globally set, current language)
|
|
||||||
* from a JSON object. Fall back to the default language of the JSON object
|
|
||||||
* if no match exists.
|
|
||||||
*/
|
|
||||||
export function getJsonI18n<K extends string>(
|
|
||||||
obj: Record<K, string>,
|
|
||||||
key: K,
|
|
||||||
): string {
|
|
||||||
return obj[key];
|
|
||||||
}
|
|
@ -14,7 +14,8 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as core from "@gnu-taler/taler-wallet-core";
|
import { setupI18n } from "@gnu-taler/taler-util"
|
||||||
|
import { strings } from '../src/i18n'
|
||||||
|
|
||||||
const mockConfig = {
|
const mockConfig = {
|
||||||
backendURL: 'http://demo.taler.net',
|
backendURL: 'http://demo.taler.net',
|
||||||
@ -45,8 +46,8 @@ export const globalTypes = {
|
|||||||
|
|
||||||
export const decorators = [
|
export const decorators = [
|
||||||
(Story, { globals }) => {
|
(Story, { globals }) => {
|
||||||
core.setupI18n(globals.locale);
|
setupI18n(globals.locale, strings);
|
||||||
return <Story />
|
return <Story />
|
||||||
},
|
},
|
||||||
// (Story) => <ConfigContextProvider value={mockConfig}> <Story /> </ConfigContextProvider>
|
// (Story) => <ConfigContextProvider value={mockConfig}> <Story /> </ConfigContextProvider>
|
||||||
];
|
];
|
||||||
|
@ -1,209 +0,0 @@
|
|||||||
/*
|
|
||||||
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/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation helpers for React components and template literals.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imports
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as i18nCore from "@gnu-taler/taler-wallet-core";
|
|
||||||
import { Component, ComponentChildren, h, JSX, toChildArray, VNode } from "preact";
|
|
||||||
/**
|
|
||||||
* Convert template strings to a msgid
|
|
||||||
*/
|
|
||||||
function toI18nString(stringSeq: ReadonlyArray<string>): string {
|
|
||||||
let s = "";
|
|
||||||
for (let i = 0; i < stringSeq.length; i++) {
|
|
||||||
s += stringSeq[i];
|
|
||||||
if (i < stringSeq.length - 1) {
|
|
||||||
s += `%${i + 1}$s`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const str = i18nCore.str;
|
|
||||||
export const internalSetStrings = i18nCore.internalSetStrings;
|
|
||||||
export const strings = i18nCore.strings;
|
|
||||||
|
|
||||||
|
|
||||||
interface TranslateSwitchProps {
|
|
||||||
target: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
function stringifyChildren(children: any): string {
|
|
||||||
let n = 1;
|
|
||||||
const ss = toChildArray(children).map((c) => {
|
|
||||||
if (typeof c === "string") {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return `%${n++}$s`;
|
|
||||||
});
|
|
||||||
const s = ss.join("").replace(/ +/g, " ").trim();
|
|
||||||
console.log("translation lookup", JSON.stringify(s));
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TranslateProps {
|
|
||||||
/**
|
|
||||||
* Component that the translated element should be wrapped in.
|
|
||||||
* Defaults to "div".
|
|
||||||
*/
|
|
||||||
wrap?: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props to give to the wrapped component.
|
|
||||||
*/
|
|
||||||
wrapProps?: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translated elements
|
|
||||||
*/
|
|
||||||
children: ComponentChildren;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTranslatedChildren(
|
|
||||||
translation: string,
|
|
||||||
children: ComponentChildren,
|
|
||||||
): ComponentChildren {
|
|
||||||
const tr = translation.split(/%(\d+)\$s/);
|
|
||||||
const childArray = toChildArray(children);
|
|
||||||
// Merge consecutive string children.
|
|
||||||
const placeholderChildren = [];
|
|
||||||
for (let i = 0; i < childArray.length; i++) {
|
|
||||||
const x = childArray[i];
|
|
||||||
if (x === undefined) {
|
|
||||||
continue;
|
|
||||||
} else if (typeof x === "string") {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
placeholderChildren.push(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const result = [];
|
|
||||||
for (let i = 0; i < tr.length; i++) {
|
|
||||||
if (i % 2 == 0) {
|
|
||||||
// Text
|
|
||||||
result.push(tr[i]);
|
|
||||||
} else {
|
|
||||||
const childIdx = Number.parseInt(tr[i]) - 1;
|
|
||||||
result.push(placeholderChildren[childIdx]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate text node children of this component.
|
|
||||||
* If a child component might produce a text node, it must be wrapped
|
|
||||||
* in a another non-text element.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* ```
|
|
||||||
* <Translate>
|
|
||||||
* Hello. Your score is <span><PlayerScore player={player} /></span>
|
|
||||||
* </Translate>
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export function Translate({children, wrap, wrapProps}: TranslateProps): VNode {
|
|
||||||
const s = stringifyChildren(children);
|
|
||||||
const translation: string = i18nCore.jed.ngettext(s, s, 1);
|
|
||||||
const result = getTranslatedChildren(translation, children);
|
|
||||||
if (!wrap) {
|
|
||||||
return <div>{result}</div>;
|
|
||||||
}
|
|
||||||
return h(wrap, wrapProps, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Switch translation based on singular or plural based on the target prop.
|
|
||||||
* Should only contain TranslateSingular and TransplatePlural as children.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* ```
|
|
||||||
* <TranslateSwitch target={n}>
|
|
||||||
* <TranslateSingular>I have {n} apple.</TranslateSingular>
|
|
||||||
* <TranslatePlural>I have {n} apples.</TranslatePlural>
|
|
||||||
* </TranslateSwitch>
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export class TranslateSwitch extends Component<
|
|
||||||
TranslateSwitchProps,
|
|
||||||
void
|
|
||||||
> {
|
|
||||||
render(): JSX.Element {
|
|
||||||
let singular: VNode<TranslationPluralProps> | undefined;
|
|
||||||
let plural: VNode<TranslationPluralProps> | undefined;
|
|
||||||
const children = this.props.children;
|
|
||||||
if (children) {
|
|
||||||
toChildArray(children).forEach((child: any) => {
|
|
||||||
if (child.type === TranslatePlural) {
|
|
||||||
plural = child;
|
|
||||||
}
|
|
||||||
if (child.type === TranslateSingular) {
|
|
||||||
singular = child;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!singular || !plural) {
|
|
||||||
console.error("translation not found");
|
|
||||||
return h("span", {}, ["translation not found"]);
|
|
||||||
}
|
|
||||||
singular.props.target = this.props.target;
|
|
||||||
plural.props.target = this.props.target;
|
|
||||||
// We're looking up the translation based on the
|
|
||||||
// singular, even if we must use the plural form.
|
|
||||||
return singular;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TranslationPluralProps {
|
|
||||||
target: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See [[TranslateSwitch]].
|
|
||||||
*/
|
|
||||||
export class TranslatePlural extends Component<
|
|
||||||
TranslationPluralProps,
|
|
||||||
void
|
|
||||||
> {
|
|
||||||
render(): JSX.Element {
|
|
||||||
const s = stringifyChildren(this.props.children);
|
|
||||||
const translation = i18nCore.jed.ngettext(s, s, 1);
|
|
||||||
const result = getTranslatedChildren(translation, this.props.children);
|
|
||||||
return <div>{result}</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See [[TranslateSwitch]].
|
|
||||||
*/
|
|
||||||
export class TranslateSingular extends Component<
|
|
||||||
TranslationPluralProps,
|
|
||||||
void
|
|
||||||
> {
|
|
||||||
render(): JSX.Element {
|
|
||||||
const s = stringifyChildren(this.props.children);
|
|
||||||
const translation = i18nCore.jed.ngettext(s, s, this.props.target);
|
|
||||||
const result = getTranslatedChildren(translation, this.props.children);
|
|
||||||
return <div>{result}</div>;
|
|
||||||
}
|
|
||||||
}
|
|
24
packages/taler-wallet-webextension/src/i18n/index.ts
Normal file
24
packages/taler-wallet-webextension/src/i18n/index.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
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/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translation helpers for React components and template literals.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports.
|
||||||
|
*/
|
||||||
|
export { strings } from "./strings";
|
@ -22,14 +22,14 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import * as i18n from "../i18n";
|
// import * as i18n from "../i18n";
|
||||||
|
|
||||||
import { renderAmount, ProgressButton } from "../renderHtml";
|
import { renderAmount, ProgressButton } from "../renderHtml";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
import { useState, useEffect } from "preact/hooks";
|
import { useState, useEffect } from "preact/hooks";
|
||||||
|
|
||||||
import { getJsonI18n } from "@gnu-taler/taler-wallet-core";
|
import { getJsonI18n, i18n } from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
PreparePayResult,
|
PreparePayResult,
|
||||||
ConfirmPayResult,
|
ConfirmPayResult,
|
||||||
@ -171,19 +171,19 @@ export function TalerPayDialog({ talerPayUri }: Props): JSX.Element {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<i18n.Translate wrap="p">
|
<i18n.Translate>
|
||||||
The merchant <span>{merchantName}</span> offers you to purchase:
|
The merchant <span>{merchantName}</span> offers you to purchase:
|
||||||
</i18n.Translate>
|
</i18n.Translate>
|
||||||
<div style={{ textAlign: "center" }}>
|
<div style={{ textAlign: "center" }}>
|
||||||
<strong>{contractTerms.summary}</strong>
|
<strong>{contractTerms.summary}</strong>
|
||||||
</div>
|
</div>
|
||||||
{totalFees ? (
|
{totalFees ? (
|
||||||
<i18n.Translate wrap="p">
|
<i18n.Translate>
|
||||||
The total price is <span>{amount} </span>
|
The total price is <span>{amount} </span>
|
||||||
(plus <span>{renderAmount(totalFees)}</span> fees).
|
(plus <span>{renderAmount(totalFees)}</span> fees).
|
||||||
</i18n.Translate>
|
</i18n.Translate>
|
||||||
) : (
|
) : (
|
||||||
<i18n.Translate wrap="p">
|
<i18n.Translate>
|
||||||
The total price is <span>{amount}</span>.
|
The total price is <span>{amount}</span>.
|
||||||
</i18n.Translate>
|
</i18n.Translate>
|
||||||
)}
|
)}
|
||||||
|
@ -19,8 +19,13 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { PaymentStatus, TransactionPayment, TransactionType, TransactionWithdrawal, TransactionDeposit, TransactionRefresh, TransactionTip, TransactionRefund, WithdrawalType, TransactionCommon } from '@gnu-taler/taler-util';
|
import {
|
||||||
import { Fragment, h } from 'preact';
|
PaymentStatus,
|
||||||
|
TransactionCommon, TransactionDeposit, TransactionPayment,
|
||||||
|
TransactionRefresh, TransactionRefund, TransactionTip, TransactionType,
|
||||||
|
TransactionWithdrawal,
|
||||||
|
WithdrawalType
|
||||||
|
} from '@gnu-taler/taler-util';
|
||||||
import { WalletTransactionView as Component } from './popup';
|
import { WalletTransactionView as Component } from './popup';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -174,7 +179,7 @@ export const Refund = dynamic({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const RefundPending = dynamic({
|
export const RefundPending = dynamic({
|
||||||
transaction: { ...exampleData.refund , pending: true }
|
transaction: { ...exampleData.refund, pending: true }
|
||||||
});
|
});
|
||||||
|
|
||||||
export const RefundWithProducts = dynamic({
|
export const RefundWithProducts = dynamic({
|
||||||
|
@ -37,13 +37,13 @@ import {
|
|||||||
AmountString,
|
AmountString,
|
||||||
Timestamp,
|
Timestamp,
|
||||||
amountFractionalBase,
|
amountFractionalBase,
|
||||||
|
i18n,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { Component, ComponentChildren, Fragment, JSX } from "preact";
|
import { Component, ComponentChildren, Fragment, JSX } from "preact";
|
||||||
import { route, Route, Router } from 'preact-router';
|
import { route, Route, Router } from 'preact-router';
|
||||||
import { Match } from 'preact-router/match';
|
import { Match } from 'preact-router/match';
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import * as i18n from "../i18n";
|
|
||||||
import { PageLink, renderAmount } from "../renderHtml";
|
import { PageLink, renderAmount } from "../renderHtml";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
import { PermissionsCheckbox, useExtendedPermissions, Diagnostics } from "./welcome";
|
import { PermissionsCheckbox, useExtendedPermissions, Diagnostics } from "./welcome";
|
||||||
@ -92,10 +92,10 @@ function bigAmount(amount: AmountJson): JSX.Element {
|
|||||||
|
|
||||||
function EmptyBalanceView(): JSX.Element {
|
function EmptyBalanceView(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<i18n.Translate wrap="p">
|
<p><i18n.Translate>
|
||||||
You have no balance to show. Need some{" "}
|
You have no balance to show. Need some{" "}
|
||||||
<PageLink pageName="/welcome">help</PageLink> getting started?
|
<PageLink pageName="/welcome">help</PageLink> getting started?
|
||||||
</i18n.Translate>
|
</i18n.Translate></p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,13 +166,13 @@ class WalletBalanceView extends Component<any, any> {
|
|||||||
|
|
||||||
if (!Amounts.isZero(pendingIncoming)) {
|
if (!Amounts.isZero(pendingIncoming)) {
|
||||||
incoming = (
|
incoming = (
|
||||||
<i18n.Translate wrap="span">
|
<span><i18n.Translate>
|
||||||
<span style={{ color: "darkgreen" }}>
|
<span style={{ color: "darkgreen" }}>
|
||||||
{"+"}
|
{"+"}
|
||||||
{renderAmount(entry.pendingIncoming)}
|
{renderAmount(entry.pendingIncoming)}
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
incoming
|
incoming
|
||||||
</i18n.Translate>
|
</i18n.Translate></span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,14 +436,14 @@ interface WalletTransactionProps {
|
|||||||
|
|
||||||
export function WalletTransactionView({ transaction, onDelete, onBack }: WalletTransactionProps) {
|
export function WalletTransactionView({ transaction, onDelete, onBack }: WalletTransactionProps) {
|
||||||
if (!transaction) {
|
if (!transaction) {
|
||||||
return <div>Loading ...</div>;
|
return <div><i18n.Translate>Loading ...</i18n.Translate></div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Footer() {
|
function Footer() {
|
||||||
return <footer style={{ marginTop: 'auto', display: 'flex' }}>
|
return <footer style={{ marginTop: 'auto', display: 'flex' }}>
|
||||||
<button onClick={onBack}>back</button>
|
<button onClick={onBack}><i18n.Translate>back</i18n.Translate></button>
|
||||||
<div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
|
<div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
|
||||||
<button onClick={onDelete}>remove</button>
|
<button onClick={onDelete}><i18n.Translate>remove</i18n.Translate></button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -21,8 +21,7 @@
|
|||||||
* @author Florian Dold
|
* @author Florian Dold
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as i18n from "../i18n";
|
import { i18n } from '@gnu-taler/taler-util'
|
||||||
|
|
||||||
import { renderAmount } from "../renderHtml";
|
import { renderAmount } from "../renderHtml";
|
||||||
|
|
||||||
import { useState, useEffect } from "preact/hooks";
|
import { useState, useEffect } from "preact/hooks";
|
||||||
@ -64,11 +63,11 @@ export function View({ talerWithdrawUri, details, cancelled, selectedExchange, a
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Digital Cash Withdrawal</h1>
|
<h1>Digital Cash Withdrawal</h1>
|
||||||
<i18n.Translate wrap="p">
|
<p><i18n.Translate>
|
||||||
You are about to withdraw{" "}
|
You are about to withdraw{" "}
|
||||||
<strong>{renderAmount(details.amount)}</strong> from your bank account
|
<strong>{renderAmount(details.amount)}</strong> from your bank account
|
||||||
into your wallet.
|
into your wallet.
|
||||||
</i18n.Translate>
|
</i18n.Translate></p>
|
||||||
{selectedExchange ? (
|
{selectedExchange ? (
|
||||||
<p>
|
<p>
|
||||||
The exchange <strong>{selectedExchange}</strong> will be used as the
|
The exchange <strong>{selectedExchange}</strong> will be used as the
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// import * as test from "ava";
|
// import * as test from "ava";
|
||||||
import { internalSetStrings, str, Translate } from "../src/i18n";
|
import { internalSetStrings, str, Translate } from "@gnu-taler/taler-util";
|
||||||
import { render, configure } from "enzyme";
|
import { render, configure } from "enzyme";
|
||||||
import Adapter from 'enzyme-adapter-preact-pure';
|
import Adapter from 'enzyme-adapter-preact-pure';
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user