diff options
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths')
44 files changed, 666 insertions, 614 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/Create.stories.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/Create.stories.tsx index 052d61544..91b6b4b56 100644 --- a/packages/merchant-backoffice-ui/src/paths/admin/create/Create.stories.tsx +++ b/packages/merchant-backoffice-ui/src/paths/admin/create/Create.stories.tsx @@ -20,6 +20,7 @@ */ import { h, VNode, FunctionalComponent } from "preact"; +import { ConfigContextProvider } from "../../../context/config.js"; import { CreatePage as TestedComponent } from "./CreatePage.js"; export default { @@ -35,7 +36,16 @@ function createExample<Props>( Component: FunctionalComponent<Props>, props: Partial<Props>, ) { - const r = (args: any) => <Component {...args} />; + const r = (args: any) => ( + <ConfigContextProvider + value={{ + currency: "ARS", + version: "1", + }} + > + <Component {...args} /> + </ConfigContextProvider> + ); r.args = props; return r; } diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx index 6fcabb18b..bf5f5d7c9 100644 --- a/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx @@ -19,20 +19,19 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { Amounts } from "@gnu-taler/taler-util"; +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { h, VNode } from "preact"; import { useState } from "preact/hooks"; -import * as yup from "yup"; import { AsyncButton } from "../../../components/exception/AsyncButton.js"; import { FormErrors, FormProvider, } from "../../../components/form/FormProvider.js"; +import { DefaultInstanceFormFields } from "../../../components/instance/DefaultInstanceFormFields.js"; import { SetTokenNewInstanceModal } from "../../../components/modal/index.js"; import { MerchantBackend } from "../../../declaration.js"; -import { Translate, useTranslator } from "../../../i18n/index.js"; -import { DefaultInstanceFormFields } from "../../../components/instance/DefaultInstanceFormFields.js"; import { INSTANCE_ID_REGEX, PAYTO_REGEX } from "../../../utils/constants.js"; -import { Amounts } from "@gnu-taler/taler-util"; import { undefinedIfEmpty } from "../../../utils/table.js"; export type Entity = MerchantBackend.Instances.InstanceConfigurationMessage & { @@ -61,55 +60,57 @@ export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { const [isTokenDialogActive, updateIsTokenDialogActive] = useState<boolean>(false); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const errors: FormErrors<Entity> = { id: !value.id - ? i18n`required` + ? i18n.str`required` : !INSTANCE_ID_REGEX.test(value.id) - ? i18n`is not valid` + ? i18n.str`is not valid` : undefined, - name: !value.name ? i18n`required` : undefined, + name: !value.name ? i18n.str`required` : undefined, payto_uris: !value.payto_uris || !value.payto_uris.length - ? i18n`required` + ? i18n.str`required` : undefinedIfEmpty( value.payto_uris.map((p) => { - return !PAYTO_REGEX.test(p) ? i18n`is not valid` : undefined; + return !PAYTO_REGEX.test(p) ? i18n.str`is not valid` : undefined; }), ), default_max_deposit_fee: !value.default_max_deposit_fee - ? i18n`required` + ? i18n.str`required` : !Amounts.parse(value.default_max_deposit_fee) - ? i18n`invalid format` + ? i18n.str`invalid format` : undefined, default_max_wire_fee: !value.default_max_wire_fee - ? i18n`required` + ? i18n.str`required` : !Amounts.parse(value.default_max_wire_fee) - ? i18n`invalid format` + ? i18n.str`invalid format` : undefined, default_wire_fee_amortization: value.default_wire_fee_amortization === undefined - ? i18n`required` + ? i18n.str`required` : isNaN(value.default_wire_fee_amortization) - ? i18n`is not a number` + ? i18n.str`is not a number` : value.default_wire_fee_amortization < 1 - ? i18n`must be 1 or greater` + ? i18n.str`must be 1 or greater` : undefined, - default_pay_delay: !value.default_pay_delay ? i18n`required` : undefined, + default_pay_delay: !value.default_pay_delay + ? i18n.str`required` + : undefined, default_wire_transfer_delay: !value.default_wire_transfer_delay - ? i18n`required` + ? i18n.str`required` : undefined, address: undefinedIfEmpty({ address_lines: value.address?.address_lines && value.address?.address_lines.length > 7 - ? i18n`max 7 lines` + ? i18n.str`max 7 lines` : undefined, }), jurisdiction: undefinedIfEmpty({ address_lines: value.address?.address_lines && value.address?.address_lines.length > 7 - ? i18n`max 7 lines` + ? i18n.str`max 7 lines` : undefined, }), }; @@ -174,14 +175,14 @@ export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { <h1 class="title"> <button class="button is-danger has-tooltip-bottom" - data-tooltip={i18n`change authorization configuration`} + data-tooltip={i18n.str`change authorization configuration`} onClick={() => updateIsTokenDialogActive(true)} > <div class="icon is-centered"> <i class="mdi mdi-lock-reset" /> </div> <span> - <Translate>Set access token</Translate> + <i18n.Translate>Set access token</i18n.Translate> </span> </button> </h1> @@ -205,7 +206,7 @@ export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { <div class="buttons is-right mt-5"> {onBack && ( <button class="button" onClick={onBack}> - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> )} <AsyncButton @@ -213,11 +214,11 @@ export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { disabled={!isTokenSet || hasErrors} data-tooltip={ hasErrors - ? i18n`Need to complete marked fields and choose authorization method` + ? i18n.str`Need to complete marked fields and choose authorization method` : "confirm operation" } > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </AsyncButton> </div> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx index ed2f3f068..4da6916a0 100644 --- a/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx @@ -17,12 +17,12 @@ * * @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 { NotificationCard } from "../../../components/menu/index.js"; import { MerchantBackend } from "../../../declaration.js"; import { useAdminAPI } from "../../../hooks/instance.js"; -import { useTranslator } from "../../../i18n/index.js"; import { Notification } from "../../../utils/types.js"; import { CreatePage } from "./CreatePage.js"; import { InstanceCreatedSuccessfully } from "./InstanceCreatedSuccessfully.js"; @@ -38,7 +38,7 @@ export default function Create({ onBack, onConfirm, forceId }: Props): VNode { const { createInstance } = useAdminAPI(); const [notif, setNotif] = useState<Notification | undefined>(undefined); const [createdOk, setCreatedOk] = useState<Entity | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); if (createdOk) { return ( @@ -62,7 +62,7 @@ export default function Create({ onBack, onConfirm, forceId }: Props): VNode { }) .catch((error) => { setNotif({ - message: i18n`Failed to create instance`, + message: i18n.str`Failed to create instance`, type: "ERROR", description: error.message, }); diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/stories.ts b/packages/merchant-backoffice-ui/src/paths/admin/create/stories.tsx index 45b94ec8c..0012f9b9b 100644 --- a/packages/merchant-backoffice-ui/src/paths/admin/create/stories.ts +++ b/packages/merchant-backoffice-ui/src/paths/admin/create/stories.tsx @@ -20,6 +20,7 @@ */ import { h, VNode, FunctionalComponent } from "preact"; +import { ConfigContextProvider } from "../../../context/config.js"; import { CreatePage as TestedComponent } from "./CreatePage.js"; export default { @@ -32,17 +33,20 @@ export default { }; function createExample<Props>( - Component: FunctionalComponent<Props>, + Internal: FunctionalComponent<Props>, props: Partial<Props>, ) { - const r = (args: any) => h(Component, args); - // const r = (args: any) => <Component {...args} />; - r.args = props; - return r; + const component = (args: any) => ( + <ConfigContextProvider + value={{ + currency: "TESTKUDOS", + version: "1", + }} + > + <Internal {...(props as any)} /> + </ConfigContextProvider> + ); + return { component, props }; } export const Example = createExample(TestedComponent, {}); -// export const Example = (a: any): VNode => <CreatePage {...a} />; -// Example.args = { -// isLoading: false -// } diff --git a/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx b/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx index 546f34f3a..223db2fed 100644 --- a/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx +++ b/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx @@ -19,10 +19,10 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { h, VNode } from "preact"; import { StateUpdater, useEffect, useState } from "preact/hooks"; import { MerchantBackend } from "../../../declaration.js"; -import { Translate, useTranslator } from "../../../i18n/index.js"; interface Props { instances: MerchantBackend.Instances.Instance[]; @@ -68,7 +68,7 @@ export function CardTable({ } }, [actionQueue, selected, onUpdate]); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div class="card has-table"> @@ -77,7 +77,7 @@ export function CardTable({ <span class="icon"> <i class="mdi mdi-desktop-mac" /> </span> - <Translate>Instances</Translate> + <i18n.Translate>Instances</i18n.Translate> </p> <div class="card-header-icon" aria-label="more options"> @@ -90,11 +90,14 @@ export function CardTable({ ) } > - <Translate>Delete</Translate> + <i18n.Translate>Delete</i18n.Translate> </button> </div> <div class="card-header-icon" aria-label="more options"> - <span class="has-tooltip-left" data-tooltip={i18n`add new instance`}> + <span + class="has-tooltip-left" + data-tooltip={i18n.str`add new instance`} + > <button class="button is-info" type="button" onClick={onCreate}> <span class="icon is-small"> <i class="mdi mdi-plus mdi-36px" /> @@ -149,6 +152,7 @@ function Table({ onDelete, onPurge, }: TableProps): VNode { + const { i18n } = useTranslationContext(); return ( <div class="table-container"> <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> @@ -171,10 +175,10 @@ function Table({ </label> </th> <th> - <Translate>ID</Translate> + <i18n.Translate>ID</i18n.Translate> </th> <th> - <Translate>Name</Translate> + <i18n.Translate>Name</i18n.Translate> </th> <th /> </tr> @@ -213,7 +217,7 @@ function Table({ type="button" onClick={(): void => onUpdate(i.id)} > - <Translate>Edit</Translate> + <i18n.Translate>Edit</i18n.Translate> </button> {!i.deleted && ( <button @@ -221,7 +225,7 @@ function Table({ type="button" onClick={(): void => onDelete(i)} > - <Translate>Delete</Translate> + <i18n.Translate>Delete</i18n.Translate> </button> )} {i.deleted && ( @@ -230,7 +234,7 @@ function Table({ type="button" onClick={(): void => onPurge(i)} > - <Translate>Purge</Translate> + <i18n.Translate>Purge</i18n.Translate> </button> )} </div> @@ -245,6 +249,7 @@ function Table({ } function EmptyTable(): VNode { + const { i18n } = useTranslationContext(); return ( <div class="content has-text-grey has-text-centered"> <p> @@ -253,9 +258,9 @@ function EmptyTable(): VNode { </span> </p> <p> - <Translate> + <i18n.Translate> There is no instances yet, add more pressing the + sign - </Translate> + </i18n.Translate> </p> </div> ); diff --git a/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx b/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx index 5180c671c..7376a88cb 100644 --- a/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx +++ b/packages/merchant-backoffice-ui/src/paths/admin/list/View.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 { MerchantBackend } from "../../../declaration.js"; import { CardTable as CardTableActive } from "./TableActive.js"; -import { useState } from "preact/hooks"; -import { Translate, useTranslator } from "../../../i18n/index.js"; interface Props { instances: MerchantBackend.Instances.Instance[]; @@ -48,7 +48,7 @@ export function View({ const showIsActive = show === "active" ? "is-active" : ""; const showIsDeleted = show === "deleted" ? "is-active" : ""; const showAll = show === null ? "is-active" : ""; - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const showingInstances = showIsDeleted ? instances.filter((i) => i.deleted) @@ -66,30 +66,30 @@ export function View({ <li class={showIsActive}> <div class="has-tooltip-right" - data-tooltip={i18n`Only show active instances`} + data-tooltip={i18n.str`Only show active instances`} > <a onClick={() => setShow("active")}> - <Translate>Active</Translate> + <i18n.Translate>Active</i18n.Translate> </a> </div> </li> <li class={showIsDeleted}> <div class="has-tooltip-right" - data-tooltip={i18n`Only show deleted instances`} + data-tooltip={i18n.str`Only show deleted instances`} > <a onClick={() => setShow("deleted")}> - <Translate>Deleted</Translate> + <i18n.Translate>Deleted</i18n.Translate> </a> </div> </li> <li class={showAll}> <div class="has-tooltip-right" - data-tooltip={i18n`Show all instances`} + data-tooltip={i18n.str`Show all instances`} > <a onClick={() => setShow(null)}> - <Translate>All</Translate> + <i18n.Translate>All</i18n.Translate> </a> </div> </li> diff --git a/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx index 36d58dd41..9a81b72d4 100644 --- a/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx @@ -19,6 +19,7 @@ * @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 { Loading } from "../../../components/exception/loading.js"; @@ -27,7 +28,6 @@ import { DeleteModal, PurgeModal } from "../../../components/modal/index.js"; import { MerchantBackend } from "../../../declaration.js"; import { HttpError } from "../../../hooks/backend.js"; import { useAdminAPI, useBackendInstances } from "../../../hooks/instance.js"; -import { useTranslator } from "../../../i18n/index.js"; import { Notification } from "../../../utils/types.js"; import { View } from "./View.js"; @@ -56,7 +56,7 @@ export default function Instances({ useState<MerchantBackend.Instances.Instance | null>(null); const { deleteInstance, purgeInstance } = useAdminAPI(); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); if (result.clientError && result.isUnauthorized) return onUnauthorized(); if (result.clientError && result.isNotfound) return onNotFound(); @@ -84,12 +84,12 @@ export default function Instances({ await deleteInstance(deleting.id); // pushNotification({ message: 'delete_success', type: 'SUCCESS' }) setNotif({ - message: i18n`Instance "${deleting.name}" (ID: ${deleting.id}) has been deleted`, + message: i18n.str`Instance "${deleting.name}" (ID: ${deleting.id}) has been deleted`, type: "SUCCESS", }); } catch (error) { setNotif({ - message: i18n`Failed to delete instance`, + message: i18n.str`Failed to delete instance`, type: "ERROR", description: error instanceof Error ? error.message : undefined, }); @@ -107,12 +107,12 @@ export default function Instances({ try { await purgeInstance(purging.id); setNotif({ - message: i18n`Instance "${purging.name}" (ID: ${purging.id}) has been disabled`, + message: i18n.str`Instance "${purging.name}" (ID: ${purging.id}) has been disabled`, type: "SUCCESS", }); } catch (error) { setNotif({ - message: i18n`Failed to purge instance`, + message: i18n.str`Failed to purge instance`, type: "ERROR", description: error instanceof Error ? error.message : undefined, }); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/details/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/details/DetailPage.tsx index 59aa7a1d2..4ab415e85 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/details/DetailPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/details/DetailPage.tsx @@ -19,12 +19,12 @@ * @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 { FormProvider } from "../../../components/form/FormProvider.js"; import { Input } from "../../../components/form/Input.js"; import { MerchantBackend } from "../../../declaration.js"; -import { useTranslator } from "../../../i18n/index.js"; type Entity = MerchantBackend.Instances.InstanceReconfigurationMessage; interface Props { @@ -49,7 +49,7 @@ function convert( export function DetailPage({ selected }: Props): VNode { const [value, valueHandler] = useState<Partial<Entity>>(convert(selected)); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div> @@ -73,11 +73,11 @@ export function DetailPage({ selected }: Props): VNode { <div class="column" /> <div class="column is-6"> <FormProvider<Entity> object={value} valueHandler={valueHandler}> - <Input<Entity> name="name" readonly label={i18n`Name`} /> + <Input<Entity> name="name" readonly label={i18n.str`Name`} /> <Input<Entity> name="payto_uris" readonly - label={i18n`Account address`} + label={i18n.str`Account address`} /> </FormProvider> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx index 9ac1c4381..cdbe732a4 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx @@ -20,6 +20,7 @@ */ import { h, VNode, FunctionalComponent } from "preact"; +import { ConfigContextProvider } from "../../../context/config.js"; import { DetailPage as TestedComponent } from "./DetailPage.js"; export default { @@ -32,12 +33,20 @@ export default { }; function createExample<Props>( - Component: FunctionalComponent<Props>, + Internal: FunctionalComponent<Props>, props: Partial<Props>, ) { - const r = (args: any) => <Component {...args} />; - r.args = props; - return r; + const component = (args: any) => ( + <ConfigContextProvider + value={{ + currency: "TESTKUDOS", + version: "1", + }} + > + <Internal {...(props as any)} /> + </ConfigContextProvider> + ); + return { component, props }; } export const Example = createExample(TestedComponent, { diff --git a/packages/merchant-backoffice-ui/src/paths/instance/index.stories.ts b/packages/merchant-backoffice-ui/src/paths/instance/index.stories.ts index 3670c2807..fcb75cd7c 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/index.stories.ts +++ b/packages/merchant-backoffice-ui/src/paths/instance/index.stories.ts @@ -15,4 +15,3 @@ */ export * as details from "./details/stories.js"; - diff --git a/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx index c10121fb3..7966a2cdd 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx @@ -19,16 +19,16 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { h, VNode } from "preact"; import { MerchantBackend } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; export interface Props { status: MerchantBackend.Instances.AccountKycRedirects; } export function ListPage({ status }: Props): VNode { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <section class="section is-main-section"> @@ -38,7 +38,7 @@ export function ListPage({ status }: Props): VNode { <span class="icon"> <i class="mdi mdi-clock" /> </span> - <Translate>Pending KYC verification</Translate> + <i18n.Translate>Pending KYC verification</i18n.Translate> </p> <div class="card-header-icon" aria-label="more options" /> @@ -63,7 +63,7 @@ export function ListPage({ status }: Props): VNode { <span class="icon"> <i class="mdi mdi-clock" /> </span> - <Translate>Timed out</Translate> + <i18n.Translate>Timed out</i18n.Translate> </p> <div class="card-header-icon" aria-label="more options" /> @@ -93,19 +93,20 @@ interface TimedOutTableProps { } function PendingTable({ entries }: PendingTableProps): VNode { + const { i18n } = useTranslationContext(); return ( <div class="table-container"> <table class="table is-striped is-hoverable is-fullwidth"> <thead> <tr> <th> - <Translate>Exchange</Translate> + <i18n.Translate>Exchange</i18n.Translate> </th> <th> - <Translate>Target account</Translate> + <i18n.Translate>Target account</i18n.Translate> </th> <th> - <Translate>KYC URL</Translate> + <i18n.Translate>KYC URL</i18n.Translate> </th> </tr> </thead> @@ -130,19 +131,20 @@ function PendingTable({ entries }: PendingTableProps): VNode { } function TimedOutTable({ entries }: TimedOutTableProps): VNode { + const { i18n } = useTranslationContext(); return ( <div class="table-container"> <table class="table is-striped is-hoverable is-fullwidth"> <thead> <tr> <th> - <Translate>Exchange</Translate> + <i18n.Translate>Exchange</i18n.Translate> </th> <th> - <Translate>Code</Translate> + <i18n.Translate>Code</i18n.Translate> </th> <th> - <Translate>Http Status</Translate> + <i18n.Translate>Http Status</i18n.Translate> </th> </tr> </thead> @@ -163,6 +165,7 @@ function TimedOutTable({ entries }: TimedOutTableProps): VNode { } function EmptyTable(): VNode { + const { i18n } = useTranslationContext(); return ( <div class="content has-text-grey has-text-centered"> <p> @@ -171,7 +174,7 @@ function EmptyTable(): VNode { </span> </p> <p> - <Translate>No pending kyc verification!</Translate> + <i18n.Translate>No pending kyc verification!</i18n.Translate> </p> </div> ); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx index 145df717d..0c2e92418 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx @@ -19,29 +19,29 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { add, isAfter, isBefore, isFuture } from "date-fns"; import { Amounts } from "@gnu-taler/taler-util"; +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; +import { add, isAfter, isBefore, isFuture } from "date-fns"; import { Fragment, h, VNode } from "preact"; import { useEffect, useState } from "preact/hooks"; import { - FormProvider, FormErrors, + FormProvider, } from "../../../../components/form/FormProvider.js"; import { Input } from "../../../../components/form/Input.js"; +import { InputBoolean } from "../../../../components/form/InputBoolean.js"; import { InputCurrency } from "../../../../components/form/InputCurrency.js"; import { InputDate } from "../../../../components/form/InputDate.js"; import { InputGroup } from "../../../../components/form/InputGroup.js"; import { InputLocation } from "../../../../components/form/InputLocation.js"; +import { InputNumber } from "../../../../components/form/InputNumber.js"; +import { InventoryProductForm } from "../../../../components/product/InventoryProductForm.js"; +import { NonInventoryProductFrom } from "../../../../components/product/NonInventoryProductForm.js"; import { ProductList } from "../../../../components/product/ProductList.js"; import { useConfigContext } from "../../../../context/config.js"; import { Duration, MerchantBackend, WithId } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; import { OrderCreateSchema as schema } from "../../../../schemas/index.js"; import { rate } from "../../../../utils/amount.js"; -import { InventoryProductForm } from "../../../../components/product/InventoryProductForm.js"; -import { NonInventoryProductFrom } from "../../../../components/product/NonInventoryProductForm.js"; -import { InputNumber } from "../../../../components/form/InputNumber.js"; -import { InputBoolean } from "../../../../components/form/InputBoolean.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; interface Props { @@ -140,65 +140,65 @@ export function CreatePage({ const inventoryList = Object.values(value.inventoryProducts || {}); const productList = Object.values(value.products || {}); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const errors: FormErrors<Entity> = { pricing: undefinedIfEmpty({ - summary: !value.pricing?.summary ? i18n`required` : undefined, + summary: !value.pricing?.summary ? i18n.str`required` : undefined, order_price: !value.pricing?.order_price - ? i18n`required` + ? i18n.str`required` : Amounts.isZero(value.pricing.order_price) - ? i18n`must be greater than 0` + ? i18n.str`must be greater than 0` : undefined, }), extra: value.extra && !stringIsValidJSON(value.extra) - ? i18n`not a valid json` + ? i18n.str`not a valid json` : undefined, payments: undefinedIfEmpty({ refund_deadline: !value.payments?.refund_deadline ? undefined : !isFuture(value.payments.refund_deadline) - ? i18n`should be in the future` + ? i18n.str`should be in the future` : value.payments.pay_deadline && isBefore(value.payments.refund_deadline, value.payments.pay_deadline) - ? i18n`refund deadline cannot be before pay deadline` + ? i18n.str`refund deadline cannot be before pay deadline` : value.payments.wire_transfer_deadline && isBefore( value.payments.wire_transfer_deadline, value.payments.refund_deadline, ) - ? i18n`wire transfer deadline cannot be before refund deadline` + ? i18n.str`wire transfer deadline cannot be before refund deadline` : undefined, pay_deadline: !value.payments?.pay_deadline ? undefined : !isFuture(value.payments.pay_deadline) - ? i18n`should be in the future` + ? i18n.str`should be in the future` : value.payments.wire_transfer_deadline && isBefore( value.payments.wire_transfer_deadline, value.payments.pay_deadline, ) - ? i18n`wire transfer deadline cannot be before pay deadline` + ? i18n.str`wire transfer deadline cannot be before pay deadline` : undefined, auto_refund_deadline: !value.payments?.auto_refund_deadline ? undefined : !isFuture(value.payments.auto_refund_deadline) - ? i18n`should be in the future` + ? i18n.str`should be in the future` : !value.payments?.refund_deadline - ? i18n`should have a refund deadline` + ? i18n.str`should have a refund deadline` : !isAfter( value.payments.refund_deadline, value.payments.auto_refund_deadline, ) - ? i18n`auto refund cannot be after refund deadline` + ? i18n.str`auto refund cannot be after refund deadline` : undefined, }), shipping: undefinedIfEmpty({ delivery_date: !value.shipping?.delivery_date ? undefined : !isFuture(value.shipping.delivery_date) - ? i18n`should be in the future` + ? i18n.str`should be in the future` : undefined, }), }; @@ -349,7 +349,7 @@ export function CreatePage({ {/* // FIXME: translating plural singular */} <InputGroup name="inventory_products" - label={i18n`Manage products in order`} + label={i18n.str`Manage products in order`} alternative={ allProducts.length > 0 && ( <p> @@ -358,7 +358,7 @@ export function CreatePage({ </p> ) } - tooltip={i18n`Manage list of products in the order.`} + tooltip={i18n.str`Manage list of products in the order.`} > <InventoryProductForm currentProducts={value.inventoryProducts || {}} @@ -379,8 +379,8 @@ export function CreatePage({ list={allProducts} actions={[ { - name: i18n`Remove`, - tooltip: i18n`Remove this product from the order.`, + name: i18n.str`Remove`, + tooltip: i18n.str`Remove this product from the order.`, handler: (e, index) => { if (e.product_id) { removeProductFromTheInventoryList(e.product_id); @@ -404,13 +404,13 @@ export function CreatePage({ <Fragment> <InputCurrency name="pricing.products_price" - label={i18n`Total price`} + label={i18n.str`Total price`} readonly - tooltip={i18n`total product price added up`} + tooltip={i18n.str`total product price added up`} /> <InputCurrency name="pricing.order_price" - label={i18n`Total price`} + label={i18n.str`Total price`} addonAfter={ discountOrRise > 0 && (discountOrRise < 1 @@ -419,103 +419,103 @@ export function CreatePage({ )}` : `rise of %${Math.round((discountOrRise - 1) * 100)}`) } - tooltip={i18n`Amount to be paid by the customer`} + tooltip={i18n.str`Amount to be paid by the customer`} /> </Fragment> ) : ( <InputCurrency name="pricing.order_price" - label={i18n`Order price`} - tooltip={i18n`final order price`} + label={i18n.str`Order price`} + tooltip={i18n.str`final order price`} /> )} <Input name="pricing.summary" inputType="multiline" - label={i18n`Summary`} - tooltip={i18n`Title of the order to be shown to the customer`} + label={i18n.str`Summary`} + tooltip={i18n.str`Title of the order to be shown to the customer`} /> <InputGroup name="shipping" - label={i18n`Shipping and Fulfillment`} + label={i18n.str`Shipping and Fulfillment`} initialActive > <InputDate name="shipping.delivery_date" - label={i18n`Delivery date`} - tooltip={i18n`Deadline for physical delivery assured by the merchant.`} + label={i18n.str`Delivery date`} + tooltip={i18n.str`Deadline for physical delivery assured by the merchant.`} /> {value.shipping?.delivery_date && ( <InputGroup name="shipping.delivery_location" - label={i18n`Location`} - tooltip={i18n`address where the products will be delivered`} + label={i18n.str`Location`} + tooltip={i18n.str`address where the products will be delivered`} > <InputLocation name="shipping.delivery_location" /> </InputGroup> )} <Input name="shipping.fullfilment_url" - label={i18n`Fulfillment URL`} - tooltip={i18n`URL to which the user will be redirected after successful payment.`} + label={i18n.str`Fulfillment URL`} + tooltip={i18n.str`URL to which the user will be redirected after successful payment.`} /> </InputGroup> <InputGroup name="payments" - label={i18n`Taler payment options`} - tooltip={i18n`Override default Taler payment settings for this order`} + label={i18n.str`Taler payment options`} + tooltip={i18n.str`Override default Taler payment settings for this order`} > <InputDate name="payments.pay_deadline" - label={i18n`Payment deadline`} - tooltip={i18n`Deadline for the customer to pay for the offer before it expires. Inventory products will be reserved until this deadline.`} + label={i18n.str`Payment deadline`} + tooltip={i18n.str`Deadline for the customer to pay for the offer before it expires. Inventory products will be reserved until this deadline.`} /> <InputDate name="payments.refund_deadline" - label={i18n`Refund deadline`} - tooltip={i18n`Time until which the order can be refunded by the merchant.`} + label={i18n.str`Refund deadline`} + tooltip={i18n.str`Time until which the order can be refunded by the merchant.`} /> <InputDate name="payments.wire_transfer_deadline" - label={i18n`Wire transfer deadline`} - tooltip={i18n`Deadline for the exchange to make the wire transfer.`} + label={i18n.str`Wire transfer deadline`} + tooltip={i18n.str`Deadline for the exchange to make the wire transfer.`} /> <InputDate name="payments.auto_refund_deadline" - label={i18n`Auto-refund deadline`} - tooltip={i18n`Time until which the wallet will automatically check for refunds without user interaction.`} + label={i18n.str`Auto-refund deadline`} + tooltip={i18n.str`Time until which the wallet will automatically check for refunds without user interaction.`} /> <InputCurrency name="payments.max_fee" - label={i18n`Maximum deposit fee`} - tooltip={i18n`Maximum deposit fees the merchant is willing to cover for this order. Higher deposit fees must be covered in full by the consumer.`} + label={i18n.str`Maximum deposit fee`} + tooltip={i18n.str`Maximum deposit fees the merchant is willing to cover for this order. Higher deposit fees must be covered in full by the consumer.`} /> <InputCurrency name="payments.max_wire_fee" - label={i18n`Maximum wire fee`} - tooltip={i18n`Maximum aggregate wire fees the merchant is willing to cover for this order. Wire fees exceeding this amount are to be covered by the customers.`} + label={i18n.str`Maximum wire fee`} + tooltip={i18n.str`Maximum aggregate wire fees the merchant is willing to cover for this order. Wire fees exceeding this amount are to be covered by the customers.`} /> <InputNumber name="payments.wire_fee_amortization" - label={i18n`Wire fee amortization`} - tooltip={i18n`Factor by which wire fees exceeding the above threshold are divided to determine the share of excess wire fees to be paid explicitly by the consumer.`} + label={i18n.str`Wire fee amortization`} + tooltip={i18n.str`Factor by which wire fees exceeding the above threshold are divided to determine the share of excess wire fees to be paid explicitly by the consumer.`} /> <InputBoolean name="payments.createToken" - label={i18n`Create token`} - tooltip={i18n`Uncheck this option if the merchant backend generated an order ID with enough entropy to prevent adversarial claims.`} + label={i18n.str`Create token`} + tooltip={i18n.str`Uncheck this option if the merchant backend generated an order ID with enough entropy to prevent adversarial claims.`} /> <InputNumber name="payments.minimum_age" - label={i18n`Minimum age required`} - tooltip={i18n`Any value greater than 0 will limit the coins able be used to pay this contract. If empty the age restriction will be defined by the products`} + label={i18n.str`Minimum age required`} + tooltip={i18n.str`Any value greater than 0 will limit the coins able be used to pay this contract. If empty the age restriction will be defined by the products`} help={ minAgeByProducts > 0 - ? i18n`Min age defined by the producs is ${minAgeByProducts}` + ? i18n.str`Min age defined by the producs is ${minAgeByProducts}` : undefined } /> @@ -523,14 +523,14 @@ export function CreatePage({ <InputGroup name="extra" - label={i18n`Additional information`} - tooltip={i18n`Custom information to be included in the contract for this order.`} + label={i18n.str`Additional information`} + tooltip={i18n.str`Custom information to be included in the contract for this order.`} > <Input name="extra" inputType="multiline" label={`Value`} - tooltip={i18n`You must enter a value in JavaScript Object Notation (JSON).`} + tooltip={i18n.str`You must enter a value in JavaScript Object Notation (JSON).`} /> </InputGroup> </FormProvider> @@ -538,7 +538,7 @@ export function CreatePage({ <div class="buttons is-right mt-5"> {onBack && ( <button class="button" onClick={onBack}> - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> )} <button @@ -546,7 +546,7 @@ export function CreatePage({ onClick={submit} disabled={hasErrors} > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </button> </div> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx index 6d3ac311a..88c33e2f8 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx @@ -13,11 +13,11 @@ 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 { useEffect, useState } from "preact/hooks"; import { CreatedSuccessfully } from "../../../../components/notifications/CreatedSuccessfully.js"; import { useOrderAPI } from "../../../../hooks/order.js"; -import { Translate } from "../../../../i18n/index.js"; import { Entity } from "./index.js"; interface Props { @@ -33,7 +33,7 @@ export function OrderCreatedSuccessfully({ }: Props): VNode { const { getPaymentURL } = useOrderAPI(); const [url, setURL] = useState<string | undefined>(undefined); - + const { i18n } = useTranslationContext(); useEffect(() => { getPaymentURL(entity.response.order_id).then((response) => { setURL(response.data); @@ -48,7 +48,7 @@ export function OrderCreatedSuccessfully({ <div class="field is-horizontal"> <div class="field-label is-normal"> <label class="label"> - <Translate>Amount</Translate> + <i18n.Translate>Amount</i18n.Translate> </label> </div> <div class="field-body is-flex-grow-3"> @@ -66,7 +66,7 @@ export function OrderCreatedSuccessfully({ <div class="field is-horizontal"> <div class="field-label is-normal"> <label class="label"> - <Translate>Summary</Translate> + <i18n.Translate>Summary</i18n.Translate> </label> </div> <div class="field-body is-flex-grow-3"> @@ -84,7 +84,7 @@ export function OrderCreatedSuccessfully({ <div class="field is-horizontal"> <div class="field-label is-normal"> <label class="label"> - <Translate>Order ID</Translate> + <i18n.Translate>Order ID</i18n.Translate> </label> </div> <div class="field-body is-flex-grow-3"> @@ -98,7 +98,7 @@ export function OrderCreatedSuccessfully({ <div class="field is-horizontal"> <div class="field-label is-normal"> <label class="label"> - <Translate>Payment URL</Translate> + <i18n.Translate>Payment URL</i18n.Translate> </label> </div> <div class="field-body is-flex-grow-3"> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx index e8927dd70..1fba3c3e9 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx @@ -20,6 +20,7 @@ */ import { AmountJson, Amounts } from "@gnu-taler/taler-util"; +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { format } from "date-fns"; import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; @@ -34,7 +35,6 @@ import { TextField } from "../../../../components/form/TextField.js"; import { ProductList } from "../../../../components/product/ProductList.js"; import { useBackendContext } from "../../../../context/backend.js"; import { MerchantBackend } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; import { mergeRefunds } from "../../../../utils/amount.js"; import { RefundModal } from "../list/Table.js"; import { Event, Timeline } from "./Timeline.js"; @@ -56,84 +56,84 @@ type Unpaid = MerchantBackend.Orders.CheckPaymentUnpaidResponse; type Claimed = MerchantBackend.Orders.CheckPaymentClaimedResponse; function ContractTerms({ value }: { value: CT }) { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( - <InputGroup name="contract_terms" label={i18n`Contract Terms`}> + <InputGroup name="contract_terms" label={i18n.str`Contract Terms`}> <FormProvider<CT> object={value} valueHandler={null}> <Input<CT> readonly name="summary" - label={i18n`Summary`} - tooltip={i18n`human-readable description of the whole purchase`} + label={i18n.str`Summary`} + tooltip={i18n.str`human-readable description of the whole purchase`} /> <InputCurrency<CT> readonly name="amount" - label={i18n`Amount`} - tooltip={i18n`total price for the transaction`} + label={i18n.str`Amount`} + tooltip={i18n.str`total price for the transaction`} /> {value.fulfillment_url && ( <Input<CT> readonly name="fulfillment_url" - label={i18n`Fulfillment URL`} - tooltip={i18n`URL for this purchase`} + label={i18n.str`Fulfillment URL`} + tooltip={i18n.str`URL for this purchase`} /> )} <Input<CT> readonly name="max_fee" - label={i18n`Max fee`} - tooltip={i18n`maximum total deposit fee accepted by the merchant for this contract`} + label={i18n.str`Max fee`} + tooltip={i18n.str`maximum total deposit fee accepted by the merchant for this contract`} /> <Input<CT> readonly name="max_wire_fee" - label={i18n`Max wire fee`} - tooltip={i18n`maximum wire fee accepted by the merchant`} + label={i18n.str`Max wire fee`} + tooltip={i18n.str`maximum wire fee accepted by the merchant`} /> <Input<CT> readonly name="wire_fee_amortization" - label={i18n`Wire fee amortization`} - tooltip={i18n`over how many customer transactions does the merchant expect to amortize wire fees on average`} + label={i18n.str`Wire fee amortization`} + tooltip={i18n.str`over how many customer transactions does the merchant expect to amortize wire fees on average`} /> <InputDate<CT> readonly name="timestamp" - label={i18n`Created at`} - tooltip={i18n`time when this contract was generated`} + label={i18n.str`Created at`} + tooltip={i18n.str`time when this contract was generated`} /> <InputDate<CT> readonly name="refund_deadline" - label={i18n`Refund deadline`} - tooltip={i18n`after this deadline has passed no refunds will be accepted`} + label={i18n.str`Refund deadline`} + tooltip={i18n.str`after this deadline has passed no refunds will be accepted`} /> <InputDate<CT> readonly name="pay_deadline" - label={i18n`Payment deadline`} - tooltip={i18n`after this deadline, the merchant won't accept payments for the contract`} + label={i18n.str`Payment deadline`} + tooltip={i18n.str`after this deadline, the merchant won't accept payments for the contract`} /> <InputDate<CT> readonly name="wire_transfer_deadline" - label={i18n`Wire transfer deadline`} - tooltip={i18n`transfer deadline for the exchange`} + label={i18n.str`Wire transfer deadline`} + tooltip={i18n.str`transfer deadline for the exchange`} /> <InputDate<CT> readonly name="delivery_date" - label={i18n`Delivery date`} - tooltip={i18n`time indicating when the order should be delivered`} + label={i18n.str`Delivery date`} + tooltip={i18n.str`time indicating when the order should be delivered`} /> {value.delivery_date && ( <InputGroup name="delivery_location" - label={i18n`Location`} - tooltip={i18n`where the order will be delivered`} + label={i18n.str`Location`} + tooltip={i18n.str`where the order will be delivered`} > <InputLocation name="payments.delivery_location" /> </InputGroup> @@ -141,14 +141,14 @@ function ContractTerms({ value }: { value: CT }) { <InputDuration<CT> readonly name="auto_refund" - label={i18n`Auto-refund delay`} - tooltip={i18n`how long the wallet should try to get an automatic refund for the purchase`} + label={i18n.str`Auto-refund delay`} + tooltip={i18n.str`how long the wallet should try to get an automatic refund for the purchase`} /> <Input<CT> readonly name="extra" - label={i18n`Extra info`} - tooltip={i18n`extra data that is only interpreted by the merchant frontend`} + label={i18n.str`Extra info`} + tooltip={i18n.str`extra data that is only interpreted by the merchant frontend`} /> </FormProvider> </InputGroup> @@ -203,7 +203,7 @@ function ClaimedPage({ } const [value, valueHandler] = useState<Partial<Claimed>>(order); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div> @@ -216,9 +216,9 @@ function ClaimedPage({ <div class="level"> <div class="level-left"> <div class="level-item"> - <Translate>Order</Translate> #{id} + <i18n.Translate>Order</i18n.Translate> #{id} <div class="tag is-info ml-4"> - <Translate>claimed</Translate> + <i18n.Translate>claimed</i18n.Translate> </div> </div> </div> @@ -244,7 +244,7 @@ function ClaimedPage({ > <p> <b> - <Translate>claimed at</Translate>: + <i18n.Translate>claimed at</i18n.Translate>: </b>{" "} {format( new Date(order.contract_terms.timestamp.t_s * 1000), @@ -262,13 +262,13 @@ function ClaimedPage({ <div class="columns"> <div class="column is-4"> <div class="title"> - <Translate>Timeline</Translate> + <i18n.Translate>Timeline</i18n.Translate> </div> <Timeline events={events} /> </div> <div class="column is-8"> <div class="title"> - <Translate>Payment details</Translate> + <i18n.Translate>Payment details</i18n.Translate> </div> <FormProvider<Claimed> object={value} @@ -278,17 +278,17 @@ function ClaimedPage({ name="contract_terms.summary" readonly inputType="multiline" - label={i18n`Summary`} + label={i18n.str`Summary`} /> <InputCurrency name="contract_terms.amount" readonly - label={i18n`Amount`} + label={i18n.str`Amount`} /> <Input<Claimed> name="order_status" readonly - label={i18n`Order status`} + label={i18n.str`Order status`} /> </FormProvider> </div> @@ -298,7 +298,7 @@ function ClaimedPage({ {order.contract_terms.products.length ? ( <Fragment> <div class="title"> - <Translate>Product list</Translate> + <i18n.Translate>Product list</i18n.Translate> </div> <ProductList list={order.contract_terms.products} /> </Fragment> @@ -426,7 +426,7 @@ function PaidPage({ const refundurl = `${proto}://refund/${refundHost}/${order.contract_terms.order_id}/`; const refundable = new Date().getTime() < order.contract_terms.refund_deadline.t_s * 1000; - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const amount = Amounts.parseOrThrow(order.contract_terms.amount); const refund_taken = order.refund_details.reduce((prev, cur) => { @@ -446,18 +446,18 @@ function PaidPage({ <div class="level"> <div class="level-left"> <div class="level-item"> - <Translate>Order</Translate> #{id} + <i18n.Translate>Order</i18n.Translate> #{id} <div class="tag is-success ml-4"> - <Translate>paid</Translate> + <i18n.Translate>paid</i18n.Translate> </div> {order.wired ? ( <div class="tag is-success ml-4"> - <Translate>wired</Translate> + <i18n.Translate>wired</i18n.Translate> </div> ) : null} {order.refunded ? ( <div class="tag is-danger ml-4"> - <Translate>refunded</Translate> + <i18n.Translate>refunded</i18n.Translate> </div> ) : null} </div> @@ -477,8 +477,8 @@ function PaidPage({ class="has-tooltip-left" data-tooltip={ refundable - ? i18n`refund order` - : i18n`not refundable` + ? i18n.str`refund order` + : i18n.str`not refundable` } > <button @@ -486,7 +486,7 @@ function PaidPage({ disabled={!refundable} onClick={() => onRefund(id)} > - <Translate>refund</Translate> + <i18n.Translate>refund</i18n.Translate> </button> </span> </div> @@ -533,41 +533,41 @@ function PaidPage({ <div class="columns"> <div class="column is-4"> <div class="title"> - <Translate>Timeline</Translate> + <i18n.Translate>Timeline</i18n.Translate> </div> <Timeline events={events} /> </div> <div class="column is-8"> <div class="title"> - <Translate>Payment details</Translate> + <i18n.Translate>Payment details</i18n.Translate> </div> <FormProvider<Paid> object={value} valueHandler={valueHandler} > - {/* <InputCurrency<Paid> name="deposit_total" readonly label={i18n`Deposit total`} /> */} + {/* <InputCurrency<Paid> name="deposit_total" readonly label={i18n.str`Deposit total`} /> */} {order.refunded && ( <InputCurrency<Paid> name="refund_amount" readonly - label={i18n`Refunded amount`} + label={i18n.str`Refunded amount`} /> )} {order.refunded && ( <InputCurrency<Paid> name="refund_taken" readonly - label={i18n`Refund taken`} + label={i18n.str`Refund taken`} /> )} <Input<Paid> name="order_status" readonly - label={i18n`Order status`} + label={i18n.str`Order status`} /> <TextField<Paid> name="order_status_url" - label={i18n`Status URL`} + label={i18n.str`Status URL`} > <a target="_blank" @@ -580,7 +580,7 @@ function PaidPage({ {order.refunded && ( <TextField<Paid> name="order_status_url" - label={i18n`Refund URI`} + label={i18n.str`Refund URI`} > <a target="_blank" rel="noreferrer" href={refundurl}> {refundurl} @@ -595,7 +595,7 @@ function PaidPage({ {order.contract_terms.products.length ? ( <Fragment> <div class="title"> - <Translate>Product list</Translate> + <i18n.Translate>Product list</i18n.Translate> </div> <ProductList list={order.contract_terms.products} /> </Fragment> @@ -620,7 +620,7 @@ function UnpaidPage({ order: MerchantBackend.Orders.CheckPaymentUnpaidResponse; }) { const [value, valueHandler] = useState<Partial<Unpaid>>(order); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div> <section class="hero is-hero-bar"> @@ -629,11 +629,11 @@ function UnpaidPage({ <div class="level-left"> <div class="level-item"> <h1 class="title"> - <Translate>Order</Translate> #{id} + <i18n.Translate>Order</i18n.Translate> #{id} </h1> </div> <div class="tag is-dark"> - <Translate>unpaid</Translate> + <i18n.Translate>unpaid</i18n.Translate> </div> </div> </div> @@ -651,7 +651,7 @@ function UnpaidPage({ > <p> <b> - <Translate>pay at</Translate>: + <i18n.Translate>pay at</i18n.Translate>: </b>{" "} <a href={order.order_status_url} @@ -663,7 +663,7 @@ function UnpaidPage({ </p> <p> <b> - <Translate>created at</Translate>: + <i18n.Translate>created at</i18n.Translate>: </b>{" "} {order.creation_time.t_s === "never" ? "never" @@ -687,26 +687,29 @@ function UnpaidPage({ <Input<Unpaid> readonly name="summary" - label={i18n`Summary`} - tooltip={i18n`human-readable description of the whole purchase`} + label={i18n.str`Summary`} + tooltip={i18n.str`human-readable description of the whole purchase`} /> <InputCurrency<Unpaid> readonly name="total_amount" - label={i18n`Amount`} - tooltip={i18n`total price for the transaction`} + label={i18n.str`Amount`} + tooltip={i18n.str`total price for the transaction`} /> <Input<Unpaid> name="order_status" readonly - label={i18n`Order status`} + label={i18n.str`Order status`} /> <Input<Unpaid> name="order_status_url" readonly - label={i18n`Order status URL`} + label={i18n.str`Order status URL`} /> - <TextField<Unpaid> name="taler_pay_uri" label={i18n`Payment URI`}> + <TextField<Unpaid> + name="taler_pay_uri" + label={i18n.str`Payment URI`} + > <a target="_blank" rel="noreferrer" href={value.taler_pay_uri}> {value.taler_pay_uri} </a> @@ -722,7 +725,7 @@ function UnpaidPage({ export function DetailPage({ id, selected, onRefund, onBack }: Props): VNode { const [showRefund, setShowRefund] = useState<string | undefined>(undefined); - + const { i18n } = useTranslationContext(); const DetailByStatus = function () { switch (selected.order_status) { case "claimed": @@ -734,10 +737,10 @@ export function DetailPage({ id, selected, onRefund, onBack }: Props): VNode { default: return ( <div> - <Translate> + <i18n.Translate> Unknown order status. This is an error, please contact the administrator. - </Translate> + </i18n.Translate> </div> ); } @@ -761,7 +764,7 @@ export function DetailPage({ id, selected, onRefund, onBack }: Props): VNode { <div class="column is-four-fifths"> <div class="buttons is-right mt-5"> <button class="button" onClick={onBack}> - <Translate>Back</Translate> + <i18n.Translate>Back</i18n.Translate> </button> </div> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx index 4633688ba..bb0240982 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx @@ -13,13 +13,13 @@ 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 { useState } from "preact/hooks"; import { Loading } from "../../../../components/exception/loading.js"; import { NotificationCard } from "../../../../components/menu/index.js"; import { HttpError } from "../../../../hooks/backend.js"; -import { useOrderDetails, useOrderAPI } from "../../../../hooks/order.js"; -import { useTranslator } from "../../../../i18n/index.js"; +import { useOrderAPI, useOrderDetails } from "../../../../hooks/order.js"; import { Notification } from "../../../../utils/types.js"; import { DetailPage } from "./DetailPage.js"; @@ -43,7 +43,7 @@ export default function Update({ const result = useOrderDetails(oid); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); if (result.clientError && result.isUnauthorized) return onUnauthorized(); if (result.clientError && result.isNotfound) return onNotFound(); @@ -61,13 +61,13 @@ export default function Update({ refundOrder(id, value) .then(() => setNotif({ - message: i18n`refund created successfully`, + message: i18n.str`refund created successfully`, type: "SUCCESS", }), ) .catch((error) => setNotif({ - message: i18n`could not create the refund`, + message: i18n.str`could not create the refund`, type: "ERROR", description: error.message, }), diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx index bca90e352..3639ae912 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx @@ -19,12 +19,12 @@ * @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 { DatePicker } from "../../../../components/picker/DatePicker.js"; import { MerchantBackend, WithId } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; import { CardTable } from "./Table.js"; export interface ListPageProps { @@ -74,8 +74,8 @@ export function ListPage({ isNotWiredActive, onCreate, }: ListPageProps): VNode { - const i18n = useTranslator(); - const dateTooltip = i18n`select date to show nearby orders`; + const { i18n } = useTranslationContext(); + const dateTooltip = i18n.str`select date to show nearby orders`; const [pickDate, setPickDate] = useState(false); const [orderId, setOrderId] = useState<string>(""); @@ -91,13 +91,13 @@ export function ListPage({ type="text" value={orderId} onChange={(e) => setOrderId(e.currentTarget.value)} - placeholder={i18n`order id`} + placeholder={i18n.str`order id`} /> {errorOrderId && <p class="help is-danger">{errorOrderId}</p>} </div> <span class="has-tooltip-bottom" - data-tooltip={i18n`jump to order with the given order ID`} + data-tooltip={i18n.str`jump to order with the given order ID`} > <button class="button" @@ -119,40 +119,40 @@ export function ListPage({ <li class={isAllActive}> <div class="has-tooltip-right" - data-tooltip={i18n`remove all filters`} + data-tooltip={i18n.str`remove all filters`} > <a onClick={onShowAll}> - <Translate>All</Translate> + <i18n.Translate>All</i18n.Translate> </a> </div> </li> <li class={isPaidActive}> <div class="has-tooltip-right" - data-tooltip={i18n`only show paid orders`} + data-tooltip={i18n.str`only show paid orders`} > <a onClick={onShowPaid}> - <Translate>Paid</Translate> + <i18n.Translate>Paid</i18n.Translate> </a> </div> </li> <li class={isRefundedActive}> <div class="has-tooltip-right" - data-tooltip={i18n`only show orders with refunds`} + data-tooltip={i18n.str`only show orders with refunds`} > <a onClick={onShowRefunded}> - <Translate>Refunded</Translate> + <i18n.Translate>Refunded</i18n.Translate> </a> </div> </li> <li class={isNotWiredActive}> <div class="has-tooltip-left" - data-tooltip={i18n`only show orders where customers paid, but wire payments from payment provider are still pending`} + data-tooltip={i18n.str`only show orders where customers paid, but wire payments from payment provider are still pending`} > <a onClick={onShowNotWired}> - <Translate>Not wired</Translate> + <i18n.Translate>Not wired</i18n.Translate> </a> </div> </li> @@ -165,7 +165,10 @@ export function ListPage({ {jumpToDate && ( <div class="control"> <a class="button" onClick={() => onSelectDate(undefined)}> - <span class="icon" data-tooltip={i18n`clear date filter`}> + <span + class="icon" + data-tooltip={i18n.str`clear date filter`} + > <i class="mdi mdi-close" /> </span> </a> @@ -178,7 +181,7 @@ export function ListPage({ type="text" readonly value={!jumpToDate ? "" : format(jumpToDate, "yyyy/MM/dd")} - placeholder={i18n`date (YYYY/MM/DD)`} + placeholder={i18n.str`date (YYYY/MM/DD)`} onClick={() => { setPickDate(true); }} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx index a1ec8d291..b0a836f81 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx @@ -20,6 +20,7 @@ */ import { Amounts } from "@gnu-taler/taler-util"; +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { format } from "date-fns"; import { h, VNode } from "preact"; import { StateUpdater, useState } from "preact/hooks"; @@ -34,7 +35,6 @@ import { InputSelector } from "../../../../components/form/InputSelector.js"; import { ConfirmModal } from "../../../../components/modal/index.js"; import { useConfigContext } from "../../../../context/config.js"; import { MerchantBackend, WithId } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; import { mergeRefunds } from "../../../../utils/amount.js"; type Entity = MerchantBackend.Orders.OrderHistoryEntry & WithId; @@ -63,7 +63,7 @@ export function CardTable({ }: Props): VNode { const [rowSelection, rowSelectionHandler] = useState<string[]>([]); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div class="card has-table"> @@ -72,13 +72,13 @@ export function CardTable({ <span class="icon"> <i class="mdi mdi-cash-register" /> </span> - <Translate>Orders</Translate> + <i18n.Translate>Orders</i18n.Translate> </p> <div class="card-header-icon" aria-label="more options" /> <div class="card-header-icon" aria-label="more options"> - <span class="has-tooltip-left" data-tooltip={i18n`create order`}> + <span class="has-tooltip-left" data-tooltip={i18n.str`create order`}> <button class="button is-info" type="button" onClick={onCreate}> <span class="icon is-small"> <i class="mdi mdi-plus mdi-36px" /> @@ -135,6 +135,7 @@ function Table({ hasMoreAfter, hasMoreBefore, }: TableProps): VNode { + const { i18n } = useTranslationContext(); return ( <div class="table-container"> {onLoadMoreBefore && ( @@ -143,20 +144,20 @@ function Table({ disabled={!hasMoreBefore} onClick={onLoadMoreBefore} > - <Translate>load newer orders</Translate> + <i18n.Translate>load newer orders</i18n.Translate> </button> )} <table class="table is-striped is-hoverable is-fullwidth"> <thead> <tr> <th style={{ minWidth: 100 }}> - <Translate>Date</Translate> + <i18n.Translate>Date</i18n.Translate> </th> <th style={{ minWidth: 100 }}> - <Translate>Amount</Translate> + <i18n.Translate>Amount</i18n.Translate> </th> <th style={{ minWidth: 400 }}> - <Translate>Summary</Translate> + <i18n.Translate>Summary</i18n.Translate> </th> <th style={{ minWidth: 50 }} /> </tr> @@ -196,7 +197,7 @@ function Table({ type="button" onClick={(): void => onRefund(i)} > - <Translate>Refund</Translate> + <i18n.Translate>Refund</i18n.Translate> </button> )} {!i.paid && ( @@ -205,7 +206,7 @@ function Table({ type="button" onClick={(): void => onCopyURL(i)} > - <Translate>copy url</Translate> + <i18n.Translate>copy url</i18n.Translate> </button> )} </div> @@ -221,7 +222,7 @@ function Table({ disabled={!hasMoreAfter} onClick={onLoadMoreAfter} > - <Translate>load older orders</Translate> + <i18n.Translate>load older orders</i18n.Translate> </button> )} </div> @@ -229,6 +230,7 @@ function Table({ } function EmptyTable(): VNode { + const { i18n } = useTranslationContext(); return ( <div class="content has-text-grey has-text-centered"> <p> @@ -237,7 +239,9 @@ function EmptyTable(): VNode { </span> </p> <p> - <Translate>No orders have been found matching your query!</Translate> + <i18n.Translate> + No orders have been found matching your query! + </i18n.Translate> </p> </div> ); @@ -256,7 +260,7 @@ export function RefundModal({ }: RefundModalProps): VNode { type State = { mainReason?: string; description?: string; refund?: string }; const [form, setValue] = useState<State>({}); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); // const [errors, setErrors] = useState<FormErrors<State>>({}); const refunds = ( @@ -281,20 +285,20 @@ export function RefundModal({ : orderPrice; const isRefundable = Amounts.isNonZero(totalRefundable); - const duplicatedText = i18n`duplicated`; + const duplicatedText = i18n.str`duplicated`; const errors: FormErrors<State> = { - mainReason: !form.mainReason ? i18n`required` : undefined, + mainReason: !form.mainReason ? i18n.str`required` : undefined, description: !form.description && form.mainReason !== duplicatedText - ? i18n`required` + ? i18n.str`required` : undefined, refund: !form.refund - ? i18n`required` + ? i18n.str`required` : !Amounts.parse(form.refund) - ? i18n`invalid format` + ? i18n.str`invalid format` : Amounts.cmp(totalRefundable, Amounts.parse(form.refund)!) === -1 - ? i18n`this value exceed the refundable amount` + ? i18n.str`this value exceed the refundable amount` : undefined, }; const hasErrors = Object.keys(errors).some( @@ -339,13 +343,13 @@ export function RefundModal({ <thead> <tr> <th> - <Translate>date</Translate> + <i18n.Translate>date</i18n.Translate> </th> <th> - <Translate>amount</Translate> + <i18n.Translate>amount</i18n.Translate> </th> <th> - <Translate>reason</Translate> + <i18n.Translate>reason</i18n.Translate> </th> </tr> </thead> @@ -381,28 +385,28 @@ export function RefundModal({ > <InputCurrency<State> name="refund" - label={i18n`Refund`} - tooltip={i18n`amount to be refunded`} + label={i18n.str`Refund`} + tooltip={i18n.str`amount to be refunded`} > - <Translate>Max refundable:</Translate>{" "} + <i18n.Translate>Max refundable:</i18n.Translate>{" "} {Amounts.stringify(totalRefundable)} </InputCurrency> <InputSelector name="mainReason" - label={i18n`Reason`} + label={i18n.str`Reason`} values={[ - i18n`Choose one...`, + i18n.str`Choose one...`, duplicatedText, - i18n`requested by the customer`, - i18n`other`, + i18n.str`requested by the customer`, + i18n.str`other`, ]} - tooltip={i18n`why this order is being refunded`} + tooltip={i18n.str`why this order is being refunded`} /> {form.mainReason && form.mainReason !== duplicatedText ? ( <Input<State> - label={i18n`Description`} + label={i18n.str`Description`} name="description" - tooltip={i18n`more information to give context`} + tooltip={i18n.str`more information to give context`} /> ) : undefined} </FormProvider> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx index 315d78c63..e29c57a7c 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx @@ -19,7 +19,8 @@ * @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 { useState } from "preact/hooks"; import { Loading } from "../../../../components/exception/loading.js"; import { NotificationCard } from "../../../../components/menu/index.js"; @@ -31,10 +32,9 @@ import { useOrderAPI, useOrderDetails, } from "../../../../hooks/order.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { Notification } from "../../../../utils/types.js"; -import { RefundModal } from "./Table.js"; import { ListPage } from "./ListPage.js"; +import { RefundModal } from "./Table.js"; interface Props { onUnauthorized: () => VNode; @@ -64,7 +64,7 @@ export default function OrderList({ const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const [errorOrderId, setErrorOrderId] = useState<string | undefined>( undefined, ); @@ -86,7 +86,7 @@ export default function OrderList({ async function testIfOrderExistAndSelect(orderId: string): Promise<void> { if (!orderId) { - setErrorOrderId(i18n`Enter an order id`); + setErrorOrderId(i18n.str`Enter an order id`); return; } try { @@ -94,7 +94,7 @@ export default function OrderList({ onSelect(orderId); setErrorOrderId(undefined); } catch { - setErrorOrderId(i18n`order not found`); + setErrorOrderId(i18n.str`order not found`); } } @@ -136,13 +136,13 @@ export default function OrderList({ refundOrder(orderToBeRefunded.order_id, value) .then(() => setNotif({ - message: i18n`refund created successfully`, + message: i18n.str`refund created successfully`, type: "SUCCESS", }), ) .catch((error) => setNotif({ - message: i18n`could not create the refund`, + message: i18n.str`could not create the refund`, type: "ERROR", description: error.message, }), @@ -151,7 +151,7 @@ export default function OrderList({ } onLoadError={(error) => { setNotif({ - message: i18n`could not create the refund`, + message: i18n.str`could not create the refund`, type: "ERROR", description: error.message, }); @@ -161,7 +161,7 @@ export default function OrderList({ onUnauthorized={onUnauthorized} onNotFound={() => { setNotif({ - message: i18n`could not get the order to refund`, + message: i18n.str`could not get the order to refund`, type: "ERROR", // description: error.message }); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx index f6d7000ef..c18646be0 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx @@ -19,12 +19,12 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { h, VNode } from "preact"; import { AsyncButton } from "../../../../components/exception/AsyncButton.js"; import { ProductForm } from "../../../../components/product/ProductForm.js"; import { MerchantBackend } from "../../../../declaration.js"; import { useListener } from "../../../../hooks/listener.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; type Entity = MerchantBackend.Products.ProductAddDetail & { product_id: string; @@ -43,7 +43,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { }, ); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div> @@ -56,19 +56,19 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { <div class="buttons is-right mt-5"> {onBack && ( <button class="button" onClick={onBack}> - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> )} <AsyncButton onClick={submitForm} data-tooltip={ !submitForm - ? i18n`Need to complete marked fields` + ? i18n.str`Need to complete marked fields` : "confirm operation" } disabled={!submitForm} > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </AsyncButton> </div> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/create/index.tsx index 62ecaf512..f82d85e94 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/products/create/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/products/create/index.tsx @@ -19,12 +19,12 @@ * @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 { NotificationCard } from "../../../../components/menu/index.js"; import { MerchantBackend } from "../../../../declaration.js"; import { useProductAPI } from "../../../../hooks/product.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { Notification } from "../../../../utils/types.js"; import { CreatePage } from "./CreatePage.js"; @@ -36,7 +36,7 @@ interface Props { export default function CreateProduct({ onConfirm, onBack }: Props): VNode { const { createProduct } = useProductAPI(); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <Fragment> @@ -48,7 +48,7 @@ export default function CreateProduct({ onConfirm, onBack }: Props): VNode { .then(() => onConfirm()) .catch((error) => { setNotif({ - message: i18n`could not create product`, + message: i18n.str`could not create product`, type: "ERROR", description: error.message, }); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx index 515b36895..97d5afee5 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx @@ -19,19 +19,19 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { Amounts } from "@gnu-taler/taler-util"; +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { format } from "date-fns"; import { ComponentChildren, Fragment, h, VNode } from "preact"; import { StateUpdater, useState } from "preact/hooks"; +import emptyImage from "../../../../assets/empty.png"; import { - FormProvider, FormErrors, + FormProvider, } from "../../../../components/form/FormProvider.js"; import { InputCurrency } from "../../../../components/form/InputCurrency.js"; import { InputNumber } from "../../../../components/form/InputNumber.js"; import { MerchantBackend, WithId } from "../../../../declaration.js"; -import emptyImage from "../../../../assets/empty.png"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; -import { Amounts } from "@gnu-taler/taler-util"; type Entity = MerchantBackend.Products.ProductDetail & WithId; @@ -57,7 +57,7 @@ export function CardTable({ const [rowSelection, rowSelectionHandler] = useState<string | undefined>( undefined, ); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div class="card has-table"> <header class="card-header"> @@ -65,12 +65,12 @@ export function CardTable({ <span class="icon"> <i class="mdi mdi-shopping" /> </span> - <Translate>Products</Translate> + <i18n.Translate>Products</i18n.Translate> </p> <div class="card-header-icon" aria-label="more options"> <span class="has-tooltip-left" - data-tooltip={i18n`add product to inventory`} + data-tooltip={i18n.str`add product to inventory`} > <button class="button is-info" type="button" onClick={onCreate}> <span class="icon is-small"> @@ -121,32 +121,32 @@ function Table({ onUpdate, onDelete, }: TableProps): VNode { - const i18n = useTranslator(); + 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>Sell</Translate> + <i18n.Translate>Sell</i18n.Translate> </th> <th> - <Translate>Taxes</Translate> + <i18n.Translate>Taxes</i18n.Translate> </th> <th> - <Translate>Profit</Translate> + <i18n.Translate>Profit</i18n.Translate> </th> <th> - <Translate>Stock</Translate> + <i18n.Translate>Stock</i18n.Translate> </th> <th> - <Translate>Sold</Translate> + <i18n.Translate>Sold</i18n.Translate> </th> <th /> </tr> @@ -207,7 +207,7 @@ function Table({ } style={{ cursor: "pointer" }} > - {isFree ? i18n`free` : `${i.price} / ${i.unit}`} + {isFree ? i18n.str`free` : `${i.price} / ${i.unit}`} </td> <td onClick={() => @@ -245,26 +245,26 @@ function Table({ <div class="buttons is-right"> <span class="has-tooltip-bottom" - data-tooltip={i18n`go to product update page`} + data-tooltip={i18n.str`go to product update page`} > <button class="button is-small is-success " type="button" onClick={(): void => onSelect(i)} > - <Translate>Update</Translate> + <i18n.Translate>Update</i18n.Translate> </button> </span> <span class="has-tooltip-left" - data-tooltip={i18n`remove this product from the database`} + data-tooltip={i18n.str`remove this product from the database`} > <button class="button is-small is-danger" type="button" onClick={(): void => onDelete(i)} > - <Translate>Delete</Translate> + <i18n.Translate>Delete</i18n.Translate> </button> </span> </div> @@ -316,7 +316,7 @@ function FastProductWithInfiniteStockUpdateForm({ onCancel, }: FastProductUpdateFormProps) { const [value, valueHandler] = useState<UpdatePrice>({ price: product.price }); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <Fragment> @@ -327,18 +327,18 @@ function FastProductWithInfiniteStockUpdateForm({ > <InputCurrency<FastProductUpdate> name="price" - label={i18n`Price`} - tooltip={i18n`update the product with new price`} + label={i18n.str`Price`} + tooltip={i18n.str`update the product with new price`} /> </FormProvider> <div class="buttons is-right mt-5"> <button class="button" onClick={onCancel}> - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> <span class="has-tooltip-left" - data-tooltip={i18n`update product with new price`} + data-tooltip={i18n.str`update product with new price`} > <button class="button is-info" @@ -349,7 +349,7 @@ function FastProductWithInfiniteStockUpdateForm({ }) } > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </button> </span> </div> @@ -383,7 +383,7 @@ function FastProductWithManagedStockUpdateForm({ const hasErrors = Object.keys(errors).some( (k) => (errors as any)[k] !== undefined, ); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <Fragment> @@ -395,31 +395,31 @@ function FastProductWithManagedStockUpdateForm({ > <InputNumber<FastProductUpdate> name="incoming" - label={i18n`Incoming`} - tooltip={i18n`add more elements to the inventory`} + label={i18n.str`Incoming`} + tooltip={i18n.str`add more elements to the inventory`} /> <InputNumber<FastProductUpdate> name="lost" - label={i18n`Lost`} - tooltip={i18n`report elements lost in the inventory`} + label={i18n.str`Lost`} + tooltip={i18n.str`report elements lost in the inventory`} /> <InputCurrency<FastProductUpdate> name="price" - label={i18n`Price`} - tooltip={i18n`new price for the product`} + label={i18n.str`Price`} + tooltip={i18n.str`new price for the product`} /> </FormProvider> <div class="buttons is-right mt-5"> <button class="button" onClick={onCancel}> - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> <span class="has-tooltip-left" data-tooltip={ hasErrors - ? i18n`the are value with errors` - : i18n`update product with new stock and price` + ? i18n.str`the are value with errors` + : i18n.str`update product with new stock and price` } > <button @@ -434,7 +434,7 @@ function FastProductWithManagedStockUpdateForm({ }) } > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </button> </span> </div> @@ -451,6 +451,7 @@ function FastProductUpdateForm(props: FastProductUpdateFormProps) { } function EmptyTable(): VNode { + const { i18n } = useTranslationContext(); return ( <div class="content has-text-grey has-text-centered"> <p> @@ -459,9 +460,9 @@ function EmptyTable(): VNode { </span> </p> <p> - <Translate> + <i18n.Translate> There is no products yet, add more pressing the + sign - </Translate> + </i18n.Translate> </p> </div> ); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx index 7e9118d24..41a07a7aa 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx @@ -19,6 +19,7 @@ * @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 { Loading } from "../../../../components/exception/loading.js"; @@ -29,7 +30,6 @@ import { useInstanceProducts, useProductAPI, } from "../../../../hooks/product.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { Notification } from "../../../../utils/types.js"; import { CardTable } from "./Table.js"; @@ -51,7 +51,7 @@ export default function ProductList({ const { deleteProduct, updateProduct } = useProductAPI(); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); if (result.clientError && result.isUnauthorized) return onUnauthorized(); if (result.clientError && result.isNotfound) return onNotFound(); @@ -69,13 +69,13 @@ export default function ProductList({ updateProduct(id, prod) .then(() => setNotif({ - message: i18n`product updated successfully`, + message: i18n.str`product updated successfully`, type: "SUCCESS", }), ) .catch((error) => setNotif({ - message: i18n`could not update the product`, + message: i18n.str`could not update the product`, type: "ERROR", description: error.message, }), @@ -86,13 +86,13 @@ export default function ProductList({ deleteProduct(prod.id) .then(() => setNotif({ - message: i18n`product delete successfully`, + message: i18n.str`product delete successfully`, type: "SUCCESS", }), ) .catch((error) => setNotif({ - message: i18n`could not delete the product`, + message: i18n.str`could not delete the product`, type: "ERROR", description: error.message, }), diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/update/UpdatePage.tsx index 841c0222f..d179ef87c 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/products/update/UpdatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/products/update/UpdatePage.tsx @@ -19,12 +19,12 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { h, VNode } from "preact"; import { AsyncButton } from "../../../../components/exception/AsyncButton.js"; import { ProductForm } from "../../../../components/product/ProductForm.js"; -import { MerchantBackend, WithId } from "../../../../declaration.js"; +import { MerchantBackend } from "../../../../declaration.js"; import { useListener } from "../../../../hooks/listener.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; type Entity = MerchantBackend.Products.ProductDetail & { product_id: string }; @@ -42,7 +42,7 @@ export function UpdatePage({ product, onUpdate, onBack }: Props): VNode { }, ); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div> @@ -53,7 +53,7 @@ export function UpdatePage({ product, onUpdate, onBack }: Props): VNode { <div class="level-left"> <div class="level-item"> <span class="is-size-4"> - <Translate>Product id:</Translate> + <i18n.Translate>Product id:</i18n.Translate> <b>{product.product_id}</b> </span> </div> @@ -75,19 +75,19 @@ export function UpdatePage({ product, onUpdate, onBack }: Props): VNode { <div class="buttons is-right mt-5"> {onBack && ( <button class="button" onClick={onBack}> - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> )} <AsyncButton onClick={submitForm} data-tooltip={ !submitForm - ? i18n`Need to complete marked fields` + ? i18n.str`Need to complete marked fields` : "confirm operation" } disabled={!submitForm} > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </AsyncButton> </div> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/update/index.tsx index 3988fc9f0..e141dc52c 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/products/update/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/products/update/index.tsx @@ -19,6 +19,7 @@ * @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 { Loading } from "../../../../components/exception/loading.js"; @@ -26,7 +27,6 @@ import { NotificationCard } from "../../../../components/menu/index.js"; import { MerchantBackend } from "../../../../declaration.js"; import { HttpError } from "../../../../hooks/backend.js"; import { useProductAPI, useProductDetails } from "../../../../hooks/product.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { Notification } from "../../../../utils/types.js"; import { UpdatePage } from "./UpdatePage.js"; @@ -51,7 +51,7 @@ export default function UpdateProduct({ const result = useProductDetails(pid); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); if (result.clientError && result.isUnauthorized) return onUnauthorized(); if (result.clientError && result.isNotfound) return onNotFound(); @@ -69,7 +69,7 @@ export default function UpdateProduct({ .then(onConfirm) .catch((error) => { setNotif({ - message: i18n`could not create product`, + message: i18n.str`could not create product`, type: "ERROR", description: error.message, }); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx index 2c3e963b8..de2319636 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx @@ -19,24 +19,23 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { Fragment, h, VNode } from "preact"; import { StateUpdater, useEffect, useState } from "preact/hooks"; +import { AsyncButton } from "../../../../components/exception/AsyncButton.js"; import { FormErrors, FormProvider, } from "../../../../components/form/FormProvider.js"; import { Input } from "../../../../components/form/Input.js"; import { InputCurrency } from "../../../../components/form/InputCurrency.js"; +import { InputSelector } from "../../../../components/form/InputSelector.js"; import { ExchangeBackend, MerchantBackend } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; -import { AsyncButton } from "../../../../components/exception/AsyncButton.js"; -import { canonicalizeBaseUrl, ExchangeKeysJson } from "@gnu-taler/taler-util"; +import { request } from "../../../../hooks/backend.js"; import { PAYTO_WIRE_METHOD_LOOKUP, URL_REGEX, } from "../../../../utils/constants.js"; -import { request } from "../../../../hooks/backend.js"; -import { InputSelector } from "../../../../components/form/InputSelector.js"; type Entity = MerchantBackend.Tips.ReserveCreateRequest; @@ -66,7 +65,7 @@ function ViewStep({ submitForm, setReserve, }: ViewProps): VNode { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const [wireMethods, setWireMethods] = useState<Array<string>>([]); const [exchangeQueryError, setExchangeQueryError] = useState< string | undefined @@ -82,12 +81,12 @@ function ViewStep({ initial_balance: !reserve.initial_balance ? "cannot be empty" : !(parseInt(reserve.initial_balance.split(":")[1], 10) > 0) - ? i18n`it should be greater than 0` + ? i18n.str`it should be greater than 0` : undefined, exchange_url: !reserve.exchange_url - ? i18n`cannot be empty` + ? i18n.str`cannot be empty` : !URL_REGEX.test(reserve.exchange_url) - ? i18n`must be a valid URL` + ? i18n.str`must be a valid URL` : !exchangeQueryError ? undefined : exchangeQueryError, @@ -106,20 +105,20 @@ function ViewStep({ > <InputCurrency<Entity> name="initial_balance" - label={i18n`Initial balance`} - tooltip={i18n`balance prior to deposit`} + label={i18n.str`Initial balance`} + tooltip={i18n.str`balance prior to deposit`} /> <Input<Entity> name="exchange_url" - label={i18n`Exchange URL`} - tooltip={i18n`URL of exchange`} + label={i18n.str`Exchange URL`} + tooltip={i18n.str`URL of exchange`} /> </FormProvider> <div class="buttons is-right mt-5"> {onBack && ( <button class="button" onClick={onBack}> - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> )} <AsyncButton @@ -143,12 +142,12 @@ function ViewStep({ }} data-tooltip={ hasErrors - ? i18n`Need to complete marked fields` + ? i18n.str`Need to complete marked fields` : "confirm operation" } disabled={hasErrors} > - <Translate>Next</Translate> + <i18n.Translate>Next</i18n.Translate> </AsyncButton> </div> </Fragment> @@ -157,7 +156,9 @@ function ViewStep({ case Steps.WIRE_METHOD: { const errors: FormErrors<Entity> = { - wire_method: !reserve.wire_method ? i18n`cannot be empty` : undefined, + wire_method: !reserve.wire_method + ? i18n.str`cannot be empty` + : undefined, }; const hasErrors = Object.keys(errors).some( @@ -172,22 +173,22 @@ function ViewStep({ > <InputCurrency<Entity> name="initial_balance" - label={i18n`Initial balance`} - tooltip={i18n`balance prior to deposit`} + label={i18n.str`Initial balance`} + tooltip={i18n.str`balance prior to deposit`} readonly /> <Input<Entity> name="exchange_url" - label={i18n`Exchange URL`} - tooltip={i18n`URL of exchange`} + label={i18n.str`Exchange URL`} + tooltip={i18n.str`URL of exchange`} readonly /> <InputSelector<Entity> name="wire_method" - label={i18n`Wire method`} - tooltip={i18n`method to use for wire transfer`} + label={i18n.str`Wire method`} + tooltip={i18n.str`method to use for wire transfer`} values={wireMethods} - placeholder={i18n`Select one wire method`} + placeholder={i18n.str`Select one wire method`} /> </FormProvider> <div class="buttons is-right mt-5"> @@ -196,19 +197,19 @@ function ViewStep({ class="button" onClick={() => setCurrentStep(Steps.EXCHANGE)} > - <Translate>Back</Translate> + <i18n.Translate>Back</i18n.Translate> </button> )} <AsyncButton onClick={submitForm} data-tooltip={ hasErrors - ? i18n`Need to complete marked fields` + ? i18n.str`Need to complete marked fields` : "confirm operation" } disabled={hasErrors} > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </AsyncButton> </div> </Fragment> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx index 9bb228e1f..92427f3dc 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx @@ -14,11 +14,11 @@ 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 { QR } from "../../../../components/exception/QR.js"; import { CreatedSuccessfully as Template } from "../../../../components/notifications/CreatedSuccessfully.js"; import { MerchantBackend } from "../../../../declaration.js"; -import { Translate } from "../../../../i18n/index.js"; -import { QR } from "../../../../components/exception/QR.js"; type Entity = { request: MerchantBackend.Tips.ReserveCreateRequest; @@ -37,7 +37,7 @@ export function CreatedSuccessfully({ onCreateAnother, }: Props): VNode { const link = `${entity.response.payto_uri}?message=${entity.response.reserve_pub}&amount=${entity.request.initial_balance}`; - + const { i18n } = useTranslationContext(); return ( <Template onConfirm={onConfirm} onCreateAnother={onCreateAnother}> <div class="field is-horizontal"> @@ -85,16 +85,16 @@ export function CreatedSuccessfully({ </div> </div> <p class="is-size-5"> - <Translate> + <i18n.Translate> To complete the setup of the reserve, you must now initiate a wire transfer using the given wire transfer subject and crediting the specified amount to the indicated account of the exchange. - </Translate> + </i18n.Translate> </p> <p class="is-size-5"> - <Translate> + <i18n.Translate> If your system supports RFC 8905, you can do this by opening this URI: - </Translate> + </i18n.Translate> </p> <pre> <a target="_blank" rel="noreferrer" href={link}> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/index.tsx index 8b3ffb4ac..0d39fc298 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/index.tsx @@ -19,12 +19,12 @@ * @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 { NotificationCard } from "../../../../components/menu/index.js"; import { MerchantBackend } from "../../../../declaration.js"; import { useReservesAPI } from "../../../../hooks/reserves.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { Notification } from "../../../../utils/types.js"; import { CreatedSuccessfully } from "./CreatedSuccessfully.js"; import { CreatePage } from "./CreatePage.js"; @@ -35,7 +35,7 @@ interface Props { export default function CreateReserve({ onBack, onConfirm }: Props): VNode { const { createReserve } = useReservesAPI(); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const [createdOk, setCreatedOk] = useState< | { @@ -59,7 +59,7 @@ export default function CreateReserve({ onBack, onConfirm }: Props): VNode { .then((r) => setCreatedOk({ request, response: r.data })) .catch((error) => { setNotif({ - message: i18n`could not create reserve`, + message: i18n.str`could not create reserve`, type: "ERROR", description: error.message, }); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx index b0b291859..1d54198c8 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx @@ -20,6 +20,7 @@ */ import { Amounts } from "@gnu-taler/taler-util"; +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { format } from "date-fns"; import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; @@ -29,13 +30,9 @@ import { Input } from "../../../../components/form/Input.js"; import { InputCurrency } from "../../../../components/form/InputCurrency.js"; import { InputDate } from "../../../../components/form/InputDate.js"; import { TextField } from "../../../../components/form/TextField.js"; -import { - ContinueModal, - SimpleModal, -} from "../../../../components/modal/index.js"; +import { SimpleModal } from "../../../../components/modal/index.js"; import { MerchantBackend } from "../../../../declaration.js"; import { useTipDetails } from "../../../../hooks/reserves.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; import { TipInfo } from "./TipInfo.js"; type Entity = MerchantBackend.Tips.ReserveDetail; @@ -48,7 +45,7 @@ interface Props { } export function DetailPage({ id, selected, onBack }: Props): VNode { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const didExchangeAckTransfer = Amounts.isNonZero( Amounts.parseOrThrow(selected.exchange_initial_amount), ); @@ -62,22 +59,22 @@ export function DetailPage({ id, selected, onBack }: Props): VNode { <FormProvider object={{ ...selected, id }} valueHandler={null}> <InputDate<Entity> name="creation_time" - label={i18n`Created at`} + label={i18n.str`Created at`} readonly /> <InputDate<Entity> name="expiration_time" - label={i18n`Valid until`} + label={i18n.str`Valid until`} readonly /> <InputCurrency<Entity> name="merchant_initial_amount" - label={i18n`Created balance`} + label={i18n.str`Created balance`} readonly /> <TextField<Entity> name="exchange_url" - label={i18n`Exchange URL`} + label={i18n.str`Exchange URL`} readonly > <a target="_blank" rel="noreferrer" href={selected.exchange_url}> @@ -89,27 +86,27 @@ export function DetailPage({ id, selected, onBack }: Props): VNode { <Fragment> <InputCurrency<Entity> name="exchange_initial_amount" - label={i18n`Exchange balance`} + label={i18n.str`Exchange balance`} readonly /> <InputCurrency<Entity> name="pickup_amount" - label={i18n`Picked up`} + label={i18n.str`Picked up`} readonly /> <InputCurrency<Entity> name="committed_amount" - label={i18n`Committed`} + label={i18n.str`Committed`} readonly /> </Fragment> )} <Input<Entity> name="payto_uri" - label={i18n`Account address`} + label={i18n.str`Account address`} readonly /> - <Input name="id" label={i18n`Subject`} readonly /> + <Input name="id" label={i18n.str`Subject`} readonly /> </FormProvider> {didExchangeAckTransfer ? ( @@ -120,7 +117,7 @@ export function DetailPage({ id, selected, onBack }: Props): VNode { <span class="icon"> <i class="mdi mdi-cash-register" /> </span> - <Translate>Tips</Translate> + <i18n.Translate>Tips</i18n.Translate> </p> </header> <div class="card-content"> @@ -139,18 +136,18 @@ export function DetailPage({ id, selected, onBack }: Props): VNode { ) : ( <Fragment> <p class="is-size-5"> - <Translate> + <i18n.Translate> To complete the setup of the reserve, you must now initiate a wire transfer using the given wire transfer subject and crediting the specified amount to the indicated account of the exchange. - </Translate> + </i18n.Translate> </p> <p class="is-size-5"> - <Translate> + <i18n.Translate> If your system supports RFC 8905, you can do this by opening this URI: - </Translate> + </i18n.Translate> </p> <pre> <a target="_blank" rel="noreferrer" href={link}> @@ -163,7 +160,7 @@ export function DetailPage({ id, selected, onBack }: Props): VNode { <div class="buttons is-right mt-5"> <button class="button" onClick={onBack}> - <Translate>Back</Translate> + <i18n.Translate>Back</i18n.Translate> </button> </div> </div> @@ -174,6 +171,7 @@ export function DetailPage({ id, selected, onBack }: Props): VNode { } function EmptyTable(): VNode { + const { i18n } = useTranslationContext(); return ( <div class="content has-text-grey has-text-centered"> <p> @@ -182,7 +180,9 @@ function EmptyTable(): VNode { </span> </p> <p> - <Translate>No tips has been authorized from this reserve</Translate> + <i18n.Translate> + No tips has been authorized from this reserve + </i18n.Translate> </p> </div> ); @@ -193,22 +193,23 @@ interface TableProps { } function Table({ tips }: TableProps): VNode { + const { i18n } = useTranslationContext(); return ( <div class="table-container"> <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> <thead> <tr> <th> - <Translate>Authorized</Translate> + <i18n.Translate>Authorized</i18n.Translate> </th> <th> - <Translate>Picked up</Translate> + <i18n.Translate>Picked up</i18n.Translate> </th> <th> - <Translate>Reason</Translate> + <i18n.Translate>Reason</i18n.Translate> </th> <th> - <Translate>Expiration</Translate> + <i18n.Translate>Expiration</i18n.Translate> </th> </tr> </thead> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeTipModal.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeTipModal.tsx index 5200abedf..3a591c555 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeTipModal.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeTipModal.tsx @@ -19,8 +19,10 @@ * @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 * as yup from "yup"; import { FormErrors, FormProvider, @@ -32,10 +34,8 @@ import { ContinueModal, } from "../../../../components/modal/index.js"; import { MerchantBackend } from "../../../../declaration.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { AuthorizeTipSchema } from "../../../../schemas/index.js"; import { CreatedSuccessfully } from "./CreatedSuccessfully.js"; -import * as yup from "yup"; interface AuthorizeTipModalProps { onCancel: () => void; @@ -54,7 +54,7 @@ export function AuthorizeTipModal({ // const result = useOrderDetails(id) type State = MerchantBackend.Tips.TipCreateRequest; const [form, setValue] = useState<Partial<State>>({}); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); // const [errors, setErrors] = useState<FormErrors<State>>({}) let errors: FormErrors<State> = {}; @@ -104,19 +104,19 @@ export function AuthorizeTipModal({ > <InputCurrency<State> name="amount" - label={i18n`Amount`} - tooltip={i18n`amount of tip`} + label={i18n.str`Amount`} + tooltip={i18n.str`amount of tip`} /> <Input<State> name="justification" - label={i18n`Justification`} + label={i18n.str`Justification`} inputType="multiline" - tooltip={i18n`reason for the tip`} + tooltip={i18n.str`reason for the tip`} /> <Input<State> name="next_url" - label={i18n`URL after tip`} - tooltip={i18n`URL to visit after tip payment`} + label={i18n.str`URL after tip`} + tooltip={i18n.str`URL to visit after tip payment`} /> </FormProvider> </ConfirmModal> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/Table.tsx index 86b79d1dd..36768855d 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/Table.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/Table.tsx @@ -19,10 +19,10 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { format } from "date-fns"; import { Fragment, h, VNode } from "preact"; import { MerchantBackend, WithId } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; type Entity = MerchantBackend.Tips.ReserveStatusEntry & WithId; @@ -51,7 +51,7 @@ export function CardTable({ return prev; }, new Array<Array<Entity>>([], [])); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <Fragment> @@ -62,7 +62,7 @@ export function CardTable({ <span class="icon"> <i class="mdi mdi-cash" /> </span> - <Translate>Reserves not yet funded</Translate> + <i18n.Translate>Reserves not yet funded</i18n.Translate> </p> </header> <div class="card-content"> @@ -86,11 +86,14 @@ export function CardTable({ <span class="icon"> <i class="mdi mdi-cash" /> </span> - <Translate>Reserves ready</Translate> + <i18n.Translate>Reserves ready</i18n.Translate> </p> <div class="card-header-icon" aria-label="more options" /> <div class="card-header-icon" aria-label="more options"> - <span class="has-tooltip-left" data-tooltip={i18n`add new reserve`}> + <span + class="has-tooltip-left" + data-tooltip={i18n.str`add new reserve`} + > <button class="button is-info" type="button" onClick={onCreate}> <span class="icon is-small"> <i class="mdi mdi-plus mdi-36px" /> @@ -127,26 +130,26 @@ interface TableProps { } function Table({ instances, onNewTip, onSelect, onDelete }: TableProps): VNode { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div class="table-container"> <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> <thead> <tr> <th> - <Translate>Created at</Translate> + <i18n.Translate>Created at</i18n.Translate> </th> <th> - <Translate>Expires at</Translate> + <i18n.Translate>Expires at</i18n.Translate> </th> <th> - <Translate>Initial</Translate> + <i18n.Translate>Initial</i18n.Translate> </th> <th> - <Translate>Picked up</Translate> + <i18n.Translate>Picked up</i18n.Translate> </th> <th> - <Translate>Committed</Translate> + <i18n.Translate>Committed</i18n.Translate> </th> <th /> </tr> @@ -196,7 +199,7 @@ function Table({ instances, onNewTip, onSelect, onDelete }: TableProps): VNode { <div class="buttons is-right"> <button class="button is-small is-danger has-tooltip-left" - data-tooltip={i18n`delete selected reserve from the database`} + data-tooltip={i18n.str`delete selected reserve from the database`} type="button" onClick={(): void => onDelete(i)} > @@ -204,7 +207,7 @@ function Table({ instances, onNewTip, onSelect, onDelete }: TableProps): VNode { </button> <button class="button is-small is-info has-tooltip-left" - data-tooltip={i18n`authorize new tip from selected reserve`} + data-tooltip={i18n.str`authorize new tip from selected reserve`} type="button" onClick={(): void => onNewTip(i)} > @@ -222,6 +225,7 @@ function Table({ instances, onNewTip, onSelect, onDelete }: TableProps): VNode { } function EmptyTable(): VNode { + const { i18n } = useTranslationContext(); return ( <div class="content has-text-grey has-text-centered"> <p> @@ -230,10 +234,10 @@ function EmptyTable(): VNode { </span> </p> <p> - <Translate> + <i18n.Translate> There is no ready reserves yet, add more pressing the + sign or fund them - </Translate> + </i18n.Translate> </p> </div> ); @@ -244,20 +248,20 @@ function TableWithoutFund({ onSelect, onDelete, }: TableProps): VNode { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div class="table-container"> <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> <thead> <tr> <th> - <Translate>Created at</Translate> + <i18n.Translate>Created at</i18n.Translate> </th> <th> - <Translate>Expires at</Translate> + <i18n.Translate>Expires at</i18n.Translate> </th> <th> - <Translate>Expected Balance</Translate> + <i18n.Translate>Expected Balance</i18n.Translate> </th> <th /> </tr> @@ -296,7 +300,7 @@ function TableWithoutFund({ <button class="button is-small is-danger jb-modal has-tooltip-left" type="button" - data-tooltip={i18n`delete selected reserve from the database`} + data-tooltip={i18n.str`delete selected reserve from the database`} onClick={(): void => onDelete(i)} > Delete diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/index.tsx index 182b3f72c..9c3255ee8 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/index.tsx @@ -19,6 +19,7 @@ * @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 { Loading } from "../../../../components/exception/loading.js"; @@ -29,10 +30,9 @@ import { useInstanceReserves, useReservesAPI, } from "../../../../hooks/reserves.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { Notification } from "../../../../utils/types.js"; -import { CardTable } from "./Table.js"; import { AuthorizeTipModal } from "./AutorizeTipModal.js"; +import { CardTable } from "./Table.js"; interface Props { onUnauthorized: () => VNode; @@ -57,7 +57,7 @@ export default function ListTips({ const result = useInstanceReserves(); const { deleteReserve, authorizeTipReserve } = useReservesAPI(); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const [reserveForTip, setReserveForTip] = useState<string | undefined>( undefined, ); @@ -93,7 +93,7 @@ export default function ListTips({ }); } catch (error) { setNotif({ - message: i18n`could not create the tip`, + message: i18n.str`could not create the tip`, type: "ERROR", description: error instanceof Error ? error.message : undefined, }); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx index dba4b5d14..2a47c22a0 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx @@ -19,6 +19,7 @@ * @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 { AsyncButton } from "../../../../components/exception/AsyncButton.js"; @@ -33,7 +34,6 @@ import { InputNumber } from "../../../../components/form/InputNumber.js"; import { InputWithAddon } from "../../../../components/form/InputWithAddon.js"; import { useBackendContext } from "../../../../context/backend.js"; import { MerchantBackend } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; type Entity = MerchantBackend.Template.TemplateAddDetails; @@ -44,7 +44,7 @@ interface Props { } export function CreatePage({ onCreate, onBack }: Props): VNode { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const backend = useBackendContext(); const [state, setState] = useState<Partial<Entity>>({ @@ -57,23 +57,23 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { }); const errors: FormErrors<Entity> = { - template_id: !state.template_id ? i18n`should not be empty` : undefined, + template_id: !state.template_id ? i18n.str`should not be empty` : undefined, template_description: !state.template_description - ? i18n`should not be empty` + ? i18n.str`should not be empty` : undefined, template_contract: !state.template_contract ? undefined : undefinedIfEmpty({ minimum_age: state.template_contract.minimum_age < 0 - ? i18n`should be greater that 0` + ? i18n.str`should be greater that 0` : undefined, pay_duration: !state.template_contract.pay_duration - ? i18n`can't be empty` + ? i18n.str`can't be empty` : state.template_contract.pay_duration.d_us === "forever" ? undefined : state.template_contract.pay_duration.d_us < 1000 - ? i18n`to short` + ? i18n.str`to short` : undefined, }), }; @@ -101,57 +101,57 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { <InputWithAddon<Entity> name="template_id" addonBefore={`${backend.url}/instances/templates/`} - label={i18n`Identifier`} - tooltip={i18n`Name of the template in URLs.`} + label={i18n.str`Identifier`} + tooltip={i18n.str`Name of the template in URLs.`} /> <Input<Entity> name="template_description" - label={i18n`Description`} + label={i18n.str`Description`} help="" - tooltip={i18n`Describe what this template stands for`} + tooltip={i18n.str`Describe what this template stands for`} /> <Input name="template_contract.summary" inputType="multiline" - label={i18n`Order summary`} - tooltip={i18n`Title of the order to be shown to the customer`} + label={i18n.str`Order summary`} + tooltip={i18n.str`Title of the order to be shown to the customer`} /> <InputCurrency name="template_contract.amount" - label={i18n`Order price`} - tooltip={i18n`Order price`} + label={i18n.str`Order price`} + tooltip={i18n.str`Order price`} /> <InputNumber name="template_contract.minimum_age" - label={i18n`Minimum age`} + label={i18n.str`Minimum age`} help="" - tooltip={i18n`Is this contract restricted to some age?`} + tooltip={i18n.str`Is this contract restricted to some age?`} /> <InputDuration name="template_contract.pay_duration" - label={i18n`Payment timeout`} + label={i18n.str`Payment timeout`} help="" - tooltip={i18n`How much time has the customer to complete the payment once the order was created.`} + tooltip={i18n.str`How much time has the customer to complete the payment once the order was created.`} /> </FormProvider> <div class="buttons is-right mt-5"> {onBack && ( <button class="button" onClick={onBack}> - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> )} <AsyncButton disabled={hasErrors} data-tooltip={ hasErrors - ? i18n`Need to complete marked fields` + ? i18n.str`Need to complete marked fields` : "confirm operation" } onClick={submitForm} > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </AsyncButton> </div> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/index.tsx index bfedb7369..dcbf70106 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/index.tsx @@ -19,14 +19,12 @@ * @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 { NotificationCard } from "../../../../components/menu/index.js"; import { MerchantBackend } from "../../../../declaration.js"; -import { useInstanceDetails } from "../../../../hooks/instance.js"; import { useTemplateAPI } from "../../../../hooks/templates.js"; -import { useTransferAPI } from "../../../../hooks/transfer.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { Notification } from "../../../../utils/types.js"; import { CreatePage } from "./CreatePage.js"; @@ -39,7 +37,7 @@ interface Props { export default function CreateTransfer({ onConfirm, onBack }: Props): VNode { const { createTemplate } = useTemplateAPI(); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <> @@ -51,7 +49,7 @@ export default function CreateTransfer({ onConfirm, onBack }: Props): VNode { .then(() => onConfirm()) .catch((error) => { setNotif({ - message: i18n`could not inform template`, + message: i18n.str`could not inform template`, type: "ERROR", description: error.message, }); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx index dd983918f..9d289e957 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx @@ -21,7 +21,7 @@ import { h, VNode } from "preact"; import { MerchantBackend } from "../../../../declaration.js"; -import { useTranslator } from "../../../../i18n/index.js"; +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { CardTable } from "./Table.js"; export interface Props { @@ -43,7 +43,7 @@ export function ListPage({ }: Props): VNode { const form = { payto_uri: "" }; - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <section class="section is-main-section"> <CardTable diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx index bc8477039..fd6ea5f6f 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx @@ -19,10 +19,10 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { h, VNode } from "preact"; import { StateUpdater, useState } from "preact/hooks"; import { MerchantBackend } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; type Entity = MerchantBackend.Template.TemplateEntry; @@ -49,7 +49,7 @@ export function CardTable({ }: Props): VNode { const [rowSelection, rowSelectionHandler] = useState<string[]>([]); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div class="card has-table"> @@ -58,10 +58,13 @@ export function CardTable({ <span class="icon"> <i class="mdi mdi-newspaper" /> </span> - <Translate>Templates</Translate> + <i18n.Translate>Templates</i18n.Translate> </p> <div class="card-header-icon" aria-label="more options"> - <span class="has-tooltip-left" data-tooltip={i18n`add new templates`}> + <span + class="has-tooltip-left" + data-tooltip={i18n.str`add new templates`} + > <button class="button is-info" type="button" onClick={onCreate}> <span class="icon is-small"> <i class="mdi mdi-plus mdi-36px" /> @@ -120,27 +123,27 @@ function Table({ hasMoreAfter, hasMoreBefore, }: TableProps): VNode { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div class="table-container"> {onLoadMoreBefore && ( <button class="button is-fullwidth" - data-tooltip={i18n`load more templates before the first one`} + data-tooltip={i18n.str`load more templates before the first one`} disabled={!hasMoreBefore} onClick={onLoadMoreBefore} > - <Translate>load newer templates</Translate> + <i18n.Translate>load newer templates</i18n.Translate> </button> )} <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> <thead> <tr> <th> - <Translate>ID</Translate> + <i18n.Translate>ID</i18n.Translate> </th> <th> - <Translate>Description</Translate> + <i18n.Translate>Description</i18n.Translate> </th> <th /> </tr> @@ -164,7 +167,7 @@ function Table({ <td> <button class="button is-danger is-small has-tooltip-left" - data-tooltip={i18n`delete selected templates from the database`} + data-tooltip={i18n.str`delete selected templates from the database`} onClick={() => onDelete(i)} > Delete @@ -178,11 +181,11 @@ function Table({ {onLoadMoreAfter && ( <button class="button is-fullwidth" - data-tooltip={i18n`load more templates after the last one`} + data-tooltip={i18n.str`load more templates after the last one`} disabled={!hasMoreAfter} onClick={onLoadMoreAfter} > - <Translate>load older templates</Translate> + <i18n.Translate>load older templates</i18n.Translate> </button> )} </div> @@ -190,6 +193,7 @@ function Table({ } function EmptyTable(): VNode { + const { i18n } = useTranslationContext(); return ( <div class="content has-text-grey has-text-centered"> <p> @@ -198,9 +202,9 @@ function EmptyTable(): VNode { </span> </p> <p> - <Translate> + <i18n.Translate> There is no templates yet, add more pressing the + sign - </Translate> + </i18n.Translate> </p> </div> ); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx index 0d58093d3..dcac23983 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx @@ -19,6 +19,7 @@ * @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 { Loading } from "../../../../components/exception/loading.js"; @@ -29,7 +30,6 @@ import { useInstanceTemplates, useTemplateAPI, } from "../../../../hooks/templates.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { Notification } from "../../../../utils/types.js"; import { ListPage } from "./ListPage.js"; @@ -49,7 +49,7 @@ export default function ListTemplates({ onNotFound, }: Props): VNode { const [position, setPosition] = useState<string | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const [notif, setNotif] = useState<Notification | undefined>(undefined); const { deleteTemplate } = useTemplateAPI(); const result = useInstanceTemplates({ position }, (id) => setPosition(id)); @@ -77,13 +77,13 @@ export default function ListTemplates({ deleteTemplate(e.template_id) .then(() => setNotif({ - message: i18n`template delete successfully`, + message: i18n.str`template delete successfully`, type: "SUCCESS", }), ) .catch((error) => setNotif({ - message: i18n`could not delete the template`, + message: i18n.str`could not delete the template`, type: "ERROR", description: error.message, }), diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx index 42d9e5825..a49e8000b 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx @@ -19,6 +19,7 @@ * @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 { AsyncButton } from "../../../../components/exception/AsyncButton.js"; @@ -31,11 +32,8 @@ import { InputCurrency } from "../../../../components/form/InputCurrency.js"; import { InputDuration } from "../../../../components/form/InputDuration.js"; import { InputNumber } from "../../../../components/form/InputNumber.js"; import { InputWithAddon } from "../../../../components/form/InputWithAddon.js"; -import { ProductForm } from "../../../../components/product/ProductForm.js"; import { useBackendContext } from "../../../../context/backend.js"; import { MerchantBackend, WithId } from "../../../../declaration.js"; -import { useListener } from "../../../../hooks/listener.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; type Entity = MerchantBackend.Template.TemplatePatchDetails & WithId; @@ -47,28 +45,28 @@ interface Props { } export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const backend = useBackendContext(); const [state, setState] = useState<Partial<Entity>>(template); const errors: FormErrors<Entity> = { template_description: !state.template_description - ? i18n`should not be empty` + ? i18n.str`should not be empty` : undefined, template_contract: !state.template_contract ? undefined : undefinedIfEmpty({ minimum_age: state.template_contract.minimum_age < 0 - ? i18n`should be greater that 0` + ? i18n.str`should be greater that 0` : undefined, pay_duration: !state.template_contract.pay_duration - ? i18n`can't be empty` + ? i18n.str`can't be empty` : state.template_contract.pay_duration.d_us === "forever" ? undefined : state.template_contract.pay_duration.d_us < 1000 - ? i18n`to short` + ? i18n.str`to short` : undefined, }), }; @@ -112,57 +110,57 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { name="id" addonBefore={`templates/`} readonly - label={i18n`Identifier`} - tooltip={i18n`Name of the template in URLs.`} + label={i18n.str`Identifier`} + tooltip={i18n.str`Name of the template in URLs.`} /> <Input<Entity> name="template_description" - label={i18n`Description`} + label={i18n.str`Description`} help="" - tooltip={i18n`Describe what this template stands for`} + tooltip={i18n.str`Describe what this template stands for`} /> <Input name="template_contract.summary" inputType="multiline" - label={i18n`Order summary`} - tooltip={i18n`Title of the order to be shown to the customer`} + label={i18n.str`Order summary`} + tooltip={i18n.str`Title of the order to be shown to the customer`} /> <InputCurrency name="template_contract.amount" - label={i18n`Order price`} - tooltip={i18n`total product price added up`} + label={i18n.str`Order price`} + tooltip={i18n.str`total product price added up`} /> <InputNumber name="template_contract.minimum_age" - label={i18n`Minimum age`} + label={i18n.str`Minimum age`} help="" - tooltip={i18n`Is this contract restricted to some age?`} + tooltip={i18n.str`Is this contract restricted to some age?`} /> <InputDuration name="template_contract.pay_duration" - label={i18n`Payment timeout`} + label={i18n.str`Payment timeout`} help="" - tooltip={i18n`How much time has the customer to complete the payment once the order was created.`} + tooltip={i18n.str`How much time has the customer to complete the payment once the order was created.`} /> </FormProvider> <div class="buttons is-right mt-5"> {onBack && ( <button class="button" onClick={onBack}> - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> )} <AsyncButton disabled={hasErrors} data-tooltip={ hasErrors - ? i18n`Need to complete marked fields` + ? i18n.str`Need to complete marked fields` : "confirm operation" } onClick={submitForm} > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </AsyncButton> </div> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx index 25dc9abdc..4a4cc4274 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx @@ -19,18 +19,17 @@ * @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 { Loading } from "../../../../components/exception/loading.js"; import { NotificationCard } from "../../../../components/menu/index.js"; import { MerchantBackend, WithId } from "../../../../declaration.js"; import { HttpError } from "../../../../hooks/backend.js"; -import { useProductAPI, useProductDetails } from "../../../../hooks/product.js"; import { useTemplateAPI, useTemplateDetails, } from "../../../../hooks/templates.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { Notification } from "../../../../utils/types.js"; import { UpdatePage } from "./UpdatePage.js"; @@ -56,7 +55,7 @@ export default function UpdateTemplate({ const result = useTemplateDetails(tid); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); if (result.clientError && result.isUnauthorized) return onUnauthorized(); if (result.clientError && result.isNotfound) return onNotFound(); @@ -74,7 +73,7 @@ export default function UpdateTemplate({ .then(onConfirm) .catch((error) => { setNotif({ - message: i18n`could not update template`, + message: i18n.str`could not update template`, type: "ERROR", description: error.message, }); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx index 5b041df7c..5303d14d9 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx @@ -19,6 +19,7 @@ * @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 { AsyncButton } from "../../../../components/exception/AsyncButton.js"; @@ -31,7 +32,6 @@ import { InputCurrency } from "../../../../components/form/InputCurrency.js"; import { InputSelector } from "../../../../components/form/InputSelector.js"; import { useConfigContext } from "../../../../context/config.js"; import { MerchantBackend } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; import { CROCKFORD_BASE32_REGEX, URL_REGEX, @@ -46,7 +46,7 @@ interface Props { } export function CreatePage({ accounts, onCreate, onBack }: Props): VNode { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const { currency } = useConfigContext(); const [state, setState] = useState<Partial<Entity>>({ @@ -58,18 +58,18 @@ export function CreatePage({ accounts, onCreate, onBack }: Props): VNode { const errors: FormErrors<Entity> = { wtid: !state.wtid - ? i18n`cannot be empty` + ? i18n.str`cannot be empty` : !CROCKFORD_BASE32_REGEX.test(state.wtid) - ? i18n`check the id, does not look valid` + ? i18n.str`check the id, does not look valid` : state.wtid.length !== 52 - ? i18n`should have 52 characters, current ${state.wtid.length}` + ? i18n.str`should have 52 characters, current ${state.wtid.length}` : undefined, - payto_uri: !state.payto_uri ? i18n`cannot be empty` : undefined, - credit_amount: !state.credit_amount ? i18n`cannot be empty` : undefined, + payto_uri: !state.payto_uri ? i18n.str`cannot be empty` : undefined, + credit_amount: !state.credit_amount ? i18n.str`cannot be empty` : undefined, exchange_url: !state.exchange_url - ? i18n`cannot be empty` + ? i18n.str`cannot be empty` : !URL_REGEX.test(state.exchange_url) - ? i18n`URL doesn't have the right format` + ? i18n.str`URL doesn't have the right format` : undefined, }; @@ -95,46 +95,46 @@ export function CreatePage({ accounts, onCreate, onBack }: Props): VNode { > <InputSelector name="payto_uri" - label={i18n`Credited bank account`} + label={i18n.str`Credited bank account`} values={accounts} - placeholder={i18n`Select one account`} - tooltip={i18n`Bank account of the merchant where the payment was received`} + placeholder={i18n.str`Select one account`} + tooltip={i18n.str`Bank account of the merchant where the payment was received`} /> <Input<Entity> name="wtid" - label={i18n`Wire transfer ID`} + label={i18n.str`Wire transfer ID`} help="" - tooltip={i18n`unique identifier of the wire transfer used by the exchange, must be 52 characters long`} + tooltip={i18n.str`unique identifier of the wire transfer used by the exchange, must be 52 characters long`} /> <Input<Entity> name="exchange_url" - label={i18n`Exchange URL`} - tooltip={i18n`Base URL of the exchange that made the transfer, should have been in the wire transfer subject`} + label={i18n.str`Exchange URL`} + tooltip={i18n.str`Base URL of the exchange that made the transfer, should have been in the wire transfer subject`} help="http://exchange.taler:8081/" /> <InputCurrency<Entity> name="credit_amount" - label={i18n`Amount credited`} - tooltip={i18n`Actual amount that was wired to the merchant's bank account`} + label={i18n.str`Amount credited`} + tooltip={i18n.str`Actual amount that was wired to the merchant's bank account`} /> </FormProvider> <div class="buttons is-right mt-5"> {onBack && ( <button class="button" onClick={onBack}> - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> )} <AsyncButton disabled={hasErrors} data-tooltip={ hasErrors - ? i18n`Need to complete marked fields` + ? i18n.str`Need to complete marked fields` : "confirm operation" } onClick={submitForm} > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </AsyncButton> </div> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx index db01a57b6..8f41593dd 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx @@ -19,13 +19,13 @@ * @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 { NotificationCard } from "../../../../components/menu/index.js"; import { MerchantBackend } from "../../../../declaration.js"; import { useInstanceDetails } from "../../../../hooks/instance.js"; import { useTransferAPI } from "../../../../hooks/transfer.js"; -import { useTranslator } from "../../../../i18n/index.js"; import { Notification } from "../../../../utils/types.js"; import { CreatePage } from "./CreatePage.js"; @@ -38,7 +38,7 @@ interface Props { export default function CreateTransfer({ onConfirm, onBack }: Props): VNode { const { informTransfer } = useTransferAPI(); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const instance = useInstanceDetails(); const accounts = !instance.ok ? [] @@ -55,7 +55,7 @@ export default function CreateTransfer({ onConfirm, onBack }: Props): VNode { .then(() => onConfirm()) .catch((error) => { setNotif({ - message: i18n`could not inform transfer`, + message: i18n.str`could not inform transfer`, type: "ERROR", description: error.message, }); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx index cad989980..c77f7737b 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.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 { FormProvider } from "../../../../components/form/FormProvider.js"; import { InputSelector } from "../../../../components/form/InputSelector.js"; import { MerchantBackend } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; import { CardTable } from "./Table.js"; export interface Props { @@ -61,7 +61,7 @@ export function ListPage({ }: Props): VNode { const form = { payto_uri: payTo }; - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <section class="section is-main-section"> <div class="columns"> @@ -73,10 +73,10 @@ export function ListPage({ > <InputSelector name="payto_uri" - label={i18n`Address`} + label={i18n.str`Address`} values={accounts} - placeholder={i18n`Select one account`} - tooltip={i18n`filter by account address`} + placeholder={i18n.str`Select one account`} + tooltip={i18n.str`filter by account address`} /> </FormProvider> </div> @@ -87,30 +87,30 @@ export function ListPage({ <li class={isAllTransfers ? "is-active" : ""}> <div class="has-tooltip-right" - data-tooltip={i18n`remove all filters`} + data-tooltip={i18n.str`remove all filters`} > <a onClick={onShowAll}> - <Translate>All</Translate> + <i18n.Translate>All</i18n.Translate> </a> </div> </li> <li class={isVerifiedTransfers ? "is-active" : ""}> <div class="has-tooltip-right" - data-tooltip={i18n`only show wire transfers confirmed by the merchant`} + data-tooltip={i18n.str`only show wire transfers confirmed by the merchant`} > <a onClick={onShowVerified}> - <Translate>Verified</Translate> + <i18n.Translate>Verified</i18n.Translate> </a> </div> </li> <li class={isNonVerifiedTransfers ? "is-active" : ""}> <div class="has-tooltip-right" - data-tooltip={i18n`only show wire transfers claimed by the exchange`} + data-tooltip={i18n.str`only show wire transfers claimed by the exchange`} > <a onClick={onShowUnverified}> - <Translate>Unverified</Translate> + <i18n.Translate>Unverified</i18n.Translate> </a> </div> </li> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx index 2341fb80a..e38d375f9 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx @@ -19,11 +19,11 @@ * @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 { StateUpdater, useState } from "preact/hooks"; import { MerchantBackend, WithId } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; type Entity = MerchantBackend.Transfers.TransferDetails & WithId; @@ -49,7 +49,7 @@ export function CardTable({ }: Props): VNode { const [rowSelection, rowSelectionHandler] = useState<string[]>([]); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div class="card has-table"> @@ -58,10 +58,13 @@ export function CardTable({ <span class="icon"> <i class="mdi mdi-bank" /> </span> - <Translate>Transfers</Translate> + <i18n.Translate>Transfers</i18n.Translate> </p> <div class="card-header-icon" aria-label="more options"> - <span class="has-tooltip-left" data-tooltip={i18n`add new transfer`}> + <span + class="has-tooltip-left" + data-tooltip={i18n.str`add new transfer`} + > <button class="button is-info" type="button" onClick={onCreate}> <span class="icon is-small"> <i class="mdi mdi-plus mdi-36px" /> @@ -117,42 +120,42 @@ function Table({ hasMoreAfter, hasMoreBefore, }: TableProps): VNode { - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div class="table-container"> {onLoadMoreBefore && ( <button class="button is-fullwidth" - data-tooltip={i18n`load more transfers before the first one`} + data-tooltip={i18n.str`load more transfers before the first one`} disabled={!hasMoreBefore} onClick={onLoadMoreBefore} > - <Translate>load newer transfers</Translate> + <i18n.Translate>load newer transfers</i18n.Translate> </button> )} <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> <thead> <tr> <th> - <Translate>ID</Translate> + <i18n.Translate>ID</i18n.Translate> </th> <th> - <Translate>Credit</Translate> + <i18n.Translate>Credit</i18n.Translate> </th> <th> - <Translate>Address</Translate> + <i18n.Translate>Address</i18n.Translate> </th> <th> - <Translate>Exchange URL</Translate> + <i18n.Translate>Exchange URL</i18n.Translate> </th> <th> - <Translate>Confirmed</Translate> + <i18n.Translate>Confirmed</i18n.Translate> </th> <th> - <Translate>Verified</Translate> + <i18n.Translate>Verified</i18n.Translate> </th> <th> - <Translate>Executed at</Translate> + <i18n.Translate>Executed at</i18n.Translate> </th> <th /> </tr> @@ -165,23 +168,23 @@ function Table({ <td>{i.credit_amount}</td> <td>{i.payto_uri}</td> <td>{i.exchange_url}</td> - <td>{i.confirmed ? i18n`yes` : i18n`no`}</td> - <td>{i.verified ? i18n`yes` : i18n`no`}</td> + <td>{i.confirmed ? i18n.str`yes` : i18n.str`no`}</td> + <td>{i.verified ? i18n.str`yes` : i18n.str`no`}</td> <td> {i.execution_time ? i.execution_time.t_s == "never" - ? i18n`never` + ? i18n.str`never` : format( i.execution_time.t_s * 1000, "yyyy/MM/dd HH:mm:ss", ) - : i18n`unknown`} + : i18n.str`unknown`} </td> <td> {i.verified === undefined ? ( <button class="button is-danger is-small has-tooltip-left" - data-tooltip={i18n`delete selected transfer from the database`} + data-tooltip={i18n.str`delete selected transfer from the database`} onClick={() => onDelete(i)} > Delete @@ -196,11 +199,11 @@ function Table({ {onLoadMoreAfter && ( <button class="button is-fullwidth" - data-tooltip={i18n`load more transfer after the last one`} + data-tooltip={i18n.str`load more transfer after the last one`} disabled={!hasMoreAfter} onClick={onLoadMoreAfter} > - <Translate>load older transfers</Translate> + <i18n.Translate>load older transfers</i18n.Translate> </button> )} </div> @@ -208,6 +211,7 @@ function Table({ } function EmptyTable(): VNode { + const { i18n } = useTranslationContext(); return ( <div class="content has-text-grey has-text-centered"> <p> @@ -216,9 +220,9 @@ function EmptyTable(): VNode { </span> </p> <p> - <Translate> + <i18n.Translate> There is no transfer yet, add more pressing the + sign - </Translate> + </i18n.Translate> </p> </div> ); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/update/UpdatePage.tsx index d7acdf023..1365a59da 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/update/UpdatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/update/UpdatePage.tsx @@ -19,21 +19,20 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { Amounts } from "@gnu-taler/taler-util"; +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { h, VNode } from "preact"; import { useState } from "preact/hooks"; -import * as yup from "yup"; import { AsyncButton } from "../../../components/exception/AsyncButton.js"; import { - FormProvider, FormErrors, + FormProvider, } from "../../../components/form/FormProvider.js"; +import { DefaultInstanceFormFields } from "../../../components/instance/DefaultInstanceFormFields.js"; import { UpdateTokenModal } from "../../../components/modal/index.js"; import { useInstanceContext } from "../../../context/instance.js"; import { MerchantBackend } from "../../../declaration.js"; -import { Translate, useTranslator } from "../../../i18n/index.js"; -import { DefaultInstanceFormFields } from "../../../components/instance/DefaultInstanceFormFields.js"; import { PAYTO_REGEX } from "../../../utils/constants.js"; -import { Amounts } from "@gnu-taler/taler-util"; import { undefinedIfEmpty } from "../../../utils/table.js"; type Entity = MerchantBackend.Instances.InstanceReconfigurationMessage & { @@ -95,50 +94,52 @@ export function UpdatePage({ const [value, valueHandler] = useState<Partial<Entity>>(convert(selected)); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); const errors: FormErrors<Entity> = { - name: !value.name ? i18n`required` : undefined, + name: !value.name ? i18n.str`required` : undefined, payto_uris: !value.payto_uris || !value.payto_uris.length - ? i18n`required` + ? i18n.str`required` : undefinedIfEmpty( value.payto_uris.map((p) => { - return !PAYTO_REGEX.test(p) ? i18n`is not valid` : undefined; + return !PAYTO_REGEX.test(p) ? i18n.str`is not valid` : undefined; }), ), default_max_deposit_fee: !value.default_max_deposit_fee - ? i18n`required` + ? i18n.str`required` : !Amounts.parse(value.default_max_deposit_fee) - ? i18n`invalid format` + ? i18n.str`invalid format` : undefined, default_max_wire_fee: !value.default_max_wire_fee - ? i18n`required` + ? i18n.str`required` : !Amounts.parse(value.default_max_wire_fee) - ? i18n`invalid format` + ? i18n.str`invalid format` : undefined, default_wire_fee_amortization: value.default_wire_fee_amortization === undefined - ? i18n`required` + ? i18n.str`required` : isNaN(value.default_wire_fee_amortization) - ? i18n`is not a number` + ? i18n.str`is not a number` : value.default_wire_fee_amortization < 1 - ? i18n`must be 1 or greater` + ? i18n.str`must be 1 or greater` : undefined, - default_pay_delay: !value.default_pay_delay ? i18n`required` : undefined, + default_pay_delay: !value.default_pay_delay + ? i18n.str`required` + : undefined, default_wire_transfer_delay: !value.default_wire_transfer_delay - ? i18n`required` + ? i18n.str`required` : undefined, address: undefinedIfEmpty({ address_lines: value.address?.address_lines && value.address?.address_lines.length > 7 - ? i18n`max 7 lines` + ? i18n.str`max 7 lines` : undefined, }), jurisdiction: undefinedIfEmpty({ address_lines: value.address?.address_lines && value.address?.address_lines.length > 7 - ? i18n`max 7 lines` + ? i18n.str`max 7 lines` : undefined, }), }; @@ -160,7 +161,7 @@ export function UpdatePage({ <div class="level-left"> <div class="level-item"> <span class="is-size-4"> - <Translate>Instance id</Translate>: <b>{id}</b> + <i18n.Translate>Instance id</i18n.Translate>: <b>{id}</b> </span> </div> </div> @@ -169,7 +170,7 @@ export function UpdatePage({ <h1 class="title"> <button class="button is-danger" - data-tooltip={i18n`Change the authorization method use for this instance.`} + data-tooltip={i18n.str`Change the authorization method use for this instance.`} onClick={(): void => { setActive(!active); }} @@ -178,7 +179,7 @@ export function UpdatePage({ <i class="mdi mdi-lock-reset" /> </div> <span> - <Translate>Manage access token</Translate> + <i18n.Translate>Manage access token</i18n.Translate> </span> </button> </h1> @@ -229,19 +230,19 @@ export function UpdatePage({ onClick={onBack} data-tooltip="cancel operation" > - <Translate>Cancel</Translate> + <i18n.Translate>Cancel</i18n.Translate> </button> <AsyncButton onClick={submit} data-tooltip={ hasErrors - ? i18n`Need to complete marked fields` + ? i18n.str`Need to complete marked fields` : "confirm operation" } disabled={hasErrors} > - <Translate>Confirm</Translate> + <i18n.Translate>Confirm</i18n.Translate> </AsyncButton> </div> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx index 480274e66..668fe9a8d 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx @@ -13,6 +13,7 @@ You should have received a copy of the GNU General Public License along with GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ +import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { Loading } from "../../../components/exception/loading.js"; @@ -26,7 +27,6 @@ import { useManagedInstanceDetails, useManagementAPI, } from "../../../hooks/instance.js"; -import { useTranslator } from "../../../i18n/index.js"; import { Notification } from "../../../utils/types.js"; import { UpdatePage } from "./UpdatePage.js"; @@ -70,7 +70,7 @@ function CommonUpdate( ): VNode { const { changeToken } = useInstanceContext(); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); if (result.clientError && result.isUnauthorized) return onUnauthorized(); if (result.clientError && result.isNotfound) return onNotFound(); @@ -91,7 +91,7 @@ function CommonUpdate( .then(onConfirm) .catch((error: Error) => setNotif({ - message: i18n`Failed to create instance`, + message: i18n.str`Failed to create instance`, type: "ERROR", description: error.message, }), |