aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2022-12-20 17:45:24 -0300
committerSebastian <sebasjm@gmail.com>2022-12-20 17:45:24 -0300
commitc59f9a2556731ad95ab8bd7eefe7fa8a41629834 (patch)
tree5cb60195d66cebbee0ba99e05eafe22f369a46a8
parent382e66b179d6fda2598936196b2ae1b97bfab8ef (diff)
downloadwallet-core-c59f9a2556731ad95ab8bd7eefe7fa8a41629834.tar.xz
use translation context from web-utils, don't use match react-router since is broken
-rwxr-xr-xpackages/merchant-backoffice-ui/build.mjs3
-rw-r--r--packages/merchant-backoffice-ui/package.json24
-rw-r--r--packages/merchant-backoffice-ui/src/Application.tsx23
-rw-r--r--packages/merchant-backoffice-ui/src/ApplicationReadyRoutes.tsx32
-rw-r--r--packages/merchant-backoffice-ui/src/InstanceRoutes.tsx58
-rw-r--r--packages/merchant-backoffice-ui/src/components/exception/AsyncButton.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/components/exception/login.tsx12
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputArray.tsx10
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputCurrency.tsx9
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputDate.tsx14
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputDuration.tsx28
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputImage.tsx10
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputLocation.tsx27
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputPaytoForm.tsx98
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputSearchProduct.tsx18
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputSecured.tsx17
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputStock.tsx46
-rw-r--r--packages/merchant-backoffice-ui/src/components/form/InputTaxes.tsx25
-rw-r--r--packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx56
-rw-r--r--packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx4
-rw-r--r--packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx28
-rw-r--r--packages/merchant-backoffice-ui/src/components/menu/index.tsx99
-rw-r--r--packages/merchant-backoffice-ui/src/components/modal/index.tsx96
-rw-r--r--packages/merchant-backoffice-ui/src/components/picker/DurationPicker.tsx12
-rw-r--r--packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx26
-rw-r--r--packages/merchant-backoffice-ui/src/components/product/NonInventoryProductForm.tsx44
-rw-r--r--packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx38
-rw-r--r--packages/merchant-backoffice-ui/src/components/product/ProductList.tsx13
-rw-r--r--packages/merchant-backoffice-ui/src/context/fetch.ts2
-rw-r--r--packages/merchant-backoffice-ui/src/context/listener.ts35
-rw-r--r--packages/merchant-backoffice-ui/src/context/translation.ts66
-rw-r--r--packages/merchant-backoffice-ui/src/i18n/index.tsx215
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/create/Create.stories.tsx12
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx53
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/create/stories.tsx (renamed from packages/merchant-backoffice-ui/src/paths/admin/create/stories.ts)22
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx29
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx18
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx12
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/details/DetailPage.tsx8
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx17
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/index.stories.ts1
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx25
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx132
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx12
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx151
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx10
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx33
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx68
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx20
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx10
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/products/create/index.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx79
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx12
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/products/update/UpdatePage.tsx14
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/products/update/index.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx55
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx14
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/reserves/create/index.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx53
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeTipModal.tsx18
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/reserves/list/Table.tsx44
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/reserves/list/index.tsx8
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx44
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/create/index.tsx8
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx4
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx32
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx8
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx44
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx7
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx42
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx22
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx50
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/update/UpdatePage.tsx53
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/stories.test.ts13
-rw-r--r--packages/merchant-backoffice-ui/tests/functions/regex.test.ts32
-rw-r--r--packages/merchant-backoffice-ui/tests/header.test.tsx18
-rw-r--r--packages/web-util/src/tests/hook.ts2
-rw-r--r--pnpm-lock.yaml50
81 files changed, 1167 insertions, 1422 deletions
diff --git a/packages/merchant-backoffice-ui/build.mjs b/packages/merchant-backoffice-ui/build.mjs
index 611ef7044..4097e4e9a 100755
--- a/packages/merchant-backoffice-ui/build.mjs
+++ b/packages/merchant-backoffice-ui/build.mjs
@@ -64,8 +64,7 @@ function getFilesInDirectory(startPath, regex) {
return result
}
-const allTestFiles = getFilesInDirectory(path.join(BASE, 'tests'), /.test.tsx?$/)
-
+const allTestFiles = getFilesInDirectory(path.join(BASE, 'src'), /.test.tsx?$/)
const entryPoints = ["src/index.tsx", "src/stories.tsx", ...allTestFiles];
let GIT_ROOT = BASE;
diff --git a/packages/merchant-backoffice-ui/package.json b/packages/merchant-backoffice-ui/package.json
index 085f92d76..ca8923e05 100644
--- a/packages/merchant-backoffice-ui/package.json
+++ b/packages/merchant-backoffice-ui/package.json
@@ -3,12 +3,13 @@
"name": "@gnu-taler/merchant-backoffice",
"version": "0.0.4",
"license": "MIT",
+ "type": "module",
"scripts": {
"build": "./build.mjs",
"check": "tsc",
"compile": "tsc && ./build.mjs",
"dev": "preact watch --port ${PORT:=8080} --no-sw --no-esm",
- "test": "pnpm compile && mocha --require source-map-support/register '*.test.js' 'dist/**/test.js'",
+ "test": "pnpm compile && mocha --require source-map-support/register 'dist/**/*.test.js' 'dist/**/test.js'",
"lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
"i18n:extract": "pogen extract",
"i18n:merge": "pogen merge",
@@ -38,7 +39,7 @@
"date-fns": "2.29.3",
"history": "4.10.1",
"jed": "1.1.1",
- "preact": "10.6.5",
+ "preact": "10.11.3",
"preact-router": "3.2.1",
"qrcode-generator": "1.4.4",
"swr": "1.3.0",
@@ -79,22 +80,5 @@
"sass": "1.56.1",
"typedoc": "^0.20.36",
"typescript": "4.8.4"
- },
- "jest": {
- "preset": "jest-preset-preact",
- "transformIgnorePatterns": [
- "node_modules/.pnpm/(?!(@gnu-taler\\+taler-util))",
- "\\.pnp\\.[^\\/]+$"
- ],
- "setupFiles": [
- "<rootDir>/tests/__mocks__/browserMocks.ts",
- "<rootDir>/tests/__mocks__/setupTests.ts"
- ],
- "moduleNameMapper": {
- "\\.(css|less)$": "identity-obj-proxy"
- },
- "transform": {
- "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|po)$": "<rootDir>/tests/__mocks__/fileTransformer.js"
- }
}
-}
+} \ No newline at end of file
diff --git a/packages/merchant-backoffice-ui/src/Application.tsx b/packages/merchant-backoffice-ui/src/Application.tsx
index 0b92375c1..84536396d 100644
--- a/packages/merchant-backoffice-ui/src/Application.tsx
+++ b/packages/merchant-backoffice-ui/src/Application.tsx
@@ -19,6 +19,10 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import {
+ TranslationProvider,
+ useTranslationContext,
+} from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { route } from "preact-router";
import { useMemo } from "preact/hooks";
@@ -33,16 +37,15 @@ import {
useBackendContext,
} from "./context/backend.js";
import { ConfigContextProvider } from "./context/config.js";
-import { TranslationProvider } from "./context/translation.js";
import { useBackendConfig } from "./hooks/backend.js";
-import { useTranslator } from "./i18n/index.js";
+import { strings } from "./i18n/strings.js";
import LoginPage from "./paths/login/index.js";
export function Application(): VNode {
return (
// <FetchContextProvider>
<BackendContextProvider>
- <TranslationProvider>
+ <TranslationProvider source={strings}>
<ApplicationStatusRoutes />
</TranslationProvider>
</BackendContextProvider>
@@ -53,7 +56,7 @@ export function Application(): VNode {
function ApplicationStatusRoutes(): VNode {
const { updateLoginStatus, triedToLog } = useBackendContext();
const result = useBackendConfig();
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const updateLoginInfoAndGoToRoot = (url: string, token?: string) => {
updateLoginStatus(url, token);
@@ -88,7 +91,7 @@ function ApplicationStatusRoutes(): VNode {
<NotYetReadyAppMenu title="Error" />
<NotificationCard
notification={{
- message: i18n`Server not found`,
+ message: i18n.str`Server not found`,
type: "ERROR",
description: `Check your url`,
}}
@@ -103,9 +106,9 @@ function ApplicationStatusRoutes(): VNode {
<NotYetReadyAppMenu title="Error" />
<NotificationCard
notification={{
- message: i18n`Couldn't access the server`,
+ message: i18n.str`Couldn't access the server`,
type: "ERROR",
- description: i18n`Got message ${result.message} from ${result.info?.url}`,
+ description: i18n.str`Got message ${result.message} from ${result.info?.url}`,
}}
/>
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
@@ -120,9 +123,9 @@ function ApplicationStatusRoutes(): VNode {
<NotYetReadyAppMenu title="Error" />
<NotificationCard
notification={{
- message: i18n`Unexpected Error`,
+ message: i18n.str`Unexpected Error`,
type: "ERROR",
- description: i18n`Got message ${result.message} from ${result.info?.url}`,
+ description: i18n.str`Got message ${result.message} from ${result.info?.url}`,
}}
/>
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
@@ -130,7 +133,7 @@ function ApplicationStatusRoutes(): VNode {
);
return (
- <div id="app" class="has-navbar-fixed-top">
+ <div class="has-navbar-fixed-top">
<ConfigContextProvider value={ctx}>
<ApplicationReadyRoutes />
</ConfigContextProvider>
diff --git a/packages/merchant-backoffice-ui/src/ApplicationReadyRoutes.tsx b/packages/merchant-backoffice-ui/src/ApplicationReadyRoutes.tsx
index fe4493bff..4390ef877 100644
--- a/packages/merchant-backoffice-ui/src/ApplicationReadyRoutes.tsx
+++ b/packages/merchant-backoffice-ui/src/ApplicationReadyRoutes.tsx
@@ -18,23 +18,23 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
+import { createHashHistory } from "history";
import { Fragment, h, VNode } from "preact";
import Router, { Route, route } from "preact-router";
+import { useState } from "preact/hooks";
+import {
+ NotificationCard,
+ NotYetReadyAppMenu,
+} from "./components/menu/index.js";
import { useBackendContext } from "./context/backend.js";
import { useBackendInstancesTestForAdmin } from "./hooks/backend.js";
import { InstanceRoutes } from "./InstanceRoutes.js";
import LoginPage from "./paths/login/index.js";
import { INSTANCE_ID_LOOKUP } from "./utils/constants.js";
-import {
- NotYetReadyAppMenu,
- NotificationCard,
-} from "./components/menu/index.js";
-import { useTranslator } from "./i18n/index.js";
-import { createHashHistory } from "history";
-import { useState } from "preact/hooks";
export function ApplicationReadyRoutes(): VNode {
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const {
url: backendURL,
updateLoginStatus,
@@ -54,8 +54,8 @@ export function ApplicationReadyRoutes(): VNode {
<NotYetReadyAppMenu title="Login" onLogout={clearTokenAndGoToRoot} />
<NotificationCard
notification={{
- message: i18n`Access denied`,
- description: i18n`Check your token is valid`,
+ message: i18n.str`Access denied`,
+ description: i18n.str`Check your token is valid`,
type: "ERROR",
}}
/>
@@ -81,8 +81,8 @@ export function ApplicationReadyRoutes(): VNode {
<NotYetReadyAppMenu title="Error" onLogout={clearTokenAndGoToRoot} />
<NotificationCard
notification={{
- message: i18n`Couldn't access the server.`,
- description: i18n`Could not infer instance id from url ${backendURL}`,
+ message: i18n.str`Couldn't access the server.`,
+ description: i18n.str`Could not infer instance id from url ${backendURL}`,
type: "ERROR",
}}
/>
@@ -108,7 +108,12 @@ export function ApplicationReadyRoutes(): VNode {
);
}
-function DefaultMainRoute({ instance, admin, instanceNameByBackendURL }: any) {
+function DefaultMainRoute({
+ instance,
+ admin,
+ instanceNameByBackendURL,
+ url, //from preact-router
+}: any): VNode {
const [instanceName, setInstanceName] = useState(
instanceNameByBackendURL || instance || "default",
);
@@ -116,6 +121,7 @@ function DefaultMainRoute({ instance, admin, instanceNameByBackendURL }: any) {
return (
<InstanceRoutes
admin={admin}
+ path={url}
id={instanceName}
setInstanceName={setInstanceName}
/>
diff --git a/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx b/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx
index 817de5f7b..8ac5c698b 100644
--- a/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx
+++ b/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx
@@ -19,6 +19,8 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
+import { format } from "date-fns";
import { Fragment, FunctionComponent, h, VNode } from "preact";
import { Route, route, Router } from "preact-router";
import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
@@ -26,39 +28,37 @@ import { Loading } from "./components/exception/loading.js";
import { Menu, NotificationCard } from "./components/menu/index.js";
import { useBackendContext } from "./context/backend.js";
import { InstanceContextProvider } from "./context/instance.js";
+import { HttpError } from "./hooks/backend.js";
import {
useBackendDefaultToken,
useBackendInstanceToken,
useLocalStorage,
} from "./hooks/index.js";
-import { HttpError } from "./hooks/backend.js";
-import { Translate, useTranslator } from "./i18n/index.js";
+import { useInstanceKYCDetails } from "./hooks/instance.js";
import InstanceCreatePage from "./paths/admin/create/index.js";
import InstanceListPage from "./paths/admin/list/index.js";
+import ListKYCPage from "./paths/instance/kyc/list/index.js";
import OrderCreatePage from "./paths/instance/orders/create/index.js";
import OrderDetailsPage from "./paths/instance/orders/details/index.js";
import OrderListPage from "./paths/instance/orders/list/index.js";
import ProductCreatePage from "./paths/instance/products/create/index.js";
import ProductListPage from "./paths/instance/products/list/index.js";
import ProductUpdatePage from "./paths/instance/products/update/index.js";
-import TransferListPage from "./paths/instance/transfers/list/index.js";
-import TransferCreatePage from "./paths/instance/transfers/create/index.js";
-import TemplateListPage from "./paths/instance/templates/list/index.js";
-import TemplateUpdatePage from "./paths/instance/templates/update/index.js";
-import TemplateCreatePage from "./paths/instance/templates/create/index.js";
import ReservesCreatePage from "./paths/instance/reserves/create/index.js";
import ReservesDetailsPage from "./paths/instance/reserves/details/index.js";
import ReservesListPage from "./paths/instance/reserves/list/index.js";
-import ListKYCPage from "./paths/instance/kyc/list/index.js";
+import TemplateCreatePage from "./paths/instance/templates/create/index.js";
+import TemplateListPage from "./paths/instance/templates/list/index.js";
+import TemplateUpdatePage from "./paths/instance/templates/update/index.js";
+import TransferCreatePage from "./paths/instance/transfers/create/index.js";
+import TransferListPage from "./paths/instance/transfers/list/index.js";
import InstanceUpdatePage, {
- Props as InstanceUpdatePageProps,
AdminUpdate as InstanceAdminUpdatePage,
+ Props as InstanceUpdatePageProps,
} from "./paths/instance/update/index.js";
import LoginPage from "./paths/login/index.js";
import NotFoundPage from "./paths/notfound/index.js";
import { Notification } from "./utils/types.js";
-import { useInstanceKYCDetails } from "./hooks/instance.js";
-import { format } from "date-fns";
export enum InstancePaths {
// details = '/',
@@ -99,10 +99,16 @@ export enum AdminPaths {
export interface Props {
id: string;
admin?: boolean;
+ path: string;
setInstanceName: (s: string) => void;
}
-export function InstanceRoutes({ id, admin, setInstanceName }: Props): VNode {
+export function InstanceRoutes({
+ id,
+ admin,
+ path,
+ setInstanceName,
+}: Props): VNode {
const [_, updateDefaultToken] = useBackendDefaultToken();
const [token, updateToken] = useBackendInstanceToken(id);
const {
@@ -113,7 +119,7 @@ export function InstanceRoutes({ id, admin, setInstanceName }: Props): VNode {
const cleaner = useCallback(() => {
updateToken(undefined);
}, [id]);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
type GlobalNotifState = (Notification & { to: string }) | undefined;
const [globalNotification, setGlobalNotification] =
@@ -144,8 +150,8 @@ export function InstanceRoutes({ id, admin, setInstanceName }: Props): VNode {
function ServerErrorRedirectTo(to: InstancePaths | AdminPaths) {
return function ServerErrorRedirectToImpl(error: HttpError) {
setGlobalNotification({
- message: i18n`The backend reported a problem: HTTP status #${error.status}`,
- description: i18n`Diagnostic from ${error.info?.url} is "${error.message}"`,
+ message: i18n.str`The backend reported a problem: HTTP status #${error.status}`,
+ description: i18n.str`Diagnostic from ${error.info?.url} is "${error.message}"`,
details:
error.clientError || error.serverError
? error.error?.detail
@@ -161,8 +167,8 @@ export function InstanceRoutes({ id, admin, setInstanceName }: Props): VNode {
<Fragment>
<NotificationCard
notification={{
- message: i18n`Access denied`,
- description: i18n`The access token provided is invalid.`,
+ message: i18n.str`Access denied`,
+ description: i18n.str`The access token provided is invalid.`,
type: "ERROR",
}}
/>
@@ -177,8 +183,8 @@ export function InstanceRoutes({ id, admin, setInstanceName }: Props): VNode {
<Fragment>
<NotificationCard
notification={{
- message: i18n`No 'default' instance configured yet.`,
- description: i18n`Create a 'default' instance to begin using the merchant backoffice.`,
+ message: i18n.str`No 'default' instance configured yet.`,
+ description: i18n.str`Create a 'default' instance to begin using the merchant backoffice.`,
type: "INFO",
}}
/>
@@ -208,6 +214,7 @@ export function InstanceRoutes({ id, admin, setInstanceName }: Props): VNode {
<Menu
instance={id}
admin={admin}
+ path={path}
onLogout={clearTokenAndGoToRoot}
setInstanceName={setInstanceName}
/>
@@ -488,7 +495,7 @@ function AdminInstanceUpdatePage({
() => ({ id, token, admin: true, changeToken }),
[id, token],
);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<InstanceContextProvider value={value}>
@@ -500,8 +507,8 @@ function AdminInstanceUpdatePage({
<Fragment>
<NotificationCard
notification={{
- message: i18n`The backend reported a problem: HTTP status #${error.status}`,
- description: i18n`Diagnostic from ${error.info?.url} is "${error.message}"`,
+ message: i18n.str`The backend reported a problem: HTTP status #${error.status}`,
+ description: i18n.str`Diagnostic from ${error.info?.url} is "${error.message}"`,
details:
error.clientError || error.serverError
? error.error?.detail
@@ -518,8 +525,8 @@ function AdminInstanceUpdatePage({
<Fragment>
<NotificationCard
notification={{
- message: i18n`Access denied`,
- description: i18n`The access token provided is invalid`,
+ message: i18n.str`Access denied`,
+ description: i18n.str`The access token provided is invalid`,
type: "ERROR",
}}
/>
@@ -534,6 +541,7 @@ function AdminInstanceUpdatePage({
function KycBanner(): VNode {
const kycStatus = useInstanceKYCDetails();
+ const { i18n } = useTranslationContext();
const today = format(new Date(), "yyyy-MM-dd");
const [lastHide, setLastHide] = useLocalStorage("kyc-last-hide");
const hasBeenHidden = today === lastHide;
@@ -552,7 +560,7 @@ function KycBanner(): VNode {
</p>
<div class="buttons is-right">
<button class="button" onClick={() => setLastHide(today)}>
- <Translate>Hide for today</Translate>
+ <i18n.Translate>Hide for today</i18n.Translate>
</button>
</div>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/exception/AsyncButton.tsx b/packages/merchant-backoffice-ui/src/components/exception/AsyncButton.tsx
index 510bc29b8..aa50dfa91 100644
--- a/packages/merchant-backoffice-ui/src/components/exception/AsyncButton.tsx
+++ b/packages/merchant-backoffice-ui/src/components/exception/AsyncButton.tsx
@@ -22,7 +22,7 @@
import { ComponentChildren, h } from "preact";
import { LoadingModal } from "../modal/index.js";
import { useAsync } from "../../hooks/async.js";
-import { Translate } from "../../i18n/index.js";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
type Props = {
children: ComponentChildren;
@@ -33,14 +33,14 @@ type Props = {
export function AsyncButton({ onClick, disabled, children, ...rest }: Props) {
const { isSlow, isLoading, request, cancel } = useAsync(onClick);
-
+ const { i18n } = useTranslationContext();
if (isSlow) {
return <LoadingModal onCancel={cancel} />;
}
if (isLoading) {
return (
<button class="button">
- <Translate>Loading...</Translate>
+ <i18n.Translate>Loading...</i18n.Translate>
</button>
);
}
diff --git a/packages/merchant-backoffice-ui/src/components/exception/login.tsx b/packages/merchant-backoffice-ui/src/components/exception/login.tsx
index d1898915d..552e76ed6 100644
--- a/packages/merchant-backoffice-ui/src/components/exception/login.tsx
+++ b/packages/merchant-backoffice-ui/src/components/exception/login.tsx
@@ -19,11 +19,11 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useBackendContext } from "../../context/backend.js";
import { useInstanceContext } from "../../context/instance.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { Notification } from "../../utils/types.js";
interface Props {
@@ -51,7 +51,7 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode {
const [token, setToken] = useState(currentToken);
const [url, setURL] = useState(backendUrl);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div class="columns is-centered">
@@ -61,13 +61,13 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode {
class="modal-card-head"
style={{ border: "1px solid", borderBottom: 0 }}
>
- <p class="modal-card-title">{i18n`Login required`}</p>
+ <p class="modal-card-title">{i18n.str`Login required`}</p>
</header>
<section
class="modal-card-body"
style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }}
>
- <Translate>Please enter your access token.</Translate>
+ <i18n.Translate>Please enter your access token.</i18n.Translate>
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">URL</label>
@@ -95,7 +95,7 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode {
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">
- <Translate>Access Token</Translate>
+ <i18n.Translate>Access Token</i18n.Translate>
</label>
</div>
<div class="field-body">
@@ -133,7 +133,7 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode {
onConfirm(url, normalizeToken(token));
}}
>
- <Translate>Confirm</Translate>
+ <i18n.Translate>Confirm</i18n.Translate>
</button>
</footer>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputArray.tsx b/packages/merchant-backoffice-ui/src/components/form/InputArray.tsx
index b5da1117a..8f0249bb2 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputArray.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputArray.tsx
@@ -18,9 +18,9 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { InputProps, useField } from "./useField.js";
export interface Props<T> extends InputProps<T> {
@@ -52,7 +52,7 @@ export function InputArray<T>({
const array: any[] = (value ? value! : []) as any;
const [currentValue, setCurrentValue] = useState("");
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div class="field is-horizontal">
@@ -99,7 +99,7 @@ export function InputArray<T>({
const v = fromStr(currentValue);
if (!isValid(v)) {
setLocalError(
- i18n`The value ${v} is invalid for a payment url`,
+ i18n.str`The value ${v} is invalid for a payment url`,
);
return;
}
@@ -107,9 +107,9 @@ export function InputArray<T>({
onChange([v, ...array] as any);
setCurrentValue("");
}}
- data-tooltip={i18n`add element to the list`}
+ data-tooltip={i18n.str`add element to the list`}
>
- <Translate>add</Translate>
+ <i18n.Translate>add</i18n.Translate>
</button>
</p>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputCurrency.tsx b/packages/merchant-backoffice-ui/src/components/form/InputCurrency.tsx
index 57a5163b7..3b84855da 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputCurrency.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputCurrency.tsx
@@ -18,7 +18,7 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { ComponentChildren, h } from "preact";
+import { ComponentChildren, h, VNode } from "preact";
import { useConfigContext } from "../../context/config.js";
import { Amount } from "../../declaration.js";
import { InputWithAddon } from "./InputWithAddon.js";
@@ -42,7 +42,7 @@ export function InputCurrency<T>({
addonAfter,
children,
side,
-}: Props<keyof T>) {
+}: Props<keyof T>): VNode {
const config = useConfigContext();
return (
<InputWithAddon<T>
@@ -60,7 +60,8 @@ export function InputCurrency<T>({
toStr={(v?: Amount) => v?.split(":")[1] || ""}
fromStr={(v: string) => (!v ? "" : `${config.currency}:${v}`)}
inputExtra={{ min: 0 }}
- children={children}
- />
+ >
+ {children}
+ </InputWithAddon>
);
}
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputDate.tsx b/packages/merchant-backoffice-ui/src/components/form/InputDate.tsx
index 4704b3312..fba798bd5 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputDate.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputDate.tsx
@@ -18,10 +18,10 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { format } from "date-fns";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { DatePicker } from "../picker/DatePicker.js";
import { InputProps, useField } from "./useField.js";
@@ -43,7 +43,7 @@ export function InputDate<T>({
withTimestampSupport,
}: Props<keyof T>): VNode {
const [opened, setOpened] = useState(false);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const { error, required, value, onChange } = useField<T>(name);
@@ -120,25 +120,25 @@ export function InputDate<T>({
<span
data-tooltip={
withTimestampSupport
- ? i18n`change value to unknown date`
- : i18n`change value to empty`
+ ? i18n.str`change value to unknown date`
+ : i18n.str`change value to empty`
}
>
<button
class="button is-info mr-3"
onClick={() => onChange(undefined as any)}
>
- <Translate>clear</Translate>
+ <i18n.Translate>clear</i18n.Translate>
</button>
</span>
)}
{withTimestampSupport && (
- <span data-tooltip={i18n`change value to never`}>
+ <span data-tooltip={i18n.str`change value to never`}>
<button
class="button is-info"
onClick={() => onChange({ t_s: "never" } as any)}
>
- <Translate>never</Translate>
+ <i18n.Translate>never</i18n.Translate>
</button>
</span>
)}
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputDuration.tsx b/packages/merchant-backoffice-ui/src/components/form/InputDuration.tsx
index 658cc4db7..3f25d1dc7 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputDuration.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputDuration.tsx
@@ -18,10 +18,10 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { intervalToDuration, formatDuration } from "date-fns";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
+import { formatDuration, intervalToDuration } from "date-fns";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { SimpleModal } from "../modal/index.js";
import { DurationPicker } from "../picker/DurationPicker.js";
import { InputProps, useField } from "./useField.js";
@@ -43,14 +43,14 @@ export function InputDuration<T>({
withForever,
}: Props<keyof T>): VNode {
const [opened, setOpened] = useState(false);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const { error, required, value, onChange } = useField<T>(name);
let strValue = "";
if (!value) {
strValue = "";
} else if (value.d_us === "forever") {
- strValue = i18n`forever`;
+ strValue = i18n.str`forever`;
} else {
strValue = formatDuration(
intervalToDuration({ start: 0, end: value.d_us / 1000 }),
@@ -59,17 +59,17 @@ export function InputDuration<T>({
formatDistance: (name, value) => {
switch (name) {
case "xMonths":
- return i18n`${value}M`;
+ return i18n.str`${value}M`;
case "xYears":
- return i18n`${value}Y`;
+ return i18n.str`${value}Y`;
case "xDays":
- return i18n`${value}d`;
+ return i18n.str`${value}d`;
case "xHours":
- return i18n`${value}h`;
+ return i18n.str`${value}h`;
case "xMinutes":
- return i18n`${value}min`;
+ return i18n.str`${value}min`;
case "xSeconds":
- return i18n`${value}sec`;
+ return i18n.str`${value}sec`;
}
},
localize: {
@@ -134,22 +134,22 @@ export function InputDuration<T>({
{error && <p class="help is-danger">{error}</p>}
</div>
{withForever && (
- <span data-tooltip={i18n`change value to never`}>
+ <span data-tooltip={i18n.str`change value to never`}>
<button
class="button is-info mr-3"
onClick={() => onChange({ d_us: "forever" } as any)}
>
- <Translate>forever</Translate>
+ <i18n.Translate>forever</i18n.Translate>
</button>
</span>
)}
{!readonly && (
- <span data-tooltip={i18n`change value to empty`}>
+ <span data-tooltip={i18n.str`change value to empty`}>
<button
class="button is-info "
onClick={() => onChange(undefined as any)}
>
- <Translate>clear</Translate>
+ <i18n.Translate>clear</i18n.Translate>
</button>
</span>
)}
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputImage.tsx b/packages/merchant-backoffice-ui/src/components/form/InputImage.tsx
index d5b2aadb6..43a7af1a3 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputImage.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputImage.tsx
@@ -18,9 +18,9 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { ComponentChildren, h, VNode } from "preact";
import { useRef, useState } from "preact/hooks";
-import { Translate } from "../../i18n/index.js";
import { MAX_IMAGE_SIZE as MAX_IMAGE_UPLOAD_SIZE } from "../../utils/constants.js";
import { InputProps, useField } from "./useField.js";
@@ -43,7 +43,7 @@ export function InputImage<T>({
const { error, value, onChange } = useField<T>(name);
const image = useRef<HTMLInputElement>(null);
-
+ const { i18n } = useTranslationContext();
const [sizeError, setSizeError] = useState(false);
return (
@@ -102,17 +102,17 @@ export function InputImage<T>({
{error && <p class="help is-danger">{error}</p>}
{sizeError && (
<p class="help is-danger">
- <Translate>Image should be smaller than 1 MB</Translate>
+ <i18n.Translate>Image should be smaller than 1 MB</i18n.Translate>
</p>
)}
{!value && (
<button class="button" onClick={() => image.current?.click()}>
- <Translate>Add</Translate>
+ <i18n.Translate>Add</i18n.Translate>
</button>
)}
{value && (
<button class="button" onClick={() => onChange(undefined!)}>
- <Translate>Remove</Translate>
+ <i18n.Translate>Remove</i18n.Translate>
</button>
)}
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputLocation.tsx b/packages/merchant-backoffice-ui/src/components/form/InputLocation.tsx
index 613b2f1e6..ef5a0995c 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputLocation.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputLocation.tsx
@@ -19,31 +19,34 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
import { Fragment, h } from "preact";
-import { useTranslator } from "../../i18n/index.js";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Input } from "./Input.js";
export function InputLocation({ name }: { name: string }) {
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<>
- <Input name={`${name}.country`} label={i18n`Country`} />
+ <Input name={`${name}.country`} label={i18n.str`Country`} />
<Input
name={`${name}.address_lines`}
inputType="multiline"
- label={i18n`Address`}
+ label={i18n.str`Address`}
toStr={(v: string[] | undefined) => (!v ? "" : v.join("\n"))}
fromStr={(v: string) => v.split("\n")}
/>
- <Input name={`${name}.building_number`} label={i18n`Building number`} />
- <Input name={`${name}.building_name`} label={i18n`Building name`} />
- <Input name={`${name}.street`} label={i18n`Street`} />
- <Input name={`${name}.post_code`} label={i18n`Post code`} />
- <Input name={`${name}.town_location`} label={i18n`Town location`} />
- <Input name={`${name}.town`} label={i18n`Town`} />
- <Input name={`${name}.district`} label={i18n`District`} />
+ <Input
+ name={`${name}.building_number`}
+ label={i18n.str`Building number`}
+ />
+ <Input name={`${name}.building_name`} label={i18n.str`Building name`} />
+ <Input name={`${name}.street`} label={i18n.str`Street`} />
+ <Input name={`${name}.post_code`} label={i18n.str`Post code`} />
+ <Input name={`${name}.town_location`} label={i18n.str`Town location`} />
+ <Input name={`${name}.town`} label={i18n.str`Town`} />
+ <Input name={`${name}.district`} label={i18n.str`District`} />
<Input
name={`${name}.country_subdivision`}
- label={i18n`Country subdivision`}
+ label={i18n.str`Country subdivision`}
/>
</>
);
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputPaytoForm.tsx b/packages/merchant-backoffice-ui/src/components/form/InputPaytoForm.tsx
index 085febea4..7bf39152b 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputPaytoForm.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputPaytoForm.tsx
@@ -18,9 +18,9 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { h, VNode, Fragment } from "preact";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
+import { Fragment, h, VNode } from "preact";
import { useCallback, useState } from "preact/hooks";
-import { Translate, Translator, useTranslator } from "../../i18n/index.js";
import { COUNTRY_TABLE } from "../../utils/constants.js";
import { undefinedIfEmpty } from "../../utils/table.js";
import { FormErrors, FormProvider } from "./FormProvider.js";
@@ -69,24 +69,30 @@ function checkAddressChecksum(address: string) {
return true;
}
-function validateBitcoin(addr: string, i18n: Translator): string | undefined {
+function validateBitcoin(
+ addr: string,
+ i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): string | undefined {
try {
const valid = /^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$/.test(addr);
if (valid) return undefined;
} catch (e) {
console.log(e);
}
- return i18n`This is not a valid bitcoin address.`;
+ return i18n.str`This is not a valid bitcoin address.`;
}
-function validateEthereum(addr: string, i18n: Translator): string | undefined {
+function validateEthereum(
+ addr: string,
+ i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): string | undefined {
try {
const valid = isEthereumAddress(addr);
if (valid) return undefined;
} catch (e) {
console.log(e);
}
- return i18n`This is not a valid Ethereum address.`;
+ return i18n.str`This is not a valid Ethereum address.`;
}
/**
@@ -103,12 +109,15 @@ function validateEthereum(addr: string, i18n: Translator): string | undefined {
* If the remainder is 1, the check digit test is passed and the IBAN might be valid.
*
*/
-function validateIBAN(iban: string, i18n: Translator): string | undefined {
+function validateIBAN(
+ iban: string,
+ i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): string | undefined {
// Check total length
if (iban.length < 4)
- return i18n`IBAN numbers usually have more that 4 digits`;
+ return i18n.str`IBAN numbers usually have more that 4 digits`;
if (iban.length > 34)
- return i18n`IBAN numbers usually have less that 34 digits`;
+ return i18n.str`IBAN numbers usually have less that 34 digits`;
const A_code = "A".charCodeAt(0);
const Z_code = "Z".charCodeAt(0);
@@ -116,7 +125,7 @@ function validateIBAN(iban: string, i18n: Translator): string | undefined {
// check supported country
const code = IBAN.substr(0, 2);
const found = code in COUNTRY_TABLE;
- if (!found) return i18n`IBAN country code not found`;
+ if (!found) return i18n.str`IBAN country code not found`;
// 2.- Move the four initial characters to the end of the string
const step2 = IBAN.substr(4) + iban.substr(0, 4);
@@ -140,7 +149,8 @@ function validateIBAN(iban: string, i18n: Translator): string | undefined {
}
const checksum = calculate_iban_checksum(step3);
- if (checksum !== 1) return i18n`IBAN number is not valid, checksum is wrong`;
+ if (checksum !== 1)
+ return i18n.str`IBAN number is not valid, checksum is wrong`;
return undefined;
}
@@ -175,7 +185,7 @@ export function InputPaytoForm<T>({
payToPath = `/${value.path1}`;
}
}
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const ops = value.options!;
const url = tryUrl(`payto://${value.target}${payToPath}`);
@@ -188,9 +198,9 @@ export function InputPaytoForm<T>({
const paytoURL = !url ? "" : url.toString();
const errors: FormErrors<Entity> = {
- target: value.target === noTargetValue ? i18n`required` : undefined,
+ target: value.target === noTargetValue ? i18n.str`required` : undefined,
path1: !value.path1
- ? i18n`required`
+ ? i18n.str`required`
: value.target === "iban"
? validateIBAN(value.path1, i18n)
: value.target === "bitcoin"
@@ -201,12 +211,12 @@ export function InputPaytoForm<T>({
path2:
value.target === "x-taler-bank"
? !value.path2
- ? i18n`required`
+ ? i18n.str`required`
: undefined
: undefined,
options: undefinedIfEmpty({
"receiver-name": !value.options?.["receiver-name"]
- ? i18n`required`
+ ? i18n.str`required`
: undefined,
}),
};
@@ -235,23 +245,23 @@ export function InputPaytoForm<T>({
>
<InputSelector<Entity>
name="target"
- label={i18n`Target type`}
- tooltip={i18n`Method to use for wire transfer`}
+ label={i18n.str`Target type`}
+ tooltip={i18n.str`Method to use for wire transfer`}
values={targets}
- toStr={(v) => (v === noTargetValue ? i18n`Choose one...` : v)}
+ toStr={(v) => (v === noTargetValue ? i18n.str`Choose one...` : v)}
/>
{value.target === "ach" && (
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Routing`}
- tooltip={i18n`Routing number.`}
+ label={i18n.str`Routing`}
+ tooltip={i18n.str`Routing number.`}
/>
<Input<Entity>
name="path2"
- label={i18n`Account`}
- tooltip={i18n`Account number.`}
+ label={i18n.str`Account`}
+ tooltip={i18n.str`Account number.`}
/>
</Fragment>
)}
@@ -259,8 +269,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Code`}
- tooltip={i18n`Business Identifier Code.`}
+ label={i18n.str`Code`}
+ tooltip={i18n.str`Business Identifier Code.`}
/>
</Fragment>
)}
@@ -268,8 +278,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Account`}
- tooltip={i18n`Bank Account Number.`}
+ label={i18n.str`Account`}
+ tooltip={i18n.str`Bank Account Number.`}
inputExtra={{ style: { textTransform: "uppercase" } }}
/>
</Fragment>
@@ -278,8 +288,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Account`}
- tooltip={i18n`Unified Payment Interface.`}
+ label={i18n.str`Account`}
+ tooltip={i18n.str`Unified Payment Interface.`}
/>
</Fragment>
)}
@@ -287,8 +297,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Address`}
- tooltip={i18n`Bitcoin protocol.`}
+ label={i18n.str`Address`}
+ tooltip={i18n.str`Bitcoin protocol.`}
/>
</Fragment>
)}
@@ -296,8 +306,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Address`}
- tooltip={i18n`Ethereum protocol.`}
+ label={i18n.str`Address`}
+ tooltip={i18n.str`Ethereum protocol.`}
/>
</Fragment>
)}
@@ -305,8 +315,8 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Address`}
- tooltip={i18n`Interledger protocol.`}
+ label={i18n.str`Address`}
+ tooltip={i18n.str`Interledger protocol.`}
/>
</Fragment>
)}
@@ -315,13 +325,13 @@ export function InputPaytoForm<T>({
<Fragment>
<Input<Entity>
name="path1"
- label={i18n`Host`}
- tooltip={i18n`Bank host.`}
+ label={i18n.str`Host`}
+ tooltip={i18n.str`Bank host.`}
/>
<Input<Entity>
name="path2"
- label={i18n`Account`}
- tooltip={i18n`Bank account.`}
+ label={i18n.str`Account`}
+ tooltip={i18n.str`Bank account.`}
/>
</Fragment>
)}
@@ -329,8 +339,8 @@ export function InputPaytoForm<T>({
{value.target !== noTargetValue && (
<Input
name="options.receiver-name"
- label={i18n`Name`}
- tooltip={i18n`Bank account owner's name.`}
+ label={i18n.str`Name`}
+ tooltip={i18n.str`Bank account owner's name.`}
/>
)}
@@ -357,7 +367,7 @@ export function InputPaytoForm<T>({
/>
</div>
))}
- {!paytos.length && i18n`No accounts yet.`}
+ {!paytos.length && i18n.str`No accounts yet.`}
</div>
</div>
@@ -365,11 +375,11 @@ export function InputPaytoForm<T>({
<div class="buttons is-right mt-5">
<button
class="button is-info"
- data-tooltip={i18n`add tax to the tax list`}
+ data-tooltip={i18n.str`add tax to the tax list`}
disabled={hasErrors}
onClick={submit}
>
- <Translate>Add</Translate>
+ <i18n.Translate>Add</i18n.Translate>
</button>
</div>
)}
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputSearchProduct.tsx b/packages/merchant-backoffice-ui/src/components/form/InputSearchProduct.tsx
index fceee9d56..7f65fb8ae 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputSearchProduct.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputSearchProduct.tsx
@@ -18,11 +18,11 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import emptyImage from "../../assets/empty.png";
import { MerchantBackend, WithId } from "../../declaration.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { FormErrors, FormProvider } from "./FormProvider.js";
import { InputWithAddon } from "./InputWithAddon.js";
@@ -50,7 +50,7 @@ export function InputSearchProduct({
const errors: FormErrors<ProductSearch> = {
name: undefined,
};
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
if (selected) {
return (
@@ -63,10 +63,11 @@ export function InputSearchProduct({
<div class="media-content">
<div class="content">
<p class="media-meta">
- <Translate>Product id</Translate>: <b>{selected.id}</b>
+ <i18n.Translate>Product id</i18n.Translate>: <b>{selected.id}</b>
</p>
<p>
- <Translate>Description</Translate>: {selected.description}
+ <i18n.Translate>Description</i18n.Translate>:{" "}
+ {selected.description}
</p>
<div class="buttons is-right mt-5">
<button
@@ -90,8 +91,8 @@ export function InputSearchProduct({
>
<InputWithAddon<ProductSearch>
name="name"
- label={i18n`Product`}
- tooltip={i18n`search products by it's description or id`}
+ label={i18n.str`Product`}
+ tooltip={i18n.str`search products by it's description or id`}
addonAfter={
<span class="icon">
<i class="mdi mdi-magnify" />
@@ -120,6 +121,7 @@ interface ProductListProps {
}
function ProductList({ name, onSelect, list }: ProductListProps) {
+ const { i18n } = useTranslationContext();
if (!name) {
/* FIXME
this BR is added to occupy the space that will be added when the
@@ -146,7 +148,9 @@ function ProductList({ name, onSelect, list }: ProductListProps) {
<div class="dropdown-content">
{!filtered.length ? (
<div class="dropdown-item">
- <Translate>no products found with that description</Translate>
+ <i18n.Translate>
+ no products found with that description
+ </i18n.Translate>
</div>
) : (
filtered.map((p) => (
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputSecured.tsx b/packages/merchant-backoffice-ui/src/components/form/InputSecured.tsx
index 799978683..d900168b4 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputSecured.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputSecured.tsx
@@ -18,14 +18,15 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { InputProps, useField } from "./useField.js";
export type Props<T> = InputProps<T>;
const TokenStatus = ({ prev, post }: any) => {
+ const { i18n } = useTranslationContext();
if (
(prev === undefined || prev === null) &&
(post === undefined || post === null)
@@ -33,11 +34,11 @@ const TokenStatus = ({ prev, post }: any) => {
return null;
return prev === post ? null : post === null ? (
<span class="tag is-danger is-align-self-center ml-2">
- <Translate>Deleting</Translate>
+ <i18n.Translate>Deleting</i18n.Translate>
</span>
) : (
<span class="tag is-warning is-align-self-center ml-2">
- <Translate>Changing</Translate>
+ <i18n.Translate>Changing</i18n.Translate>
</span>
);
};
@@ -55,7 +56,7 @@ export function InputSecured<T>({
const [active, setActive] = useState(false);
const [newValue, setNuewValue] = useState("");
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<Fragment>
@@ -84,7 +85,7 @@ export function InputSecured<T>({
<i class="mdi mdi-lock-reset" />
</div>
<span>
- <Translate>Manage access token</Translate>
+ <i18n.Translate>Manage access token</i18n.Translate>
</span>
</button>
<TokenStatus prev={initial} post={value} />
@@ -125,7 +126,7 @@ export function InputSecured<T>({
<i class="mdi mdi-lock-outline" />
</div>
<span>
- <Translate>Update</Translate>
+ <i18n.Translate>Update</i18n.Translate>
</span>
</button>
</div>
@@ -154,7 +155,7 @@ export function InputSecured<T>({
<i class="mdi mdi-lock-open-variant" />
</div>
<span>
- <Translate>Remove</Translate>
+ <i18n.Translate>Remove</i18n.Translate>
</span>
</button>
</div>
@@ -171,7 +172,7 @@ export function InputSecured<T>({
<i class="mdi mdi-lock-open-variant" />
</div>
<span>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</span>
</button>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx b/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx
index 57aa5968d..1052aaaae 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx
@@ -18,17 +18,16 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h } from "preact";
-import { MerchantBackend, Timestamp } from "../../declaration.js";
-import { InputProps, useField } from "./useField.js";
-import { FormProvider, FormErrors } from "./FormProvider.js";
import { useLayoutEffect, useState } from "preact/hooks";
-import { Input } from "./Input.js";
-import { InputGroup } from "./InputGroup.js";
-import { InputNumber } from "./InputNumber.js";
+import { MerchantBackend, Timestamp } from "../../declaration.js";
+import { FormErrors, FormProvider } from "./FormProvider.js";
import { InputDate } from "./InputDate.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
+import { InputGroup } from "./InputGroup.js";
import { InputLocation } from "./InputLocation.js";
+import { InputNumber } from "./InputNumber.js";
+import { InputProps, useField } from "./useField.js";
export interface Props<T> extends InputProps<T> {
alreadyExist?: boolean;
@@ -64,7 +63,7 @@ export function InputStock<T>({
incoming: 0,
lost: 0,
});
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
useLayoutEffect(() => {
if (!formValue) {
@@ -97,7 +96,7 @@ export function InputStock<T>({
{!alreadyExist ? (
<button
class="button"
- data-tooltip={i18n`click here to configure the stock of the product, leave it as is and the backend will not control stock`}
+ data-tooltip={i18n.str`click here to configure the stock of the product, leave it as is and the backend will not control stock`}
onClick={(): void => {
valueHandler({
current: 0,
@@ -107,17 +106,17 @@ export function InputStock<T>({
}}
>
<span>
- <Translate>Manage stock</Translate>
+ <i18n.Translate>Manage stock</i18n.Translate>
</span>
</button>
) : (
<button
class="button"
- data-tooltip={i18n`this product has been configured without stock control`}
+ data-tooltip={i18n.str`this product has been configured without stock control`}
disabled
>
<span>
- <Translate>Infinite</Translate>
+ <i18n.Translate>Infinite</i18n.Translate>
</span>
</button>
)}
@@ -134,7 +133,7 @@ export function InputStock<T>({
const stockAddedErrors: FormErrors<typeof addedStock> = {
lost:
currentStock + addedStock.incoming < addedStock.lost
- ? i18n`lost cannot be greater than current and incoming (max ${
+ ? i18n.str`lost cannot be greater than current and incoming (max ${
currentStock + addedStock.incoming
})`
: undefined,
@@ -142,8 +141,8 @@ export function InputStock<T>({
// const stockUpdateDescription = stockAddedErrors.lost ? '' : (
// !!addedStock.incoming || !!addedStock.lost ?
- // i18n`current stock will change from ${currentStock} to ${currentStock + addedStock.incoming - addedStock.lost}` :
- // i18n`current stock will stay at ${currentStock}`
+ // i18n.str`current stock will change from ${currentStock} to ${currentStock + addedStock.incoming - addedStock.lost}` :
+ // i18n.str`current stock will stay at ${currentStock}`
// )
return (
@@ -174,8 +173,8 @@ export function InputStock<T>({
object={addedStock}
valueHandler={setAddedStock as any}
>
- <InputNumber name="incoming" label={i18n`Incoming`} />
- <InputNumber name="lost" label={i18n`Lost`} />
+ <InputNumber name="incoming" label={i18n.str`Incoming`} />
+ <InputNumber name="lost" label={i18n.str`Lost`} />
</FormProvider>
{/* <div class="field is-horizontal">
@@ -190,17 +189,17 @@ export function InputStock<T>({
) : (
<InputNumber<Entity>
name="current"
- label={i18n`Current`}
+ label={i18n.str`Current`}
side={
<button
class="button is-danger"
- data-tooltip={i18n`remove stock control for this product`}
+ data-tooltip={i18n.str`remove stock control for this product`}
onClick={(): void => {
valueHandler(undefined as any);
}}
>
<span>
- <Translate>without stock</Translate>
+ <i18n.Translate>without stock</i18n.Translate>
</span>
</button>
}
@@ -209,11 +208,14 @@ export function InputStock<T>({
<InputDate<Entity>
name="nextRestock"
- label={i18n`Next restock`}
+ label={i18n.str`Next restock`}
withTimestampSupport
/>
- <InputGroup<Entity> name="address" label={i18n`Delivery address`}>
+ <InputGroup<Entity>
+ name="address"
+ label={i18n.str`Delivery address`}
+ >
<InputLocation name="address" />
</InputGroup>
</FormProvider>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputTaxes.tsx b/packages/merchant-backoffice-ui/src/components/form/InputTaxes.tsx
index d95463790..552ee73e2 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputTaxes.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputTaxes.tsx
@@ -18,11 +18,11 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useCallback, useState } from "preact/hooks";
import * as yup from "yup";
import { MerchantBackend } from "../../declaration.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { TaxSchema as schema } from "../../schemas/index.js";
import { FormErrors, FormProvider } from "./FormProvider.js";
import { Input } from "./Input.js";
@@ -67,7 +67,7 @@ export function InputTaxes<T>({
valueHandler({});
}, [value]);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
//FIXME: translating plural singular
return (
@@ -110,34 +110,35 @@ export function InputTaxes<T>({
/>
</div>
))}
- {!taxes.length && i18n`No taxes configured for this product.`}
+ {!taxes.length && i18n.str`No taxes configured for this product.`}
</div>
</div>
<Input<Entity>
name="tax"
- label={i18n`Amount`}
- tooltip={i18n`Taxes can be in currencies that differ from the main currency used by the merchant.`}
+ label={i18n.str`Amount`}
+ tooltip={i18n.str`Taxes can be in currencies that differ from the main currency used by the merchant.`}
>
- <Translate>
- Enter currency and value separated with a colon, e.g. "USD:2.3".
- </Translate>
+ <i18n.Translate>
+ Enter currency and value separated with a colon, e.g.
+ &quot;USD:2.3&quot;.
+ </i18n.Translate>
</Input>
<Input<Entity>
name="name"
- label={i18n`Description`}
- tooltip={i18n`Legal name of the tax, e.g. VAT or import duties.`}
+ label={i18n.str`Description`}
+ tooltip={i18n.str`Legal name of the tax, e.g. VAT or import duties.`}
/>
<div class="buttons is-right mt-5">
<button
class="button is-info"
- data-tooltip={i18n`add tax to the tax list`}
+ data-tooltip={i18n.str`add tax to the tax list`}
disabled={hasErrors}
onClick={submit}
>
- <Translate>Add</Translate>
+ <i18n.Translate>Add</i18n.Translate>
</button>
</div>
</FormProvider>
diff --git a/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx b/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
index 9dfa33840..c497773d9 100644
--- a/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
+++ b/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
@@ -19,9 +19,9 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useBackendContext } from "../../context/backend.js";
-import { useTranslator } from "../../i18n/index.js";
import { Entity } from "../../paths/admin/create/CreatePage.js";
import { Input } from "../form/Input.js";
import { InputCurrency } from "../form/InputCurrency.js";
@@ -39,7 +39,7 @@ export function DefaultInstanceFormFields({
readonlyId?: boolean;
showId: boolean;
}): VNode {
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const backend = useBackendContext();
return (
<Fragment>
@@ -48,86 +48,86 @@ export function DefaultInstanceFormFields({
name="id"
addonBefore={`${backend.url}/instances/`}
readonly={readonlyId}
- label={i18n`Identifier`}
- tooltip={i18n`Name of the instance in URLs. The 'default' instance is special in that it is used to administer other instances.`}
+ label={i18n.str`Identifier`}
+ tooltip={i18n.str`Name of the instance in URLs. The 'default' instance is special in that it is used to administer other instances.`}
/>
)}
<Input<Entity>
name="name"
- label={i18n`Business name`}
- tooltip={i18n`Legal name of the business represented by this instance.`}
+ label={i18n.str`Business name`}
+ tooltip={i18n.str`Legal name of the business represented by this instance.`}
/>
<Input<Entity>
name="email"
- label={i18n`Email`}
- tooltip={i18n`Contact email`}
+ label={i18n.str`Email`}
+ tooltip={i18n.str`Contact email`}
/>
<Input<Entity>
name="website"
- label={i18n`Website URL`}
- tooltip={i18n`URL.`}
+ label={i18n.str`Website URL`}
+ tooltip={i18n.str`URL.`}
/>
<InputImage<Entity>
name="logo"
- label={i18n`Logo`}
- tooltip={i18n`Logo image.`}
+ label={i18n.str`Logo`}
+ tooltip={i18n.str`Logo image.`}
/>
<InputPaytoForm<Entity>
name="payto_uris"
- label={i18n`Bank account`}
- tooltip={i18n`URI specifying bank account for crediting revenue.`}
+ label={i18n.str`Bank account`}
+ tooltip={i18n.str`URI specifying bank account for crediting revenue.`}
/>
<InputCurrency<Entity>
name="default_max_deposit_fee"
- label={i18n`Default max deposit fee`}
- tooltip={i18n`Maximum deposit fees this merchant is willing to pay per order by default.`}
+ label={i18n.str`Default max deposit fee`}
+ tooltip={i18n.str`Maximum deposit fees this merchant is willing to pay per order by default.`}
/>
<InputCurrency<Entity>
name="default_max_wire_fee"
- label={i18n`Default max wire fee`}
- tooltip={i18n`Maximum wire fees this merchant is willing to pay per wire transfer by default.`}
+ label={i18n.str`Default max wire fee`}
+ tooltip={i18n.str`Maximum wire fees this merchant is willing to pay per wire transfer by default.`}
/>
<Input<Entity>
name="default_wire_fee_amortization"
- label={i18n`Default wire fee amortization`}
- tooltip={i18n`Number of orders excess wire transfer fees will be divided by to compute per order surcharge.`}
+ label={i18n.str`Default wire fee amortization`}
+ tooltip={i18n.str`Number of orders excess wire transfer fees will be divided by to compute per order surcharge.`}
/>
<InputGroup
name="address"
- label={i18n`Address`}
- tooltip={i18n`Physical location of the merchant.`}
+ label={i18n.str`Address`}
+ tooltip={i18n.str`Physical location of the merchant.`}
>
<InputLocation name="address" />
</InputGroup>
<InputGroup
name="jurisdiction"
- label={i18n`Jurisdiction`}
- tooltip={i18n`Jurisdiction for legal disputes with the merchant.`}
+ label={i18n.str`Jurisdiction`}
+ tooltip={i18n.str`Jurisdiction for legal disputes with the merchant.`}
>
<InputLocation name="jurisdiction" />
</InputGroup>
<InputDuration<Entity>
name="default_pay_delay"
- label={i18n`Default payment delay`}
+ label={i18n.str`Default payment delay`}
withForever
- tooltip={i18n`Time customers have to pay an order before the offer expires by default.`}
+ tooltip={i18n.str`Time customers have to pay an order before the offer expires by default.`}
/>
<InputDuration<Entity>
name="default_wire_transfer_delay"
- label={i18n`Default wire transfer delay`}
- tooltip={i18n`Maximum time an exchange is allowed to delay wiring funds to the merchant, enabling it to aggregate smaller payments into larger wire transfers and reducing wire fees.`}
+ label={i18n.str`Default wire transfer delay`}
+ tooltip={i18n.str`Maximum time an exchange is allowed to delay wiring funds to the merchant, enabling it to aggregate smaller payments into larger wire transfers and reducing wire fees.`}
withForever
/>
</Fragment>
diff --git a/packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx b/packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx
index d618d6480..a1de8541e 100644
--- a/packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx
+++ b/packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx
@@ -19,11 +19,11 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import langIcon from "../../assets/icons/languageicon.svg";
-import { useTranslationContext } from "../../context/translation.js";
-import { strings as messages } from "../../i18n/strings";
+import { strings as messages } from "../../i18n/strings.js";
type LangsNames = {
[P in keyof typeof messages]: string;
diff --git a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
index ea49be99a..92d144b1a 100644
--- a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
+++ b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
@@ -19,13 +19,11 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
-import { useCallback } from "preact/hooks";
import { useBackendContext } from "../../context/backend.js";
import { useConfigContext } from "../../context/config.js";
-import { useInstanceContext } from "../../context/instance.js";
import { useInstanceKYCDetails } from "../../hooks/instance.js";
-import { Translate } from "../../i18n/index.js";
import { LangSelector } from "./LangSelector.js";
const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
@@ -48,7 +46,7 @@ export function Sidebar({
}: Props): VNode {
const config = useConfigContext();
const backend = useBackendContext();
-
+ const { i18n } = useTranslationContext();
const kycStatus = useInstanceKYCDetails();
const needKYC = kycStatus.ok && kycStatus.data.type === "redirect";
@@ -81,7 +79,7 @@ export function Sidebar({
{instance ? (
<Fragment>
<p class="menu-label">
- <Translate>Instance</Translate>
+ <i18n.Translate>Instance</i18n.Translate>
</p>
<ul class="menu-list">
<li>
@@ -90,7 +88,7 @@ export function Sidebar({
<i class="mdi mdi-square-edit-outline" />
</span>
<span class="menu-item-label">
- <Translate>Settings</Translate>
+ <i18n.Translate>Settings</i18n.Translate>
</span>
</a>
</li>
@@ -100,7 +98,7 @@ export function Sidebar({
<i class="mdi mdi-cash-register" />
</span>
<span class="menu-item-label">
- <Translate>Orders</Translate>
+ <i18n.Translate>Orders</i18n.Translate>
</span>
</a>
</li>
@@ -110,7 +108,7 @@ export function Sidebar({
<i class="mdi mdi-shopping" />
</span>
<span class="menu-item-label">
- <Translate>Products</Translate>
+ <i18n.Translate>Products</i18n.Translate>
</span>
</a>
</li>
@@ -120,7 +118,7 @@ export function Sidebar({
<i class="mdi mdi-bank" />
</span>
<span class="menu-item-label">
- <Translate>Transfers</Translate>
+ <i18n.Translate>Transfers</i18n.Translate>
</span>
</a>
</li>
@@ -130,7 +128,7 @@ export function Sidebar({
<i class="mdi mdi-newspaper" />
</span>
<span class="menu-item-label">
- <Translate>Templates</Translate>
+ <i18n.Translate>Templates</i18n.Translate>
</span>
</a>
</li>
@@ -156,7 +154,7 @@ export function Sidebar({
</Fragment>
) : undefined}
<p class="menu-label">
- <Translate>Connection</Translate>
+ <i18n.Translate>Connection</i18n.Translate>
</p>
<ul class="menu-list">
<li>
@@ -190,7 +188,7 @@ export function Sidebar({
{admin && !mimic && (
<Fragment>
<p class="menu-label">
- <Translate>Instances</Translate>
+ <i18n.Translate>Instances</i18n.Translate>
</p>
<li>
<a href={"/instance/new"} class="has-icon">
@@ -198,7 +196,7 @@ export function Sidebar({
<i class="mdi mdi-plus" />
</span>
<span class="menu-item-label">
- <Translate>New</Translate>
+ <i18n.Translate>New</i18n.Translate>
</span>
</a>
</li>
@@ -208,7 +206,7 @@ export function Sidebar({
<i class="mdi mdi-format-list-bulleted" />
</span>
<span class="menu-item-label">
- <Translate>List</Translate>
+ <i18n.Translate>List</i18n.Translate>
</span>
</a>
</li>
@@ -223,7 +221,7 @@ export function Sidebar({
<i class="mdi mdi-logout default" />
</span>
<span class="menu-item-label">
- <Translate>Log out</Translate>
+ <i18n.Translate>Log out</i18n.Translate>
</span>
</a>
</li>
diff --git a/packages/merchant-backoffice-ui/src/components/menu/index.tsx b/packages/merchant-backoffice-ui/src/components/menu/index.tsx
index 23935ec98..ccbd9442f 100644
--- a/packages/merchant-backoffice-ui/src/components/menu/index.tsx
+++ b/packages/merchant-backoffice-ui/src/components/menu/index.tsx
@@ -15,7 +15,6 @@
*/
import { ComponentChildren, Fragment, h, VNode } from "preact";
-import Match from "preact-router/match";
import { useEffect, useState } from "preact/hooks";
import { AdminPaths } from "../../AdminRoutes.js";
import { InstancePaths } from "../../InstanceRoutes.js";
@@ -58,6 +57,7 @@ function getAdminTitle(path: string, instance: string) {
interface MenuProps {
title?: string;
+ path: string;
instance: string;
admin?: boolean;
onLogout?: () => void;
@@ -81,64 +81,59 @@ export function Menu({
onLogout,
title,
instance,
+ path,
admin,
setInstanceName,
}: MenuProps): VNode {
const [mobileOpen, setMobileOpen] = useState(false);
+ const titleWithSubtitle = title
+ ? title
+ : !admin
+ ? getInstanceTitle(path, instance)
+ : getAdminTitle(path, instance);
+ const adminInstance = instance === "default";
+ const mimic = admin && !adminInstance;
return (
- <Match>
- {({ path }: any) => {
- const titleWithSubtitle = title
- ? title
- : !admin
- ? getInstanceTitle(path, instance)
- : getAdminTitle(path, instance);
- const adminInstance = instance === "default";
- const mimic = admin && !adminInstance;
- return (
- <WithTitle title={titleWithSubtitle}>
- <div
- class={mobileOpen ? "has-aside-mobile-expanded" : ""}
- onClick={() => setMobileOpen(false)}
- >
- <NavigationBar
- onMobileMenu={() => setMobileOpen(!mobileOpen)}
- title={titleWithSubtitle}
- />
-
- {onLogout && (
- <Sidebar
- onLogout={onLogout}
- admin={admin}
- mimic={mimic}
- instance={instance}
- mobile={mobileOpen}
- />
- )}
-
- {mimic && (
- <nav class="level">
- <div class="level-item has-text-centered has-background-warning">
- <p class="is-size-5">
- You are viewing the instance <b>"{instance}"</b>.{" "}
- <a
- href="#/instances"
- onClick={(e) => {
- setInstanceName("default");
- }}
- >
- go back
- </a>
- </p>
- </div>
- </nav>
- )}
+ <WithTitle title={titleWithSubtitle}>
+ <div
+ class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+ onClick={() => setMobileOpen(false)}
+ >
+ <NavigationBar
+ onMobileMenu={() => setMobileOpen(!mobileOpen)}
+ title={titleWithSubtitle}
+ />
+
+ {onLogout && (
+ <Sidebar
+ onLogout={onLogout}
+ admin={admin}
+ mimic={mimic}
+ instance={instance}
+ mobile={mobileOpen}
+ />
+ )}
+
+ {mimic && (
+ <nav class="level">
+ <div class="level-item has-text-centered has-background-warning">
+ <p class="is-size-5">
+ You are viewing the instance <b>&quot;{instance}&quot;</b>.{" "}
+ <a
+ href="#/instances"
+ onClick={(e) => {
+ setInstanceName("default");
+ }}
+ >
+ go back
+ </a>
+ </p>
</div>
- </WithTitle>
- );
- }}
- </Match>
+ </nav>
+ )}
+ </div>
+ </WithTitle>
);
}
diff --git a/packages/merchant-backoffice-ui/src/components/modal/index.tsx b/packages/merchant-backoffice-ui/src/components/modal/index.tsx
index 6e5575f63..c9c7d0ce5 100644
--- a/packages/merchant-backoffice-ui/src/components/modal/index.tsx
+++ b/packages/merchant-backoffice-ui/src/components/modal/index.tsx
@@ -19,12 +19,12 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { ComponentChildren, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useInstanceContext } from "../../context/instance.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { DEFAULT_REQUEST_TIMEOUT } from "../../utils/constants.js";
-import { Loading, Spinner } from "../exception/loading.js";
+import { Spinner } from "../exception/loading.js";
import { FormProvider } from "../form/FormProvider.js";
import { Input } from "../form/Input.js";
@@ -49,6 +49,7 @@ export function ConfirmModal({
disabled,
label = "Confirm",
}: Props): VNode {
+ const { i18n } = useTranslationContext();
return (
<div class={active ? "modal is-active" : "modal"}>
<div class="modal-background " onClick={onCancel} />
@@ -65,14 +66,14 @@ export function ConfirmModal({
<footer class="modal-card-foot">
<div class="buttons is-right" style={{ width: "100%" }}>
<button class="button " onClick={onCancel}>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</button>
<button
class={danger ? "button is-danger " : "button is-info "}
disabled={disabled}
onClick={onConfirm}
>
- <Translate>{label}</Translate>
+ <i18n.Translate>{label}</i18n.Translate>
</button>
</div>
</footer>
@@ -94,6 +95,7 @@ export function ContinueModal({
children,
disabled,
}: Props): VNode {
+ const { i18n } = useTranslationContext();
return (
<div class={active ? "modal is-active" : "modal"}>
<div class="modal-background " onClick={onCancel} />
@@ -110,7 +112,7 @@ export function ContinueModal({
disabled={disabled}
onClick={onConfirm}
>
- <Translate>Continue</Translate>
+ <i18n.Translate>Continue</i18n.Translate>
</button>
</div>
</footer>
@@ -147,6 +149,7 @@ export function ClearConfirmModal({
onConfirm,
children,
}: Props & { onClear?: () => void }): VNode {
+ const { i18n } = useTranslationContext();
return (
<div class="modal is-active">
<div class="modal-background " onClick={onCancel} />
@@ -163,19 +166,19 @@ export function ClearConfirmModal({
onClick={onClear}
disabled={onClear === undefined}
>
- <Translate>Clear</Translate>
+ <i18n.Translate>Clear</i18n.Translate>
</button>
)}
<div class="buttons is-right" style={{ width: "100%" }}>
<button class="button " onClick={onCancel}>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</button>
<button
class="button is-info"
onClick={onConfirm}
disabled={onConfirm === undefined}
>
- <Translate>Confirm</Translate>
+ <i18n.Translate>Confirm</i18n.Translate>
</button>
</div>
</footer>
@@ -210,7 +213,7 @@ export function DeleteModal({
onConfirm={() => onConfirm(element.id)}
>
<p>
- If you delete the instance named <b>"{element.name}"</b> (ID:{" "}
+ If you delete the instance named <b>&quot;{element.name}&quot;</b> (ID:{" "}
<b>{element.id}</b>), the merchant will no longer be able to process
orders or refunds
</p>
@@ -241,12 +244,13 @@ export function PurgeModal({
onConfirm={() => onConfirm(element.id)}
>
<p>
- If you purge the instance named <b>"{element.name}"</b> (ID:{" "}
- <b>{element.id}</b>), you will also delete all it's transaction data.
+ If you purge the instance named <b>&quot;{element.name}&quot;</b> (ID:{" "}
+ <b>{element.id}</b>), you will also delete all it&apos;s transaction
+ data.
</p>
<p>
The instance will disappear from your list, and you will no longer be
- able to access it's data.
+ able to access it&apos;s data.
</p>
<p class="warning">
Purging an instance <b>cannot be undone</b>.
@@ -275,20 +279,22 @@ export function UpdateTokenModal({
new_token: "",
repeat_token: "",
});
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const hasInputTheCorrectOldToken = oldToken && oldToken !== form.old_token;
const errors = {
old_token: hasInputTheCorrectOldToken
- ? i18n`is not the same as the current access token`
+ ? i18n.str`is not the same as the current access token`
: undefined,
new_token: !form.new_token
- ? i18n`cannot be empty`
+ ? i18n.str`cannot be empty`
: form.new_token === form.old_token
- ? i18n`cannot be the same as the old token`
+ ? i18n.str`cannot be the same as the old token`
: undefined,
repeat_token:
- form.new_token !== form.repeat_token ? i18n`is not the same` : undefined,
+ form.new_token !== form.repeat_token
+ ? i18n.str`is not the same`
+ : undefined,
};
const hasErrors = Object.keys(errors).some(
@@ -297,7 +303,7 @@ export function UpdateTokenModal({
const instance = useInstanceContext();
- const text = i18n`You are updating the access token from instance with id ${instance.id}`;
+ const text = i18n.str`You are updating the access token from instance with id ${instance.id}`;
return (
<ClearConfirmModal
@@ -313,28 +319,28 @@ export function UpdateTokenModal({
{oldToken && (
<Input<State>
name="old_token"
- label={i18n`Old access token`}
- tooltip={i18n`access token currently in use`}
+ label={i18n.str`Old access token`}
+ tooltip={i18n.str`access token currently in use`}
inputType="password"
/>
)}
<Input<State>
name="new_token"
- label={i18n`New access token`}
- tooltip={i18n`next access token to be used`}
+ label={i18n.str`New access token`}
+ tooltip={i18n.str`next access token to be used`}
inputType="password"
/>
<Input<State>
name="repeat_token"
- label={i18n`Repeat access token`}
- tooltip={i18n`confirm the same access token`}
+ label={i18n.str`Repeat access token`}
+ tooltip={i18n.str`confirm the same access token`}
inputType="password"
/>
</FormProvider>
<p>
- <Translate>
+ <i18n.Translate>
Clearing the access token will mean public access to the instance
- </Translate>
+ </i18n.Translate>
</p>
</div>
<div class="column" />
@@ -353,16 +359,18 @@ export function SetTokenNewInstanceModal({
new_token: "",
repeat_token: "",
});
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const errors = {
new_token: !form.new_token
- ? i18n`cannot be empty`
+ ? i18n.str`cannot be empty`
: form.new_token === form.old_token
- ? i18n`cannot be the same as the old access token`
+ ? i18n.str`cannot be the same as the old access token`
: undefined,
repeat_token:
- form.new_token !== form.repeat_token ? i18n`is not the same` : undefined,
+ form.new_token !== form.repeat_token
+ ? i18n.str`is not the same`
+ : undefined,
};
const hasErrors = Object.keys(errors).some(
@@ -374,7 +382,7 @@ export function SetTokenNewInstanceModal({
<div class="modal-background " onClick={onCancel} />
<div class="modal-card">
<header class="modal-card-head">
- <p class="modal-card-title">{i18n`You are setting the access token for the new instance`}</p>
+ <p class="modal-card-title">{i18n.str`You are setting the access token for the new instance`}</p>
<button class="delete " aria-label="close" onClick={onCancel} />
</header>
<section class="modal-card-body is-main-section">
@@ -388,22 +396,22 @@ export function SetTokenNewInstanceModal({
>
<Input<State>
name="new_token"
- label={i18n`New access token`}
- tooltip={i18n`next access token to be used`}
+ label={i18n.str`New access token`}
+ tooltip={i18n.str`next access token to be used`}
inputType="password"
/>
<Input<State>
name="repeat_token"
- label={i18n`Repeat access token`}
- tooltip={i18n`confirm the same access token`}
+ label={i18n.str`Repeat access token`}
+ tooltip={i18n.str`confirm the same access token`}
inputType="password"
/>
</FormProvider>
<p>
- <Translate>
+ <i18n.Translate>
With external authorization method no check will be done by
the merchant backend
- </Translate>
+ </i18n.Translate>
</p>
</div>
<div class="column" />
@@ -416,19 +424,19 @@ export function SetTokenNewInstanceModal({
onClick={onClear}
disabled={onClear === undefined}
>
- <Translate>Set external authorization</Translate>
+ <i18n.Translate>Set external authorization</i18n.Translate>
</button>
)}
<div class="buttons is-right" style={{ width: "100%" }}>
<button class="button " onClick={onCancel}>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</button>
<button
class="button is-info"
onClick={() => onConfirm(form.new_token!)}
disabled={hasErrors}
>
- <Translate>Set access token</Translate>
+ <i18n.Translate>Set access token</i18n.Translate>
</button>
</div>
</footer>
@@ -443,14 +451,14 @@ export function SetTokenNewInstanceModal({
}
export function LoadingModal({ onCancel }: { onCancel: () => void }): VNode {
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div class="modal is-active">
<div class="modal-background " onClick={onCancel} />
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">
- <Translate>Operation in progress...</Translate>
+ <i18n.Translate>Operation in progress...</i18n.Translate>
</p>
</header>
<section class="modal-card-body">
@@ -459,12 +467,12 @@ export function LoadingModal({ onCancel }: { onCancel: () => void }): VNode {
<Spinner />
<div class="column" />
</div>
- <p>{i18n`The operation will be automatically canceled after ${DEFAULT_REQUEST_TIMEOUT} seconds`}</p>
+ <p>{i18n.str`The operation will be automatically canceled after ${DEFAULT_REQUEST_TIMEOUT} seconds`}</p>
</section>
<footer class="modal-card-foot">
<div class="buttons is-right" style={{ width: "100%" }}>
<button class="button " onClick={onCancel}>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</button>
</div>
</footer>
diff --git a/packages/merchant-backoffice-ui/src/components/picker/DurationPicker.tsx b/packages/merchant-backoffice-ui/src/components/picker/DurationPicker.tsx
index 629e50b8c..0e8baac06 100644
--- a/packages/merchant-backoffice-ui/src/components/picker/DurationPicker.tsx
+++ b/packages/merchant-backoffice-ui/src/components/picker/DurationPicker.tsx
@@ -19,9 +19,9 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { useTranslator } from "../../i18n/index.js";
import "../../scss/DurationPicker.scss";
export interface Props {
@@ -46,13 +46,13 @@ export function DurationPicker({
const ms = ss * 60;
const hs = ms * 60;
const ds = hs * 24;
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div class="rdp-picker">
{days && (
<DurationColumn
- unit={i18n`days`}
+ unit={i18n.str`days`}
max={99}
value={Math.floor(value / ds)}
onDecrease={value >= ds ? () => onChange(value - ds) : undefined}
@@ -62,7 +62,7 @@ export function DurationPicker({
)}
{hours && (
<DurationColumn
- unit={i18n`hours`}
+ unit={i18n.str`hours`}
max={23}
min={1}
value={Math.floor(value / hs) % 24}
@@ -73,7 +73,7 @@ export function DurationPicker({
)}
{minutes && (
<DurationColumn
- unit={i18n`minutes`}
+ unit={i18n.str`minutes`}
max={59}
min={1}
value={Math.floor(value / ms) % 60}
@@ -84,7 +84,7 @@ export function DurationPicker({
)}
{seconds && (
<DurationColumn
- unit={i18n`seconds`}
+ unit={i18n.str`seconds`}
max={59}
value={Math.floor(value / ss) % 60}
onDecrease={value >= ss ? () => onChange(value - ss) : undefined}
diff --git a/packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx b/packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx
index da47f1be3..0cb2d555e 100644
--- a/packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx
+++ b/packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx
@@ -13,14 +13,14 @@
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { FormProvider, FormErrors } from "../form/FormProvider.js";
-import { InputNumber } from "../form/InputNumber.js";
-import { InputSearchProduct } from "../form/InputSearchProduct.js";
import { MerchantBackend, WithId } from "../../declaration.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
import { ProductMap } from "../../paths/instance/orders/create/CreatePage.js";
+import { FormErrors, FormProvider } from "../form/FormProvider.js";
+import { InputNumber } from "../form/InputNumber.js";
+import { InputSearchProduct } from "../form/InputSearchProduct.js";
type Form = {
product: MerchantBackend.Products.ProductDetail & WithId;
@@ -45,21 +45,23 @@ export function InventoryProductForm({
const [state, setState] = useState<Partial<Form>>(initialState);
const [errors, setErrors] = useState<FormErrors<Form>>({});
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
const productWithInfiniteStock =
state.product && state.product.total_stock === -1;
const submit = (): void => {
if (!state.product) {
- setErrors({ product: i18n`You must enter a valid product identifier.` });
+ setErrors({
+ product: i18n.str`You must enter a valid product identifier.`,
+ });
return;
}
if (productWithInfiniteStock) {
onAddProduct(state.product, 1);
} else {
if (!state.quantity || state.quantity <= 0) {
- setErrors({ quantity: i18n`Quantity must be greater than 0!` });
+ setErrors({ quantity: i18n.str`Quantity must be greater than 0!` });
return;
}
const currentStock =
@@ -71,7 +73,7 @@ export function InventoryProductForm({
if (state.quantity + p.quantity > currentStock) {
const left = currentStock - p.quantity;
setErrors({
- quantity: i18n`This quantity exceeds remaining stock. Currently, only ${left} units remain unreserved in stock.`,
+ quantity: i18n.str`This quantity exceeds remaining stock. Currently, only ${left} units remain unreserved in stock.`,
});
return;
}
@@ -80,7 +82,7 @@ export function InventoryProductForm({
if (state.quantity > currentStock) {
const left = currentStock;
setErrors({
- quantity: i18n`This quantity exceeds remaining stock. Currently, only ${left} units remain unreserved in stock.`,
+ quantity: i18n.str`This quantity exceeds remaining stock. Currently, only ${left} units remain unreserved in stock.`,
});
return;
}
@@ -104,15 +106,15 @@ export function InventoryProductForm({
{!productWithInfiniteStock && (
<InputNumber<Form>
name="quantity"
- label={i18n`Quantity`}
- tooltip={i18n`how many products will be added`}
+ label={i18n.str`Quantity`}
+ tooltip={i18n.str`how many products will be added`}
/>
)}
</div>
<div class="column">
<div class="buttons is-right">
<button class="button is-success" onClick={submit}>
- <Translate>Add from inventory</Translate>
+ <i18n.Translate>Add from inventory</i18n.Translate>
</button>
</div>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/product/NonInventoryProductForm.tsx b/packages/merchant-backoffice-ui/src/components/product/NonInventoryProductForm.tsx
index fe9692c02..3e7262657 100644
--- a/packages/merchant-backoffice-ui/src/components/product/NonInventoryProductForm.tsx
+++ b/packages/merchant-backoffice-ui/src/components/product/NonInventoryProductForm.tsx
@@ -13,19 +13,19 @@
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useCallback, useEffect, useState } from "preact/hooks";
import * as yup from "yup";
+import { MerchantBackend } from "../../declaration.js";
+import { useListener } from "../../hooks/listener.js";
+import { NonInventoryProductSchema as schema } from "../../schemas/index.js";
import { FormErrors, FormProvider } from "../form/FormProvider.js";
import { Input } from "../form/Input.js";
import { InputCurrency } from "../form/InputCurrency.js";
import { InputImage } from "../form/InputImage.js";
import { InputNumber } from "../form/InputNumber.js";
import { InputTaxes } from "../form/InputTaxes.js";
-import { MerchantBackend } from "../../declaration.js";
-import { useListener } from "../../hooks/listener.js";
-import { Translate, useTranslator } from "../../i18n/index.js";
-import { NonInventoryProductSchema as schema } from "../../schemas/index.js";
type Entity = MerchantBackend.Product;
@@ -62,17 +62,17 @@ export function NonInventoryProductFrom({
return Promise.resolve();
});
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<Fragment>
<div class="buttons">
<button
class="button is-success"
- data-tooltip={i18n`describe and add a product that is not in the inventory list`}
+ data-tooltip={i18n.str`describe and add a product that is not in the inventory list`}
onClick={() => setShowCreateProduct(true)}
>
- <Translate>Add custom product</Translate>
+ <i18n.Translate>Add custom product</i18n.Translate>
</button>
</div>
{showCreateProduct && (
@@ -83,7 +83,7 @@ export function NonInventoryProductFrom({
/>
<div class="modal-card">
<header class="modal-card-head">
- <p class="modal-card-title">{i18n`Complete information of the product`}</p>
+ <p class="modal-card-title">{i18n.str`Complete information of the product`}</p>
<button
class="delete "
aria-label="close"
@@ -102,14 +102,14 @@ export function NonInventoryProductFrom({
class="button "
onClick={() => setShowCreateProduct(false)}
>
- <Translate>Cancel</Translate>
+ <i18n.Translate>Cancel</i18n.Translate>
</button>
<button
class="button is-info "
disabled={!submitForm}
onClick={submitForm}
>
- <Translate>Confirm</Translate>
+ <i18n.Translate>Confirm</i18n.Translate>
</button>
</div>
</footer>
@@ -170,7 +170,7 @@ export function ProductForm({ onSubscribe, initial }: ProductProps): VNode {
onSubscribe(hasErrors ? undefined : submit);
}, [submit, hasErrors]);
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div>
@@ -182,33 +182,33 @@ export function ProductForm({ onSubscribe, initial }: ProductProps): VNode {
>
<InputImage<NonInventoryProduct>
name="image"
- label={i18n`Image`}
- tooltip={i18n`photo of the product`}
+ label={i18n.str`Image`}
+ tooltip={i18n.str`photo of the product`}
/>
<Input<NonInventoryProduct>
name="description"
inputType="multiline"
- label={i18n`Description`}
- tooltip={i18n`full product description`}
+ label={i18n.str`Description`}
+ tooltip={i18n.str`full product description`}
/>
<Input<NonInventoryProduct>
name="unit"
- label={i18n`Unit`}
- tooltip={i18n`name of the product unit`}
+ label={i18n.str`Unit`}
+ tooltip={i18n.str`name of the product unit`}
/>
<InputCurrency<NonInventoryProduct>
name="price"
- label={i18n`Price`}
- tooltip={i18n`amount in the current currency`}
+ label={i18n.str`Price`}
+ tooltip={i18n.str`amount in the current currency`}
/>
<InputNumber<NonInventoryProduct>
name="quantity"
- label={i18n`Quantity`}
- tooltip={i18n`how many products will be added`}
+ label={i18n.str`Quantity`}
+ tooltip={i18n.str`how many products will be added`}
/>
- <InputTaxes<NonInventoryProduct> name="taxes" label={i18n`Taxes`} />
+ <InputTaxes<NonInventoryProduct> name="taxes" label={i18n.str`Taxes`} />
</FormProvider>
</div>
);
diff --git a/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx b/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx
index a6bb090a5..973f88677 100644
--- a/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx
+++ b/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx
@@ -19,17 +19,17 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { h } from "preact";
import { useCallback, useEffect, useState } from "preact/hooks";
import * as yup from "yup";
import { useBackendContext } from "../../context/backend.js";
import { MerchantBackend } from "../../declaration.js";
-import { useTranslator } from "../../i18n/index.js";
import {
ProductCreateSchema as createSchema,
ProductUpdateSchema as updateSchema,
} from "../../schemas/index.js";
-import { FormProvider, FormErrors } from "../form/FormProvider.js";
+import { FormErrors, FormProvider } from "../form/FormProvider.js";
import { Input } from "../form/Input.js";
import { InputCurrency } from "../form/InputCurrency.js";
import { InputImage } from "../form/InputImage.js";
@@ -115,7 +115,7 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) {
}, [submit, hasErrors]);
const backend = useBackendContext();
- const i18n = useTranslator();
+ const { i18n } = useTranslationContext();
return (
<div>
@@ -129,46 +129,46 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) {
<InputWithAddon<Entity>
name="product_id"
addonBefore={`${backend.url}/product/`}
- label={i18n`ID`}
- tooltip={i18n`product identification to use in URLs (for internal use only)`}
+ label={i18n.str`ID`}
+ tooltip={i18n.str`product identification to use in URLs (for internal use only)`}
/>
)}
<InputImage<Entity>
name="image"
- label={i18n`Image`}
- tooltip={i18n`illustration of the product for customers`}
+ label={i18n.str`Image`}
+ tooltip={i18n.str`illustration of the product for customers`}
/>
<Input<Entity>
name="description"
inputType="multiline"
- label={i18n`Description`}
- tooltip={i18n`product description for customers`}
+ label={i18n.str`Description`}
+ tooltip={i18n.str`product description for customers`}
/>
<InputNumber<Entity>
name="minimum_age"
- label={i18n`Age restricted`}
- tooltip={i18n`is this product restricted for customer below certain age?`}
+ label={i18n.str`Age restricted`}
+ tooltip={i18n.str`is this product restricted for customer below certain age?`}
/>
<Input<Entity>
name="unit"
- label={i18n`Unit`}
- tooltip={i18n`unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 items, 5 meters) for customers`}
+ label={i18n.str`Unit`}
+ tooltip={i18n.str`unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 items, 5 meters) for customers`}
/>
<InputCurrency<Entity>
name="price"
- label={i18n`Price`}
- tooltip={i18n`sale price for customers, including taxes, for above units of the product`}
+ label={i18n.str`Price`}
+ tooltip={i18n.str`sale price for customers, including taxes, for above units of the product`}
/>
<InputStock
name="stock"
- label={i18n`Stock`}
+ label={i18n.str`Stock`}
alreadyExist={alreadyExist}
- tooltip={i18n`product inventory for products with finite supply (for internal use only)`}
+ tooltip={i18n.str`product inventory for products with finite supply (for internal use only)`}
/>
<InputTaxes<Entity>
name="taxes"
- label={i18n`Taxes`}
- tooltip={i18n`taxes included in the product price, exposed to customers`}
+ label={i18n.str`Taxes`}
+ tooltip={i18n.str`taxes included in the product price, exposed to customers`}
/>
</FormProvider>
</div>
diff --git a/packages/merchant-backoffice-ui/src/components/product/ProductList.tsx b/packages/merchant-backoffice-ui/src/components/product/ProductList.tsx
index 774da8975..29556ea70 100644
--- a/packages/merchant-backoffice-ui/src/components/product/ProductList.tsx
+++ b/packages/merchant-backoffice-ui/src/components/product/ProductList.tsx
@@ -16,8 +16,8 @@
import { Amounts } from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import emptyImage from "../../assets/empty.png";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { MerchantBackend } from "../../declaration.js";
-import { Translate } from "../../i18n/index.js";
interface Props {
list: MerchantBackend.Product[];
@@ -28,25 +28,26 @@ interface Props {
}[];
}
export function ProductList({ list, actions = [] }: Props): VNode {
+ const { i18n } = useTranslationContext();
return (
<div class="table-container">
<table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
<thead>
<tr>
<th>
- <Translate>image</Translate>
+ <i18n.Translate>image</i18n.Translate>
</th>
<th>
- <Translate>description</Translate>
+ <i18n.Translate>description</i18n.Translate>
</th>
<th>
- <Translate>quantity</Translate>
+ <i18n.Translate>quantity</i18n.Translate>
</th>
<th>
- <Translate>unit price</Translate>
+ <i18n.Translate>unit price</i18n.Translate>
</th>
<th>
- <Translate>total price</Translate>
+ <i18n.Translate>total price</i18n.Translate>
</th>
<th />
</tr>
diff --git a/packages/merchant-backoffice-ui/src/context/fetch.ts b/packages/merchant-backoffice-ui/src/context/fetch.ts
index 3106a6abe..88c9bc30c 100644
--- a/packages/merchant-backoffice-ui/src/context/fetch.ts
+++ b/packages/merchant-backoffice-ui/src/context/fetch.ts
@@ -29,7 +29,7 @@ interface Type {
useSWRInfinite: typeof useSWRInfinite;
}
-const Context = createContext<Type>({} as any);
+const Context = createContext<Type>({} as Type);
export const useFetchContext = (): Type => useContext(Context);
export const FetchContextProvider = ({
diff --git a/packages/merchant-backoffice-ui/src/context/listener.ts b/packages/merchant-backoffice-ui/src/context/listener.ts
deleted file mode 100644
index cf51bb718..000000000
--- a/packages/merchant-backoffice-ui/src/context/listener.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2023 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-import { createContext } from "preact";
-import { useContext } from "preact/hooks";
-
-interface Type {
- id: string;
- token?: string;
- admin?: boolean;
- changeToken: (t?: string) => void;
-}
-
-const Context = createContext<Type>({} as any);
-
-export const ListenerContextProvider = Context.Provider;
-export const useListenerContext = (): Type => useContext(Context);
diff --git a/packages/merchant-backoffice-ui/src/context/translation.ts b/packages/merchant-backoffice-ui/src/context/translation.ts
deleted file mode 100644
index 027eac14c..000000000
--- a/packages/merchant-backoffice-ui/src/context/translation.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2023 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-import { createContext, h, VNode } from "preact";
-import { useContext, useEffect } from "preact/hooks";
-import { useLang } from "../hooks";
-import * as jedLib from "jed";
-import { strings } from "../i18n/strings";
-
-interface Type {
- lang: string;
- handler: any;
- changeLanguage: (l: string) => void;
-}
-const initial = {
- lang: "en",
- handler: null,
- changeLanguage: () => {
- // do not change anything
- },
-};
-const Context = createContext<Type>(initial);
-
-interface Props {
- initial?: string;
- children: any;
- forceLang?: string;
-}
-
-export const TranslationProvider = ({
- initial,
- children,
- forceLang,
-}: Props): VNode => {
- const [lang, changeLanguage] = useLang(initial);
- useEffect(() => {
- if (forceLang) {
- changeLanguage(forceLang);
- }
- });
- const handler = new jedLib.Jed(strings[lang]);
- return h(Context.Provider, {
- value: { lang, handler, changeLanguage },
- children,
- });
-};
-
-export const useTranslationContext = (): Type => useContext(Context);
diff --git a/packages/merchant-backoffice-ui/src/i18n/index.tsx b/packages/merchant-backoffice-ui/src/i18n/index.tsx
deleted file mode 100644
index da8d2dece..000000000
--- a/packages/merchant-backoffice-ui/src/i18n/index.tsx
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2023 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- * Translation helpers for React components and template literals.
- */
-
-/**
- * Imports
- */
-import { ComponentChild, ComponentChildren, h, Fragment, VNode } from "preact";
-
-import { useTranslationContext } from "../context/translation.js";
-
-export type Translator = (
- stringSeq: TemplateStringsArray,
- ...values: any[]
-) => string;
-export function useTranslator(): Translator {
- const ctx = useTranslationContext();
- const jed = ctx.handler;
- return function str(
- stringSeq: TemplateStringsArray,
- ...values: any[]
- ): string {
- const s = toI18nString(stringSeq);
- if (!s) return s;
- const tr = jed
- .translate(s)
- .ifPlural(1, s)
- .fetch(...values);
- return tr;
- };
-}
-
-/**
- * Convert template strings to a msgid
- */
-function toI18nString(stringSeq: ReadonlyArray<string>): string {
- let s = "";
- for (let i = 0; i < stringSeq.length; i++) {
- s += stringSeq[i];
- if (i < stringSeq.length - 1) {
- s += `%${i + 1}$s`;
- }
- }
- return s;
-}
-
-interface TranslateSwitchProps {
- target: number;
- children: ComponentChildren;
-}
-
-function stringifyChildren(children: ComponentChildren): string {
- let n = 1;
- const ss = (children instanceof Array ? children : [children]).map((c) => {
- if (typeof c === "string") {
- return c;
- }
- return `%${n++}$s`;
- });
- const s = ss.join("").replace(/ +/g, " ").trim();
- return s;
-}
-
-interface TranslateProps {
- children: ComponentChildren;
- /**
- * Component that the translated element should be wrapped in.
- * Defaults to "div".
- */
- wrap?: any;
-
- /**
- * Props to give to the wrapped component.
- */
- wrapProps?: any;
-}
-
-function getTranslatedChildren(
- translation: string,
- children: ComponentChildren,
-): ComponentChild[] {
- const tr = translation.split(/%(\d+)\$s/);
- const childArray = children instanceof Array ? children : [children];
- // Merge consecutive string children.
- const placeholderChildren = Array<ComponentChild>();
- for (let i = 0; i < childArray.length; i++) {
- const x = childArray[i];
- if (x === undefined) {
- continue;
- } else if (typeof x === "string") {
- continue;
- } else {
- placeholderChildren.push(x);
- }
- }
- const result = Array<ComponentChild>();
- for (let i = 0; i < tr.length; i++) {
- if (i % 2 == 0) {
- // Text
- result.push(tr[i]);
- } else {
- const childIdx = Number.parseInt(tr[i], 10) - 1;
- result.push(placeholderChildren[childIdx]);
- }
- }
- return result;
-}
-
-/**
- * Translate text node children of this component.
- * If a child component might produce a text node, it must be wrapped
- * in a another non-text element.
- *
- * Example:
- * ```
- * <Translate>
- * Hello. Your score is <span><PlayerScore player={player} /></span>
- * </Translate>
- * ```
- */
-export function Translate({ children }: TranslateProps): VNode {
- const s = stringifyChildren(children);
- const ctx = useTranslationContext();
- const translation: string = ctx.handler.ngettext(s, s, 1);
- const result = getTranslatedChildren(translation, children);
- return <Fragment>{result}</Fragment>;
-}
-
-/**
- * Switch translation based on singular or plural based on the target prop.
- * Should only contain TranslateSingular and TransplatePlural as children.
- *
- * Example:
- * ```
- * <TranslateSwitch target={n}>
- * <TranslateSingular>I have {n} apple.</TranslateSingular>
- * <TranslatePlural>I have {n} apples.</TranslatePlural>
- * </TranslateSwitch>
- * ```
- */
-export function TranslateSwitch({ children, target }: TranslateSwitchProps) {
- let singular: VNode<TranslationPluralProps> | undefined;
- let plural: VNode<TranslationPluralProps> | undefined;
- // const children = this.props.children;
- if (children) {
- (children instanceof Array ? children : [children]).forEach(
- (child: any) => {
- if (child.type === TranslatePlural) {
- plural = child;
- }
- if (child.type === TranslateSingular) {
- singular = child;
- }
- },
- );
- }
- if (!singular || !plural) {
- console.error("translation not found");
- return h("span", {}, ["translation not found"]);
- }
- singular.props.target = target;
- plural.props.target = target;
- // We're looking up the translation based on the
- // singular, even if we must use the plural form.
- return singular;
-}
-
-interface TranslationPluralProps {
- children: ComponentChildren;
- target: number;
-}
-
-/**
- * See [[TranslateSwitch]].
- */
-export function TranslatePlural({
- children,
- target,
-}: TranslationPluralProps): VNode {
- const s = stringifyChildren(children);
- const ctx = useTranslationContext();
- const translation = ctx.handler.ngettext(s, s, 1);
- const result = getTranslatedChildren(translation, children);
- return <Fragment>{result}</Fragment>;
-}
-
-/**
- * See [[TranslateSwitch]].
- */
-export function TranslateSingular({
- children,
- target,
-}: TranslationPluralProps): VNode {
- const s = stringifyChildren(children);
- const ctx = useTranslationContext();
- const translation = ctx.handler.ngettext(s, s, target);
- const result = getTranslatedChildren(translation, children);
- return <Fragment>{result}</Fragment>;
-}
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,
}),
diff --git a/packages/merchant-backoffice-ui/src/stories.test.ts b/packages/merchant-backoffice-ui/src/stories.test.ts
index 6a401dd25..e85be31b7 100644
--- a/packages/merchant-backoffice-ui/src/stories.test.ts
+++ b/packages/merchant-backoffice-ui/src/stories.test.ts
@@ -20,15 +20,13 @@
*/
import { setupI18n } from "@gnu-taler/taler-util";
import { parseGroupImport } from "@gnu-taler/web-util/lib/index.browser";
-
+import { h as create } from "preact";
+import { render as renderToString } from "preact-render-to-string";
import * as admin from "./paths/admin/index.stories.js";
import * as instance from "./paths/instance/index.stories.js";
setupI18n("en", { en: {} });
-import { h as create } from "preact"
-import { render as renderToString } from "preact-render-to-string";
-
describe("All the examples:", () => {
const cms = parseGroupImport({ admin, instance });
cms.forEach((group) => {
@@ -37,8 +35,11 @@ describe("All the examples:", () => {
describe(`Component: ${component.name}`, () => {
component.examples.forEach((example) => {
it(`should render example: ${example.name}`, () => {
- const vdom = create(example.render.component, example.render.props)
- const html = renderToString(vdom)
+ const vdom = create(
+ example.render.component,
+ example.render.props,
+ );
+ const html = renderToString(vdom);
// console.log(html)
});
});
diff --git a/packages/merchant-backoffice-ui/tests/functions/regex.test.ts b/packages/merchant-backoffice-ui/tests/functions/regex.test.ts
index 12a318c3d..d866a13a0 100644
--- a/packages/merchant-backoffice-ui/tests/functions/regex.test.ts
+++ b/packages/merchant-backoffice-ui/tests/functions/regex.test.ts
@@ -14,10 +14,10 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
- /**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
import { AMOUNT_REGEX, PAYTO_REGEX } from "../../src/utils/constants.js";
@@ -29,11 +29,11 @@ describe('payto uri format', () => {
'payto://void/?amount=EUR:10.5',
'payto://ilp/g.acme.bob'
]
-
- test('should be valid', () => {
+
+ it('should be valid', () => {
valids.forEach(v => expect(v).toMatch(PAYTO_REGEX))
});
-
+
const invalids = [
// has two question marks
'payto://iban/DE75?512108001245126199?amount=EUR:200.0&message=hello',
@@ -46,10 +46,10 @@ describe('payto uri format', () => {
// payto:// is incomplete
'payto: //ilp/g.acme.bob'
]
-
- test('should not be valid', () => {
+
+ it('should not be valid', () => {
invalids.forEach(v => expect(v).not.toMatch(PAYTO_REGEX))
- });
+ });
})
describe('amount format', () => {
@@ -62,11 +62,11 @@ describe('amount format', () => {
'ARSCOL:10',
'THISISTHEMOTHERCOIN:1,000,000.123,123',
]
-
- test('should be valid', () => {
+
+ it('should be valid', () => {
valids.forEach(v => expect(v).toMatch(AMOUNT_REGEX))
});
-
+
const invalids = [
//no currency name
':10',
@@ -79,9 +79,9 @@ describe('amount format', () => {
//missing value
'USD:',
]
-
- test('should not be valid', () => {
+
+ it('should not be valid', () => {
invalids.forEach(v => expect(v).not.toMatch(AMOUNT_REGEX))
- });
+ });
}) \ No newline at end of file
diff --git a/packages/merchant-backoffice-ui/tests/header.test.tsx b/packages/merchant-backoffice-ui/tests/header.test.tsx
index c917366e7..1cf2b7e6c 100644
--- a/packages/merchant-backoffice-ui/tests/header.test.tsx
+++ b/packages/merchant-backoffice-ui/tests/header.test.tsx
@@ -23,23 +23,23 @@ import { h } from "preact";
import { ProductList } from "../src/components/product/ProductList.js";
// See: https://github.com/preactjs/enzyme-adapter-preact-pure
// import { shallow } from 'enzyme';
+import { render } from "@testing-library/preact";
import * as backend from "../src/context/config.js";
-import { render, findAllByText } from "@testing-library/preact";
-import * as i18n from "../src/context/translation.js";
+// import * as i18n from "../src/context/translation.js";
-import * as jedLib from "jed";
-const handler = new jedLib.Jed("en");
+// import * as jedLib from "jed";
+// const handler = new jedLib.Jed("en");
describe("Initial Test of the Sidebar", () => {
beforeEach(() => {
jest
.spyOn(backend, "useConfigContext")
.mockImplementation(() => ({ version: "", currency: "" }));
- jest.spyOn(i18n, "useTranslationContext").mockImplementation(() => ({
- changeLanguage: () => null,
- handler,
- lang: "en",
- }));
+ // jest.spyOn(i18n, "useTranslationContext").mockImplementation(() => ({
+ // changeLanguage: () => null,
+ // handler,
+ // lang: "en",
+ // }));
});
test("Product list renders a table", () => {
const context = render(
diff --git a/packages/web-util/src/tests/hook.ts b/packages/web-util/src/tests/hook.ts
index 0ec47f252..ddc96eb0e 100644
--- a/packages/web-util/src/tests/hook.ts
+++ b/packages/web-util/src/tests/hook.ts
@@ -120,6 +120,7 @@ interface Mounted<T> {
*
* @returns testing API
*/
+// eslint-disable-next-line @typescript-eslint/ban-types
export function mountHook<T extends object>(
hookToBeTested: () => RecursiveState<T>,
Context?: ({ children }: { children: any }) => VNode | null,
@@ -242,6 +243,7 @@ interface HookTestResultError {
*
* @returns testing result, should also be checked to be "ok"
*/
+// eslint-disable-next-line @typescript-eslint/ban-types
export async function hookBehaveLikeThis<T extends object, PropsType>(
hookFunction: (p: PropsType) => RecursiveState<T>,
props: PropsType,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index cec9f0f64..9460653d4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -374,7 +374,7 @@ importers:
jest: ^26.6.3
jest-preset-preact: ^4.0.2
mocha: ^9.2.0
- preact: 10.6.5
+ preact: 10.11.3
preact-render-to-string: ^5.2.6
preact-router: 3.2.1
qrcode-generator: 1.4.4
@@ -391,16 +391,16 @@ importers:
date-fns: 2.29.3
history: 4.10.1
jed: 1.1.1
- preact: 10.6.5
- preact-router: 3.2.1_preact@10.6.5
+ preact: 10.11.3
+ preact-router: 3.2.1_preact@10.11.3
qrcode-generator: 1.4.4
swr: 1.3.0
yup: 0.32.11
devDependencies:
'@creativebulma/bulma-tooltip': 1.2.0
'@gnu-taler/pogen': link:../pogen
- '@testing-library/preact': 2.0.1_preact@10.6.5
- '@testing-library/preact-hooks': 1.1.0_vfcmu6iy7nffpurikpgxo6gwxi
+ '@testing-library/preact': 2.0.1_preact@10.11.3
+ '@testing-library/preact-hooks': 1.1.0_eng4adldpgibddgycwaukopxga
'@types/history': 4.7.11
'@types/jest': 26.0.24
'@types/mocha': 8.2.3
@@ -424,9 +424,9 @@ importers:
html-webpack-skip-assets-plugin: 1.0.3
inline-chunk-html-plugin: 1.1.1
jest: 26.6.3
- jest-preset-preact: 4.0.5_moqeqtbsr7edkxzj3jgnhqkxsm
+ jest-preset-preact: 4.0.5_w5bq6jgm3cbfmbu2zwqko4iate
mocha: 9.2.2
- preact-render-to-string: 5.2.6_preact@10.6.5
+ preact-render-to-string: 5.2.6_preact@10.11.3
rimraf: 3.0.2
sass: 1.56.1
typedoc: 0.20.37_typescript@4.8.4
@@ -5795,14 +5795,14 @@ packages:
preact: 10.11.2
dev: true
- /@testing-library/preact-hooks/1.1.0_vfcmu6iy7nffpurikpgxo6gwxi:
+ /@testing-library/preact-hooks/1.1.0_eng4adldpgibddgycwaukopxga:
resolution: {integrity: sha512-+JIor+NsOHkK3oIrwMDGKGHXTN0JJi462dBJlj4FNbGaDPTlctE6eu2ranWQirh7/FJMkWfzQCP+tk7jmY8ZrQ==}
peerDependencies:
'@testing-library/preact': ^2.0.0
preact: ^10.4.8
dependencies:
- '@testing-library/preact': 2.0.1_preact@10.6.5
- preact: 10.6.5
+ '@testing-library/preact': 2.0.1_preact@10.11.3
+ preact: 10.11.3
dev: true
/@testing-library/preact/2.0.1_preact@10.11.2:
@@ -5815,14 +5815,14 @@ packages:
preact: 10.11.2
dev: true
- /@testing-library/preact/2.0.1_preact@10.6.5:
+ /@testing-library/preact/2.0.1_preact@10.11.3:
resolution: {integrity: sha512-79kwVOY+3caoLgaPbiPzikjgY0Aya7Fc7TvGtR1upCnz2wrtmPDnN2t9vO7I7vDP2zoA+feSwOH5Q0BFErhaaQ==}
engines: {node: '>= 10'}
peerDependencies:
preact: '>=10 || ^10.0.0-alpha.0 || ^10.0.0-beta.0'
dependencies:
'@testing-library/dom': 7.31.2
- preact: 10.6.5
+ preact: 10.11.3
dev: true
/@tootallnate/once/1.1.2:
@@ -14567,7 +14567,7 @@ packages:
- supports-color
dev: true
- /jest-preset-preact/4.0.5_moqeqtbsr7edkxzj3jgnhqkxsm:
+ /jest-preset-preact/4.0.5_w5bq6jgm3cbfmbu2zwqko4iate:
resolution: {integrity: sha512-MnU7mfpnwopJkdx0WoEyRmrNDIvRN+w6sOur0zEhaRYYMo0gJM7UdZHWTV8k6uo0+ypY+m0kQW6kMukUx4v8JQ==}
peerDependencies:
jest: 26.x || 27.x
@@ -14584,8 +14584,8 @@ packages:
isomorphic-unfetch: 3.1.0
jest: 26.6.3
jest-watch-typeahead: 0.6.5_jest@26.6.3
- preact: 10.6.5
- preact-render-to-string: 5.2.6_preact@10.6.5
+ preact: 10.11.3
+ preact-render-to-string: 5.2.6_preact@10.11.3
transitivePeerDependencies:
- encoding
- supports-color
@@ -17955,15 +17955,6 @@ packages:
preact: 10.11.3
pretty-format: 3.8.0
- /preact-render-to-string/5.2.6_preact@10.6.5:
- resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==}
- peerDependencies:
- preact: '>=10'
- dependencies:
- preact: 10.6.5
- pretty-format: 3.8.0
- dev: true
-
/preact-router/3.2.1_preact@10.11.2:
resolution: {integrity: sha512-KEN2VN1DxUlTwzW5IFkF13YIA2OdQ2OvgJTkQREF+AA2NrHRLaGbB68EjS4IeZOa1shvQ1FvEm3bSLta4sXBhg==}
peerDependencies:
@@ -17980,23 +17971,12 @@ packages:
preact: 10.11.3
dev: false
- /preact-router/3.2.1_preact@10.6.5:
- resolution: {integrity: sha512-KEN2VN1DxUlTwzW5IFkF13YIA2OdQ2OvgJTkQREF+AA2NrHRLaGbB68EjS4IeZOa1shvQ1FvEm3bSLta4sXBhg==}
- peerDependencies:
- preact: '>=10'
- dependencies:
- preact: 10.6.5
- dev: false
-
/preact/10.11.2:
resolution: {integrity: sha512-skAwGDFmgxhq1DCBHke/9e12ewkhc7WYwjuhHB8HHS8zkdtITXLRmUMTeol2ldxvLwYtwbFeifZ9uDDWuyL4Iw==}
/preact/10.11.3:
resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==}
- /preact/10.6.5:
- resolution: {integrity: sha512-i+LXM6JiVjQXSt2jG2vZZFapGpCuk1fl8o6ii3G84MA3xgj686FKjs4JFDkmUVhtxyq21+4ay74zqPykz9hU6w==}
-
/prelude-ls/1.1.2:
resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==}
engines: {node: '>= 0.8.0'}