aboutsummaryrefslogtreecommitdiff
path: root/packages/merchant-backoffice-ui/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'packages/merchant-backoffice-ui/src/components')
-rw-r--r--packages/merchant-backoffice-ui/src/components/exception/AsyncButton.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/components/exception/login.tsx12
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputArray.tsx10
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputCurrency.tsx9
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputDate.tsx14
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputDuration.tsx28
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputImage.tsx10
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputLocation.tsx27
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputPaytoForm.tsx98
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputSearchProduct.tsx18
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputSecured.tsx17
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputStock.tsx46
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputTaxes.tsx25
-rw-r--r--packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx56
-rw-r--r--packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx4
-rw-r--r--packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx28
-rw-r--r--packages/merchant-backoffice-ui/src/components/menu/index.tsx99
-rw-r--r--packages/merchant-backoffice-ui/src/components/modal/index.tsx96
-rw-r--r--packages/merchant-backoffice-ui/src/components/picker/DurationPicker.tsx12
-rw-r--r--packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx26
-rw-r--r--packages/merchant-backoffice-ui/src/components/product/NonInventoryProductForm.tsx44
-rw-r--r--packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx38
-rw-r--r--packages/merchant-backoffice-ui/src/components/product/ProductList.tsx13
23 files changed, 381 insertions, 355 deletions
diff --git a/packages/merchant-backoffice-ui/src/components/exception/AsyncButton.tsx b/packages/merchant-backoffice-ui/src/components/exception/AsyncButton.tsx
index 510bc29b8..aa50dfa91 100644
--- a/packages/merchant-backoffice-ui/src/components/exception/AsyncButton.tsx
+++ b/packages/merchant-backoffice-ui/src/components/exception/AsyncButton.tsx
@@ -22,7 +22,7 @@
import { ComponentChildren, h } from "preact";
import { LoadingModal } from "../modal/index.js";
import { useAsync } from "../../hooks/async.js";
-import { Translate } from "../../i18n/index.js";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
type Props = {
children: ComponentChildren;
@@ -33,14 +33,14 @@ type Props = {
export function AsyncButton({ onClick, disabled, children, ...rest }: Props) {
const { isSlow, isLoading, request, cancel } = useAsync(onClick);
-
+ const { i18n } = useTranslationContext();
if (isSlow) {
return <LoadingModal onCancel={cancel} />;
}
if (isLoading) {
return (
<button class="button">
- <Translate>Loading...</Translate>
+ <i18n.Translate>Loading...</i18n.Translate>
</button>
);
}
diff --git a/packages/merchant-backoffice-ui/src/components/exception/login.tsx b/packages/merchant-backoffice-ui/src/components/exception/login.tsx
index d1898915d..552e76ed6 100644
--- a/packages/merchant-backoffice-ui/src/components/exception/login.tsx
+++ b/packages/merchant-backoffice-ui/src/components/exception/login.tsx
@@ -19,11 +19,11 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useBackendContext } from "../../context/backend.js";
import { useInstanceContext } from "../../context/instance.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { Notification } from "../../utils/types.js";
interface Props {
@@ -51,7 +51,7 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode {
const [token, setToken] = useState(currentToken);
const [url, setURL] = useState(backendUrl);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div class="columns is-centered">
@@ -61,13 +61,13 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode {
class="modal-card-head"
style={{ border: "1px solid", borderBottom: 0 }}
>
- <p class="modal-card-title">{i18n`Login required`}</p>
+ <p class="modal-card-title">{i18n.str`Login required`}</p>
</header>
<section
class="modal-card-body"
style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }}
>
- <Translate>Please enter your access token.</Translate>
+ <i18n.Translate>Please enter your access token.</i18n.Translate>
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">URL</label>
@@ -95,7 +95,7 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode {
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">
- <Translate>Access Token</Translate>
+ <i18n.Translate>Access Token</i18n.Translate>
</label>
</div>
<div class="field-body">
@@ -133,7 +133,7 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode {
onConfirm(url, normalizeToken(token));
}}
>
- <Translate>Confirm</Translate>
+ <i18n.Translate>Confirm</i18n.Translate>
</button>
</footer>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputArray.tsx b/packages/merchant-backoffice-ui/src/components/form/InputArray.tsx
index b5da1117a..8f0249bb2 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputArray.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputArray.tsx
@@ -18,9 +18,9 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { InputProps, useField } from "./useField.js";
export interface Props<T> extends InputProps<T> {
@@ -52,7 +52,7 @@ export function InputArray<T>({
const array: any[] = (value ? value! : []) as any;
const [currentValue, setCurrentValue] = useState("");
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div class="field is-horizontal">
@@ -99,7 +99,7 @@ export function InputArray<T>({
const v = fromStr(currentValue);
if (!isValid(v)) {
setLocalError(
- i18n`The value ${v} is invalid for a payment url`,
+ i18n.str`The value ${v} is invalid for a payment url`,
);
return;
}
@@ -107,9 +107,9 @@ export function InputArray<T>({
onChange([v, ...array] as any);
setCurrentValue("");
}}
- data-tooltip={i18n`add element to the list`}
+ data-tooltip={i18n.str`add element to the list`}
>
- <Translate>add</Translate>
+ <i18n.Translate>add</i18n.Translate>
</button>
</p>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputCurrency.tsx b/packages/merchant-backoffice-ui/src/components/form/InputCurrency.tsx
index 57a5163b7..3b84855da 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputCurrency.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputCurrency.tsx
@@ -18,7 +18,7 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { ComponentChildren, h } from "preact";
+import { ComponentChildren, h, VNode } from "preact";
import { useConfigContext } from "../../context/config.js";
import { Amount } from "../../declaration.js";
import { InputWithAddon } from "./InputWithAddon.js";
@@ -42,7 +42,7 @@ export function InputCurrency<T>({
addonAfter,
children,
side,
-}: Props<keyof T>) {
+}: Props<keyof T>): VNode {
const config = useConfigContext();
return (
<InputWithAddon<T>
@@ -60,7 +60,8 @@ export function InputCurrency<T>({
toStr={(v?: Amount) => v?.split(":")[1] || ""}
fromStr={(v: string) => (!v ? "" : `${config.currency}:${v}`)}
inputExtra={{ min: 0 }}
- children={children}
- />
+ >
+ {children}
+ </InputWithAddon>
);
}
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputDate.tsx b/packages/merchant-backoffice-ui/src/components/form/InputDate.tsx
index 4704b3312..fba798bd5 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputDate.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputDate.tsx
@@ -18,10 +18,10 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { format } from "date-fns";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { DatePicker } from "../picker/DatePicker.js";
import { InputProps, useField } from "./useField.js";
@@ -43,7 +43,7 @@ export function InputDate<T>({
withTimestampSupport,
}: Props<keyof T>): VNode {
const [opened, setOpened] = useState(false);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const { error, required, value, onChange } = useField<T>(name);
@@ -120,25 +120,25 @@ export function InputDate<T>({
<span
data-tooltip={
withTimestampSupport
- ? i18n`change value to unknown date`
- : i18n`change value to empty`
+ ? i18n.str`change value to unknown date`
+ : i18n.str`change value to empty`
}
>
<button
class="button is-info mr-3"
onClick={() => onChange(undefined as any)}
>
- <Translate>clear</Translate>
+ <i18n.Translate>clear</i18n.Translate>
</button>
</span>
)}
{withTimestampSupport && (
- <span data-tooltip={i18n`change value to never`}>
+ <span data-tooltip={i18n.str`change value to never`}>
<button
class="button is-info"
onClick={() => onChange({ t_s: "never" } as any)}
>
- <Translate>never</Translate>
+ <i18n.Translate>never</i18n.Translate>
</button>
</span>
)}
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputDuration.tsx b/packages/merchant-backoffice-ui/src/components/form/InputDuration.tsx
index 658cc4db7..3f25d1dc7 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputDuration.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputDuration.tsx
@@ -18,10 +18,10 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { intervalToDuration, formatDuration } from "date-fns";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
+import { formatDuration, intervalToDuration } from "date-fns";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { SimpleModal } from "../modal/index.js";
import { DurationPicker } from "../picker/DurationPicker.js";
import { InputProps, useField } from "./useField.js";
@@ -43,14 +43,14 @@ export function InputDuration<T>({
withForever,
}: Props<keyof T>): VNode {
const [opened, setOpened] = useState(false);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const { error, required, value, onChange } = useField<T>(name);
let strValue = "";
if (!value) {
strValue = "";
} else if (value.d_us === "forever") {
- strValue = i18n`forever`;
+ strValue = i18n.str`forever`;
} else {
strValue = formatDuration(
intervalToDuration({ start: 0, end: value.d_us / 1000 }),
@@ -59,17 +59,17 @@ export function InputDuration<T>({
formatDistance: (name, value) => {
switch (name) {
case "xMonths":
- return i18n`${value}M`;
+ return i18n.str`${value}M`;
case "xYears":
- return i18n`${value}Y`;
+ return i18n.str`${value}Y`;
case "xDays":
- return i18n`${value}d`;
+ return i18n.str`${value}d`;
case "xHours":
- return i18n`${value}h`;
+ return i18n.str`${value}h`;
case "xMinutes":
- return i18n`${value}min`;
+ return i18n.str`${value}min`;
case "xSeconds":
- return i18n`${value}sec`;
+ return i18n.str`${value}sec`;
}
},
localize: {
@@ -134,22 +134,22 @@ export function InputDuration<T>({
{error && <p class="help is-danger">{error}</p>}
</div>
{withForever && (
- <span data-tooltip={i18n`change value to never`}>
+ <span data-tooltip={i18n.str`change value to never`}>
<button
class="button is-info mr-3"
onClick={() => onChange({ d_us: "forever" } as any)}
>
- <Translate>forever</Translate>
+ <i18n.Translate>forever</i18n.Translate>
</button>
</span>
)}
{!readonly && (
- <span data-tooltip={i18n`change value to empty`}>
+ <span data-tooltip={i18n.str`change value to empty`}>
<button
class="button is-info "
onClick={() => onChange(undefined as any)}
>
- <Translate>clear</Translate>
+ <i18n.Translate>clear</i18n.Translate>
</button>
</span>
)}
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputImage.tsx b/packages/merchant-backoffice-ui/src/components/form/InputImage.tsx
index d5b2aadb6..43a7af1a3 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputImage.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputImage.tsx
@@ -18,9 +18,9 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { ComponentChildren, h, VNode } from "preact";
import { useRef, useState } from "preact/hooks";
-import { Translate } from "../../i18n/index.js";
import { MAX_IMAGE_SIZE as MAX_IMAGE_UPLOAD_SIZE } from "../../utils/constants.js";
import { InputProps, useField } from "./useField.js";
@@ -43,7 +43,7 @@ export function InputImage<T>({
const { error, value, onChange } = useField<T>(name);
const image = useRef<HTMLInputElement>(null);
-
+ const { i18n } = useTranslationContext();
const [sizeError, setSizeError] = useState(false);
return (
@@ -102,17 +102,17 @@ export function InputImage<T>({
{error && <p class="help is-danger">{error}</p>}
{sizeError && (
<p class="help is-danger">
- <Translate>Image should be smaller than 1 MB</Translate>
+ <i18n.Translate>Image should be smaller than 1 MB</i18n.Translate>
</p>
)}
{!value && (
<button class="button" onClick={() => image.current?.click()}>
- <Translate>Add</Translate>
+ <i18n.Translate>Add</i18n.Translate>
</button>
)}
{value && (
<button class="button" onClick={() => onChange(undefined!)}>
- <Translate>Remove</Translate>
+ <i18n.Translate>Remove</i18n.Translate>
</button>
)}
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputLocation.tsx b/packages/merchant-backoffice-ui/src/components/form/InputLocation.tsx
index 613b2f1e6..ef5a0995c 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputLocation.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputLocation.tsx
@@ -19,31 +19,34 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
import { Fragment, h } from "preact";
-import { useTranslator } from "../../i18n/index.js";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Input } from "./Input.js";
export function InputLocation({ name }: { name: string }) {
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<>
- <Input name={`${name}.country`} label={i18n`Country`} />
+ <Input name={`${name}.country`} label={i18n.str`Country`} />
<Input
name={`${name}.address_lines`}
inputType="multiline"
- label={i18n`Address`}
+ label={i18n.str`Address`}
toStr={(v: string[] | undefined) => (!v ? "" : v.join("\n"))}
fromStr={(v: string) => v.split("\n")}
/>
- <Input name={`${name}.building_number`} label={i18n`Building number`} />
- <Input name={`${name}.building_name`} label={i18n`Building name`} />
- <Input name={`${name}.street`} label={i18n`Street`} />
- <Input name={`${name}.post_code`} label={i18n`Post code`} />
- <Input name={`${name}.town_location`} label={i18n`Town location`} />
- <Input name={`${name}.town`} label={i18n`Town`} />
- <Input name={`${name}.district`} label={i18n`District`} />
+ <Input
+ name={`${name}.building_number`}
+ label={i18n.str`Building number`}
+ />
+ <Input name={`${name}.building_name`} label={i18n.str`Building name`} />
+ <Input name={`${name}.street`} label={i18n.str`Street`} />
+ <Input name={`${name}.post_code`} label={i18n.str`Post code`} />
+ <Input name={`${name}.town_location`} label={i18n.str`Town location`} />
+ <Input name={`${name}.town`} label={i18n.str`Town`} />
+ <Input name={`${name}.district`} label={i18n.str`District`} />
<Input
name={`${name}.country_subdivision`}
- label={i18n`Country subdivision`}
+ label={i18n.str`Country subdivision`}
/>
</>
);
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputPaytoForm.tsx b/packages/merchant-backoffice-ui/src/components/form/InputPaytoForm.tsx
index 085febea4..7bf39152b 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputPaytoForm.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputPaytoForm.tsx
@@ -18,9 +18,9 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { h, VNode, Fragment } from "preact";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
+import { Fragment, h, VNode } from "preact";
import { useCallback, useState } from "preact/hooks";
-import { Translate, Translator, useTranslator } from "../../i18n/index.js";
import { COUNTRY_TABLE } from "../../utils/constants.js";
import { undefinedIfEmpty } from "../../utils/table.js";
import { FormErrors, FormProvider } from "./FormProvider.js";
@@ -69,24 +69,30 @@ function checkAddressChecksum(address: string) {
return true;
}
-function validateBitcoin(addr: string, i18n: Translator): string | undefined {
+function validateBitcoin(
+ addr: string,
+ i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): string | undefined {
try {
const valid = /^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$/.test(addr);
if (valid) return undefined;
} catch (e) {
console.log(e);
}
- return i18n`This is not a valid bitcoin address.`;
+ return i18n.str`This is not a valid bitcoin address.`;
}
-function validateEthereum(addr: string, i18n: Translator): string | undefined {
+function validateEthereum(
+ addr: string,
+ i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): string | undefined {
try {
const valid = isEthereumAddress(addr);
if (valid) return undefined;
} catch (e) {
console.log(e);
}
- return i18n`This is not a valid Ethereum address.`;
+ return i18n.str`This is not a valid Ethereum address.`;
}
/**
@@ -103,12 +109,15 @@ function validateEthereum(addr: string, i18n: Translator): string | undefined {
* If the remainder is 1, the check digit test is passed and the IBAN might be valid.
*
*/
-function validateIBAN(iban: string, i18n: Translator): string | undefined {
+function validateIBAN(
+ iban: string,
+ i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): string | undefined {
// Check total length
if (iban.length < 4)
- return i18n`IBAN numbers usually have more that 4 digits`;
+ return i18n.str`IBAN numbers usually have more that 4 digits`;
if (iban.length > 34)
- return i18n`IBAN numbers usually have less that 34 digits`;
+ return i18n.str`IBAN numbers usually have less that 34 digits`;
const A_code = "A".charCodeAt(0);
const Z_code = "Z".charCodeAt(0);
@@ -116,7 +125,7 @@ function validateIBAN(iban: string, i18n: Translator): string | undefined {
// check supported country
const code = IBAN.substr(0, 2);
const found = code in COUNTRY_TABLE;
- if (!found) return i18n`IBAN country code not found`;
+ if (!found) return i18n.str`IBAN country code not found`;
// 2.- Move the four initial characters to the end of the string
const step2 = IBAN.substr(4) + iban.substr(0, 4);
@@ -140,7 +149,8 @@ function validateIBAN(iban: string, i18n: Translator): string | undefined {
}
const checksum = calculate_iban_checksum(step3);
- if (checksum !== 1) return i18n`IBAN number is not valid, checksum is wrong`;
+ if (checksum !== 1)
+ return i18n.str`IBAN number is not valid, checksum is wrong`;
return undefined;
}
@@ -175,7 +185,7 @@ export function InputPaytoForm<T>({
payToPath = `/${value.path1}`;
}
}
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const ops = value.options!;
const url = tryUrl(`payto://${value.target}${payToPath}`);
@@ -188,9 +198,9 @@ export function InputPaytoForm<T>({
const paytoURL = !url ? "" : url.toString();
const errors: FormErrors<Entity> = {
- target: value.target === noTargetValue ? i18n`required` : undefined,
+ target: value.target === noTargetValue ? i18n.str`required` : undefined,
path1: !value.path1
- ? i18n`required`
+ ? i18n.str`required`
: value.target === "iban"
? validateIBAN(value.path1, i18n)
: value.target === "bitcoin"
@@ -201,12 +211,12 @@ export function InputPaytoForm<T>({
path2:
value.target === "x-taler-bank"
? !value.path2
- ? i18n`required`
+ ? i18n.str`required`
: undefined
: undefined,
options: undefinedIfEmpty({
"receiver-name": !value.options?.["receiver-name"]
- ? i18n`required`
+ ? i18n.str`required`
: undefined,
}),
};
@@ -235,23 +245,23 @@ export function InputPaytoForm<T>({
>
<InputSelector<Entity>
name="target"
- label={i18n`Target type`}
- tooltip={i18n`Method to use for wire transfer`}
+ label={i18n.str`Target type`}
+ tooltip={i18n.str`Method to use for wire transfer`}
values={targets}
- toStr={(v) => (v === noTargetValue ? i18n`Choose one...` : v)}
+ toStr={(v) => (v === noTargetValue ? i18n.str`Choose one...` : v)}
/>
{value.target === "ach" && (
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Routing`}
- tooltip={i18n`Routing number.`}
+ label={i18n.str`Routing`}
+ tooltip={i18n.str`Routing number.`}
/>
<Input<Entity>
name="path2"
- label={i18n`Account`}
- tooltip={i18n`Account number.`}
+ label={i18n.str`Account`}
+ tooltip={i18n.str`Account number.`}
/>
</Fragment>
)}
@@ -259,8 +269,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Code`}
- tooltip={i18n`Business Identifier Code.`}
+ label={i18n.str`Code`}
+ tooltip={i18n.str`Business Identifier Code.`}
/>
</Fragment>
)}
@@ -268,8 +278,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Account`}
- tooltip={i18n`Bank Account Number.`}
+ label={i18n.str`Account`}
+ tooltip={i18n.str`Bank Account Number.`}
inputExtra={{ style: { textTransform: "uppercase" } }}
/>
</Fragment>
@@ -278,8 +288,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Account`}
- tooltip={i18n`Unified Payment Interface.`}
+ label={i18n.str`Account`}
+ tooltip={i18n.str`Unified Payment Interface.`}
/>
</Fragment>
)}
@@ -287,8 +297,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Address`}
- tooltip={i18n`Bitcoin protocol.`}
+ label={i18n.str`Address`}
+ tooltip={i18n.str`Bitcoin protocol.`}
/>
</Fragment>
)}
@@ -296,8 +306,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Address`}
- tooltip={i18n`Ethereum protocol.`}
+ label={i18n.str`Address`}
+ tooltip={i18n.str`Ethereum protocol.`}
/>
</Fragment>
)}
@@ -305,8 +315,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Address`}
- tooltip={i18n`Interledger protocol.`}
+ label={i18n.str`Address`}
+ tooltip={i18n.str`Interledger protocol.`}
/>
</Fragment>
)}
@@ -315,13 +325,13 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Host`}
- tooltip={i18n`Bank host.`}
+ label={i18n.str`Host`}
+ tooltip={i18n.str`Bank host.`}
/>
<Input<Entity>
name="path2"
- label={i18n`Account`}
- tooltip={i18n`Bank account.`}
+ label={i18n.str`Account`}
+ tooltip={i18n.str`Bank account.`}
/>
</Fragment>
)}
@@ -329,8 +339,8 @@ export function InputPaytoForm<T>({
{value.target !== noTargetValue && (
<Input
name="options.receiver-name"
- label={i18n`Name`}
- tooltip={i18n`Bank account owner's name.`}
+ label={i18n.str`Name`}
+ tooltip={i18n.str`Bank account owner's name.`}
/>
)}
@@ -357,7 +367,7 @@ export function InputPaytoForm<T>({
/>
</div>
))}
- {!paytos.length && i18n`No accounts yet.`}
+ {!paytos.length && i18n.str`No accounts yet.`}
</div>
</div>
@@ -365,11 +375,11 @@ export function InputPaytoForm<T>({
<div class="buttons is-right mt-5">
<button
class="button is-info"
- data-tooltip={i18n`add tax to the tax list`}
+ data-tooltip={i18n.str`add tax to the tax list`}
disabled={hasErrors}
onClick={submit}
>
- <Translate>Add</Translate>
+ <i18n.Translate>Add</i18n.Translate>
</button>
</div>
)}
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputSearchProduct.tsx b/packages/merchant-backoffice-ui/src/components/form/InputSearchProduct.tsx
index fceee9d56..7f65fb8ae 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputSearchProduct.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputSearchProduct.tsx
@@ -18,11 +18,11 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import emptyImage from "../../assets/empty.png";
import { MerchantBackend, WithId } from "../../declaration.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { FormErrors, FormProvider } from "./FormProvider.js";
import { InputWithAddon } from "./InputWithAddon.js";
@@ -50,7 +50,7 @@ export function InputSearchProduct({
const errors: FormErrors<ProductSearch> = {
name: undefined,
};
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
if (selected) {
return (
@@ -63,10 +63,11 @@ export function InputSearchProduct({
<div class="media-content">
<div class="content">
<p class="media-meta">
- <Translate>Product id</Translate>: <b>{selected.id}</b>
+ <i18n.Translate>Product id</i18n.Translate>: <b>{selected.id}</b>
</p>
<p>
- <Translate>Description</Translate>: {selected.description}
+ <i18n.Translate>Description</i18n.Translate>:{" "}
+ {selected.description}
</p>
<div class="buttons is-right mt-5">
<button
@@ -90,8 +91,8 @@ export function InputSearchProduct({
>
<InputWithAddon<ProductSearch>
name="name"
- label={i18n`Product`}
- tooltip={i18n`search products by it's description or id`}
+ label={i18n.str`Product`}
+ tooltip={i18n.str`search products by it's description or id`}
addonAfter={
<span class="icon">
<i class="mdi mdi-magnify" />
@@ -120,6 +121,7 @@ interface ProductListProps {
}
function ProductList({ name, onSelect, list }: ProductListProps) {
+ const { i18n } = useTranslationContext();
if (!name) {
/* FIXME
this BR is added to occupy the space that will be added when the
@@ -146,7 +148,9 @@ function ProductList({ name, onSelect, list }: ProductListProps) {
<div class="dropdown-content">
{!filtered.length ? (
<div class="dropdown-item">
- <Translate>no products found with that description</Translate>
+ <i18n.Translate>
+ no products found with that description
+ </i18n.Translate>
</div>
) : (
filtered.map((p) => (
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputSecured.tsx b/packages/merchant-backoffice-ui/src/components/form/InputSecured.tsx
index 799978683..d900168b4 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputSecured.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputSecured.tsx
@@ -18,14 +18,15 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { InputProps, useField } from "./useField.js";
export type Props<T> = InputProps<T>;
const TokenStatus = ({ prev, post }: any) => {
+ const { i18n } = useTranslationContext();
if (
(prev === undefined || prev === null) &&
(post === undefined || post === null)
@@ -33,11 +34,11 @@ const TokenStatus = ({ prev, post }: any) => {
return null;
return prev === post ? null : post === null ? (
<span class="tag is-danger is-align-self-center ml-2">
- <Translate>Deleting</Translate>
+ <i18n.Translate>Deleting</i18n.Translate>
</span>
) : (
<span class="tag is-warning is-align-self-center ml-2">
- <Translate>Changing</Translate>
+ <i18n.Translate>Changing</i18n.Translate>
</span>
);
};
@@ -55,7 +56,7 @@ export function InputSecured<T>({
const [active, setActive] = useState(false);
const [newValue, setNuewValue] = useState("");
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<Fragment>
@@ -84,7 +85,7 @@ export function InputSecured<T>({
<i class="mdi mdi-lock-reset" />
</div>
<span>
- <Translate>Manage access token</Translate>
+ <i18n.Translate>Manage access token</i18n.Translate>
</span>
</button>
<TokenStatus prev={initial} post={value} />
@@ -125,7 +126,7 @@ export function InputSecured<T>({
<i class="mdi mdi-lock-outline" />
</div>
<span>
- <Translate>Update</Translate>
+ <i18n.Translate>Update</i18n.Translate>
</span>
</button>
</div>
@@ -154,7 +155,7 @@ export function InputSecured<T>({
<i class="mdi mdi-lock-open-variant" />
</div>
<span>
- <Translate>Remove</Translate>
+ <i18n.Translate>Remove</i18n.Translate>
</span>
</button>
</div>
@@ -171,7 +172,7 @@ export function InputSecured<T>({
<i class="mdi mdi-lock-open-variant" />
</div>
<span>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</span>
</button>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx b/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx
index 57aa5968d..1052aaaae 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx
@@ -18,17 +18,16 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h } from "preact";
-import { MerchantBackend, Timestamp } from "../../declaration.js";
-import { InputProps, useField } from "./useField.js";
-import { FormProvider, FormErrors } from "./FormProvider.js";
import { useLayoutEffect, useState } from "preact/hooks";
-import { Input } from "./Input.js";
-import { InputGroup } from "./InputGroup.js";
-import { InputNumber } from "./InputNumber.js";
+import { MerchantBackend, Timestamp } from "../../declaration.js";
+import { FormErrors, FormProvider } from "./FormProvider.js";
import { InputDate } from "./InputDate.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
+import { InputGroup } from "./InputGroup.js";
import { InputLocation } from "./InputLocation.js";
+import { InputNumber } from "./InputNumber.js";
+import { InputProps, useField } from "./useField.js";
export interface Props<T> extends InputProps<T> {
alreadyExist?: boolean;
@@ -64,7 +63,7 @@ export function InputStock<T>({
incoming: 0,
lost: 0,
});
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
useLayoutEffect(() => {
if (!formValue) {
@@ -97,7 +96,7 @@ export function InputStock<T>({
{!alreadyExist ? (
<button
class="button"
- data-tooltip={i18n`click here to configure the stock of the product, leave it as is and the backend will not control stock`}
+ data-tooltip={i18n.str`click here to configure the stock of the product, leave it as is and the backend will not control stock`}
onClick={(): void => {
valueHandler({
current: 0,
@@ -107,17 +106,17 @@ export function InputStock<T>({
}}
>
<span>
- <Translate>Manage stock</Translate>
+ <i18n.Translate>Manage stock</i18n.Translate>
</span>
</button>
) : (
<button
class="button"
- data-tooltip={i18n`this product has been configured without stock control`}
+ data-tooltip={i18n.str`this product has been configured without stock control`}
disabled
>
<span>
- <Translate>Infinite</Translate>
+ <i18n.Translate>Infinite</i18n.Translate>
</span>
</button>
)}
@@ -134,7 +133,7 @@ export function InputStock<T>({
const stockAddedErrors: FormErrors<typeof addedStock> = {
lost:
currentStock + addedStock.incoming < addedStock.lost
- ? i18n`lost cannot be greater than current and incoming (max ${
+ ? i18n.str`lost cannot be greater than current and incoming (max ${
currentStock + addedStock.incoming
})`
: undefined,
@@ -142,8 +141,8 @@ export function InputStock<T>({
// const stockUpdateDescription = stockAddedErrors.lost ? '' : (
// !!addedStock.incoming || !!addedStock.lost ?
- // i18n`current stock will change from ${currentStock} to ${currentStock + addedStock.incoming - addedStock.lost}` :
- // i18n`current stock will stay at ${currentStock}`
+ // i18n.str`current stock will change from ${currentStock} to ${currentStock + addedStock.incoming - addedStock.lost}` :
+ // i18n.str`current stock will stay at ${currentStock}`
// )
return (
@@ -174,8 +173,8 @@ export function InputStock<T>({
object={addedStock}
valueHandler={setAddedStock as any}
>
- <InputNumber name="incoming" label={i18n`Incoming`} />
- <InputNumber name="lost" label={i18n`Lost`} />
+ <InputNumber name="incoming" label={i18n.str`Incoming`} />
+ <InputNumber name="lost" label={i18n.str`Lost`} />
</FormProvider>
{/* <div class="field is-horizontal">
@@ -190,17 +189,17 @@ export function InputStock<T>({
) : (
<InputNumber<Entity>
name="current"
- label={i18n`Current`}
+ label={i18n.str`Current`}
side={
<button
class="button is-danger"
- data-tooltip={i18n`remove stock control for this product`}
+ data-tooltip={i18n.str`remove stock control for this product`}
onClick={(): void => {
valueHandler(undefined as any);
}}
>
<span>
- <Translate>without stock</Translate>
+ <i18n.Translate>without stock</i18n.Translate>
</span>
</button>
}
@@ -209,11 +208,14 @@ export function InputStock<T>({
<InputDate<Entity>
name="nextRestock"
- label={i18n`Next restock`}
+ label={i18n.str`Next restock`}
withTimestampSupport
/>
- <InputGroup<Entity> name="address" label={i18n`Delivery address`}>
+ <InputGroup<Entity>
+ name="address"
+ label={i18n.str`Delivery address`}
+ >
<InputLocation name="address" />
</InputGroup>
</FormProvider>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputTaxes.tsx b/packages/merchant-backoffice-ui/src/components/form/InputTaxes.tsx
index d95463790..552ee73e2 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputTaxes.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputTaxes.tsx
@@ -18,11 +18,11 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useCallback, useState } from "preact/hooks";
import * as yup from "yup";
import { MerchantBackend } from "../../declaration.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { TaxSchema as schema } from "../../schemas/index.js";
import { FormErrors, FormProvider } from "./FormProvider.js";
import { Input } from "./Input.js";
@@ -67,7 +67,7 @@ export function InputTaxes<T>({
valueHandler({});
}, [value]);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
//FIXME: translating plural singular
return (
@@ -110,34 +110,35 @@ export function InputTaxes<T>({
/>
</div>
))}
- {!taxes.length && i18n`No taxes configured for this product.`}
+ {!taxes.length && i18n.str`No taxes configured for this product.`}
</div>
</div>
<Input<Entity>
name="tax"
- label={i18n`Amount`}
- tooltip={i18n`Taxes can be in currencies that differ from the main currency used by the merchant.`}
+ label={i18n.str`Amount`}
+ tooltip={i18n.str`Taxes can be in currencies that differ from the main currency used by the merchant.`}
>
- <Translate>
- Enter currency and value separated with a colon, e.g. "USD:2.3".
- </Translate>
+ <i18n.Translate>
+ Enter currency and value separated with a colon, e.g.
+ &quot;USD:2.3&quot;.
+ </i18n.Translate>
</Input>
<Input<Entity>
name="name"
- label={i18n`Description`}
- tooltip={i18n`Legal name of the tax, e.g. VAT or import duties.`}
+ label={i18n.str`Description`}
+ tooltip={i18n.str`Legal name of the tax, e.g. VAT or import duties.`}
/>
<div class="buttons is-right mt-5">
<button
class="button is-info"
- data-tooltip={i18n`add tax to the tax list`}
+ data-tooltip={i18n.str`add tax to the tax list`}
disabled={hasErrors}
onClick={submit}
>
- <Translate>Add</Translate>
+ <i18n.Translate>Add</i18n.Translate>
</button>
</div>
</FormProvider>
diff --git a/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx b/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
index 9dfa33840..c497773d9 100644
--- a/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
+++ b/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
@@ -19,9 +19,9 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useBackendContext } from "../../context/backend.js";
-import { useTranslator } from "../../i18n/index.js";
import { Entity } from "../../paths/admin/create/CreatePage.js";
import { Input } from "../form/Input.js";
import { InputCurrency } from "../form/InputCurrency.js";
@@ -39,7 +39,7 @@ export function DefaultInstanceFormFields({
readonlyId?: boolean;
showId: boolean;
}): VNode {
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const backend = useBackendContext();
return (
<Fragment>
@@ -48,86 +48,86 @@ export function DefaultInstanceFormFields({
name="id"
addonBefore={`${backend.url}/instances/`}
readonly={readonlyId}
- label={i18n`Identifier`}
- tooltip={i18n`Name of the instance in URLs. The 'default' instance is special in that it is used to administer other instances.`}
+ label={i18n.str`Identifier`}
+ tooltip={i18n.str`Name of the instance in URLs. The 'default' instance is special in that it is used to administer other instances.`}
/>
)}
<Input<Entity>
name="name"
- label={i18n`Business name`}
- tooltip={i18n`Legal name of the business represented by this instance.`}
+ label={i18n.str`Business name`}
+ tooltip={i18n.str`Legal name of the business represented by this instance.`}
/>
<Input<Entity>
name="email"
- label={i18n`Email`}
- tooltip={i18n`Contact email`}
+ label={i18n.str`Email`}
+ tooltip={i18n.str`Contact email`}
/>
<Input<Entity>
name="website"
- label={i18n`Website URL`}
- tooltip={i18n`URL.`}
+ label={i18n.str`Website URL`}
+ tooltip={i18n.str`URL.`}
/>
<InputImage<Entity>
name="logo"
- label={i18n`Logo`}
- tooltip={i18n`Logo image.`}
+ label={i18n.str`Logo`}
+ tooltip={i18n.str`Logo image.`}
/>
<InputPaytoForm<Entity>
name="payto_uris"
- label={i18n`Bank account`}
- tooltip={i18n`URI specifying bank account for crediting revenue.`}
+ label={i18n.str`Bank account`}
+ tooltip={i18n.str`URI specifying bank account for crediting revenue.`}
/>
<InputCurrency<Entity>
name="default_max_deposit_fee"
- label={i18n`Default max deposit fee`}
- tooltip={i18n`Maximum deposit fees this merchant is willing to pay per order by default.`}
+ label={i18n.str`Default max deposit fee`}
+ tooltip={i18n.str`Maximum deposit fees this merchant is willing to pay per order by default.`}
/>
<InputCurrency<Entity>
name="default_max_wire_fee"
- label={i18n`Default max wire fee`}
- tooltip={i18n`Maximum wire fees this merchant is willing to pay per wire transfer by default.`}
+ label={i18n.str`Default max wire fee`}
+ tooltip={i18n.str`Maximum wire fees this merchant is willing to pay per wire transfer by default.`}
/>
<Input<Entity>
name="default_wire_fee_amortization"
- label={i18n`Default wire fee amortization`}
- tooltip={i18n`Number of orders excess wire transfer fees will be divided by to compute per order surcharge.`}
+ label={i18n.str`Default wire fee amortization`}
+ tooltip={i18n.str`Number of orders excess wire transfer fees will be divided by to compute per order surcharge.`}
/>
<InputGroup
name="address"
- label={i18n`Address`}
- tooltip={i18n`Physical location of the merchant.`}
+ label={i18n.str`Address`}
+ tooltip={i18n.str`Physical location of the merchant.`}
>
<InputLocation name="address" />
</InputGroup>
<InputGroup
name="jurisdiction"
- label={i18n`Jurisdiction`}
- tooltip={i18n`Jurisdiction for legal disputes with the merchant.`}
+ label={i18n.str`Jurisdiction`}
+ tooltip={i18n.str`Jurisdiction for legal disputes with the merchant.`}
>
<InputLocation name="jurisdiction" />
</InputGroup>
<InputDuration<Entity>
name="default_pay_delay"
- label={i18n`Default payment delay`}
+ label={i18n.str`Default payment delay`}
withForever
- tooltip={i18n`Time customers have to pay an order before the offer expires by default.`}
+ tooltip={i18n.str`Time customers have to pay an order before the offer expires by default.`}
/>
<InputDuration<Entity>
name="default_wire_transfer_delay"
- label={i18n`Default wire transfer delay`}
- tooltip={i18n`Maximum time an exchange is allowed to delay wiring funds to the merchant, enabling it to aggregate smaller payments into larger wire transfers and reducing wire fees.`}
+ label={i18n.str`Default wire transfer delay`}
+ tooltip={i18n.str`Maximum time an exchange is allowed to delay wiring funds to the merchant, enabling it to aggregate smaller payments into larger wire transfers and reducing wire fees.`}
withForever
/>
</Fragment>
diff --git a/packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx b/packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx
index d618d6480..a1de8541e 100644
--- a/packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx
+++ b/packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx
@@ -19,11 +19,11 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import langIcon from "../../assets/icons/languageicon.svg";
-import { useTranslationContext } from "../../context/translation.js";
-import { strings as messages } from "../../i18n/strings";
+import { strings as messages } from "../../i18n/strings.js";
type LangsNames = {
[P in keyof typeof messages]: string;
diff --git a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
index ea49be99a..92d144b1a 100644
--- a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
+++ b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
@@ -19,13 +19,11 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
-import { useCallback } from "preact/hooks";
import { useBackendContext } from "../../context/backend.js";
import { useConfigContext } from "../../context/config.js";
-import { useInstanceContext } from "../../context/instance.js";
import { useInstanceKYCDetails } from "../../hooks/instance.js";
-import { Translate } from "../../i18n/index.js";
import { LangSelector } from "./LangSelector.js";
const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
@@ -48,7 +46,7 @@ export function Sidebar({
}: Props): VNode {
const config = useConfigContext();
const backend = useBackendContext();
-
+ const { i18n } = useTranslationContext();
const kycStatus = useInstanceKYCDetails();
const needKYC = kycStatus.ok && kycStatus.data.type === "redirect";
@@ -81,7 +79,7 @@ export function Sidebar({
{instance ? (
<Fragment>
<p class="menu-label">
- <Translate>Instance</Translate>
+ <i18n.Translate>Instance</i18n.Translate>
</p>
<ul class="menu-list">
<li>
@@ -90,7 +88,7 @@ export function Sidebar({
<i class="mdi mdi-square-edit-outline" />
</span>
<span class="menu-item-label">
- <Translate>Settings</Translate>
+ <i18n.Translate>Settings</i18n.Translate>
</span>
</a>
</li>
@@ -100,7 +98,7 @@ export function Sidebar({
<i class="mdi mdi-cash-register" />
</span>
<span class="menu-item-label">
- <Translate>Orders</Translate>
+ <i18n.Translate>Orders</i18n.Translate>
</span>
</a>
</li>
@@ -110,7 +108,7 @@ export function Sidebar({
<i class="mdi mdi-shopping" />
</span>
<span class="menu-item-label">
- <Translate>Products</Translate>
+ <i18n.Translate>Products</i18n.Translate>
</span>
</a>
</li>
@@ -120,7 +118,7 @@ export function Sidebar({
<i class="mdi mdi-bank" />
</span>
<span class="menu-item-label">
- <Translate>Transfers</Translate>
+ <i18n.Translate>Transfers</i18n.Translate>
</span>
</a>
</li>
@@ -130,7 +128,7 @@ export function Sidebar({
<i class="mdi mdi-newspaper" />
</span>
<span class="menu-item-label">
- <Translate>Templates</Translate>
+ <i18n.Translate>Templates</i18n.Translate>
</span>
</a>
</li>
@@ -156,7 +154,7 @@ export function Sidebar({
</Fragment>
) : undefined}
<p class="menu-label">
- <Translate>Connection</Translate>
+ <i18n.Translate>Connection</i18n.Translate>
</p>
<ul class="menu-list">
<li>
@@ -190,7 +188,7 @@ export function Sidebar({
{admin && !mimic && (
<Fragment>
<p class="menu-label">
- <Translate>Instances</Translate>
+ <i18n.Translate>Instances</i18n.Translate>
</p>
<li>
<a href={"/instance/new"} class="has-icon">
@@ -198,7 +196,7 @@ export function Sidebar({
<i class="mdi mdi-plus" />
</span>
<span class="menu-item-label">
- <Translate>New</Translate>
+ <i18n.Translate>New</i18n.Translate>
</span>
</a>
</li>
@@ -208,7 +206,7 @@ export function Sidebar({
<i class="mdi mdi-format-list-bulleted" />
</span>
<span class="menu-item-label">
- <Translate>List</Translate>
+ <i18n.Translate>List</i18n.Translate>
</span>
</a>
</li>
@@ -223,7 +221,7 @@ export function Sidebar({
<i class="mdi mdi-logout default" />
</span>
<span class="menu-item-label">
- <Translate>Log out</Translate>
+ <i18n.Translate>Log out</i18n.Translate>
</span>
</a>
</li>
diff --git a/packages/merchant-backoffice-ui/src/components/menu/index.tsx b/packages/merchant-backoffice-ui/src/components/menu/index.tsx
index 23935ec98..ccbd9442f 100644
--- a/packages/merchant-backoffice-ui/src/components/menu/index.tsx
+++ b/packages/merchant-backoffice-ui/src/components/menu/index.tsx
@@ -15,7 +15,6 @@
*/
import { ComponentChildren, Fragment, h, VNode } from "preact";
-import Match from "preact-router/match";
import { useEffect, useState } from "preact/hooks";
import { AdminPaths } from "../../AdminRoutes.js";
import { InstancePaths } from "../../InstanceRoutes.js";
@@ -58,6 +57,7 @@ function getAdminTitle(path: string, instance: string) {
interface MenuProps {
title?: string;
+ path: string;
instance: string;
admin?: boolean;
onLogout?: () => void;
@@ -81,64 +81,59 @@ export function Menu({
onLogout,
title,
instance,
+ path,
admin,
setInstanceName,
}: MenuProps): VNode {
const [mobileOpen, setMobileOpen] = useState(false);
+ const titleWithSubtitle = title
+ ? title
+ : !admin
+ ? getInstanceTitle(path, instance)
+ : getAdminTitle(path, instance);
+ const adminInstance = instance === "default";
+ const mimic = admin && !adminInstance;
return (
- <Match>
- {({ path }: any) => {
- const titleWithSubtitle = title
- ? title
- : !admin
- ? getInstanceTitle(path, instance)
- : getAdminTitle(path, instance);
- const adminInstance = instance === "default";
- const mimic = admin && !adminInstance;
- return (
- <WithTitle title={titleWithSubtitle}>
- <div
- class={mobileOpen ? "has-aside-mobile-expanded" : ""}
- onClick={() => setMobileOpen(false)}
- >
- <NavigationBar
- onMobileMenu={() => setMobileOpen(!mobileOpen)}
- title={titleWithSubtitle}
- />
-
- {onLogout && (
- <Sidebar
- onLogout={onLogout}
- admin={admin}
- mimic={mimic}
- instance={instance}
- mobile={mobileOpen}
- />
- )}
-
- {mimic && (
- <nav class="level">
- <div class="level-item has-text-centered has-background-warning">
- <p class="is-size-5">
- You are viewing the instance <b>"{instance}"</b>.{" "}
- <a
- href="#/instances"
- onClick={(e) => {
- setInstanceName("default");
- }}
- >
- go back
- </a>
- </p>
- </div>
- </nav>
- )}
+ <WithTitle title={titleWithSubtitle}>
+ <div
+ class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+ onClick={() => setMobileOpen(false)}
+ >
+ <NavigationBar
+ onMobileMenu={() => setMobileOpen(!mobileOpen)}
+ title={titleWithSubtitle}
+ />
+
+ {onLogout && (
+ <Sidebar
+ onLogout={onLogout}
+ admin={admin}
+ mimic={mimic}
+ instance={instance}
+ mobile={mobileOpen}
+ />
+ )}
+
+ {mimic && (
+ <nav class="level">
+ <div class="level-item has-text-centered has-background-warning">
+ <p class="is-size-5">
+ You are viewing the instance <b>&quot;{instance}&quot;</b>.{" "}
+ <a
+ href="#/instances"
+ onClick={(e) => {
+ setInstanceName("default");
+ }}
+ >
+ go back
+ </a>
+ </p>
</div>
- </WithTitle>
- );
- }}
- </Match>
+ </nav>
+ )}
+ </div>
+ </WithTitle>
);
}
diff --git a/packages/merchant-backoffice-ui/src/components/modal/index.tsx b/packages/merchant-backoffice-ui/src/components/modal/index.tsx
index 6e5575f63..c9c7d0ce5 100644
--- a/packages/merchant-backoffice-ui/src/components/modal/index.tsx
+++ b/packages/merchant-backoffice-ui/src/components/modal/index.tsx
@@ -19,12 +19,12 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { ComponentChildren, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useInstanceContext } from "../../context/instance.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { DEFAULT_REQUEST_TIMEOUT } from "../../utils/constants.js";
-import { Loading, Spinner } from "../exception/loading.js";
+import { Spinner } from "../exception/loading.js";
import { FormProvider } from "../form/FormProvider.js";
import { Input } from "../form/Input.js";
@@ -49,6 +49,7 @@ export function ConfirmModal({
disabled,
label = "Confirm",
}: Props): VNode {
+ const { i18n } = useTranslationContext();
return (
<div class={active ? "modal is-active" : "modal"}>
<div class="modal-background " onClick={onCancel} />
@@ -65,14 +66,14 @@ export function ConfirmModal({
<footer class="modal-card-foot">
<div class="buttons is-right" style={{ width: "100%" }}>
<button class="button " onClick={onCancel}>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</button>
<button
class={danger ? "button is-danger " : "button is-info "}
disabled={disabled}
onClick={onConfirm}
>
- <Translate>{label}</Translate>
+ <i18n.Translate>{label}</i18n.Translate>
</button>
</div>
</footer>
@@ -94,6 +95,7 @@ export function ContinueModal({
children,
disabled,
}: Props): VNode {
+ const { i18n } = useTranslationContext();
return (
<div class={active ? "modal is-active" : "modal"}>
<div class="modal-background " onClick={onCancel} />
@@ -110,7 +112,7 @@ export function ContinueModal({
disabled={disabled}
onClick={onConfirm}
>
- <Translate>Continue</Translate>
+ <i18n.Translate>Continue</i18n.Translate>
</button>
</div>
</footer>
@@ -147,6 +149,7 @@ export function ClearConfirmModal({
onConfirm,
children,
}: Props & { onClear?: () => void }): VNode {
+ const { i18n } = useTranslationContext();
return (
<div class="modal is-active">
<div class="modal-background " onClick={onCancel} />
@@ -163,19 +166,19 @@ export function ClearConfirmModal({
onClick={onClear}
disabled={onClear === undefined}
>
- <Translate>Clear</Translate>
+ <i18n.Translate>Clear</i18n.Translate>
</button>
)}
<div class="buttons is-right" style={{ width: "100%" }}>
<button class="button " onClick={onCancel}>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</button>
<button
class="button is-info"
onClick={onConfirm}
disabled={onConfirm === undefined}
>
- <Translate>Confirm</Translate>
+ <i18n.Translate>Confirm</i18n.Translate>
</button>
</div>
</footer>
@@ -210,7 +213,7 @@ export function DeleteModal({
onConfirm={() => onConfirm(element.id)}
>
<p>
- If you delete the instance named <b>"{element.name}"</b> (ID:{" "}
+ If you delete the instance named <b>&quot;{element.name}&quot;</b> (ID:{" "}
<b>{element.id}</b>), the merchant will no longer be able to process
orders or refunds
</p>
@@ -241,12 +244,13 @@ export function PurgeModal({
onConfirm={() => onConfirm(element.id)}
>
<p>
- If you purge the instance named <b>"{element.name}"</b> (ID:{" "}
- <b>{element.id}</b>), you will also delete all it's transaction data.
+ If you purge the instance named <b>&quot;{element.name}&quot;</b> (ID:{" "}
+ <b>{element.id}</b>), you will also delete all it&apos;s transaction
+ data.
</p>
<p>
The instance will disappear from your list, and you will no longer be
- able to access it's data.
+ able to access it&apos;s data.
</p>
<p class="warning">
Purging an instance <b>cannot be undone</b>.
@@ -275,20 +279,22 @@ export function UpdateTokenModal({
new_token: "",
repeat_token: "",
});
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const hasInputTheCorrectOldToken = oldToken && oldToken !== form.old_token;
const errors = {
old_token: hasInputTheCorrectOldToken
- ? i18n`is not the same as the current access token`
+ ? i18n.str`is not the same as the current access token`
: undefined,
new_token: !form.new_token
- ? i18n`cannot be empty`
+ ? i18n.str`cannot be empty`
: form.new_token === form.old_token
- ? i18n`cannot be the same as the old token`
+ ? i18n.str`cannot be the same as the old token`
: undefined,
repeat_token:
- form.new_token !== form.repeat_token ? i18n`is not the same` : undefined,
+ form.new_token !== form.repeat_token
+ ? i18n.str`is not the same`
+ : undefined,
};
const hasErrors = Object.keys(errors).some(
@@ -297,7 +303,7 @@ export function UpdateTokenModal({
const instance = useInstanceContext();
- const text = i18n`You are updating the access token from instance with id ${instance.id}`;
+ const text = i18n.str`You are updating the access token from instance with id ${instance.id}`;
return (
<ClearConfirmModal
@@ -313,28 +319,28 @@ export function UpdateTokenModal({
{oldToken && (
<Input<State>
name="old_token"
- label={i18n`Old access token`}
- tooltip={i18n`access token currently in use`}
+ label={i18n.str`Old access token`}
+ tooltip={i18n.str`access token currently in use`}
inputType="password"
/>
)}
<Input<State>
name="new_token"
- label={i18n`New access token`}
- tooltip={i18n`next access token to be used`}
+ label={i18n.str`New access token`}
+ tooltip={i18n.str`next access token to be used`}
inputType="password"
/>
<Input<State>
name="repeat_token"
- label={i18n`Repeat access token`}
- tooltip={i18n`confirm the same access token`}
+ label={i18n.str`Repeat access token`}
+ tooltip={i18n.str`confirm the same access token`}
inputType="password"
/>
</FormProvider>
<p>
- <Translate>
+ <i18n.Translate>
Clearing the access token will mean public access to the instance
- </Translate>
+ </i18n.Translate>
</p>
</div>
<div class="column" />
@@ -353,16 +359,18 @@ export function SetTokenNewInstanceModal({
new_token: "",
repeat_token: "",
});
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const errors = {
new_token: !form.new_token
- ? i18n`cannot be empty`
+ ? i18n.str`cannot be empty`
: form.new_token === form.old_token
- ? i18n`cannot be the same as the old access token`
+ ? i18n.str`cannot be the same as the old access token`
: undefined,
repeat_token:
- form.new_token !== form.repeat_token ? i18n`is not the same` : undefined,
+ form.new_token !== form.repeat_token
+ ? i18n.str`is not the same`
+ : undefined,
};
const hasErrors = Object.keys(errors).some(
@@ -374,7 +382,7 @@ export function SetTokenNewInstanceModal({
<div class="modal-background " onClick={onCancel} />
<div class="modal-card">
<header class="modal-card-head">
- <p class="modal-card-title">{i18n`You are setting the access token for the new instance`}</p>
+ <p class="modal-card-title">{i18n.str`You are setting the access token for the new instance`}</p>
<button class="delete " aria-label="close" onClick={onCancel} />
</header>
<section class="modal-card-body is-main-section">
@@ -388,22 +396,22 @@ export function SetTokenNewInstanceModal({
>
<Input<State>
name="new_token"
- label={i18n`New access token`}
- tooltip={i18n`next access token to be used`}
+ label={i18n.str`New access token`}
+ tooltip={i18n.str`next access token to be used`}
inputType="password"
/>
<Input<State>
name="repeat_token"
- label={i18n`Repeat access token`}
- tooltip={i18n`confirm the same access token`}
+ label={i18n.str`Repeat access token`}
+ tooltip={i18n.str`confirm the same access token`}
inputType="password"
/>
</FormProvider>
<p>
- <Translate>
+ <i18n.Translate>
With external authorization method no check will be done by
the merchant backend
- </Translate>
+ </i18n.Translate>
</p>
</div>
<div class="column" />
@@ -416,19 +424,19 @@ export function SetTokenNewInstanceModal({
onClick={onClear}
disabled={onClear === undefined}
>
- <Translate>Set external authorization</Translate>
+ <i18n.Translate>Set external authorization</i18n.Translate>
</button>
)}
<div class="buttons is-right" style={{ width: "100%" }}>
<button class="button " onClick={onCancel}>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</button>
<button
class="button is-info"
onClick={() => onConfirm(form.new_token!)}
disabled={hasErrors}
>
- <Translate>Set access token</Translate>
+ <i18n.Translate>Set access token</i18n.Translate>
</button>
</div>
</footer>
@@ -443,14 +451,14 @@ export function SetTokenNewInstanceModal({
}
export function LoadingModal({ onCancel }: { onCancel: () => void }): VNode {
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div class="modal is-active">
<div class="modal-background " onClick={onCancel} />
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">
- <Translate>Operation in progress...</Translate>
+ <i18n.Translate>Operation in progress...</i18n.Translate>
</p>
</header>
<section class="modal-card-body">
@@ -459,12 +467,12 @@ export function LoadingModal({ onCancel }: { onCancel: () => void }): VNode {
<Spinner />
<div class="column" />
</div>
- <p>{i18n`The operation will be automatically canceled after ${DEFAULT_REQUEST_TIMEOUT} seconds`}</p>
+ <p>{i18n.str`The operation will be automatically canceled after ${DEFAULT_REQUEST_TIMEOUT} seconds`}</p>
</section>
<footer class="modal-card-foot">
<div class="buttons is-right" style={{ width: "100%" }}>
<button class="button " onClick={onCancel}>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</button>
</div>
</footer>
diff --git a/packages/merchant-backoffice-ui/src/components/picker/DurationPicker.tsx b/packages/merchant-backoffice-ui/src/components/picker/DurationPicker.tsx
index 629e50b8c..0e8baac06 100644
--- a/packages/merchant-backoffice-ui/src/components/picker/DurationPicker.tsx
+++ b/packages/merchant-backoffice-ui/src/components/picker/DurationPicker.tsx
@@ -19,9 +19,9 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { useTranslator } from "../../i18n/index.js";
import "../../scss/DurationPicker.scss";
export interface Props {
@@ -46,13 +46,13 @@ export function DurationPicker({
const ms = ss * 60;
const hs = ms * 60;
const ds = hs * 24;
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div class="rdp-picker">
{days && (
<DurationColumn
- unit={i18n`days`}
+ unit={i18n.str`days`}
max={99}
value={Math.floor(value / ds)}
onDecrease={value >= ds ? () => onChange(value - ds) : undefined}
@@ -62,7 +62,7 @@ export function DurationPicker({
)}
{hours && (
<DurationColumn
- unit={i18n`hours`}
+ unit={i18n.str`hours`}
max={23}
min={1}
value={Math.floor(value / hs) % 24}
@@ -73,7 +73,7 @@ export function DurationPicker({
)}
{minutes && (
<DurationColumn
- unit={i18n`minutes`}
+ unit={i18n.str`minutes`}
max={59}
min={1}
value={Math.floor(value / ms) % 60}
@@ -84,7 +84,7 @@ export function DurationPicker({
)}
{seconds && (
<DurationColumn
- unit={i18n`seconds`}
+ unit={i18n.str`seconds`}
max={59}
value={Math.floor(value / ss) % 60}
onDecrease={value >= ss ? () => onChange(value - ss) : undefined}
diff --git a/packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx b/packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx
index da47f1be3..0cb2d555e 100644
--- a/packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx
+++ b/packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx
@@ -13,14 +13,14 @@
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 { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { FormProvider, FormErrors } from "../form/FormProvider.js";
-import { InputNumber } from "../form/InputNumber.js";
-import { InputSearchProduct } from "../form/InputSearchProduct.js";
import { MerchantBackend, WithId } from "../../declaration.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { ProductMap } from "../../paths/instance/orders/create/CreatePage.js";
+import { FormErrors, FormProvider } from "../form/FormProvider.js";
+import { InputNumber } from "../form/InputNumber.js";
+import { InputSearchProduct } from "../form/InputSearchProduct.js";
type Form = {
product: MerchantBackend.Products.ProductDetail & WithId;
@@ -45,21 +45,23 @@ export function InventoryProductForm({
const [state, setState] = useState<Partial<Form>>(initialState);
const [errors, setErrors] = useState<FormErrors<Form>>({});
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const productWithInfiniteStock =
state.product && state.product.total_stock === -1;
const submit = (): void => {
if (!state.product) {
- setErrors({ product: i18n`You must enter a valid product identifier.` });
+ setErrors({
+ product: i18n.str`You must enter a valid product identifier.`,
+ });
return;
}
if (productWithInfiniteStock) {
onAddProduct(state.product, 1);
} else {
if (!state.quantity || state.quantity <= 0) {
- setErrors({ quantity: i18n`Quantity must be greater than 0!` });
+ setErrors({ quantity: i18n.str`Quantity must be greater than 0!` });
return;
}
const currentStock =
@@ -71,7 +73,7 @@ export function InventoryProductForm({
if (state.quantity + p.quantity > currentStock) {
const left = currentStock - p.quantity;
setErrors({
- quantity: i18n`This quantity exceeds remaining stock. Currently, only ${left} units remain unreserved in stock.`,
+ quantity: i18n.str`This quantity exceeds remaining stock. Currently, only ${left} units remain unreserved in stock.`,
});
return;
}
@@ -80,7 +82,7 @@ export function InventoryProductForm({
if (state.quantity > currentStock) {
const left = currentStock;
setErrors({
- quantity: i18n`This quantity exceeds remaining stock. Currently, only ${left} units remain unreserved in stock.`,
+ quantity: i18n.str`This quantity exceeds remaining stock. Currently, only ${left} units remain unreserved in stock.`,
});
return;
}
@@ -104,15 +106,15 @@ export function InventoryProductForm({
{!productWithInfiniteStock && (
<InputNumber<Form>
name="quantity"
- label={i18n`Quantity`}
- tooltip={i18n`how many products will be added`}
+ label={i18n.str`Quantity`}
+ tooltip={i18n.str`how many products will be added`}
/>
)}
</div>
<div class="column">
<div class="buttons is-right">
<button class="button is-success" onClick={submit}>
- <Translate>Add from inventory</Translate>
+ <i18n.Translate>Add from inventory</i18n.Translate>
</button>
</div>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/product/NonInventoryProductForm.tsx b/packages/merchant-backoffice-ui/src/components/product/NonInventoryProductForm.tsx
index fe9692c02..3e7262657 100644
--- a/packages/merchant-backoffice-ui/src/components/product/NonInventoryProductForm.tsx
+++ b/packages/merchant-backoffice-ui/src/components/product/NonInventoryProductForm.tsx
@@ -13,19 +13,19 @@
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 { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useCallback, useEffect, useState } from "preact/hooks";
import * as yup from "yup";
+import { MerchantBackend } from "../../declaration.js";
+import { useListener } from "../../hooks/listener.js";
+import { NonInventoryProductSchema as schema } from "../../schemas/index.js";
import { FormErrors, FormProvider } from "../form/FormProvider.js";
import { Input } from "../form/Input.js";
import { InputCurrency } from "../form/InputCurrency.js";
import { InputImage } from "../form/InputImage.js";
import { InputNumber } from "../form/InputNumber.js";
import { InputTaxes } from "../form/InputTaxes.js";
-import { MerchantBackend } from "../../declaration.js";
-import { useListener } from "../../hooks/listener.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
-import { NonInventoryProductSchema as schema } from "../../schemas/index.js";
type Entity = MerchantBackend.Product;
@@ -62,17 +62,17 @@ export function NonInventoryProductFrom({
return Promise.resolve();
});
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<Fragment>
<div class="buttons">
<button
class="button is-success"
- data-tooltip={i18n`describe and add a product that is not in the inventory list`}
+ data-tooltip={i18n.str`describe and add a product that is not in the inventory list`}
onClick={() => setShowCreateProduct(true)}
>
- <Translate>Add custom product</Translate>
+ <i18n.Translate>Add custom product</i18n.Translate>
</button>
</div>
{showCreateProduct && (
@@ -83,7 +83,7 @@ export function NonInventoryProductFrom({
/>
<div class="modal-card">
<header class="modal-card-head">
- <p class="modal-card-title">{i18n`Complete information of the product`}</p>
+ <p class="modal-card-title">{i18n.str`Complete information of the product`}</p>
<button
class="delete "
aria-label="close"
@@ -102,14 +102,14 @@ export function NonInventoryProductFrom({
class="button "
onClick={() => setShowCreateProduct(false)}
>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</button>
<button
class="button is-info "
disabled={!submitForm}
onClick={submitForm}
>
- <Translate>Confirm</Translate>
+ <i18n.Translate>Confirm</i18n.Translate>
</button>
</div>
</footer>
@@ -170,7 +170,7 @@ export function ProductForm({ onSubscribe, initial }: ProductProps): VNode {
onSubscribe(hasErrors ? undefined : submit);
}, [submit, hasErrors]);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div>
@@ -182,33 +182,33 @@ export function ProductForm({ onSubscribe, initial }: ProductProps): VNode {
>
<InputImage<NonInventoryProduct>
name="image"
- label={i18n`Image`}
- tooltip={i18n`photo of the product`}
+ label={i18n.str`Image`}
+ tooltip={i18n.str`photo of the product`}
/>
<Input<NonInventoryProduct>
name="description"
inputType="multiline"
- label={i18n`Description`}
- tooltip={i18n`full product description`}
+ label={i18n.str`Description`}
+ tooltip={i18n.str`full product description`}
/>
<Input<NonInventoryProduct>
name="unit"
- label={i18n`Unit`}
- tooltip={i18n`name of the product unit`}
+ label={i18n.str`Unit`}
+ tooltip={i18n.str`name of the product unit`}
/>
<InputCurrency<NonInventoryProduct>
name="price"
- label={i18n`Price`}
- tooltip={i18n`amount in the current currency`}
+ label={i18n.str`Price`}
+ tooltip={i18n.str`amount in the current currency`}
/>
<InputNumber<NonInventoryProduct>
name="quantity"
- label={i18n`Quantity`}
- tooltip={i18n`how many products will be added`}
+ label={i18n.str`Quantity`}
+ tooltip={i18n.str`how many products will be added`}
/>
- <InputTaxes<NonInventoryProduct> name="taxes" label={i18n`Taxes`} />
+ <InputTaxes<NonInventoryProduct> name="taxes" label={i18n.str`Taxes`} />
</FormProvider>
</div>
);
diff --git a/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx b/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx
index a6bb090a5..973f88677 100644
--- a/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx
+++ b/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx
@@ -19,17 +19,17 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h } from "preact";
import { useCallback, useEffect, useState } from "preact/hooks";
import * as yup from "yup";
import { useBackendContext } from "../../context/backend.js";
import { MerchantBackend } from "../../declaration.js";
-import { useTranslator } from "../../i18n/index.js";
import {
ProductCreateSchema as createSchema,
ProductUpdateSchema as updateSchema,
} from "../../schemas/index.js";
-import { FormProvider, FormErrors } from "../form/FormProvider.js";
+import { FormErrors, FormProvider } from "../form/FormProvider.js";
import { Input } from "../form/Input.js";
import { InputCurrency } from "../form/InputCurrency.js";
import { InputImage } from "../form/InputImage.js";
@@ -115,7 +115,7 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) {
}, [submit, hasErrors]);
const backend = useBackendContext();
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div>
@@ -129,46 +129,46 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) {
<InputWithAddon<Entity>
name="product_id"
addonBefore={`${backend.url}/product/`}
- label={i18n`ID`}
- tooltip={i18n`product identification to use in URLs (for internal use only)`}
+ label={i18n.str`ID`}
+ tooltip={i18n.str`product identification to use in URLs (for internal use only)`}
/>
)}
<InputImage<Entity>
name="image"
- label={i18n`Image`}
- tooltip={i18n`illustration of the product for customers`}
+ label={i18n.str`Image`}
+ tooltip={i18n.str`illustration of the product for customers`}
/>
<Input<Entity>
name="description"
inputType="multiline"
- label={i18n`Description`}
- tooltip={i18n`product description for customers`}
+ label={i18n.str`Description`}
+ tooltip={i18n.str`product description for customers`}
/>
<InputNumber<Entity>
name="minimum_age"
- label={i18n`Age restricted`}
- tooltip={i18n`is this product restricted for customer below certain age?`}
+ label={i18n.str`Age restricted`}
+ tooltip={i18n.str`is this product restricted for customer below certain age?`}
/>
<Input<Entity>
name="unit"
- label={i18n`Unit`}
- tooltip={i18n`unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 items, 5 meters) for customers`}
+ label={i18n.str`Unit`}
+ tooltip={i18n.str`unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 items, 5 meters) for customers`}
/>
<InputCurrency<Entity>
name="price"
- label={i18n`Price`}
- tooltip={i18n`sale price for customers, including taxes, for above units of the product`}
+ label={i18n.str`Price`}
+ tooltip={i18n.str`sale price for customers, including taxes, for above units of the product`}
/>
<InputStock
name="stock"
- label={i18n`Stock`}
+ label={i18n.str`Stock`}
alreadyExist={alreadyExist}
- tooltip={i18n`product inventory for products with finite supply (for internal use only)`}
+ tooltip={i18n.str`product inventory for products with finite supply (for internal use only)`}
/>
<InputTaxes<Entity>
name="taxes"
- label={i18n`Taxes`}
- tooltip={i18n`taxes included in the product price, exposed to customers`}
+ label={i18n.str`Taxes`}
+ tooltip={i18n.str`taxes included in the product price, exposed to customers`}
/>
</FormProvider>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/product/ProductList.tsx b/packages/merchant-backoffice-ui/src/components/product/ProductList.tsx
index 774da8975..29556ea70 100644
--- a/packages/merchant-backoffice-ui/src/components/product/ProductList.tsx
+++ b/packages/merchant-backoffice-ui/src/components/product/ProductList.tsx
@@ -16,8 +16,8 @@
import { Amounts } from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import emptyImage from "../../assets/empty.png";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { MerchantBackend } from "../../declaration.js";
-import { Translate } from "../../i18n/index.js";
interface Props {
list: MerchantBackend.Product[];
@@ -28,25 +28,26 @@ interface Props {
}[];
}
export function ProductList({ list, actions = [] }: Props): VNode {
+ const { i18n } = useTranslationContext();
return (
<div class="table-container">
<table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
<thead>
<tr>
<th>
- <Translate>image</Translate>
+ <i18n.Translate>image</i18n.Translate>
</th>
<th>
- <Translate>description</Translate>
+ <i18n.Translate>description</i18n.Translate>
</th>
<th>
- <Translate>quantity</Translate>
+ <i18n.Translate>quantity</i18n.Translate>
</th>
<th>
- <Translate>unit price</Translate>
+ <i18n.Translate>unit price</i18n.Translate>
</th>
<th>
- <Translate>total price</Translate>
+ <i18n.Translate>total price</i18n.Translate>
</th>
<th />
</tr>