gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant-backoffice] branch master updated: new translation syste


From: gnunet
Subject: [taler-merchant-backoffice] branch master updated: new translation system
Date: Mon, 03 May 2021 06:27:11 +0200

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository merchant-backoffice.

The following commit(s) were added to refs/heads/master by this push:
     new 6d04003  new translation system
6d04003 is described below

commit 6d040035819e5c90a1bbe7940f4d204b2de5c1f4
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Mon May 3 01:26:16 2021 -0300

    new translation system
---
 CHANGELOG.md                                       |    3 +-
 DESIGN.md                                          |   22 +
 README.md                                          |    8 +
 build-system/Makefile                              |   11 +-
 build-translations.sh                              |   25 +
 packages/frontend/.storybook/main.js               |    2 +-
 packages/frontend/.storybook/preview.js            |   10 +-
 .../form/InputPayto.tsx => contrib/po2ts}          |   40 +-
 packages/frontend/package.json                     |    8 +-
 packages/frontend/src/ApplicationReadyRoutes.tsx   |    4 +-
 packages/frontend/src/InstanceRoutes.tsx           |   33 +-
 .../frontend/src/components/exception/login.tsx    |    9 +-
 .../frontend/src/components/form/FormProvider.tsx  |    8 +-
 packages/frontend/src/components/form/Input.tsx    |   22 +-
 .../frontend/src/components/form/InputArray.tsx    |   29 +-
 .../frontend/src/components/form/InputBoolean.tsx  |   21 +-
 .../frontend/src/components/form/InputCurrency.tsx |   12 +-
 .../frontend/src/components/form/InputDate.tsx     |   32 +-
 .../frontend/src/components/form/InputDuration.tsx |    8 +-
 .../frontend/src/components/form/InputGroup.tsx    |   25 +-
 .../frontend/src/components/form/InputImage.tsx    |   30 +-
 .../frontend/src/components/form/InputNumber.tsx   |   10 +-
 .../frontend/src/components/form/InputPayto.tsx    |    9 +-
 .../src/components/form/InputSearchProduct.tsx     |   24 +-
 .../src/components/form/InputSecured.stories.tsx   |    6 +-
 .../frontend/src/components/form/InputSecured.tsx  |   36 +-
 .../frontend/src/components/form/InputSelector.tsx |   22 +-
 .../src/components/form/InputStock.stories.tsx     |   12 +-
 .../frontend/src/components/form/InputStock.tsx    |   67 +-
 .../frontend/src/components/form/InputTaxes.tsx    |   31 +-
 .../src/components/form/InputWithAddon.tsx         |   33 +-
 packages/frontend/src/components/form/useField.tsx |   12 +-
 .../frontend/src/components/menu/LangSelector.tsx  |   15 +-
 packages/frontend/src/components/menu/SideBar.tsx  |   30 +-
 packages/frontend/src/components/modal/index.tsx   |   34 +-
 .../src/components/product/ProductForm.tsx         |   24 +-
 packages/frontend/src/context/backend.ts           |   61 +-
 .../src/{custom.d.ts => context/config.ts}         |   31 +-
 .../src/{custom.d.ts => context/instance.ts}       |   33 +-
 packages/frontend/src/context/translation.ts       |   53 +
 packages/frontend/src/custom.d.ts                  |    4 +
 packages/frontend/src/declaration.d.ts             |    2 +
 packages/frontend/src/hooks/index.ts               |   27 +-
 packages/frontend/src/hooks/instance.ts            |    3 +-
 packages/frontend/src/hooks/order.ts               |    3 +-
 packages/frontend/src/hooks/product.ts             |    6 +-
 packages/frontend/src/hooks/tips.ts                |    3 +-
 packages/frontend/src/hooks/transfer.ts            |    3 +-
 packages/frontend/src/i18n/de.po                   | 1010 +++++++
 packages/frontend/src/i18n/en.po                   | 1010 +++++++
 packages/frontend/src/i18n/es.po                   | 1018 +++++++
 packages/frontend/src/i18n/fr.po                   | 1010 +++++++
 packages/frontend/src/i18n/index.tsx               |  204 ++
 packages/frontend/src/i18n/it.po                   | 1010 +++++++
 packages/frontend/src/i18n/poheader                |   27 +
 .../{messages/index.ts => i18n/strings-prelude}    |    5 +-
 packages/frontend/src/i18n/strings.ts              | 3139 ++++++++++++++++++++
 packages/frontend/src/i18n/sv.po                   | 1010 +++++++
 .../src/i18n/taler-merchant-backoffice.pot         | 1007 +++++++
 packages/frontend/src/index.tsx                    |   22 +-
 packages/frontend/src/messages/en.po               |  627 ----
 packages/frontend/src/messages/es.po               |  202 --
 .../frontend/src/paths/admin/create/CreatePage.tsx |   74 +-
 packages/frontend/src/paths/admin/create/index.tsx |    4 +-
 packages/frontend/src/paths/admin/list/Table.tsx   |   16 +-
 packages/frontend/src/paths/admin/list/View.tsx    |    3 +-
 packages/frontend/src/paths/admin/list/index.tsx   |    1 -
 .../src/paths/instance/details/DetailPage.tsx      |    7 +-
 .../frontend/src/paths/instance/details/index.tsx  |    2 +-
 .../paths/instance/orders/create/CreatePage.tsx    |   84 +-
 .../orders/create/InventoryProductForm.tsx         |   15 +-
 .../orders/create/NonInventoryProductForm.tsx      |   18 +-
 .../paths/instance/orders/details/DetailPage.tsx   |   79 +-
 .../src/paths/instance/orders/details/index.tsx    |    7 +-
 .../src/paths/instance/orders/list/Table.tsx       |   46 +-
 .../src/paths/instance/orders/list/index.tsx       |   26 +-
 .../paths/instance/products/create/CreatePage.tsx  |    6 +-
 .../src/paths/instance/products/create/index.tsx   |    6 +-
 .../src/paths/instance/products/list/Table.tsx     |   46 +-
 .../src/paths/instance/products/list/index.tsx     |   11 +-
 .../paths/instance/products/update/UpdatePage.tsx  |    6 +-
 .../src/paths/instance/products/update/index.tsx   |    5 +-
 .../src/paths/instance/tips/list/Table.tsx         |   12 +-
 .../src/paths/instance/tips/list/index.tsx         |    2 +-
 .../src/paths/instance/transfers/list/Table.tsx    |   10 +-
 .../src/paths/instance/update/UpdatePage.tsx       |   70 +-
 packages/frontend/src/utils/functions.ts           |   42 -
 packages/frontend/tests/header.test.tsx            |    2 +-
 .../frontend/tests/hooks/swr/order-create.test.tsx |    8 +-
 .../tests/hooks/swr/order-pagination.test.tsx      |    8 +-
 .../tests/hooks/swr/product-create.test.tsx        |    8 +-
 .../tests/hooks/swr/product-delete.test.tsx        |    7 +-
 .../hooks/swr/product-details-update.test.tsx      |   10 +-
 .../tests/hooks/swr/product-update.test.tsx        |    7 +-
 packages/frontend/tests/stories.test.tsx           |    2 +-
 packages/frontend/tsconfig.json                    |    1 +
 packages/preact-messages/.gitignore                |    2 -
 packages/preact-messages/CHANGELOG.md              |   16 -
 packages/preact-messages/LICENSE                   |   20 -
 packages/preact-messages/README.md                 |  126 -
 packages/preact-messages/package.json              |   44 -
 packages/preact-messages/src/MessageProvider.ts    |  183 --
 packages/preact-messages/src/declarations.d.ts     |    3 -
 packages/preact-messages/src/get-message.ts        |   87 -
 packages/preact-messages/src/index.ts              |   32 -
 packages/preact-messages/src/message-context.ts    |   72 -
 packages/preact-messages/src/message-error.ts      |   22 -
 packages/preact-messages/src/message.ts            |   89 -
 packages/preact-messages/src/use-locales.ts        |   44 -
 packages/preact-messages/src/use-message-getter.ts |   47 -
 .../preact-messages/src/use-message-template.ts    |   31 -
 packages/preact-messages/src/use-message.ts        |   58 -
 packages/preact-messages/tsconfig.json             |   60 -
 pnpm-lock.yaml                                     |  636 +---
 114 files changed, 11386 insertions(+), 3094 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8807955..24d0aba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,7 +26,8 @@ and this project adheres to [Semantic 
Versioning](https://semver.org/spec/v2.0.0
  - cleanup instance and token management, because code is a mess and can be 
refactored 
 
  - unlock a product when is locked
- 
+ - check that there is no place where the taxes are suming up 
+ - translation missing: yup (check for some other dynamic message)
 ## [Unreleased]
  - fixed bug when updating token and not admin
  - showing a yellow bar on non-default instance navigation (admin)
diff --git a/DESIGN.md b/DESIGN.md
index 100ccf0..b245d72 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -120,3 +120,25 @@ follow this structure:
    action associated with it
 
  * (Then) a particular set of observable consequences should be expected
+
+# Accessibility 
+
+Pages and components should be built with accessibility in mind. 
+ 
+https://github.com/nickcolley/jest-axe
+https://orkhanhuseyn.medium.com/accessibility-testing-in-react-with-jest-axe-e08c2a3f3289
+http://accesibilidadweb.dlsi.ua.es/?menu=jaws
+https://webaim.org/projects/screenreadersurvey8/#intro
+https://www.gov.uk/service-manual/technology/testing-with-assistive-technologies#how-to-test
+https://es.reactjs.org/docs/accessibility.html
+
+# Internationalization
+
+Every non translated message should be written in english and wrapped into:
+
+ * i18n function from useTranslator() hook
+ * <Translate /> component
+
+Makefile has a i18n that will parse source files and update the po template.
+When *.po are updated, running the i18n target will create the strings.ts that
+the application will use in runtime.
diff --git a/README.md b/README.md
index 3607c0a..b737762 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,14 @@ Merchant Admin Frontend is a Single Page Application (SPA) 
that connect with a r
 - make
 - python>=3.8
 
+For the latest version of @gnu-taler npm packages add
+
+```shell
+@gnu-taler:registry=https://gitlab.com/api/v4/packages/npm/
+```
+
+into `.npmrc` file in your home folder.
+
 ## Compiling from source
 
 Check the requirements and run `./bootstrap` and `./configure`
diff --git a/build-system/Makefile b/build-system/Makefile
index 80e20ac..41ab169 100644
--- a/build-system/Makefile
+++ b/build-system/Makefile
@@ -1,8 +1,7 @@
 # This Makefile has been placed in the public domain.
 
-src = src
-
 PORT = 8080
+
 include ./build-system/config.mk
 
 .PHONY: compile
@@ -36,7 +35,7 @@ build:
        pnpm run build
 
 .PHONY: build
-build-single: compile
+build-single: 
        pnpm run build-single --filter merchant-backoffice
        @echo Build done, result at: 'packages/frontend/single/index.html'
 
@@ -45,7 +44,7 @@ submodules-update:
        git submodule update --recursive --remote
 
 .PHONY: check
-check: compile
+check: compile lint
        pnpm run check
 
 .PHONY: dev
@@ -83,3 +82,7 @@ install-view:
                install -m 644 -D $$file 
${prefix}/$${file#packages/frontend/storybook-static/}; \
        done
 
+.PHONY: i18n
+i18n: 
+       ./build-translations.sh
+
diff --git a/build-translations.sh b/build-translations.sh
new file mode 100755
index 0000000..0ce7d57
--- /dev/null
+++ b/build-translations.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+cd packages/frontend;
+
+PONAME=taler-merchant-backoffice
+POGEN=node_modules/@gnu-taler/pogen/bin/pogen.js
+
+find src \( -name '*.ts' -or -name '*.tsx' \) ! -name '*.d.ts' \
+    | xargs node $POGEN \
+    | msguniq \
+    | msgmerge src/i18n/poheader - \
+    > src/i18n/$PONAME.pot
+
+# merge existing translations
+for pofile in src/i18n/*.po; do 
+  echo merging $pofile; 
+  msgmerge -o $pofile $pofile src/i18n/$PONAME.pot; 
+done;
+
+# generate .ts file containing all translations
+cat src/i18n/strings-prelude > src/i18n/strings.ts
+for pofile in src/i18n/*.po; do \
+  echo appending $pofile; \
+  ./contrib/po2ts $pofile >> src/i18n/strings.ts; \
+done; 
+
diff --git a/packages/frontend/.storybook/main.js 
b/packages/frontend/.storybook/main.js
index 6e3ec15..809b0b7 100644
--- a/packages/frontend/.storybook/main.js
+++ b/packages/frontend/.storybook/main.js
@@ -27,7 +27,7 @@ module.exports = {
   ],
   "addons": [
     "@storybook/preset-scss",
-    // "@storybook/addon-a11y",
+    "@storybook/addon-a11y",
     "@storybook/addon-essentials" //docs, control, actions, viewpot, toolbar, 
background
   ],
   webpackFinal: async (config, { configType }) => {
diff --git a/packages/frontend/.storybook/preview.js 
b/packages/frontend/.storybook/preview.js
index 7330bbe..a483dcd 100644
--- a/packages/frontend/.storybook/preview.js
+++ b/packages/frontend/.storybook/preview.js
@@ -15,10 +15,8 @@
  */
 
 import "../src/scss/main.scss"
-import { MessageProvider } from "preact-messages";
-import { ConfigContextProvider } from '../src/context/backend'
-import * as messages from '../src/messages'
-import { h } from 'preact';
+import { ConfigContextProvider } from '../src/context/config'
+import { TranslationProvider } from '../src/context/translation'
 
 const mockConfig = {
   backendURL: 'http://demo.taler.net',
@@ -48,9 +46,9 @@ export const globalTypes = {
 export const decorators = [
   (Story, { globals }) => {
     
-    return <MessageProvider locale={globals.locale} onError="warn" 
messages={messages[globals.locale]} pathSep={null} onError={() => null}>
+    return <TranslationProvider initial={globals.locale}>
       <Story />
-    </MessageProvider>
+    </TranslationProvider>
   },
   (Story) => <ConfigContextProvider value={mockConfig}> <Story /> 
</ConfigContextProvider>
 ];
diff --git a/packages/frontend/src/components/form/InputPayto.tsx 
b/packages/frontend/contrib/po2ts
old mode 100644
new mode 100755
similarity index 51%
copy from packages/frontend/src/components/form/InputPayto.tsx
copy to packages/frontend/contrib/po2ts
index e019da2..a135da6
--- a/packages/frontend/src/components/form/InputPayto.tsx
+++ b/packages/frontend/contrib/po2ts
@@ -1,6 +1,7 @@
+#!/usr/bin/env node
 /*
  This file is part of GNU Taler
- (C) 2021 Taler Systems S.A.
+ (C) 2020 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
@@ -15,26 +16,27 @@
  */
 
 /**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
-import { h, VNode } from "preact";
-import { InputArray } from "./InputArray";
-import { PAYTO_REGEX } from "../../utils/constants";
-
-export interface Props<T> {
-  name: keyof T;
-  readonly?: boolean;
+ * Convert a <lang>.po file into a JavaScript / TypeScript expression.
+ */
+
+const po2json = require("po2json");
+
+const filename = process.argv[2];
+
+if (!filename) {
+  console.error("error: missing filename");
+  process.exit(1);
 }
 
-const PAYTO_START_REGEX = /^payto:\/\//
+const m = filename.match(/([a-zA-Z0-9-_]+).po/);
 
-export function InputPayto<T>({ name, readonly }: Props<T>): VNode {
-  return <InputArray<T> name={name} readonly={readonly} 
-    addonBefore="payto://" 
-    isValid={(v) => v && PAYTO_REGEX.test(v) }
-    toStr={(v?: string) => !v ? '': v.replace(PAYTO_START_REGEX, '')}
-    fromStr={(v: string) => `payto://${v}` }
-  />
+if (!m) {
+  console.error("error: unexpected filename (expected <lang>.po)");
+  process.exit(1);
 }
 
+const lang = m[1];
+const pojson = po2json.parseFileSync(filename, { format: "jed1.x", fuzzy: true 
});
+const s =
+  "strings['" + lang + "'] = " + JSON.stringify(pojson, null, "  ") + ";\n";
+console.log(s);
diff --git a/packages/frontend/package.json b/packages/frontend/package.json
index c6f2406..82e9641 100644
--- a/packages/frontend/package.json
+++ b/packages/frontend/package.json
@@ -43,12 +43,12 @@
     ]
   },
   "dependencies": {
+    "@gnu-taler/taler-util": "^0.8.2",
     "axios": "^0.21.1",
     "date-fns": "^2.21.1",
     "history": "4.10.1",
-    "messageformat": "^2.3.0",
+    "jed": "^1.1.1",
     "preact": "^10.5.13",
-    "preact-messages": "workspace:*",
     "preact-router": "^3.2.1",
     "swr": "^0.5.5",
     "yup": "^0.32.9"
@@ -57,6 +57,7 @@
     "@babel/core": "^7.13.16",
     "@babel/plugin-transform-react-jsx-source": "^7.12.13",
     "@creativebulma/bulma-tooltip": "^1.2.0",
+    "@gnu-taler/pogen": "^0.0.5",
     "@storybook/addon-a11y": "^6.2.9",
     "@storybook/addon-actions": "^6.2.9",
     "@storybook/addon-essentials": "^6.2.9",
@@ -71,7 +72,6 @@
     "@types/mocha": "^8.2.2",
     "@typescript-eslint/eslint-plugin": "^4.22.0",
     "@typescript-eslint/parser": "^4.22.0",
-    "ava": "^3.15.0",
     "babel-loader": "^8.2.2",
     "base64-inline-loader": "^1.1.1",
     "bulma": "^0.9.2",
@@ -93,8 +93,8 @@
     "inline-chunk-html-plugin": "^1.1.1",
     "jest": "^26.6.3",
     "jest-preset-preact": "^4.0.2",
-    "messageformat-po-loader": "^0.3.0",
     "node-sass": "^5.0.0",
+    "po2json": "^0.4.5",
     "preact-cli": "^3.0.5",
     "preact-render-to-json": "^3.6.6",
     "preact-render-to-string": "^5.1.19",
diff --git a/packages/frontend/src/ApplicationReadyRoutes.tsx 
b/packages/frontend/src/ApplicationReadyRoutes.tsx
index 6644118..eb30604 100644
--- a/packages/frontend/src/ApplicationReadyRoutes.tsx
+++ b/packages/frontend/src/ApplicationReadyRoutes.tsx
@@ -26,10 +26,10 @@ import { InstanceRoutes } from "./InstanceRoutes";
 import LoginPage from './paths/login';
 import { INSTANCE_ID_LOOKUP } from './utils/constants';
 import { NotYetReadyAppMenu, Menu, NotificationCard } from './components/menu';
-import { useMessageTemplate } from 'preact-messages';
+import { useTranslator } from './i18n';
 
 export function ApplicationReadyRoutes(): VNode {
-  const i18n = useMessageTemplate();
+  const i18n = useTranslator();
   const { url: backendURL, changeBackend, updateToken, clearAllTokens } = 
useBackendContext();
 
   const updateLoginStatus = (url: string, token?: string) => {
diff --git a/packages/frontend/src/InstanceRoutes.tsx 
b/packages/frontend/src/InstanceRoutes.tsx
index aa97914..c1090dc 100644
--- a/packages/frontend/src/InstanceRoutes.tsx
+++ b/packages/frontend/src/InstanceRoutes.tsx
@@ -21,14 +21,15 @@
 
 import { createHashHistory } from 'history';
 import { Fragment, FunctionComponent, h, VNode } from 'preact';
-import { useMessageTemplate } from 'preact-messages';
 import { Route, route, Router } from 'preact-router';
 import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
 import { Loading } from './components/exception/loading';
 import { NotificationCard } from './components/menu';
-import { InstanceContextProvider, useBackendContext } from './context/backend';
+import { useBackendContext } from './context/backend';
+import { InstanceContextProvider } from './context/instance';
 import { useBackendDefaultToken, useBackendInstanceToken } from './hooks';
 import { HttpError } from "./hooks/backend";
+import { useTranslator } from './i18n';
 import InstanceCreatePage from "./paths/admin/create";
 import InstanceListPage from './paths/admin/list';
 import OrderCreatePage from './paths/instance/orders/create';
@@ -83,8 +84,8 @@ export function InstanceRoutes({ id, admin }: Props): VNode {
   const [token, updateToken] = useBackendInstanceToken(id);
   const { changeBackend, addTokenCleaner } = useBackendContext();
   const cleaner = useCallback(() => { updateToken(undefined); }, [id]);
-  const i18n = useMessageTemplate('');
-  const [globalNotification, setGlobalNotification] = useState<Notification & 
{to:string} | undefined>(undefined)
+  const i18n = useTranslator();
+  const [globalNotification, setGlobalNotification] = useState<Notification & 
{ to: string } | undefined>(undefined)
 
   useEffect(() => {
     addTokenCleaner(cleaner);
@@ -104,8 +105,8 @@ export function InstanceRoutes({ id, admin }: Props): VNode 
{
 
   const ServerErrorRedirectTo = (to: InstancePaths | AdminPaths) => (error: 
HttpError) => {
     setGlobalNotification({
-      message: `HTTP status #${error.status}: Server reported a problem`,
-      description: `Got message: "${error.message}" from: ${error.info?.url}`,
+      message: i18n`HTTP status #${error.status}: Server reported a problem`,
+      description: i18n`Got message: "${error.message}" from: 
${error.info?.url}`,
       type: 'ERROR',
       to
     })
@@ -122,8 +123,8 @@ export function InstanceRoutes({ id, admin }: Props): VNode 
{
       if (admin && id === 'default') {
         return <Fragment>
           <NotificationCard notification={{
-            message: 'No default instance',
-            description: 'in order to use merchant backoffice, you should 
create the default instance',
+            message: i18n`No default instance`,
+            description: i18n`in order to use merchant backoffice, you should 
create the default instance`,
             type: 'INFO'
           }} />
           <InstanceCreatePage forceId="default" onConfirm={() => {
@@ -210,7 +211,7 @@ export function InstanceRoutes({ id, admin }: Props): VNode 
{
         onBack={() => { route(InstancePaths.product_list); }}
         onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
       />
-      <Route path={InstancePaths.product_new} 
+      <Route path={InstancePaths.product_new}
         component={ProductCreatePage}
         onConfirm={() => { route(InstancePaths.product_list); }}
         onBack={() => { route(InstancePaths.product_list); }}
@@ -272,19 +273,27 @@ function AdminInstanceUpdatePage({ id, ...rest }: { id: 
string } & InstanceUpdat
     if (token)
       updateToken(token);
   };
-  const i18n = useMessageTemplate('');
+  const i18n = useTranslator();
   return <InstanceContextProvider value={value}>
     <InstanceUpdatePage {...rest}
       onLoadError={(error: HttpError) => {
         return <Fragment>
-          <NotificationCard notification={{ message: `Server reported a 
problem: HTTP status #${error.status}`, description: `Got message: 
${error.message} from: ${error.info?.url}`, type: 'ERROR' }} />
+          <NotificationCard notification={{
+            message: i18n`Server reported a problem: HTTP status 
#${error.status}`,
+            description: i18n`Got message: ${error.message} from: 
${error.info?.url}`,
+            type: 'ERROR'
+          }} />
           <LoginPage onConfirm={updateLoginStatus} />
         </Fragment>
       }}
 
       onUnauthorized={() => {
         return <Fragment>
-          <NotificationCard notification={{ message: i18n`Access denied`, 
description: i18n`Check your token is valid`, type: 'ERROR', }} />
+          <NotificationCard notification={{
+            message: i18n`Access denied`,
+            description: i18n`Check your token is valid`,
+            type: 'ERROR',
+          }} />
           <LoginPage onConfirm={updateLoginStatus} />
         </Fragment>
       }}
diff --git a/packages/frontend/src/components/exception/login.tsx 
b/packages/frontend/src/components/exception/login.tsx
index 92f6bbe..1132bfe 100644
--- a/packages/frontend/src/components/exception/login.tsx
+++ b/packages/frontend/src/components/exception/login.tsx
@@ -20,9 +20,10 @@
 */
 
 import { h, VNode } from "preact";
-import { useMessageTemplate } from "preact-messages";
 import { useState } from "preact/hooks";
-import { useBackendContext, useInstanceContext } from "../../context/backend";
+import { useBackendContext } from "../../context/backend";
+import { useInstanceContext } from "../../context/instance";
+import { Translate, useTranslator } from "../../i18n";
 import { Notification } from "../../utils/types";
 
 interface Props {
@@ -36,7 +37,7 @@ export function LoginModal({ onConfirm, withMessage }: 
Props): VNode {
   const [token, setToken] = useState(!admin ? baseToken : instanceToken || '')
   
   const [url, setURL] = useState(backendUrl)
-  const i18n = useMessageTemplate()
+  const i18n = useTranslator()
 
   return <div class="columns is-centered">
     <div class="column is-two-thirds " >
@@ -82,7 +83,7 @@ export function LoginModal({ onConfirm, withMessage }: 
Props): VNode {
         <footer class="modal-card-foot " style={{ justifyContent: 'flex-end', 
border: '1px solid', borderTop: 0 }} >
           <button class="button is-info" onClick={(): void => {
             onConfirm(url, token ? token : undefined);
-          }} >Confirm</button>
+          }} ><Translate>Confirm</Translate></button>
         </footer>
       </div>
     </div>
diff --git a/packages/frontend/src/components/form/FormProvider.tsx 
b/packages/frontend/src/components/form/FormProvider.tsx
index 7794a76..eefe589 100644
--- a/packages/frontend/src/components/form/FormProvider.tsx
+++ b/packages/frontend/src/components/form/FormProvider.tsx
@@ -60,14 +60,8 @@ export function useFormContext<T>() {
   return useContext<FormType<T>>(FormContext)
 }
 
-export type ValidationError = {
-  type?: string;
-  message: string;
-  params?: any;
-}
-
 export type FormErrors<T> = {
-  [P in keyof T]?: ValidationError
+  [P in keyof T]?: string
 }
 
 export type FormtoStr<T> = {
diff --git a/packages/frontend/src/components/form/Input.tsx 
b/packages/frontend/src/components/form/Input.tsx
index 9b4f8dd..5b22667 100644
--- a/packages/frontend/src/components/form/Input.tsx
+++ b/packages/frontend/src/components/form/Input.tsx
@@ -19,12 +19,9 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 import { ComponentChildren, h, VNode } from "preact";
-import { Message, useMessage } from "preact-messages";
-import { useField } from "./useField";
+import { useField, InputProps } from "./useField";
 
-interface Props<T> {
-  name: T;
-  readonly?: boolean;
+interface Props<T> extends InputProps<T> {
   inputType?: 'text' | 'number' | 'multiline';
   expand?: boolean;
   toStr?: (v?: any) => string;
@@ -41,16 +38,13 @@ const TextInput = ({ inputType, error, ...rest }: any) => 
inputType === 'multili
   <textarea {...rest} class={error ? "textarea is-danger" : "textarea"} 
rows="3" /> :
   <input {...rest} class={error ? "input is-danger" : "input"} 
type={inputType} />;
 
-export function Input<T>({ name, readonly, expand, children, inputType, 
inputExtra, side, fromStr = defaultFromString, toStr = defaultToString }: 
Props<keyof T>): VNode {
-  const { error, value, onChange, formName } = useField<T>(name);
-
-  const placeholder = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.placeholder`);
-  const tooltip = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.tooltip`);
+export function Input<T>({ name, readonly, placeholder, tooltip, label, 
expand, help, children, inputType, inputExtra, side, fromStr = 
defaultFromString, toStr = defaultToString }: Props<keyof T>): VNode {
+  const { error, value, onChange } = useField<T>(name);
 
   return <div class="field is-horizontal">
     <div class="field-label is-normal">
       <label class="label">
-        <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.label`} />
+        {label}
         {tooltip && <span class="icon" data-tooltip={tooltip}>
           <i class="mdi mdi-information" />
         </span>}
@@ -64,12 +58,10 @@ export function Input<T>({ name, readonly, expand, 
children, inputType, inputExt
             placeholder={placeholder} readonly={readonly}
             name={String(name)} value={toStr(value)}
             onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void => 
onChange(fromStr(e.currentTarget.value))} />
-          <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.help`}> </Message>
+          {help}
           {children}
         </p>
-        {error ? <p class="help is-danger">
-          <Message id={`validation.${error.type}`} 
fields={error.params}>{error.message} </Message>
-        </p> : null}
+        {error && <p class="help is-danger">{error}</p>}
       </div>
       {side}
     </div>
diff --git a/packages/frontend/src/components/form/InputArray.tsx 
b/packages/frontend/src/components/form/InputArray.tsx
index fa9edfa..cbe5c50 100644
--- a/packages/frontend/src/components/form/InputArray.tsx
+++ b/packages/frontend/src/components/form/InputArray.tsx
@@ -19,14 +19,11 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 import { h, VNode } from "preact";
-import { Message, useMessage, useMessageTemplate } from "preact-messages";
 import { useState } from "preact/hooks";
-import { ValidationError } from "./FormProvider";
-import { useField } from "./useField";
+import { useTranslator } from "../../i18n";
+import { InputProps, useField } from "./useField";
 
-export interface Props<T> {
-  name: T;
-  readonly?: boolean;
+export interface Props<T> extends InputProps<T> {
   isValid?: (e: any) => boolean;
   addonBefore?: string;
   toStr?: (v?: any) => string;
@@ -36,22 +33,20 @@ export interface Props<T> {
 const defaultToString = (f?: any): string => f || ''
 const defaultFromString = (v: string): any => v as any
 
-export function InputArray<T>({ name, readonly, addonBefore, isValid = () => 
true, fromStr = defaultFromString, toStr = defaultToString }: Props<keyof T>): 
VNode {
-  const { error: formError, value, onChange, formName } = useField<T>(name);
-  const [localError, setLocalError] = useState<ValidationError | null>(null)
-  const placeholder = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.placeholder`);
-  const tooltip = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.tooltip`);
+export function InputArray<T>({ name, readonly, placeholder, tooltip, label, 
help, addonBefore, isValid = () => true, fromStr = defaultFromString, toStr = 
defaultToString }: Props<keyof T>): VNode {
+  const { error: formError, value, onChange } = useField<T>(name);
+  const [localError, setLocalError] = useState<string | null>(null)
 
   const error = formError || localError
 
   const array: any[] = (value ? value! : []) as any;
   const [currentValue, setCurrentValue] = useState('');
-  const i18n = useMessageTemplate();
+  const i18n = useTranslator();
 
   return <div class="field is-horizontal">
     <div class="field-label is-normal">
       <label class="label">
-        <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.label`} />
+        {label}
         {tooltip && <span class="icon" data-tooltip={tooltip}>
           <i class="mdi mdi-information" />
         </span>}
@@ -68,13 +63,13 @@ export function InputArray<T>({ name, readonly, 
addonBefore, isValid = () => tru
               placeholder={placeholder} readonly={readonly} disabled={readonly}
               name={String(name)} value={currentValue}
               onChange={(e): void => setCurrentValue(e.currentTarget.value)} />
-            <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.help`}> </Message>
+            {help}
           </p>
           <p class="control">
             <button class="button is-info" onClick={(): void => {
               const v = fromStr(currentValue)
               if (!isValid(v)) {
-                setLocalError({ message: i18n`The value ${v} is invalid for a 
payment url` })
+                setLocalError(i18n`The value ${v} is invalid for a payment 
url`)
                 return;
               }
               setLocalError(null)
@@ -84,9 +79,7 @@ export function InputArray<T>({ name, readonly, addonBefore, 
isValid = () => tru
             }}>add</button>
           </p>
         </div>
-        {error ? <p class="help is-danger">
-          <Message id={`validation.${error.type}`} 
fields={error.params}>{error.message}</Message>
-        </p> : null}
+        {error && <p class="help is-danger"> {help} </p>}
         {array.map((v,i) => <div key={i} class="tags has-addons mt-3 mb-0">
           <span class="tag is-medium is-info mb-0" style={{ maxWidth: '90%' 
}}>{v}</span>
           <a class="tag is-medium is-danger is-delete mb-0" onClick={() => {
diff --git a/packages/frontend/src/components/form/InputBoolean.tsx 
b/packages/frontend/src/components/form/InputBoolean.tsx
index 9c59ed1..f5e0648 100644
--- a/packages/frontend/src/components/form/InputBoolean.tsx
+++ b/packages/frontend/src/components/form/InputBoolean.tsx
@@ -19,10 +19,9 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 import { h, VNode } from "preact";
-import { Message, useMessage } from "preact-messages";
-import { useField } from "./useField";
+import { InputProps, useField } from "./useField";
 
-interface Props<T> {
+interface Props<T> extends InputProps<T> {
   name: T;
   readonly?: boolean;
   expand?: boolean;
@@ -35,12 +34,8 @@ const defaultToBoolean = (f?: any): boolean | undefined => f 
|| ''
 const defaultFromBoolean = (v: boolean | undefined): any => v as any
 
 
-
-export function InputBoolean<T>({ name, readonly, threeState, expand, 
fromBoolean = defaultFromBoolean, toBoolean = defaultToBoolean }: Props<keyof 
T>): VNode {
-  const { error, value, onChange, formName } = useField<T>(name);
-
-  const placeholder = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.placeholder`);
-  const tooltip = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.tooltip`);
+export function InputBoolean<T>({ name, readonly, placeholder, tooltip, label, 
help, threeState, expand, fromBoolean = defaultFromBoolean, toBoolean = 
defaultToBoolean }: Props<keyof T>): VNode {
+  const { error, value, onChange } = useField<T>(name);
 
   const onCheckboxClick = (): void => {
     const c = toBoolean(value)
@@ -51,7 +46,7 @@ export function InputBoolean<T>({ name, readonly, threeState, 
expand, fromBoolea
   return <div class="field is-horizontal">
     <div class="field-label is-normal">
       <label class="label">
-        <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.label`} />
+        {label}
         {tooltip && <span class="icon has-tooltip-right" 
data-tooltip={tooltip}>
           <i class="mdi mdi-information" />
         </span>}
@@ -69,11 +64,9 @@ export function InputBoolean<T>({ name, readonly, 
threeState, expand, fromBoolea
 
             <span class="check" />
           </label>
-          <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.help`}> </Message>
+          {help}
         </p>
-        {error ? <p class="help is-danger">
-          <Message id={`validation.${error.type}`} 
fields={error.params}>{error.message} </Message>
-        </p> : null}
+        {error && <p class="help is-danger">{error}</p>}
       </div>
     </div>
   </div>;
diff --git a/packages/frontend/src/components/form/InputCurrency.tsx 
b/packages/frontend/src/components/form/InputCurrency.tsx
index 18f0b2b..d3a46f4 100644
--- a/packages/frontend/src/components/form/InputCurrency.tsx
+++ b/packages/frontend/src/components/form/InputCurrency.tsx
@@ -19,23 +19,23 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 import { ComponentChildren, h } from "preact";
-import { useConfigContext } from "../../context/backend";
+import { useConfigContext } from "../../context/config";
 import { Amount } from "../../declaration";
 import { InputWithAddon } from "./InputWithAddon";
+import { InputProps } from "./useField";
 
-export interface Props<T> {
-  name: keyof T;
-  readonly?: boolean;
+export interface Props<T> extends InputProps<T> {
   expand?: boolean;
   addonAfter?: ComponentChildren;
   children?: ComponentChildren;
   side?: ComponentChildren;
 }
 
-export function InputCurrency<T>({ name, readonly, expand, addonAfter, 
children, side }: Props<T>) {
+export function InputCurrency<T>({ name, readonly, label, placeholder, help, 
tooltip, expand, addonAfter, children, side }: Props<keyof T>) {
   const config = useConfigContext()
   return <InputWithAddon<T> name={name} readonly={readonly} 
addonBefore={config.currency}
-  side={side}
+    side={side}
+    label={label} placeholder={placeholder} help={help} tooltip={tooltip}
     addonAfter={addonAfter}
     inputType='number' expand={expand}
     toStr={(v?: Amount) => v?.split(':')[1] || ''}
diff --git a/packages/frontend/src/components/form/InputDate.tsx 
b/packages/frontend/src/components/form/InputDate.tsx
index 7647c36..b4719ee 100644
--- a/packages/frontend/src/components/form/InputDate.tsx
+++ b/packages/frontend/src/components/form/InputDate.tsx
@@ -20,27 +20,23 @@
 */
 import { format } from "date-fns";
 import { h, VNode } from "preact";
-import { Message, useMessage } from "preact-messages";
 import { useState } from "preact/hooks";
+import { Translate, useTranslator } from "../../i18n";
 import { DatePicker } from "./DatePicker";
-import { useField } from "./useField";
+import { InputProps, useField } from "./useField";
 
-export interface Props<T> {
-  name: keyof T;
+export interface Props<T> extends InputProps<T> {
   readonly?: boolean;
   expand?: boolean;
   //FIXME: create separated components InputDate and InputTimestamp
   withTimestampSupport?: boolean;
 }
 
-export function InputDate<T>({ name, readonly, expand, withTimestampSupport }: 
Props<T>): VNode {
+export function InputDate<T>({ name, readonly, label, placeholder, help, 
tooltip, expand, withTimestampSupport }: Props<keyof T>): VNode {
   const [opened, setOpened] = useState(false)
-  // const [editing, setEditing] = useState(false)
-
-  const { error, value, onChange, formName } = useField<T>(name);
-
-  // const placeholder = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.placeholder`);
-  const tooltip = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.tooltip`);
+  const i18n = useTranslator()
+  
+  const { error, value, onChange } = useField<T>(name);
 
   let strValue = ''
   if (!value) {
@@ -56,7 +52,7 @@ export function InputDate<T>({ name, readonly, expand, 
withTimestampSupport }: P
   return <div class="field is-horizontal">
     <div class="field-label is-normal">
       <label class="label">
-        <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.label`} />
+        {label}
         {tooltip && <span class="icon" data-tooltip={tooltip}>
           <i class="mdi mdi-information" />
         </span>}
@@ -68,10 +64,10 @@ export function InputDate<T>({ name, readonly, expand, 
withTimestampSupport }: P
           <p class={expand ? "control is-expanded" : "control"}>
             <input class="input" type="text"
               readonly value={strValue}
-              placeholder="pick a date"
+              placeholder={i18n`pick a date`}
               onClick={() => setOpened(true)}
             />
-            <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.help`}> </Message>
+            {help}
           </p>
           <div class="control" onClick={() => setOpened(true)}>
             <a class="button is-static" >
@@ -79,12 +75,12 @@ export function InputDate<T>({ name, readonly, expand, 
withTimestampSupport }: P
             </a>
           </div>
         </div>
-        {error ? <p class="help is-danger"><Message 
id={`validation.${error.type}`} 
fields={error.params}>{error.message}</Message></p> : null}
+        {error && <p class="help is-danger">{error}</p>}
       </div>
 
-      <button class="button is-info mr-3" onClick={() => onChange(undefined as 
any)} >clear</button>
+      <button class="button is-info mr-3" onClick={() => onChange(undefined as 
any)} ><Translate>clear</Translate></button>
       {withTimestampSupport &&
-        <button class="button is-info" onClick={() => onChange({ t_ms: 'never' 
} as any)}>never</button>
+        <button class="button is-info" onClick={() => onChange({ t_ms: 'never' 
} as any)}><Translate>never</Translate></button>
       }
     </div>
     <DatePicker
@@ -92,7 +88,7 @@ export function InputDate<T>({ name, readonly, expand, 
withTimestampSupport }: P
       closeFunction={() => setOpened(false)}
       dateReceiver={(d) => {
         if (withTimestampSupport) {
-          onChange({t_ms: d.getTime()} as any)
+          onChange({ t_ms: d.getTime() } as any)
         } else {
           onChange(d as any)
         }
diff --git a/packages/frontend/src/components/form/InputDuration.tsx 
b/packages/frontend/src/components/form/InputDuration.tsx
index 1e28d34..30afd65 100644
--- a/packages/frontend/src/components/form/InputDuration.tsx
+++ b/packages/frontend/src/components/form/InputDuration.tsx
@@ -21,19 +21,19 @@
 import { formatDuration, intervalToDuration } from "date-fns";
 import { h, VNode } from "preact";
 import { RelativeTime } from "../../declaration";
-import { useField } from "./useField";
+import { InputProps, useField } from "./useField";
 import { InputWithAddon } from "./InputWithAddon";
 
-export interface Props<T> {
-  name: keyof T;
+export interface Props<T> extends InputProps<T> {
   expand?: boolean;
   readonly?: boolean;
 }
 
-export function InputDuration<T>({ name, expand, readonly }: Props<T>): VNode {
+export function InputDuration<T>({ name, expand, placeholder, tooltip, label, 
help, readonly }: Props<keyof T>): VNode {
   const { value } = useField<T>(name);
   return <InputWithAddon<T> name={name} readonly={readonly} 
addonAfter={readableDuration(value as any)}
     expand={expand}
+    label={label} placeholder={placeholder} help={help} tooltip={tooltip}
     toStr={(v?: RelativeTime) => `${(v && v.d_ms !== "forever" && v.d_ms ? 
v.d_ms : '')}`}
     fromStr={(v: string) => ({ d_ms: (parseInt(v, 10)) || undefined })}
   />
diff --git a/packages/frontend/src/components/form/InputGroup.tsx 
b/packages/frontend/src/components/form/InputGroup.tsx
index 6da2f2d..8ad50b1 100644
--- a/packages/frontend/src/components/form/InputGroup.tsx
+++ b/packages/frontend/src/components/form/InputGroup.tsx
@@ -19,25 +19,24 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 import { ComponentChildren, h, VNode } from "preact";
-import { Message } from "preact-messages";
 import { useState } from "preact/hooks";
 import { useGroupField } from "./useGroupField";
 
 export interface Props<T> {
-  name: keyof T;
+  name: T;
   children: ComponentChildren;
-  description?: string;
+  label: string;
   alternative?: ComponentChildren;
 }
 
-export function InputGroup<T>({ name, description, children, alternative}: 
Props<T>): VNode {
+export function InputGroup<T>({ name, label, children, alternative }: 
Props<keyof T>): VNode {
   const [active, setActive] = useState(false);
   const group = useGroupField<T>(name);
-  
+
   return <div class="card">
     <header class="card-header">
-      <p class={ !group?.hasError ? "card-header-title" : "card-header-title 
has-text-danger"}>
-        { description ? description : <Message 
id={`fields.groups.${String(name)}.label`} /> }
+      <p class={!group?.hasError ? "card-header-title" : "card-header-title 
has-text-danger"}>
+        {label}
       </p>
       <button class="card-header-icon" aria-label="more options" onClick={(): 
void => setActive(!active)}>
         <span class="icon">
@@ -47,16 +46,16 @@ export function InputGroup<T>({ name, description, 
children, alternative}: Props
         </span>
       </button>
     </header>
-    { active ? <div class="card-content">
+    {active ? <div class="card-content">
       <div class="content">
         {children}
       </div>
     </div> : (
       alternative ? <div class="card-content">
-      <div class="content">
-        {alternative}
-      </div>
-    </div> : undefined
-    ) }
+        <div class="content">
+          {alternative}
+        </div>
+      </div> : undefined
+    )}
   </div>;
 }
diff --git a/packages/frontend/src/components/form/InputImage.tsx 
b/packages/frontend/src/components/form/InputImage.tsx
index 7870f1f..8f10c47 100644
--- a/packages/frontend/src/components/form/InputImage.tsx
+++ b/packages/frontend/src/components/form/InputImage.tsx
@@ -19,24 +19,20 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 import { ComponentChildren, h } from "preact";
-import { Message, useMessage } from "preact-messages";
 import { useRef, useState } from "preact/hooks";
 import emptyImage from "../../assets/empty.png";
-import { useField } from "./useField";
+import { Translate } from "../../i18n";
+import { InputProps, useField } from "./useField";
 
-export interface Props<T> {
-  name: keyof T;
-  readonly?: boolean;
+export interface Props<T> extends InputProps<T> {
   expand?: boolean;
   addonAfter?: ComponentChildren;
   children?: ComponentChildren;
 }
 
-export function InputImage<T>({ name, readonly, children, expand }: Props<T>) {
-  const { error, value, onChange, formName } = useField<T>(name);
+export function InputImage<T>({ name, readonly, placeholder, tooltip, label, 
help, children, expand }: Props<keyof T>) {
+  const { error, value, onChange } = useField<T>(name);
 
-  const placeholder = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.placeholder`);
-  const tooltip = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.tooltip`);
   const image = useRef<HTMLInputElement>(null)
 
   const [sizeError, setSizeError] = useState(false)
@@ -44,7 +40,7 @@ export function InputImage<T>({ name, readonly, children, 
expand }: Props<T>) {
   return <div class="field is-horizontal">
     <div class="field-label is-normal">
       <label class="label">
-        <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.label`} />
+        {label}
         {tooltip && <span class="icon" data-tooltip={tooltip}>
           <i class="mdi mdi-information" />
         </span>}
@@ -63,7 +59,7 @@ export function InputImage<T>({ name, readonly, children, 
expand }: Props<T>) {
               if (!f || f.length != 1) {
                 return onChange(emptyImage)
               }
-              if (f[0].size > 1024*1024) {
+              if (f[0].size > 1024 * 1024) {
                 setSizeError(true)
                 return onChange(emptyImage)
               }
@@ -76,15 +72,13 @@ export function InputImage<T>({ name, readonly, children, 
expand }: Props<T>) {
                 onChange(`data:${f[0].type};base64,${b64}` as any)
               })
             }} />
-          <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.help`}> </Message>
+          {help}
           {children}
         </p>
-        {error ? <p class="help is-danger">
-          <Message id={`validation.${error.type}`} 
fields={error.params}>{error.message} </Message>
-        </p> : null}
-        {sizeError ? <p class="help is-danger">
-          <Message id={`validation.imageSizeLimit`} />
-        </p> : null}
+        {error && <p class="help is-danger">{error}</p>}
+        {sizeError && <p class="help is-danger">
+          <Translate>Image should be smaller than 1 MB</Translate>
+        </p>}
       </div>
     </div>
   </div>
diff --git a/packages/frontend/src/components/form/InputNumber.tsx 
b/packages/frontend/src/components/form/InputNumber.tsx
index 9ec31c1..ac36429 100644
--- a/packages/frontend/src/components/form/InputNumber.tsx
+++ b/packages/frontend/src/components/form/InputNumber.tsx
@@ -19,23 +19,21 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 import { ComponentChildren, h } from "preact";
-import { useConfigContext } from "../../context/backend";
-import { Amount } from "../../declaration";
-import { Input } from "./Input";
 import { InputWithAddon } from "./InputWithAddon";
+import { InputProps } from "./useField";
 
-export interface Props<T> {
-  name: keyof T;
+export interface Props<T> extends InputProps<T> {
   readonly?: boolean;
   expand?: boolean;
   side?: ComponentChildren;
   children?: ComponentChildren;
 }
 
-export function InputNumber<T>({ name, readonly, expand, children, side }: 
Props<T>) {
+export function InputNumber<T>({ name, readonly, placeholder, tooltip, label, 
help, expand, children, side }: Props<keyof T>) {
   return <InputWithAddon<T> name={name} readonly={readonly} 
     fromStr={(v) => parseInt(v, 10)} toStr={(v) => `${v}`}
     inputType='number' expand={expand}
+    label={label} placeholder={placeholder} help={help} tooltip={tooltip}
     inputExtra={{ min: 0 }}
     children={children}
     side={side}
diff --git a/packages/frontend/src/components/form/InputPayto.tsx 
b/packages/frontend/src/components/form/InputPayto.tsx
index e019da2..4425231 100644
--- a/packages/frontend/src/components/form/InputPayto.tsx
+++ b/packages/frontend/src/components/form/InputPayto.tsx
@@ -21,17 +21,16 @@
 import { h, VNode } from "preact";
 import { InputArray } from "./InputArray";
 import { PAYTO_REGEX } from "../../utils/constants";
+import { InputProps } from "./useField";
 
-export interface Props<T> {
-  name: keyof T;
-  readonly?: boolean;
-}
+export type Props<T> = InputProps<T>;
 
 const PAYTO_START_REGEX = /^payto:\/\//
 
-export function InputPayto<T>({ name, readonly }: Props<T>): VNode {
+export function InputPayto<T>({ name, readonly, placeholder, tooltip, label, 
help }: Props<keyof T>): VNode {
   return <InputArray<T> name={name} readonly={readonly} 
     addonBefore="payto://" 
+    label={label} placeholder={placeholder} help={help} tooltip={tooltip}
     isValid={(v) => v && PAYTO_REGEX.test(v) }
     toStr={(v?: string) => !v ? '': v.replace(PAYTO_START_REGEX, '')}
     fromStr={(v: string) => `payto://${v}` }
diff --git a/packages/frontend/src/components/form/InputSearchProduct.tsx 
b/packages/frontend/src/components/form/InputSearchProduct.tsx
index bc60287..2764512 100644
--- a/packages/frontend/src/components/form/InputSearchProduct.tsx
+++ b/packages/frontend/src/components/form/InputSearchProduct.tsx
@@ -23,6 +23,7 @@ import { useState } from "preact/hooks";
 import emptyImage from "../../assets/empty.png";
 import { MerchantBackend, WithId } from "../../declaration";
 import { useInstanceProducts } from "../../hooks/product";
+import { Translate, useTranslator } from "../../i18n";
 import { FormErrors, FormProvider } from "./FormProvider";
 import { InputWithAddon } from "./InputWithAddon";
 
@@ -43,6 +44,8 @@ export function InputSearchProduct({ selected, onChange }: 
Props): VNode {
   const errors: FormErrors<ProductSearch> = {
     name: undefined
   }
+  const i18n = useTranslator()
+
 
   if (selected) {
     return <article class="media">
@@ -53,8 +56,8 @@ export function InputSearchProduct({ selected, onChange }: 
Props): VNode {
       </figure>
       <div class="media-content">
         <div class="content">
-          <p class="media-meta">Product id: <b>{selected.id}</b></p>
-          <p>Description: {selected.description}</p>
+          <p class="media-meta"><Translate>Product id</Translate>: 
<b>{selected.id}</b></p>
+          <p><Translate>Description</Translate>: {selected.description}</p>
           <div class="buttons is-right mt-5">
             <button class="button" onClick={() => 
onChange(undefined)}>clear</button>
           </div>
@@ -67,12 +70,15 @@ export function InputSearchProduct({ selected, onChange }: 
Props): VNode {
 
     <InputWithAddon<ProductSearch>
       name="name"
+      label={i18n`Name`}
       addonBefore={<span class="icon" ><i class="mdi mdi-magnify" /></span>}
     >
-      <ProductList name={prodForm.name} onSelect={(p) => {
-        setProdName({ name: '' })
-        onChange(p)
-      }} />
+      <div>
+        <ProductList name={prodForm.name} onSelect={(p) => {
+          setProdName({ name: '' })
+          onChange(p)
+        }} />
+      </div>
     </InputWithAddon>
 
   </FormProvider>
@@ -93,13 +99,13 @@ function ProductList({ name, onSelect }: ProductListProps) {
 
   if (result.loading) {
     products = <div class="dropdown-content">
-      <div class="dropdown-item">loading...</div>
+      <div class="dropdown-item"><Translate>loading...</Translate></div>
     </div>
   } else if (result.ok && !!name) {
     if (!result.data.length) {
       products = <div class="dropdown-content">
         <div class="dropdown-item">
-          no products found
+          <Translate>no products found</Translate>
         </div>
       </div>
     } else {
@@ -107,7 +113,7 @@ function ProductList({ name, onSelect }: ProductListProps) {
       products = <div class="dropdown-content">
         {!filtered.length ?
           <div class="dropdown-item" >
-            no results
+            <Translate>no results</Translate>
           </div> :
           result.data.filter(p => re.test(p.id) || 
re.test(p.description)).map(p => (
             <div key={p.id} class="dropdown-item" onClick={() => onSelect(p)} 
style={{ cursor: 'pointer' }}>
diff --git a/packages/frontend/src/components/form/InputSecured.stories.tsx 
b/packages/frontend/src/components/form/InputSecured.stories.tsx
index 286f3cd..ef6a2e6 100644
--- a/packages/frontend/src/components/form/InputSecured.stories.tsx
+++ b/packages/frontend/src/components/form/InputSecured.stories.tsx
@@ -35,14 +35,14 @@ export const InitialValueEmpty = (): VNode => {
   const [state, setState] = useState<Partial<T>>({ auth_token: '' })
   return <FormProvider<T> object={state} errors={{}} valueHandler={setState}>
     Initial value: ''
-    <InputSecured<T> name="auth_token" />
+    <InputSecured<T> name="auth_token" label="token" />
   </FormProvider>
 }
 
 export const InitialValueToken = (): VNode => {
   const [state, setState] = useState<Partial<T>>({ auth_token: 'token' })
   return <FormProvider<T> object={state} errors={{}} valueHandler={setState}>
-    <InputSecured<T> name="auth_token" />
+    <InputSecured<T> name="auth_token" label="token" />
   </FormProvider>
 }
 
@@ -50,6 +50,6 @@ export const InitialValueNull = (): VNode => {
   const [state, setState] = useState<Partial<T>>({ auth_token: null })
   return <FormProvider<T> object={state} errors={{}} valueHandler={setState}>
     Initial value: ''
-    <InputSecured<T> name="auth_token" />
+    <InputSecured<T> name="auth_token" label="token" />
   </FormProvider>
 }
diff --git a/packages/frontend/src/components/form/InputSecured.tsx 
b/packages/frontend/src/components/form/InputSecured.tsx
index 20803e3..64737e3 100644
--- a/packages/frontend/src/components/form/InputSecured.tsx
+++ b/packages/frontend/src/components/form/InputSecured.tsx
@@ -19,30 +19,24 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 import { Fragment, h, VNode } from "preact";
-import { Message, useMessage } from "preact-messages";
 import { useState } from "preact/hooks";
-import { useField } from "./useField";
+import { Translate } from "../../i18n";
+import { InputProps, useField } from "./useField";
 
-export interface Props<T> {
-  name: keyof T;
-  readonly?: boolean;
-}
+export type Props<T> = InputProps<T>;
 
 const TokenStatus = ({ prev, post }: any) => {
   if ((prev === undefined || prev === null) && (post === undefined || post === 
null))
     return null
   return (prev === post) ? null : (
     post === null ?
-      <span class="tag is-danger is-align-self-center ml-2">Deleting</span> :
-      <span class="tag is-warning is-align-self-center ml-2">Changing</span>
+      <span class="tag is-danger is-align-self-center 
ml-2"><Translate>Deleting</Translate></span> :
+      <span class="tag is-warning is-align-self-center 
ml-2"><Translate>Changing</Translate></span>
   )
 }
 
-export function InputSecured<T>({ name, readonly }: Props<T>): VNode {
-  const { error, value, initial, onChange, toStr, fromStr, formName } = 
useField<T>(name);
-
-  const placeholder = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.placeholder`, {});
-  const tooltip = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.tooltip`, {});
+export function InputSecured<T>({ name, readonly, placeholder, tooltip, label, 
help }: Props<keyof T>): VNode {
+  const { error, value, initial, onChange, toStr, fromStr } = 
useField<T>(name);
 
   const [active, setActive] = useState(false);
   const [newValue, setNuewValue] = useState("")
@@ -51,7 +45,7 @@ export function InputSecured<T>({ name, readonly }: 
Props<T>): VNode {
     <div class="field is-horizontal">
       <div class="field-label is-normal">
         <label class="label">
-          <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.label`} />
+          {label}
           {tooltip && <span class="icon" data-tooltip={tooltip}>
             <i class="mdi mdi-information" />
           </span>}
@@ -63,7 +57,7 @@ export function InputSecured<T>({ name, readonly }: 
Props<T>): VNode {
             <div class="field has-addons">
               <button class="button" onClick={(): void => { 
setActive(!active); }} >
                 <div class="icon is-left"><i class="mdi mdi-lock-reset" 
/></div>
-                <span>Manage token</span>
+                <span><Translate>Manage token</Translate></span>
               </button>
               <TokenStatus prev={initial} post={value} />
             </div>
@@ -81,35 +75,35 @@ export function InputSecured<T>({ name, readonly }: 
Props<T>): VNode {
                   onInput={(e): void => {
                     setNuewValue(e.currentTarget.value)
                   }} />
-                <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.help`}> </Message>
+                {help}
               </div>
               <div class="control">
                 <button class="button is-info" disabled={fromStr(newValue) === 
value} onClick={(): void => { onChange(fromStr(newValue)); setActive(!active); 
setNuewValue(""); }} >
                   <div class="icon is-left"><i class="mdi mdi-lock-outline" 
/></div>
-                  <span>Update</span>
+                  <span><Translate>Update</Translate></span>
                 </button>
               </div>
             </div>
           </Fragment>
         }
-        {error ? <p class="help is-danger"><Message 
id={`validation.${error.type}`} 
fields={error.params}>{error.message}</Message></p> : null}
+        {error ? <p class="help is-danger">{error}</p> : null}
       </div>
     </div>
     {active &&
       <div class="field is-horizontal">
         <div class="field-body is-flex-grow-3">
-          <div class="level" style={{width:'100%'}}>
+          <div class="level" style={{ width: '100%' }}>
             <div class="level-right is-flex-grow-1">
               <div class="level-item">
                 <button class="button is-danger" disabled={null === value || 
undefined === value} onClick={(): void => { onChange(null!); 
setActive(!active); setNuewValue(""); }} >
                   <div class="icon is-left"><i class="mdi 
mdi-lock-open-variant" /></div>
-                  <span>Remove</span>
+                  <span><Translate>Remove</Translate></span>
                 </button>
               </div>
               <div class="level-item">
                 <button class="button " onClick={(): void => { 
onChange(initial!); setActive(!active); setNuewValue(""); }} >
                   <div class="icon is-left"><i class="mdi 
mdi-lock-open-variant" /></div>
-                  <span>Cancel</span>
+                  <span><Translate>Cancel</Translate></span>
                 </button>
               </div>
             </div>
diff --git a/packages/frontend/src/components/form/InputSelector.tsx 
b/packages/frontend/src/components/form/InputSelector.tsx
index d9b43d3..793f3fa 100644
--- a/packages/frontend/src/components/form/InputSelector.tsx
+++ b/packages/frontend/src/components/form/InputSelector.tsx
@@ -19,11 +19,9 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 import { h, VNode } from "preact";
-import { Message, useMessage } from "preact-messages";
-import { useField } from "./useField";
+import { InputProps, useField } from "./useField";
 
-interface Props<T> {
-  name: T;
+interface Props<T> extends InputProps<T> {
   readonly?: boolean;
   expand?: boolean;
   values: string[];
@@ -34,16 +32,14 @@ interface Props<T> {
 const defaultToString = (f?: any): string => f || ''
 const defaultFromString = (v: string): any => v as any
 
-export function InputSelector<T>({ name, readonly, expand, values, fromStr = 
defaultFromString, toStr = defaultToString }: Props<keyof T>): VNode {
-  const { error, value, onChange, formName } = useField<T>(name);
+export function InputSelector<T>({ name, readonly, expand, placeholder, 
tooltip, label, help, values, fromStr = defaultFromString, toStr = 
defaultToString }: Props<keyof T>): VNode {
+  const { error, value, onChange } = useField<T>(name);
 
-  const placeholder = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.placeholder`);
-  const tooltip = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.tooltip`);
 
   return <div class="field is-horizontal">
     <div class="field-label is-normal">
       <label class="label">
-        <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.label`} />
+        {label}
         {tooltip && <span class="icon" data-tooltip={tooltip}>
           <i class="mdi mdi-information" />
         </span>}
@@ -57,13 +53,11 @@ export function InputSelector<T>({ name, readonly, expand, 
values, fromStr = def
             onChange={(e) => { onChange(fromStr(e.currentTarget.value)) }}>
             <option>{placeholder}</option>
             {values
-              .map((v,i) => <option key={i} 
value={toStr(v)}>{toStr(v)}</option>)}
+              .map((v, i) => <option key={i} 
value={toStr(v)}>{toStr(v)}</option>)}
           </select>
-          <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.help`}> </Message>
+          {help}
         </p>
-        {error ? <p class="help is-danger">
-          <Message id={`validation.${error.type}`} 
fields={error.params}>{error.message} </Message>
-        </p> : null}
+        {error && <p class="help is-danger">{error}</p>}
       </div>
     </div>
   </div>;
diff --git a/packages/frontend/src/components/form/InputStock.stories.tsx 
b/packages/frontend/src/components/form/InputStock.stories.tsx
index 1e8a907..cc2654b 100644
--- a/packages/frontend/src/components/form/InputStock.stories.tsx
+++ b/packages/frontend/src/components/form/InputStock.stories.tsx
@@ -35,7 +35,7 @@ type T = { stock?: Stock }
 export const CreateStockEmpty = () => {
   const [state, setState] = useState<Partial<T>>({})
   return <FormProvider<T> name="product" object={state} errors={{}} 
valueHandler={setState}>
-    <InputStock<T> name="stock"  />
+    <InputStock<T> name="stock" label="Stock" />
     <div><pre>{JSON.stringify(state, undefined, 2)}</pre></div>
   </FormProvider>
 }
@@ -49,7 +49,7 @@ export const CreateStockUnknownRestock = () => {
     }
   })
   return <FormProvider<T> name="product" object={state} errors={{}} 
valueHandler={setState}>
-    <InputStock<T> name="stock"  />
+    <InputStock<T> name="stock" label="Stock"  />
     <div><pre>{JSON.stringify(state, undefined, 2)}</pre></div>
   </FormProvider>
 }
@@ -64,7 +64,7 @@ export const CreateStockNoRestock = () => {
     }
   })
   return <FormProvider<T> name="product" object={state} errors={{}} 
valueHandler={setState}>
-    <InputStock<T> name="stock"  />
+    <InputStock<T> name="stock" label="Stock"  />
     <div><pre>{JSON.stringify(state, undefined, 2)}</pre></div>
   </FormProvider>
 }
@@ -79,7 +79,7 @@ export const CreateStockWithRestock = () => {
     }
   })
   return <FormProvider<T> name="product" object={state} errors={{}} 
valueHandler={setState}>
-    <InputStock<T> name="stock"  />
+    <InputStock<T> name="stock" label="Stock"  />
     <div><pre>{JSON.stringify(state, undefined, 2)}</pre></div>
   </FormProvider>
 }
@@ -94,7 +94,7 @@ export const UpdatingProductWithManagedStock = () => {
     }
   })
   return <FormProvider<T> name="product" object={state} errors={{}} 
valueHandler={setState}>
-    <InputStock<T> name="stock" alreadyExist />
+    <InputStock<T> name="stock" label="Stock" alreadyExist />
     <div><pre>{JSON.stringify(state, undefined, 2)}</pre></div>
   </FormProvider>
 }
@@ -102,7 +102,7 @@ export const UpdatingProductWithManagedStock = () => {
 export const UpdatingProductWithInfiniteStock = () => {
   const [state, setState] = useState<Partial<T>>({})
   return <FormProvider<T> name="product" object={state} errors={{}} 
valueHandler={setState}>
-    <InputStock<T> name="stock" alreadyExist />
+    <InputStock<T> name="stock" label="Stock" alreadyExist />
     <div><pre>{JSON.stringify(state, undefined, 2)}</pre></div>
   </FormProvider>
 }
diff --git a/packages/frontend/src/components/form/InputStock.tsx 
b/packages/frontend/src/components/form/InputStock.tsx
index 02121f0..edc381f 100644
--- a/packages/frontend/src/components/form/InputStock.tsx
+++ b/packages/frontend/src/components/form/InputStock.tsx
@@ -20,18 +20,16 @@
 */
 import { Fragment, h } from "preact";
 import { MerchantBackend, Timestamp } from "../../declaration";
-import { useField } from "./useField";
+import { InputProps, useField } from "./useField";
 import { FormProvider, FormErrors } from "./FormProvider";
 import { useLayoutEffect, useState } from "preact/hooks";
 import { Input } from "./Input";
-import { Message, useMessage } from "preact-messages";
 import { InputGroup } from "./InputGroup";
 import { InputNumber } from "./InputNumber";
 import { InputDate } from "./InputDate";
+import { Translate, useTranslator } from "../../i18n";
 
-export interface Props<T> {
-  name: keyof T;
-  readonly?: boolean;
+export interface Props<T> extends InputProps<T> {
   alreadyExist?: boolean;
 }
 
@@ -52,15 +50,15 @@ interface StockDelta {
 }
 
 
-export function InputStock<T>({ name, readonly, alreadyExist }: Props<T>) {
-  const { error, value, onChange, formName } = useField<T>(name);
+export function InputStock<T>({ name, readonly, placeholder, tooltip, label, 
help, alreadyExist }: Props<keyof T>) {
+  const { error, value, onChange } = useField<T>(name);
 
   const [errors, setErrors] = useState<FormErrors<Entity>>({})
 
-  const tooltip = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.tooltip`, {});
-
   const [formValue, valueHandler] = useState<Partial<Entity>>(value)
   const [addedStock, setAddedStock] = useState<StockDelta>({ incoming: 0, 
lost: 0 })
+  const i18n = useTranslator()
+
 
   useLayoutEffect(() => {
     if (!formValue) {
@@ -79,7 +77,7 @@ export function InputStock<T>({ name, readonly, alreadyExist 
}: Props<T>) {
       <div class="field is-horizontal">
         <div class="field-label is-normal">
           <label class="label">
-            <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.label`} />
+            {label}
             {tooltip && <span class="icon" data-tooltip={tooltip}>
               <i class="mdi mdi-information" />
             </span>}
@@ -89,9 +87,9 @@ export function InputStock<T>({ name, readonly, alreadyExist 
}: Props<T>) {
           <div class="field has-addons">
             {!alreadyExist ?
               <button class="button" onClick={(): void => { valueHandler({ 
current: 0, lost: 0, sold: 0 } as Stock as any); }} >
-                <span>Manage stock</span>
+                <span><Translate>Manage stock</Translate></span>
               </button> : <button class="button" disabled >
-                <span>Infinite</span>
+                <span><Translate>Infinite</Translate></span>
               </button>
             }
           </div>
@@ -103,29 +101,32 @@ export function InputStock<T>({ name, readonly, 
alreadyExist }: Props<T>) {
   const currentStock = (formValue.current || 0) - (formValue.lost || 0) - 
(formValue.sold || 0)
 
   const stockAddedErrors: FormErrors<typeof addedStock> = {
-    lost: currentStock + addedStock.incoming < addedStock.lost ? {
-      message: `lost cannot be greater that current + incoming (max 
${currentStock + addedStock.incoming})`
-    } : undefined
+    lost: currentStock + addedStock.incoming < addedStock.lost ?
+      i18n`lost cannot be greater that current + incoming (max ${currentStock 
+ addedStock.incoming})`
+      : undefined
   }
 
   const stockUpdateDescription = stockAddedErrors.lost ? '' : (
     !!addedStock.incoming || !!addedStock.lost ?
-      `current stock will change from ${currentStock} to ${currentStock + 
addedStock.incoming - addedStock.lost}` :
-      `current stock will stay at ${currentStock}`
+      i18n`current stock will change from ${currentStock} to ${currentStock + 
addedStock.incoming - addedStock.lost}` :
+      i18n`current stock will stay at ${currentStock}`
   )
 
   return <Fragment>
     <div class="card">
       <header class="card-header">
-        <p class="card-header-title">Stock</p>
+        {label}
+        {tooltip && <span class="icon" data-tooltip={tooltip}>
+          <i class="mdi mdi-information" />
+        </span>}
       </header>
       <div class="card-content">
         <FormProvider<Entity> name="stock" errors={errors} object={formValue} 
valueHandler={valueHandler}>
           {alreadyExist ? <Fragment>
 
             <FormProvider name="added" errors={stockAddedErrors} 
object={addedStock} valueHandler={setAddedStock as any}>
-              <InputNumber name="incoming" />
-              <InputNumber name="lost" />
+              <InputNumber name="incoming" label={i18n`Incoming`} />
+              <InputNumber name="lost" label={i18n`Lost`} />
             </FormProvider>
 
             <div class="field is-horizontal">
@@ -137,32 +138,34 @@ export function InputStock<T>({ name, readonly, 
alreadyExist }: Props<T>) {
               </div>
             </div>
           </Fragment> : <InputNumber<Entity> name="current"
+            label={i18n`Current`}
             side={
               <button class="button is-danger" onClick={(): void => { 
valueHandler(undefined as any) }} >
-                <span>without stock</span>
+                <span><Translate>without stock</Translate></span>
               </button>
             }
           />}
 
-          <InputDate<Entity> name="nextRestock" withTimestampSupport />
+          <InputDate<Entity> name="nextRestock" label={i18n`Next restock`} 
withTimestampSupport />
 
-          <InputGroup<Entity> name="address">
+          <InputGroup<Entity> name="address" label={i18n`Delivery address`}>
 
-            <Input name="address.country" />
+            <Input name="address.country" label={i18n`Country`} />
 
             <Input name="address.address_lines" inputType="multiline"
+              label={i18n`Address`}
               toStr={(v: string[] | undefined) => !v ? '' : v.join('\n')}
               fromStr={(v: string) => v.split('\n')}
             />
 
-            <Input name="address.building_number" />
-            <Input name="address.building_name" />
-            <Input name="address.street" />
-            <Input name="address.post_code" />
-            <Input name="address.town_location" />
-            <Input name="address.town" />
-            <Input name="address.district" />
-            <Input name="address.country_subdivision" />
+            <Input name="address.building_number" label={i18n`Building 
number`} />
+            <Input name="address.building_name" label={i18n`Building name`} />
+            <Input name="address.street" label={i18n`Street`} />
+            <Input name="address.post_code" label={i18n`Post code`} />
+            <Input name="address.town_location" label={i18n`Town location`} />
+            <Input name="address.town" label={i18n`Town`} />
+            <Input name="address.district" label={i18n`District`} />
+            <Input name="address.country_subdivision" label={i18n`Country 
subdivision`} />
           </InputGroup>
         </FormProvider>
       </div>
diff --git a/packages/frontend/src/components/form/InputTaxes.tsx 
b/packages/frontend/src/components/form/InputTaxes.tsx
index 4fe2df1..af1dddd 100644
--- a/packages/frontend/src/components/form/InputTaxes.tsx
+++ b/packages/frontend/src/components/form/InputTaxes.tsx
@@ -22,19 +22,19 @@ import { h, VNode } from "preact";
 import { useCallback, useState } from "preact/hooks";
 import * as yup from 'yup';
 import { MerchantBackend } from "../../declaration";
+import { Translate, useTranslator } from "../../i18n";
 import { TaxSchema as schema } from '../../schemas';
 import { FormErrors, FormProvider } from "./FormProvider";
 import { Input } from "./Input";
 import { InputGroup } from "./InputGroup";
-import { useField } from "./useField";
+import { InputProps, useField } from "./useField";
 
-export interface Props<T> {
-  name: keyof T;
-  readonly?: boolean;
+export interface Props<T> extends InputProps<T> {
   isValid?: (e: any) => boolean;
 }
+
 type Entity = MerchantBackend.Tax
-export function InputTaxes<T>({ name, readonly }: Props<T>): VNode {
+export function InputTaxes<T>({ name, readonly, label }: Props<keyof T>): 
VNode {
   const { value: taxes, onChange, } = useField<T>(name);
 
   const [value, valueHandler] = useState<Partial<Entity>>({})
@@ -47,19 +47,22 @@ export function InputTaxes<T>({ name, readonly }: 
Props<T>): VNode {
       valueHandler({})
     } catch (err) {
       const errors = err.inner as yup.ValidationError[]
-      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: { type: cur.type, params: cur.params, message: cur.message 
} }), {})
+      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: cur.message }), {})
       setErrors(pathMessages)
     }
   }, [value])
 
+  const i18n = useTranslator()
+
+  //FIXME: translating plural singular
   return (
-    <InputGroup name="tax" alternative={taxes.length > 0 && <p>this product 
has {taxes.length} taxes</p>}>
+    <InputGroup name="tax" label={label} alternative={taxes.length > 0 && 
<p>this product has {taxes.length} taxes</p>}>
       <FormProvider<Entity> name="tax" errors={errors} object={value} 
valueHandler={valueHandler} >
 
         <div class="field is-horizontal">
           <div class="field-label is-normal" />
           <div class="field-body" style={{ display: 'block' }}>
-            {taxes.map((v: any, i:number) => <div key={i} class="tags 
has-addons mt-3 mb-0 mr-3" style={{ flexWrap: 'nowrap' }}>
+            {taxes.map((v: any, i: number) => <div key={i} class="tags 
has-addons mt-3 mb-0 mr-3" style={{ flexWrap: 'nowrap' }}>
               <span class="tag is-medium is-info mb-0" style={{ maxWidth: 
'90%' }}><b>{v.tax}</b>: {v.name}</span>
               <a class="tag is-medium is-danger is-delete mb-0" onClick={() => 
{
                 onChange(taxes.filter((f: any) => f !== v) as any);
@@ -67,21 +70,19 @@ export function InputTaxes<T>({ name, readonly }: 
Props<T>): VNode {
               }} />
             </div>
             )}
-            {!taxes.length && 'this product has no taxes'}
+            {!taxes.length && i18n`this product has no taxes`}
           </div>
         </div>
 
-        <Input<Entity> name="tax" >
-          currency and value separated with colon <b>USD:2.3</b>
+        <Input<Entity> name="tax" label={i18n`Amount`}>
+          <Translate>currency and value separated with colon</Translate> 
<b>USD:2.3</b>
         </Input>
 
-        <Input<Entity> name="name" />
+        <Input<Entity> name="name" label={i18n`Name`} />
 
         <div class="buttons is-right mt-5">
-          <button class="button is-info" onClick={submit}>add</button>
+          <button class="button is-info" 
onClick={submit}><Translate>Add</Translate></button>
         </div>
-
-
       </FormProvider>
     </InputGroup>
   )
diff --git a/packages/frontend/src/components/form/InputWithAddon.tsx 
b/packages/frontend/src/components/form/InputWithAddon.tsx
index fa845c4..83b6c2e 100644
--- a/packages/frontend/src/components/form/InputWithAddon.tsx
+++ b/packages/frontend/src/components/form/InputWithAddon.tsx
@@ -19,12 +19,10 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 import { ComponentChildren, h, VNode } from "preact";
-import { Message, useMessage } from "preact-messages";
-import { useField } from "./useField";
+import { useTranslator } from "../../i18n";
+import { InputProps, useField } from "./useField";
 
-export interface Props<T> {
-  name: keyof T;
-  readonly?: boolean;
+export interface Props<T> extends InputProps<T> {
   expand?: boolean;
   inputType?: 'text' | 'number';
   addonBefore?: ComponentChildren;
@@ -36,19 +34,16 @@ export interface Props<T> {
   side?: ComponentChildren;
 }
 
-const defaultToString = (f?: any):string => f || ''
-const defaultFromString = (v: string):any => v as any
+const defaultToString = (f?: any): string => f || ''
+const defaultFromString = (v: string): any => v as any
 
-export function InputWithAddon<T>({ name, readonly, addonBefore, children, 
expand, inputType, inputExtra, side, addonAfter, toStr = defaultToString, 
fromStr = defaultFromString }: Props<T>): VNode {
-  const { error, value, onChange, formName } = useField<T>(name);
-
-  const placeholder = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.placeholder`);
-  const tooltip = useMessage(`fields.${!formName ? 'instance' : 
formName}.${name}.tooltip`);
+export function InputWithAddon<T>({ name, readonly, addonBefore, children, 
expand, label, placeholder, help, tooltip, inputType, inputExtra, side, 
addonAfter, toStr = defaultToString, fromStr = defaultFromString }: Props<keyof 
T>): VNode {
+  const { error, value, onChange } = useField<T>(name);
 
   return <div class="field is-horizontal">
     <div class="field-label is-normal">
       <label class="label">
-        <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.label`} />
+        {label}
         {tooltip && <span class="icon" data-tooltip={tooltip}>
           <i class="mdi mdi-information" />
         </span>}
@@ -60,21 +55,21 @@ export function InputWithAddon<T>({ name, readonly, 
addonBefore, children, expan
           {addonBefore && <div class="control">
             <a class="button is-static">{addonBefore}</a>
           </div>}
-          <p class={ expand ? "control is-expanded" : "control" }>
-            <input {...(inputExtra||{})} class={error ? "input is-danger" : 
"input"} type={inputType}
-              placeholder={placeholder} readonly={readonly} 
+          <p class={expand ? "control is-expanded" : "control"}>
+            <input {...(inputExtra || {})} class={error ? "input is-danger" : 
"input"} type={inputType}
+              placeholder={placeholder} readonly={readonly}
               name={String(name)} value={toStr(value)}
               onChange={(e): void => onChange(fromStr(e.currentTarget.value))} 
/>
-            <Message id={`fields.${!formName ? 'instance' : 
formName}.${name}.help`}> </Message>
+            {help}
             {children}
           </p>
           {addonAfter && <div class="control">
             <a class="button is-static">{addonAfter}</a>
           </div>}
         </div>
-        {error ? <p class="help is-danger"><Message 
id={`validation.${error.type}`} 
fields={error.params}>{error.message}</Message></p> : null}
+        {error && <p class="help is-danger">{error}</p>}
       </div>
-        {side}
+      {side}
     </div>
   </div>;
 }
diff --git a/packages/frontend/src/components/form/useField.tsx 
b/packages/frontend/src/components/form/useField.tsx
index 3c6d2c7..b24635a 100644
--- a/packages/frontend/src/components/form/useField.tsx
+++ b/packages/frontend/src/components/form/useField.tsx
@@ -19,11 +19,11 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 
-import { ValidationError } from "yup";
+import { VNode } from "preact";
 import { useFormContext } from "./FormProvider";
 
 interface Use<V> {
-  error?: ValidationError;
+  error?: string;
   value: any;
   formName: string;
   initial: any;
@@ -73,3 +73,11 @@ const setValueDeeper = (object: any, names: string[], value: 
any): any => {
   return {...object, [head]: setValueDeeper(object[head] || {}, rest, value) }
 }
 
+export interface InputProps<T> {
+  name: T;
+  label: string;
+  placeholder?: string;
+  tooltip?: string;
+  readonly?: boolean;
+  help?:VNode;
+}
\ No newline at end of file
diff --git a/packages/frontend/src/components/menu/LangSelector.tsx 
b/packages/frontend/src/components/menu/LangSelector.tsx
index b180f02..e8cd38e 100644
--- a/packages/frontend/src/components/menu/LangSelector.tsx
+++ b/packages/frontend/src/components/menu/LangSelector.tsx
@@ -14,11 +14,16 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
- import { h, VNode } from "preact";
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import langIcon from '../../assets/icons/languageicon.svg';
-import { useBackendContext } from "../../context/backend";
-import * as messages from '../../messages';
+import { useTranslationContext } from "../../context/translation";
+import { strings as messages } from '../../i18n/strings'
 
 type LangsNames = {
   [P in keyof typeof messages]: string
@@ -36,7 +41,7 @@ function getLangName(s: keyof LangsNames | string) {
 
 export function LangSelector(): VNode {
   const [updatingLang, setUpdatingLang] = useState(false)
-  const { lang, setLang } = useBackendContext()
+  const { lang, changeLanguage } = useTranslationContext()
   return <div class="dropdown is-active ">
     <div class="dropdown-trigger">
       <button class="button" aria-haspopup="true" 
aria-controls="dropdown-menu" onClick={() => setUpdatingLang(!updatingLang)}>
@@ -53,7 +58,7 @@ export function LangSelector(): VNode {
       <div class="dropdown-content">
         {Object.keys(messages)
           .filter((l) => l !== lang)
-          .map(l => <a key={l} class="dropdown-item" value={l} onClick={() => 
{ setLang(l); setUpdatingLang(false) }}>{getLangName(l)}</a>)}
+          .map(l => <a key={l} class="dropdown-item" value={l} onClick={() => 
{ changeLanguage(l); setUpdatingLang(false) }}>{getLangName(l)}</a>)}
       </div>
     </div>}
   </div>
diff --git a/packages/frontend/src/components/menu/SideBar.tsx 
b/packages/frontend/src/components/menu/SideBar.tsx
index bde247a..c46b75c 100644
--- a/packages/frontend/src/components/menu/SideBar.tsx
+++ b/packages/frontend/src/components/menu/SideBar.tsx
@@ -21,7 +21,9 @@
 
 
 import { Fragment, h, VNode } from 'preact';
-import { useBackendContext, useConfigContext } from '../../context/backend';
+import { useBackendContext } from '../../context/backend';
+import { useConfigContext } from '../../context/config';
+import { Translate } from '../../i18n';
 import { LangSelector } from './LangSelector';
 
 interface Props {
@@ -47,32 +49,34 @@ export function Sidebar({ mobile, instance, onLogout, admin 
}: Props): VNode {
         </div>
       </div>
       <div class="menu is-menu-main">
-        <p class="menu-label">Instance</p>
+        <p class="menu-label">
+          <Translate>Instance</Translate>
+        </p>
         <ul class="menu-list">
           <li>
             <a href="/update" class="has-icon">
               <span class="icon"><i class="mdi mdi-square-edit-outline" 
/></span>
-              <span class="menu-item-label">Settings</span>
+              <span 
class="menu-item-label"><Translate>Settings</Translate></span>
             </a>
           </li>
           <li>
             <a href="/orders" class="has-icon">
               <span class="icon"><i class="mdi mdi-cash-register" /></span>
-              <span class="menu-item-label">Orders</span>
+              <span 
class="menu-item-label"><Translate>Orders</Translate></span>
             </a>
           </li>
           <li>
             <a href="/products" class="has-icon">
               <span class="icon"><i class="mdi mdi-shopping" /></span>
-              <span class="menu-item-label">Products</span>
+              <span 
class="menu-item-label"><Translate>Products</Translate></span>
             </a>
           </li>
-          {/* <li>
+          <li>
             <a href="/transfers" class="has-icon">
               <span class="icon"><i class="mdi mdi-bank" /></span>
-              <span class="menu-item-label">Transfers</span>
+              <span 
class="menu-item-label"><Translate>Transfers</Translate></span>
             </a>
-          </li> */}
+          </li>
           {/* <li>
             <a href="/tips" class="has-icon">
               <span class="icon"><i class="mdi mdi-cash" /></span>
@@ -80,7 +84,7 @@ export function Sidebar({ mobile, instance, onLogout, admin 
}: Props): VNode {
             </a>
           </li> */}
         </ul>
-        <p class="menu-label">Connection</p>
+        <p class="menu-label"><Translate>Connection</Translate></p>
         <ul class="menu-list">
           <li>
             <div>
@@ -105,24 +109,24 @@ export function Sidebar({ mobile, instance, onLogout, 
admin }: Props): VNode {
             </div>
           </li>
           {admin && <Fragment>
-            <p class="menu-label">Instances</p>
+            <p class="menu-label"><Translate>Instances</Translate></p>
             <li>
               <a href="/instance/new" class="has-icon">
                 <span class="icon"><i class="mdi mdi-plus" /></span>
-                <span class="menu-item-label">New</span>
+                <span class="menu-item-label"><Translate>New</Translate></span>
               </a>
             </li>
             <li>
               <a href="/instances" class="has-icon">
                 <span class="icon"><i class="mdi mdi-format-list-bulleted" 
/></span>
-                <span class="menu-item-label">List</span>
+                <span 
class="menu-item-label"><Translate>List</Translate></span>
               </a>
             </li>
           </Fragment>}
           <li>
             <a class="has-icon is-state-info is-hoverable" onClick={(): void 
=> onLogout()}>
               <span class="icon"><i class="mdi mdi-logout default" /></span>
-              <span class="menu-item-label">Log out</span>
+              <span class="menu-item-label"><Translate>Log 
out</Translate></span>
             </a>
           </li>
         </ul>
diff --git a/packages/frontend/src/components/modal/index.tsx 
b/packages/frontend/src/components/modal/index.tsx
index 6d89cfc..b597c24 100644
--- a/packages/frontend/src/components/modal/index.tsx
+++ b/packages/frontend/src/components/modal/index.tsx
@@ -21,8 +21,8 @@
 
 
 import { ComponentChildren, h, VNode } from "preact";
-import { Message } from "preact-messages";
 import { useState } from "preact/hooks";
+import { Translate, useTranslator } from "../../i18n";
 import { FormProvider } from "../form/FormProvider";
 import { Input } from "../form/Input";
 
@@ -41,16 +41,16 @@ export function ConfirmModal({ active, description, 
onCancel, onConfirm, childre
     <div class="modal-background " onClick={onCancel} />
     <div class="modal-card">
       <header class="modal-card-head">
-        {!description ? null : <p class="modal-card-title"> <Message 
id={description} /></p>}
+        {!description ? null : <p class="modal-card-title">{description}</p>}
         <button class="delete " aria-label="close" onClick={onCancel} />
       </header>
       <section class="modal-card-body">
         {children}
       </section>
       <footer class="modal-card-foot">
-        <div class="buttons is-right" style={{width: '100%'}}>
-          <button class="button " onClick={onCancel} ><Message id="Cancel" 
/></button>
-          <button class={danger ? "button is-danger " : "button is-info "} 
disabled={disabled} onClick={onConfirm} ><Message id="Confirm" /></button>
+        <div class="buttons is-right" style={{ width: '100%' }}>
+          <button class="button " onClick={onCancel} 
><Translate>Cancel</Translate></button>
+          <button class={danger ? "button is-danger " : "button is-info "} 
disabled={disabled} onClick={onConfirm} ><Translate>Confirm</Translate></button>
         </div>
       </footer>
     </div>
@@ -63,16 +63,16 @@ export function ClearConfirmModal({ description, onCancel, 
onClear, onConfirm, c
     <div class="modal-background " onClick={onCancel} />
     <div class="modal-card">
       <header class="modal-card-head">
-        {!description ? null : <p class="modal-card-title"> <Message 
id={description} /></p>}
+        {!description ? null : <p class="modal-card-title">{description}</p>}
         <button class="delete " aria-label="close" onClick={onCancel} />
       </header>
       <section class="modal-card-body">
         {children}
       </section>
       <footer class="modal-card-foot">
-        <button class="button " onClick={onCancel} ><Message id="Cancel" 
/></button>
-        <button class="button is-danger" onClick={onClear} disabled={disabled} 
><Message id="Clear" /></button>
-        <button class="button is-info" onClick={onConfirm} disabled={disabled} 
><Message id="Confirm" /></button>
+        <button class="button " onClick={onCancel} 
><Translate>Cancel</Translate></button>
+        <button class="button is-danger" onClick={onClear} disabled={disabled} 
><Translate>Clear</Translate></button>
+        <button class="button is-info" onClick={onConfirm} disabled={disabled} 
><Translate>Confirm</Translate></button>
       </footer>
     </div>
     <button class="modal-close is-large " aria-label="close" 
onClick={onCancel} />
@@ -105,24 +105,26 @@ export function UpdateTokenModal({ element, onCancel, 
onClear, onConfirm, oldTok
   const [form, setValue] = useState<Partial<State>>({
     old_token: '', new_token: ''
   })
-
+  const i18n = useTranslator()
   const errors = {
-    old_token: oldToken && oldToken !== form.old_token ? { message: 'should be 
the same' } : undefined,
-    new_token: !form.new_token ? { message: 'should be the same' } : 
(form.new_token === form.old_token ? { message: 'cant repeat' } : undefined),
+    old_token: oldToken && oldToken !== form.old_token ? i18n`should be the 
same` : undefined,
+    new_token: !form.new_token ? i18n`should be the same` : (form.new_token 
=== form.old_token ? i18n`cannot be the same as before` : undefined),
   }
 
+  const text = i18n`You are updating the authorization token from instance 
${element.name} with id ${element.id}`
+
   return <ClearConfirmModal description="update_token"
     onCancel={onCancel}
     onConfirm={() => onConfirm(form.new_token!)}
     onClear={onClear}
     disabled={!!errors.new_token || !!errors.old_token}
   >
-    <p>You are updating the authorization token from instance {element.name} 
with id <b>{element.id}</b></p>
+    <p>{text}</p>
     <FormProvider errors={errors} object={form} valueHandler={setValue}>
-      <Input name="old_token" />
-      <Input name="new_token" />
+      <Input name="old_token" label={i18n`Old token`} />
+      <Input name="new_token" label={i18n`New token`} />
     </FormProvider>
-    <p>Clearing the auth token will mean public access to the instance</p>
+    <p><Translate>Clearing the auth token will mean public access to the 
instance</Translate></p>
   </ClearConfirmModal>
 }
 
diff --git a/packages/frontend/src/components/product/ProductForm.tsx 
b/packages/frontend/src/components/product/ProductForm.tsx
index 57d7817..c73c22f 100644
--- a/packages/frontend/src/components/product/ProductForm.tsx
+++ b/packages/frontend/src/components/product/ProductForm.tsx
@@ -13,11 +13,18 @@
  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 { h } from "preact";
 import { useCallback, useEffect, useState } from "preact/hooks";
 import * as yup from 'yup';
 import { useBackendContext } from "../../context/backend";
 import { MerchantBackend } from "../../declaration";
+import { useTranslator } from "../../i18n";
 import {
   ProductCreateSchema as createSchema, ProductUpdateSchema as updateSchema
 } from '../../schemas';
@@ -71,7 +78,7 @@ export function ProductForm({ onSubscribe, initial, 
alreadyExist, }: Props) {
       return value as MerchantBackend.Products.ProductDetail & { product_id: 
string }
     } catch (err) {
       const errors = err.inner as yup.ValidationError[]
-      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: { type: cur.type, params: cur.params, message: cur.message 
} }), {})
+      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: cur.message }), {})
       setErrors(pathMessages)
     }
   }, [value])
@@ -81,20 +88,21 @@ export function ProductForm({ onSubscribe, initial, 
alreadyExist, }: Props) {
   }, [submit])
 
   const backend = useBackendContext();
+  const i18n = useTranslator()
 
   return <div>
     <FormProvider<Entity> name="product" errors={errors} object={value} 
valueHandler={valueHandler} >
 
-      {alreadyExist ? undefined : <InputWithAddon<Entity> name="product_id" 
addonBefore={`${backend.url}/product/`} />}
+      {alreadyExist ? undefined : <InputWithAddon<Entity> name="product_id" 
addonBefore={`${backend.url}/product/`} label={i18n`ID`} />}
 
-      <InputImage<Entity> name="image" />
-      <Input<Entity> name="description" inputType="multiline" />
-      <Input<Entity> name="unit" />
-      <InputCurrency<Entity> name="price" />
+      <InputImage<Entity> name="image" label={i18n`Image`} />
+      <Input<Entity> name="description" inputType="multiline" 
label={i18n`Description`} />
+      <Input<Entity> name="unit" label={i18n`Unit`} />
+      <InputCurrency<Entity> name="price" label={i18n`Price`} />
 
-      <InputStock name="stock" alreadyExist={alreadyExist} />
+      <InputStock name="stock" label={i18n`Stock`} alreadyExist={alreadyExist} 
/>
 
-      <InputTaxes<Entity> name="taxes" />
+      <InputTaxes<Entity> name="taxes" label={i18n`Taxes`} />
 
     </FormProvider>
   </div>
diff --git a/packages/frontend/src/context/backend.ts 
b/packages/frontend/src/context/backend.ts
index a74986f..e33cdd5 100644
--- a/packages/frontend/src/context/backend.ts
+++ b/packages/frontend/src/context/backend.ts
@@ -13,10 +13,17 @@
  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 { createContext } from 'preact'
-import { useContext } from 'preact/hooks'
 
-export interface BackendContextType {
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createContext, h, VNode } from 'preact'
+import { useCallback, useContext, useState } from 'preact/hooks'
+import { useBackendDefaultToken, useBackendURL } from '../hooks';
+
+interface BackendContextType {
   url: string;
   token?: string;
   triedToLog: boolean;
@@ -25,24 +32,10 @@ export interface BackendContextType {
   clearAllTokens: () => void;
   addTokenCleaner: (c: () => void) => void;
   updateToken: (token?:string) => void;
-  lang: string;
-  setLang: (lang: string) => void;
-}
-
-export interface ConfigContextType {
-  currency: string;
-  version: string;
-}
-
-export interface InstanceContextType {
-  id: string;
-  token?: string;
-  admin?: boolean;
 }
 
 const BackendContext = createContext<BackendContextType>({
   url: '',
-  lang: 'en',
   token: undefined,
   triedToLog: false,
   changeBackend: () => null,
@@ -50,17 +43,33 @@ const BackendContext = createContext<BackendContextType>({
   clearAllTokens: () => null,
   addTokenCleaner: () => null,
   updateToken: () => null,
-  setLang: () => null,
 })
 
-const ConfigContext = createContext<ConfigContextType>(null!)
+export function useBackendContextState(): BackendContextType {
+  const [url, triedToLog, changeBackend, resetBackend] = useBackendURL();
+  const [token, updateToken] = useBackendDefaultToken();
 
-const InstanceContext = createContext<InstanceContextType>({} as any)
+  const tokenCleaner = useCallback(() => { updateToken(undefined) }, [])
+  const [cleaners, setCleaners] = useState([tokenCleaner])
+  const addTokenCleaner = (c: () => void) => setCleaners(cs => [...cs, c])
+  const addTokenCleanerMemo = useCallback((c: () => void) => { 
addTokenCleaner(c) }, [tokenCleaner])
 
-export const ConfigContextProvider = ConfigContext.Provider
-export const useConfigContext = (): ConfigContextType => 
useContext(ConfigContext);
-export const BackendContextProvider = BackendContext.Provider
-export const useBackendContext = (): BackendContextType => 
useContext(BackendContext);
-export const InstanceContextProvider = InstanceContext.Provider
-export const useInstanceContext = (): InstanceContextType => 
useContext(InstanceContext);
+  const clearAllTokens = () => {
+    cleaners.forEach(c => c())
+    for (let i = 0; i < localStorage.length; i++) {
+      const k = localStorage.key(i)
+      if (k && /^backend-token/.test(k)) localStorage.removeItem(k)
+    }
+    resetBackend()
+  }
+
+  return { url, token, triedToLog, changeBackend, updateToken, resetBackend, 
clearAllTokens, addTokenCleaner: addTokenCleanerMemo }
+}
 
+export const BackendContextProvider = ({children}:{children:any}):VNode => {
+  const value = useBackendContextState()
+  
+  return h(BackendContext.Provider, {value, children});
+}
+
+export const useBackendContext = (): BackendContextType => 
useContext(BackendContext);
diff --git a/packages/frontend/src/custom.d.ts 
b/packages/frontend/src/context/config.ts
similarity index 65%
copy from packages/frontend/src/custom.d.ts
copy to packages/frontend/src/context/config.ts
index ae71b5f..5cd7723 100644
--- a/packages/frontend/src/custom.d.ts
+++ b/packages/frontend/src/context/config.ts
@@ -13,19 +13,20 @@
  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/>
  */
-declare module '*.po' {
-  const content: any;
-  export default content;
-}
-declare module "*.jpeg" {
-  const content: any;
-  export default content;
-}
-declare module "*.png" {
-  const content: any;
-  export default content;
-}
-declare module '*.svg' {
-  const content: any;
-  export default content;
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createContext } from 'preact'
+import { useContext } from 'preact/hooks'
+
+interface Type {
+  currency: string;
+  version: string;
 }
+const Context = createContext<Type>(null!)
+
+export const ConfigContextProvider = Context.Provider
+export const useConfigContext = (): Type => useContext(Context);
diff --git a/packages/frontend/src/custom.d.ts 
b/packages/frontend/src/context/instance.ts
similarity index 64%
copy from packages/frontend/src/custom.d.ts
copy to packages/frontend/src/context/instance.ts
index ae71b5f..0edfbfe 100644
--- a/packages/frontend/src/custom.d.ts
+++ b/packages/frontend/src/context/instance.ts
@@ -13,19 +13,22 @@
  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/>
  */
-declare module '*.po' {
-  const content: any;
-  export default content;
-}
-declare module "*.jpeg" {
-  const content: any;
-  export default content;
-}
-declare module "*.png" {
-  const content: any;
-  export default content;
-}
-declare module '*.svg' {
-  const content: any;
-  export default content;
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createContext } from 'preact'
+import { useContext } from 'preact/hooks'
+
+interface Type {
+  id: string;
+  token?: string;
+  admin?: boolean;
 }
+
+const Context = createContext<Type>({} as any)
+
+export const InstanceContextProvider = Context.Provider
+export const useInstanceContext = (): Type => useContext(Context);
diff --git a/packages/frontend/src/context/translation.ts 
b/packages/frontend/src/context/translation.ts
new file mode 100644
index 0000000..02ccb70
--- /dev/null
+++ b/packages/frontend/src/context/translation.ts
@@ -0,0 +1,53 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 } 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,
+}
+
+export const TranslationProvider = ({ initial, children }: Props): VNode => {
+  const [lang, changeLanguage] = useLang(initial)
+  const handler = new jedLib.Jed(strings[lang]);
+  return h(Context.Provider, { value: { lang, handler, changeLanguage }, 
children });
+}
+
+export const useTranslationContext = (): Type => useContext(Context);
\ No newline at end of file
diff --git a/packages/frontend/src/custom.d.ts 
b/packages/frontend/src/custom.d.ts
index ae71b5f..75d430c 100644
--- a/packages/frontend/src/custom.d.ts
+++ b/packages/frontend/src/custom.d.ts
@@ -17,6 +17,10 @@ declare module '*.po' {
   const content: any;
   export default content;
 }
+declare module 'jed' {
+  const x: any;
+  export = x;
+}
 declare module "*.jpeg" {
   const content: any;
   export default content;
diff --git a/packages/frontend/src/declaration.d.ts 
b/packages/frontend/src/declaration.d.ts
index 34370e0..0586cd7 100644
--- a/packages/frontend/src/declaration.d.ts
+++ b/packages/frontend/src/declaration.d.ts
@@ -328,6 +328,8 @@ export namespace MerchantBackend {
             // Merchant name corresponding to this instance.
             name: string;
 
+            deleted?: boolean;
+
             // Merchant instance this response is about ($INSTANCE)
             id: string;
 
diff --git a/packages/frontend/src/hooks/index.ts 
b/packages/frontend/src/hooks/index.ts
index 71796dd..4a01d2b 100644
--- a/packages/frontend/src/hooks/index.ts
+++ b/packages/frontend/src/hooks/index.ts
@@ -20,32 +20,9 @@
 */
 
 import { StateUpdater, useCallback, useState } from "preact/hooks";
-import { BackendContextType } from "../context/backend";
 import { ValueOrFunction } from '../utils/types';
 
 
-export function useBackendContextState(): BackendContextType {
-  const [lang, setLang] = useLang()
-  const [url, triedToLog, changeBackend, resetBackend] = useBackendURL();
-  const [token, updateToken] = useBackendDefaultToken();
-
-  const tokenCleaner = useCallback(() => { updateToken(undefined) }, [])
-  const [cleaners, setCleaners] = useState([tokenCleaner])
-  const addTokenCleaner = (c: () => void) => setCleaners(cs => [...cs, c])
-  const addTokenCleanerMemo = useCallback((c: () => void) => { 
addTokenCleaner(c) }, [tokenCleaner])
-
-  const clearAllTokens = () => {
-    cleaners.forEach(c => c())
-    for (let i = 0; i < localStorage.length; i++) {
-      const k = localStorage.key(i)
-      if (k && /^backend-token/.test(k)) localStorage.removeItem(k)
-    }
-    resetBackend()
-  }
-
-  return { url, token, triedToLog, changeBackend, updateToken, lang, setLang, 
resetBackend, clearAllTokens, addTokenCleaner: addTokenCleanerMemo }
-}
-
 export const calculateRootPath = () => {
   const rootPath = typeof window !== undefined ? window.location.origin + 
window.location.pathname : '/'
   return rootPath
@@ -82,9 +59,9 @@ export function useBackendInstanceToken(id: string): [string 
| undefined, StateU
   return [token, setToken]
 }
 
-export function useLang(): [string, StateUpdater<string>] {
+export function useLang(initial?:string): [string, StateUpdater<string>] {
   const browserLang = typeof window !== "undefined" ? navigator.language || 
(navigator as any).userLanguage : undefined;
-  const defaultLang = (browserLang || 'en').substring(0,2)
+  const defaultLang = (browserLang || initial || 'en').substring(0,2)
   return useNotNullLocalStorage('lang-preference', defaultLang)
 }
 
diff --git a/packages/frontend/src/hooks/instance.ts 
b/packages/frontend/src/hooks/instance.ts
index b4fbe4d..00fd73d 100644
--- a/packages/frontend/src/hooks/instance.ts
+++ b/packages/frontend/src/hooks/instance.ts
@@ -14,9 +14,10 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 import { MerchantBackend } from '../declaration';
-import { useBackendContext, useInstanceContext } from '../context/backend';
+import { useBackendContext } from '../context/backend';
 import { fetcher, HttpError, HttpResponse, HttpResponseOk, request, SwrError } 
from './backend';
 import useSWR, { mutate } from 'swr';
+import { useInstanceContext } from '../context/instance';
 
 
 interface InstanceAPI {
diff --git a/packages/frontend/src/hooks/order.ts 
b/packages/frontend/src/hooks/order.ts
index 3ec5400..b81058a 100644
--- a/packages/frontend/src/hooks/order.ts
+++ b/packages/frontend/src/hooks/order.ts
@@ -15,7 +15,8 @@
  */
 import { useEffect, useState } from 'preact/hooks';
 import useSWR from 'swr';
-import { useBackendContext, useInstanceContext } from '../context/backend';
+import { useBackendContext } from '../context/backend';
+import { useInstanceContext } from '../context/instance';
 import { MerchantBackend } from '../declaration';
 import { MAX_RESULT_SIZE, PAGE_SIZE } from '../utils/constants';
 import { fetcher, HttpError, HttpResponse, HttpResponseOk, 
HttpResponsePaginated, mutateAll, request } from './backend';
diff --git a/packages/frontend/src/hooks/product.ts 
b/packages/frontend/src/hooks/product.ts
index e2fe557..6dd2d13 100644
--- a/packages/frontend/src/hooks/product.ts
+++ b/packages/frontend/src/hooks/product.ts
@@ -15,7 +15,8 @@
  */
 import { useEffect } from 'preact/hooks';
 import useSWR, { trigger, useSWRInfinite, cache, mutate } from 'swr';
-import { useBackendContext, useInstanceContext } from '../context/backend';
+import { useBackendContext } from '../context/backend';
+import { useInstanceContext } from '../context/instance';
 import { MerchantBackend, WithId } from '../declaration';
 import { fetcher, HttpError, HttpResponse, HttpResponseOk, mutateAll, request 
} from './backend';
 
@@ -133,7 +134,7 @@ export function useInstanceProducts(): 
HttpResponse<(MerchantBackend.Products.Pr
 
   const { data: list, error: listError, isValidating: listLoading } = 
useSWR<HttpResponseOk<MerchantBackend.Products.InventorySummaryResponse>, 
HttpError>([`/private/products`, token, url], fetcher);
 
-  const { data: products, error: productError, setSize } = 
useSWRInfinite<HttpResponseOk<MerchantBackend.Products.ProductDetail>, 
HttpError>((pageIndex: number) => {
+  const { data: products, error: productError, setSize, size } = 
useSWRInfinite<HttpResponseOk<MerchantBackend.Products.ProductDetail>, 
HttpError>((pageIndex: number) => {
     if (!list?.data || !list.data.products.length || listError || listLoading) 
return null
     return [`/private/products/${list.data.products[pageIndex].product_id}`, 
token, url]
   }, fetcher, {
@@ -141,7 +142,6 @@ export function useInstanceProducts(): 
HttpResponse<(MerchantBackend.Products.Pr
   })
 
   useEffect(() => {
-    if (listLoading) setSize(0)
     if (list?.data && list.data.products.length > 0) {
       setSize(list.data.products.length)
     }
diff --git a/packages/frontend/src/hooks/tips.ts 
b/packages/frontend/src/hooks/tips.ts
index 97794eb..52d3762 100644
--- a/packages/frontend/src/hooks/tips.ts
+++ b/packages/frontend/src/hooks/tips.ts
@@ -14,7 +14,8 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 import useSWR from 'swr';
-import { useBackendContext, useInstanceContext } from '../context/backend';
+import { useBackendContext } from '../context/backend';
+import { useInstanceContext } from '../context/instance';
 import { MerchantBackend } from '../declaration';
 import { fetcher, HttpError, HttpResponse, HttpResponseOk, mutateAll, request 
} from './backend';
 
diff --git a/packages/frontend/src/hooks/transfer.ts 
b/packages/frontend/src/hooks/transfer.ts
index 5b783c5..d840a82 100644
--- a/packages/frontend/src/hooks/transfer.ts
+++ b/packages/frontend/src/hooks/transfer.ts
@@ -14,9 +14,10 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 import { MerchantBackend } from '../declaration';
-import { useBackendContext, useInstanceContext } from '../context/backend';
+import { useBackendContext } from '../context/backend';
 import { request, mutateAll, HttpResponse, HttpError, HttpResponseOk } from 
'./backend';
 import useSWR from 'swr';
+import { useInstanceContext } from '../context/instance';
 
 async function transferFetcher<T>(url: string, token: string, backend: 
string): Promise<HttpResponseOk<T>> {
   return request<T>(`${backend}${url}`, { token, params: { payto_uri: '' } })
diff --git a/packages/frontend/src/i18n/de.po b/packages/frontend/src/i18n/de.po
new file mode 100644
index 0000000..694798f
--- /dev/null
+++ b/packages/frontend/src/i18n/de.po
@@ -0,0 +1,1010 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/ApplicationReadyRoutes.tsx:50 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:293
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:51 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:294
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:72
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:73
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:108
+#, c-format
+msgid "HTTP status #%1$s: Server reported a problem"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:109
+#, c-format
+msgid "Got message: \"%1$s\" from: %2$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:126
+#, c-format
+msgid "No default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:127
+#, c-format
+msgid ""
+"in order to use merchant backoffice, you should create the default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:282
+#, c-format
+msgid "Server reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:283
+#, c-format
+msgid "Got message: %1$s from: %2$s"
+msgstr ""
+
+#: src/components/exception/login.tsx:46
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:49
+#, c-format
+msgid ""
+"Please enter your auth token. Token should have \"secret-token:\" and start "
+"with Bearer or ApiKey"
+msgstr ""
+
+#: src/components/exception/login.tsx:86 src/components/modal/index.tsx:53
+#: src/components/modal/index.tsx:75 src/paths/admin/create/CreatePage.tsx:140
+#: src/paths/instance/orders/create/CreatePage.tsx:337
+#: src/paths/instance/products/create/CreatePage.tsx:51
+#: src/paths/instance/products/list/Table.tsx:174
+#: src/paths/instance/products/list/Table.tsx:228
+#: src/paths/instance/products/update/UpdatePage.tsx:55
+#: src/paths/instance/update/UpdatePage.tsx:159
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:72
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:67
+#: src/paths/instance/orders/list/index.tsx:123
+#, c-format
+msgid "pick a date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:81
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:83
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:80
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:59
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:60
+#: src/components/product/ProductForm.tsx:99
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:122
+#: src/paths/instance/orders/list/Table.tsx:227
+#: src/paths/instance/products/list/Table.tsx:86
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:73
+#: src/components/form/InputTaxes.tsx:81
+#: src/paths/admin/create/CreatePage.tsx:86 src/paths/admin/list/Table.tsx:110
+#: src/paths/instance/details/DetailPage.tsx:76
+#: src/paths/instance/transfers/list/Table.tsx:112
+#: src/paths/instance/update/UpdatePage.tsx:105
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:102
+#, c-format
+msgid "loading..."
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:108
+#, c-format
+msgid "no products found"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:116
+#, c-format
+msgid "no results"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:33
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:34
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:60
+#, c-format
+msgid "Manage token"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:83
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:100
+#: src/paths/instance/orders/create/CreatePage.tsx:251
+#: src/paths/instance/orders/create/CreatePage.tsx:272
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:106 src/components/modal/index.tsx:52
+#: src/components/modal/index.tsx:73 src/paths/admin/create/CreatePage.tsx:139
+#: src/paths/instance/orders/create/CreatePage.tsx:336
+#: src/paths/instance/products/create/CreatePage.tsx:50
+#: src/paths/instance/products/list/Table.tsx:166
+#: src/paths/instance/products/list/Table.tsx:218
+#: src/paths/instance/products/update/UpdatePage.tsx:54
+#: src/paths/instance/update/UpdatePage.tsx:158
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:90
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:92
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:104
+#, c-format
+msgid "lost cannot be greater that current + incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:110
+#, c-format
+msgid "current stock will change from %1$s to %2$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:111
+#, c-format
+msgid "current stock will stay at %1$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:128
+#: src/paths/instance/products/list/Table.tsx:204
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:129
+#: src/paths/instance/products/list/Table.tsx:205
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:141
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:144
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:149
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:151
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:153
+#: src/paths/admin/create/CreatePage.tsx:99
+#: src/paths/admin/create/CreatePage.tsx:116
+#: src/paths/instance/orders/create/CreatePage.tsx:308
+#: src/paths/instance/update/UpdatePage.tsx:118
+#: src/paths/instance/update/UpdatePage.tsx:135
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:156
+#: src/paths/admin/create/CreatePage.tsx:98
+#: src/paths/admin/create/CreatePage.tsx:101
+#: src/paths/admin/create/CreatePage.tsx:118
+#: src/paths/instance/orders/create/CreatePage.tsx:310
+#: src/paths/instance/update/UpdatePage.tsx:117
+#: src/paths/instance/update/UpdatePage.tsx:120
+#: src/paths/instance/update/UpdatePage.tsx:137
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:161
+#: src/paths/admin/create/CreatePage.tsx:105
+#: src/paths/admin/create/CreatePage.tsx:122
+#: src/paths/instance/orders/create/CreatePage.tsx:314
+#: src/paths/instance/update/UpdatePage.tsx:124
+#: src/paths/instance/update/UpdatePage.tsx:141
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:162
+#: src/paths/admin/create/CreatePage.tsx:106
+#: src/paths/admin/create/CreatePage.tsx:123
+#: src/paths/instance/orders/create/CreatePage.tsx:315
+#: src/paths/instance/update/UpdatePage.tsx:125
+#: src/paths/instance/update/UpdatePage.tsx:142
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:163
+#: src/paths/admin/create/CreatePage.tsx:107
+#: src/paths/admin/create/CreatePage.tsx:124
+#: src/paths/instance/orders/create/CreatePage.tsx:316
+#: src/paths/instance/update/UpdatePage.tsx:126
+#: src/paths/instance/update/UpdatePage.tsx:143
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:164
+#: src/paths/admin/create/CreatePage.tsx:108
+#: src/paths/admin/create/CreatePage.tsx:125
+#: src/paths/instance/orders/create/CreatePage.tsx:317
+#: src/paths/instance/update/UpdatePage.tsx:127
+#: src/paths/instance/update/UpdatePage.tsx:144
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:165
+#: src/paths/admin/create/CreatePage.tsx:109
+#: src/paths/admin/create/CreatePage.tsx:126
+#: src/paths/instance/orders/create/CreatePage.tsx:318
+#: src/paths/instance/update/UpdatePage.tsx:128
+#: src/paths/instance/update/UpdatePage.tsx:145
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:166
+#: src/paths/admin/create/CreatePage.tsx:110
+#: src/paths/admin/create/CreatePage.tsx:127
+#: src/paths/instance/orders/create/CreatePage.tsx:319
+#: src/paths/instance/update/UpdatePage.tsx:129
+#: src/paths/instance/update/UpdatePage.tsx:146
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:167
+#: src/paths/admin/create/CreatePage.tsx:111
+#: src/paths/admin/create/CreatePage.tsx:128
+#: src/paths/instance/orders/create/CreatePage.tsx:320
+#: src/paths/instance/update/UpdatePage.tsx:130
+#: src/paths/instance/update/UpdatePage.tsx:147
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:168
+#: src/paths/admin/create/CreatePage.tsx:112
+#: src/paths/admin/create/CreatePage.tsx:129
+#: src/paths/instance/orders/create/CreatePage.tsx:321
+#: src/paths/instance/update/UpdatePage.tsx:131
+#: src/paths/instance/update/UpdatePage.tsx:148
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:73
+#, c-format
+msgid "this product has no taxes"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:77
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#: src/paths/instance/orders/details/DetailPage.tsx:296
+#: src/paths/instance/orders/list/Table.tsx:116
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:78
+#, c-format
+msgid "currency and value separated with colon"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:84
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:78
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:53
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:59
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:65
+#: src/paths/instance/orders/list/Table.tsx:60
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:71
+#: src/paths/instance/orders/create/CreatePage.tsx:257
+#: src/paths/instance/products/list/Table.tsx:48
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:77
+#: src/paths/instance/transfers/list/Table.tsx:59
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:87
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:112 src/paths/admin/list/Table.tsx:57
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:116
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:122
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:129
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/components/modal/index.tsx:74
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:110 src/components/modal/index.tsx:111
+#, c-format
+msgid "should be the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:111
+#, c-format
+msgid "cannot be the same as before"
+msgstr ""
+
+#: src/components/modal/index.tsx:114
+#, c-format
+msgid ""
+"You are updating the authorization token from instance %1$s with id %2$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:125
+#, c-format
+msgid "New token"
+msgstr ""
+
+#: src/components/modal/index.tsx:127
+#, c-format
+msgid "Clearing the auth token will mean public access to the instance"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:96
+#: src/paths/admin/create/CreatePage.tsx:84 src/paths/admin/list/Table.tsx:109
+#: src/paths/instance/transfers/list/Table.tsx:111
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:98
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:121
+#: src/paths/instance/products/list/Table.tsx:85
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:100
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:123
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:101
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:124
+#: src/paths/instance/products/list/Table.tsx:162
+#: src/paths/instance/products/list/Table.tsx:214
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:103
+#: src/paths/instance/products/list/Table.tsx:90
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:105
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:128
+#: src/paths/instance/products/list/Table.tsx:88
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/index.tsx:75
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/index.tsx:85
+#, c-format
+msgid "Couldn't access the server"
+msgstr ""
+
+#: src/index.tsx:87 src/index.tsx:99
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/index.tsx:97
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:88
+#: src/paths/instance/update/UpdatePage.tsx:107
+#, c-format
+msgid "Auth token"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:90
+#: src/paths/instance/details/DetailPage.tsx:77
+#: src/paths/instance/update/UpdatePage.tsx:109
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:92
+#: src/paths/instance/update/UpdatePage.tsx:111
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#: src/paths/instance/update/UpdatePage.tsx:113
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#: src/paths/instance/update/UpdatePage.tsx:115
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:115
+#: src/paths/instance/update/UpdatePage.tsx:134
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:132
+#: src/paths/instance/update/UpdatePage.tsx:151
+#, c-format
+msgid "Default pay delay"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:134
+#: src/paths/instance/update/UpdatePage.tsx:153
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/paths/admin/create/index.tsx:58
+#, c-format
+msgid "could not create instance"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:63 src/paths/admin/list/Table.tsx:131
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:128
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:149
+#: src/paths/instance/products/list/Table.tsx:245
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:236
+#, c-format
+msgid "Inventory products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:285
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:286
+#, c-format
+msgid "Total tax"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:288
+#: src/paths/instance/orders/create/CreatePage.tsx:296
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:294
+#, c-format
+msgid "Net"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#: src/paths/instance/orders/details/DetailPage.tsx:295
+#: src/paths/instance/orders/list/Table.tsx:117
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:301
+#, c-format
+msgid "Payments options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:302
+#, c-format
+msgid "Auto refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:303
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:304
+#, c-format
+msgid "Pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:306
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:307
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:324
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:325
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:326
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:327
+#, c-format
+msgid "Fullfilment url"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:330
+#, c-format
+msgid "Extra information"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:44
+#, c-format
+msgid "select a product first"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:51
+#, c-format
+msgid "should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:58
+#, c-format
+msgid ""
+"cannot be greater than current stock and quantity previously added. max: %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:64
+#, c-format
+msgid "cannot be greater than current stock %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:76
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:126
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:92
+#: src/paths/instance/orders/details/DetailPage.tsx:235
+#: src/paths/instance/orders/details/DetailPage.tsx:333
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:110
+#: src/paths/instance/orders/details/DetailPage.tsx:261
+#: src/paths/instance/orders/list/Table.tsx:136
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:126
+#: src/paths/instance/orders/details/DetailPage.tsx:349
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:127
+#: src/paths/instance/orders/details/DetailPage.tsx:350
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:138
+#: src/paths/instance/orders/details/DetailPage.tsx:289
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:142
+#: src/paths/instance/orders/details/DetailPage.tsx:293
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:146
+#: src/paths/instance/orders/details/DetailPage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:363
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:156
+#: src/paths/instance/orders/details/DetailPage.tsx:308
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:236
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:238
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:241
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:258
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:297
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:298
+#, c-format
+msgid "Deposit total"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:336
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:364
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:365
+#, c-format
+msgid "Pay URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:383
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:56
+#: src/paths/instance/orders/list/index.tsx:147
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:59
+#: src/paths/instance/orders/list/index.tsx:150
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:111
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:115
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:131
+#: src/paths/instance/orders/list/Table.tsx:223
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:145
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "No orders has been found"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:202
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:203
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:204
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:224
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:91
+#, c-format
+msgid "go to order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:107
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:108
+#, c-format
+msgid "Refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:109
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:110
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:48
+#: src/paths/instance/products/update/index.tsx:64
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:87
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:89
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:91
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:59
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:62
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:70
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:73
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:59
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:111
+#, c-format
+msgid "Committed amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:112
+#, c-format
+msgid "Exchange initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:113
+#, c-format
+msgid "Merchant initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:148
+#, c-format
+msgid "There is no tips yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:147
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
diff --git a/packages/frontend/src/i18n/en.po b/packages/frontend/src/i18n/en.po
new file mode 100644
index 0000000..694798f
--- /dev/null
+++ b/packages/frontend/src/i18n/en.po
@@ -0,0 +1,1010 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/ApplicationReadyRoutes.tsx:50 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:293
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:51 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:294
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:72
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:73
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:108
+#, c-format
+msgid "HTTP status #%1$s: Server reported a problem"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:109
+#, c-format
+msgid "Got message: \"%1$s\" from: %2$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:126
+#, c-format
+msgid "No default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:127
+#, c-format
+msgid ""
+"in order to use merchant backoffice, you should create the default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:282
+#, c-format
+msgid "Server reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:283
+#, c-format
+msgid "Got message: %1$s from: %2$s"
+msgstr ""
+
+#: src/components/exception/login.tsx:46
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:49
+#, c-format
+msgid ""
+"Please enter your auth token. Token should have \"secret-token:\" and start "
+"with Bearer or ApiKey"
+msgstr ""
+
+#: src/components/exception/login.tsx:86 src/components/modal/index.tsx:53
+#: src/components/modal/index.tsx:75 src/paths/admin/create/CreatePage.tsx:140
+#: src/paths/instance/orders/create/CreatePage.tsx:337
+#: src/paths/instance/products/create/CreatePage.tsx:51
+#: src/paths/instance/products/list/Table.tsx:174
+#: src/paths/instance/products/list/Table.tsx:228
+#: src/paths/instance/products/update/UpdatePage.tsx:55
+#: src/paths/instance/update/UpdatePage.tsx:159
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:72
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:67
+#: src/paths/instance/orders/list/index.tsx:123
+#, c-format
+msgid "pick a date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:81
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:83
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:80
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:59
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:60
+#: src/components/product/ProductForm.tsx:99
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:122
+#: src/paths/instance/orders/list/Table.tsx:227
+#: src/paths/instance/products/list/Table.tsx:86
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:73
+#: src/components/form/InputTaxes.tsx:81
+#: src/paths/admin/create/CreatePage.tsx:86 src/paths/admin/list/Table.tsx:110
+#: src/paths/instance/details/DetailPage.tsx:76
+#: src/paths/instance/transfers/list/Table.tsx:112
+#: src/paths/instance/update/UpdatePage.tsx:105
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:102
+#, c-format
+msgid "loading..."
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:108
+#, c-format
+msgid "no products found"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:116
+#, c-format
+msgid "no results"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:33
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:34
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:60
+#, c-format
+msgid "Manage token"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:83
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:100
+#: src/paths/instance/orders/create/CreatePage.tsx:251
+#: src/paths/instance/orders/create/CreatePage.tsx:272
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:106 src/components/modal/index.tsx:52
+#: src/components/modal/index.tsx:73 src/paths/admin/create/CreatePage.tsx:139
+#: src/paths/instance/orders/create/CreatePage.tsx:336
+#: src/paths/instance/products/create/CreatePage.tsx:50
+#: src/paths/instance/products/list/Table.tsx:166
+#: src/paths/instance/products/list/Table.tsx:218
+#: src/paths/instance/products/update/UpdatePage.tsx:54
+#: src/paths/instance/update/UpdatePage.tsx:158
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:90
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:92
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:104
+#, c-format
+msgid "lost cannot be greater that current + incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:110
+#, c-format
+msgid "current stock will change from %1$s to %2$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:111
+#, c-format
+msgid "current stock will stay at %1$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:128
+#: src/paths/instance/products/list/Table.tsx:204
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:129
+#: src/paths/instance/products/list/Table.tsx:205
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:141
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:144
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:149
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:151
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:153
+#: src/paths/admin/create/CreatePage.tsx:99
+#: src/paths/admin/create/CreatePage.tsx:116
+#: src/paths/instance/orders/create/CreatePage.tsx:308
+#: src/paths/instance/update/UpdatePage.tsx:118
+#: src/paths/instance/update/UpdatePage.tsx:135
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:156
+#: src/paths/admin/create/CreatePage.tsx:98
+#: src/paths/admin/create/CreatePage.tsx:101
+#: src/paths/admin/create/CreatePage.tsx:118
+#: src/paths/instance/orders/create/CreatePage.tsx:310
+#: src/paths/instance/update/UpdatePage.tsx:117
+#: src/paths/instance/update/UpdatePage.tsx:120
+#: src/paths/instance/update/UpdatePage.tsx:137
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:161
+#: src/paths/admin/create/CreatePage.tsx:105
+#: src/paths/admin/create/CreatePage.tsx:122
+#: src/paths/instance/orders/create/CreatePage.tsx:314
+#: src/paths/instance/update/UpdatePage.tsx:124
+#: src/paths/instance/update/UpdatePage.tsx:141
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:162
+#: src/paths/admin/create/CreatePage.tsx:106
+#: src/paths/admin/create/CreatePage.tsx:123
+#: src/paths/instance/orders/create/CreatePage.tsx:315
+#: src/paths/instance/update/UpdatePage.tsx:125
+#: src/paths/instance/update/UpdatePage.tsx:142
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:163
+#: src/paths/admin/create/CreatePage.tsx:107
+#: src/paths/admin/create/CreatePage.tsx:124
+#: src/paths/instance/orders/create/CreatePage.tsx:316
+#: src/paths/instance/update/UpdatePage.tsx:126
+#: src/paths/instance/update/UpdatePage.tsx:143
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:164
+#: src/paths/admin/create/CreatePage.tsx:108
+#: src/paths/admin/create/CreatePage.tsx:125
+#: src/paths/instance/orders/create/CreatePage.tsx:317
+#: src/paths/instance/update/UpdatePage.tsx:127
+#: src/paths/instance/update/UpdatePage.tsx:144
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:165
+#: src/paths/admin/create/CreatePage.tsx:109
+#: src/paths/admin/create/CreatePage.tsx:126
+#: src/paths/instance/orders/create/CreatePage.tsx:318
+#: src/paths/instance/update/UpdatePage.tsx:128
+#: src/paths/instance/update/UpdatePage.tsx:145
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:166
+#: src/paths/admin/create/CreatePage.tsx:110
+#: src/paths/admin/create/CreatePage.tsx:127
+#: src/paths/instance/orders/create/CreatePage.tsx:319
+#: src/paths/instance/update/UpdatePage.tsx:129
+#: src/paths/instance/update/UpdatePage.tsx:146
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:167
+#: src/paths/admin/create/CreatePage.tsx:111
+#: src/paths/admin/create/CreatePage.tsx:128
+#: src/paths/instance/orders/create/CreatePage.tsx:320
+#: src/paths/instance/update/UpdatePage.tsx:130
+#: src/paths/instance/update/UpdatePage.tsx:147
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:168
+#: src/paths/admin/create/CreatePage.tsx:112
+#: src/paths/admin/create/CreatePage.tsx:129
+#: src/paths/instance/orders/create/CreatePage.tsx:321
+#: src/paths/instance/update/UpdatePage.tsx:131
+#: src/paths/instance/update/UpdatePage.tsx:148
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:73
+#, c-format
+msgid "this product has no taxes"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:77
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#: src/paths/instance/orders/details/DetailPage.tsx:296
+#: src/paths/instance/orders/list/Table.tsx:116
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:78
+#, c-format
+msgid "currency and value separated with colon"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:84
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:78
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:53
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:59
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:65
+#: src/paths/instance/orders/list/Table.tsx:60
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:71
+#: src/paths/instance/orders/create/CreatePage.tsx:257
+#: src/paths/instance/products/list/Table.tsx:48
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:77
+#: src/paths/instance/transfers/list/Table.tsx:59
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:87
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:112 src/paths/admin/list/Table.tsx:57
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:116
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:122
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:129
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/components/modal/index.tsx:74
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:110 src/components/modal/index.tsx:111
+#, c-format
+msgid "should be the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:111
+#, c-format
+msgid "cannot be the same as before"
+msgstr ""
+
+#: src/components/modal/index.tsx:114
+#, c-format
+msgid ""
+"You are updating the authorization token from instance %1$s with id %2$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:125
+#, c-format
+msgid "New token"
+msgstr ""
+
+#: src/components/modal/index.tsx:127
+#, c-format
+msgid "Clearing the auth token will mean public access to the instance"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:96
+#: src/paths/admin/create/CreatePage.tsx:84 src/paths/admin/list/Table.tsx:109
+#: src/paths/instance/transfers/list/Table.tsx:111
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:98
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:121
+#: src/paths/instance/products/list/Table.tsx:85
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:100
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:123
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:101
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:124
+#: src/paths/instance/products/list/Table.tsx:162
+#: src/paths/instance/products/list/Table.tsx:214
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:103
+#: src/paths/instance/products/list/Table.tsx:90
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:105
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:128
+#: src/paths/instance/products/list/Table.tsx:88
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/index.tsx:75
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/index.tsx:85
+#, c-format
+msgid "Couldn't access the server"
+msgstr ""
+
+#: src/index.tsx:87 src/index.tsx:99
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/index.tsx:97
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:88
+#: src/paths/instance/update/UpdatePage.tsx:107
+#, c-format
+msgid "Auth token"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:90
+#: src/paths/instance/details/DetailPage.tsx:77
+#: src/paths/instance/update/UpdatePage.tsx:109
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:92
+#: src/paths/instance/update/UpdatePage.tsx:111
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#: src/paths/instance/update/UpdatePage.tsx:113
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#: src/paths/instance/update/UpdatePage.tsx:115
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:115
+#: src/paths/instance/update/UpdatePage.tsx:134
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:132
+#: src/paths/instance/update/UpdatePage.tsx:151
+#, c-format
+msgid "Default pay delay"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:134
+#: src/paths/instance/update/UpdatePage.tsx:153
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/paths/admin/create/index.tsx:58
+#, c-format
+msgid "could not create instance"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:63 src/paths/admin/list/Table.tsx:131
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:128
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:149
+#: src/paths/instance/products/list/Table.tsx:245
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:236
+#, c-format
+msgid "Inventory products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:285
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:286
+#, c-format
+msgid "Total tax"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:288
+#: src/paths/instance/orders/create/CreatePage.tsx:296
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:294
+#, c-format
+msgid "Net"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#: src/paths/instance/orders/details/DetailPage.tsx:295
+#: src/paths/instance/orders/list/Table.tsx:117
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:301
+#, c-format
+msgid "Payments options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:302
+#, c-format
+msgid "Auto refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:303
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:304
+#, c-format
+msgid "Pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:306
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:307
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:324
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:325
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:326
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:327
+#, c-format
+msgid "Fullfilment url"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:330
+#, c-format
+msgid "Extra information"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:44
+#, c-format
+msgid "select a product first"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:51
+#, c-format
+msgid "should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:58
+#, c-format
+msgid ""
+"cannot be greater than current stock and quantity previously added. max: %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:64
+#, c-format
+msgid "cannot be greater than current stock %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:76
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:126
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:92
+#: src/paths/instance/orders/details/DetailPage.tsx:235
+#: src/paths/instance/orders/details/DetailPage.tsx:333
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:110
+#: src/paths/instance/orders/details/DetailPage.tsx:261
+#: src/paths/instance/orders/list/Table.tsx:136
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:126
+#: src/paths/instance/orders/details/DetailPage.tsx:349
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:127
+#: src/paths/instance/orders/details/DetailPage.tsx:350
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:138
+#: src/paths/instance/orders/details/DetailPage.tsx:289
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:142
+#: src/paths/instance/orders/details/DetailPage.tsx:293
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:146
+#: src/paths/instance/orders/details/DetailPage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:363
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:156
+#: src/paths/instance/orders/details/DetailPage.tsx:308
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:236
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:238
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:241
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:258
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:297
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:298
+#, c-format
+msgid "Deposit total"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:336
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:364
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:365
+#, c-format
+msgid "Pay URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:383
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:56
+#: src/paths/instance/orders/list/index.tsx:147
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:59
+#: src/paths/instance/orders/list/index.tsx:150
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:111
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:115
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:131
+#: src/paths/instance/orders/list/Table.tsx:223
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:145
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "No orders has been found"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:202
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:203
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:204
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:224
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:91
+#, c-format
+msgid "go to order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:107
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:108
+#, c-format
+msgid "Refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:109
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:110
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:48
+#: src/paths/instance/products/update/index.tsx:64
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:87
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:89
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:91
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:59
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:62
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:70
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:73
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:59
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:111
+#, c-format
+msgid "Committed amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:112
+#, c-format
+msgid "Exchange initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:113
+#, c-format
+msgid "Merchant initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:148
+#, c-format
+msgid "There is no tips yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:147
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
diff --git a/packages/frontend/src/i18n/es.po b/packages/frontend/src/i18n/es.po
new file mode 100644
index 0000000..f58de31
--- /dev/null
+++ b/packages/frontend/src/i18n/es.po
@@ -0,0 +1,1018 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/ApplicationReadyRoutes.tsx:50 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:293
+#, c-format
+msgid "Access denied"
+msgstr "Acceso denegado"
+
+#: src/ApplicationReadyRoutes.tsx:51 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:294
+#, c-format
+msgid "Check your token is valid"
+msgstr "Verifica que el token sea valido"
+
+#: src/ApplicationReadyRoutes.tsx:72
+#, c-format
+msgid "Couldn't access the server."
+msgstr "No se pudo acceder al servidor"
+
+#: src/ApplicationReadyRoutes.tsx:73
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr "No se pudo inferir el id de la instancia con la url %1$s"
+
+#: src/InstanceRoutes.tsx:108
+#, c-format
+msgid "HTTP status #%1$s: Server reported a problem"
+msgstr "HTTP status #%1$s: Servidor reporto un problema"
+
+#: src/InstanceRoutes.tsx:109
+#, fuzzy, c-format
+msgid "Got message: \"%1$s\" from: %2$s"
+msgstr "Recivimos el mensaje %1$s desde %2$s"
+
+#: src/InstanceRoutes.tsx:126
+#, c-format
+msgid "No default instance"
+msgstr "Sin instancia default"
+
+#: src/InstanceRoutes.tsx:127
+#, c-format
+msgid ""
+"in order to use merchant backoffice, you should create the default instance"
+msgstr "para usar el merchant backoffice, debería crear la instancia default"
+
+#: src/InstanceRoutes.tsx:282
+#, c-format
+msgid "Server reported a problem: HTTP status #%1$s"
+msgstr "Servidir reporto un problema: HTTP status #%1$s"
+
+#: src/InstanceRoutes.tsx:283
+#, fuzzy, c-format
+msgid "Got message: %1$s from: %2$s"
+msgstr "Recivimos el mensaje %1$s desde %2$s"
+
+#: src/components/exception/login.tsx:46
+#, c-format
+msgid "Login required"
+msgstr "Login necesario"
+
+#: src/components/exception/login.tsx:49
+#, c-format
+msgid ""
+"Please enter your auth token. Token should have \"secret-token:\" and start "
+"with Bearer or ApiKey"
+msgstr ""
+"Por favor ingrese su token de autorización. El token debe tener \"secret-"
+"token\" y comenzar con Bearer o ApiKey"
+
+#: src/components/exception/login.tsx:86 src/components/modal/index.tsx:53
+#: src/components/modal/index.tsx:75 src/paths/admin/create/CreatePage.tsx:140
+#: src/paths/instance/orders/create/CreatePage.tsx:337
+#: src/paths/instance/products/create/CreatePage.tsx:51
+#: src/paths/instance/products/list/Table.tsx:174
+#: src/paths/instance/products/list/Table.tsx:228
+#: src/paths/instance/products/update/UpdatePage.tsx:55
+#: src/paths/instance/update/UpdatePage.tsx:159
+#, c-format
+msgid "Confirm"
+msgstr "Confirmar"
+
+#: src/components/form/InputArray.tsx:72
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr "El valor %1$s es invalido para una URL de pago"
+
+#: src/components/form/InputDate.tsx:67
+#: src/paths/instance/orders/list/index.tsx:123
+#, c-format
+msgid "pick a date"
+msgstr "elegir una fecha"
+
+#: src/components/form/InputDate.tsx:81
+#, fuzzy, c-format
+msgid "clear"
+msgstr "Limpiar"
+
+#: src/components/form/InputDate.tsx:83
+#, c-format
+msgid "never"
+msgstr "nunca"
+
+#: src/components/form/InputImage.tsx:80
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr "La imagen debe ser mas chica que 1 MB"
+
+#: src/components/form/InputSearchProduct.tsx:59
+#, fuzzy, c-format
+msgid "Product id"
+msgstr "Id de producto"
+
+#: src/components/form/InputSearchProduct.tsx:60
+#: src/components/product/ProductForm.tsx:99
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:122
+#: src/paths/instance/orders/list/Table.tsx:227
+#: src/paths/instance/products/list/Table.tsx:86
+#, c-format
+msgid "Description"
+msgstr "Descripcion"
+
+#: src/components/form/InputSearchProduct.tsx:73
+#: src/components/form/InputTaxes.tsx:81
+#: src/paths/admin/create/CreatePage.tsx:86 src/paths/admin/list/Table.tsx:110
+#: src/paths/instance/details/DetailPage.tsx:76
+#: src/paths/instance/transfers/list/Table.tsx:112
+#: src/paths/instance/update/UpdatePage.tsx:105
+#, c-format
+msgid "Name"
+msgstr "Nombre"
+
+#: src/components/form/InputSearchProduct.tsx:102
+#, c-format
+msgid "loading..."
+msgstr "Cargando..."
+
+#: src/components/form/InputSearchProduct.tsx:108
+#, c-format
+msgid "no products found"
+msgstr "No se encontraron productos"
+
+#: src/components/form/InputSearchProduct.tsx:116
+#, c-format
+msgid "no results"
+msgstr "Sin resultados"
+
+#: src/components/form/InputSecured.tsx:33
+#, c-format
+msgid "Deleting"
+msgstr "Borrando"
+
+#: src/components/form/InputSecured.tsx:34
+#, c-format
+msgid "Changing"
+msgstr "Cambiando"
+
+#: src/components/form/InputSecured.tsx:60
+#, c-format
+msgid "Manage token"
+msgstr "Administrar token"
+
+#: src/components/form/InputSecured.tsx:83
+#, c-format
+msgid "Update"
+msgstr "Actualizar"
+
+#: src/components/form/InputSecured.tsx:100
+#: src/paths/instance/orders/create/CreatePage.tsx:251
+#: src/paths/instance/orders/create/CreatePage.tsx:272
+#, c-format
+msgid "Remove"
+msgstr "Eliminar"
+
+#: src/components/form/InputSecured.tsx:106 src/components/modal/index.tsx:52
+#: src/components/modal/index.tsx:73 src/paths/admin/create/CreatePage.tsx:139
+#: src/paths/instance/orders/create/CreatePage.tsx:336
+#: src/paths/instance/products/create/CreatePage.tsx:50
+#: src/paths/instance/products/list/Table.tsx:166
+#: src/paths/instance/products/list/Table.tsx:218
+#: src/paths/instance/products/update/UpdatePage.tsx:54
+#: src/paths/instance/update/UpdatePage.tsx:158
+#, c-format
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: src/components/form/InputStock.tsx:90
+#, c-format
+msgid "Manage stock"
+msgstr "Administrar stock"
+
+#: src/components/form/InputStock.tsx:92
+#, c-format
+msgid "Infinite"
+msgstr "Inifinito"
+
+#: src/components/form/InputStock.tsx:104
+#, fuzzy, c-format
+msgid "lost cannot be greater that current + incoming (max %1$s)"
+msgstr "no puede ser mayor al stock actual %1$s"
+
+#: src/components/form/InputStock.tsx:110
+#, c-format
+msgid "current stock will change from %1$s to %2$s"
+msgstr "stock actual cambiará desde %1$s a %2$s"
+
+#: src/components/form/InputStock.tsx:111
+#, c-format
+msgid "current stock will stay at %1$s"
+msgstr "stock actual seguirá en %1$s"
+
+#: src/components/form/InputStock.tsx:128
+#: src/paths/instance/products/list/Table.tsx:204
+#, c-format
+msgid "Incoming"
+msgstr "Ingresando"
+
+#: src/components/form/InputStock.tsx:129
+#: src/paths/instance/products/list/Table.tsx:205
+#, c-format
+msgid "Lost"
+msgstr "Perdido"
+
+#: src/components/form/InputStock.tsx:141
+#, c-format
+msgid "Current"
+msgstr "Actual"
+
+#: src/components/form/InputStock.tsx:144
+#, c-format
+msgid "without stock"
+msgstr "sin stock"
+
+#: src/components/form/InputStock.tsx:149
+#, c-format
+msgid "Next restock"
+msgstr "Próximo reabastecimiento"
+
+#: src/components/form/InputStock.tsx:151
+#, c-format
+msgid "Delivery address"
+msgstr "Dirección de entrega"
+
+#: src/components/form/InputStock.tsx:153
+#: src/paths/admin/create/CreatePage.tsx:99
+#: src/paths/admin/create/CreatePage.tsx:116
+#: src/paths/instance/orders/create/CreatePage.tsx:308
+#: src/paths/instance/update/UpdatePage.tsx:118
+#: src/paths/instance/update/UpdatePage.tsx:135
+#, c-format
+msgid "Country"
+msgstr "País"
+
+#: src/components/form/InputStock.tsx:156
+#: src/paths/admin/create/CreatePage.tsx:98
+#: src/paths/admin/create/CreatePage.tsx:101
+#: src/paths/admin/create/CreatePage.tsx:118
+#: src/paths/instance/orders/create/CreatePage.tsx:310
+#: src/paths/instance/update/UpdatePage.tsx:117
+#: src/paths/instance/update/UpdatePage.tsx:120
+#: src/paths/instance/update/UpdatePage.tsx:137
+#, c-format
+msgid "Address"
+msgstr "Dirección"
+
+#: src/components/form/InputStock.tsx:161
+#: src/paths/admin/create/CreatePage.tsx:105
+#: src/paths/admin/create/CreatePage.tsx:122
+#: src/paths/instance/orders/create/CreatePage.tsx:314
+#: src/paths/instance/update/UpdatePage.tsx:124
+#: src/paths/instance/update/UpdatePage.tsx:141
+#, c-format
+msgid "Building number"
+msgstr "Número de edificio"
+
+#: src/components/form/InputStock.tsx:162
+#: src/paths/admin/create/CreatePage.tsx:106
+#: src/paths/admin/create/CreatePage.tsx:123
+#: src/paths/instance/orders/create/CreatePage.tsx:315
+#: src/paths/instance/update/UpdatePage.tsx:125
+#: src/paths/instance/update/UpdatePage.tsx:142
+#, c-format
+msgid "Building name"
+msgstr "Nombre de edificio"
+
+#: src/components/form/InputStock.tsx:163
+#: src/paths/admin/create/CreatePage.tsx:107
+#: src/paths/admin/create/CreatePage.tsx:124
+#: src/paths/instance/orders/create/CreatePage.tsx:316
+#: src/paths/instance/update/UpdatePage.tsx:126
+#: src/paths/instance/update/UpdatePage.tsx:143
+#, c-format
+msgid "Street"
+msgstr "Calle"
+
+#: src/components/form/InputStock.tsx:164
+#: src/paths/admin/create/CreatePage.tsx:108
+#: src/paths/admin/create/CreatePage.tsx:125
+#: src/paths/instance/orders/create/CreatePage.tsx:317
+#: src/paths/instance/update/UpdatePage.tsx:127
+#: src/paths/instance/update/UpdatePage.tsx:144
+#, c-format
+msgid "Post code"
+msgstr "Código postal"
+
+#: src/components/form/InputStock.tsx:165
+#: src/paths/admin/create/CreatePage.tsx:109
+#: src/paths/admin/create/CreatePage.tsx:126
+#: src/paths/instance/orders/create/CreatePage.tsx:318
+#: src/paths/instance/update/UpdatePage.tsx:128
+#: src/paths/instance/update/UpdatePage.tsx:145
+#, fuzzy, c-format
+msgid "Town location"
+msgstr "Ubicación de ciudad"
+
+#: src/components/form/InputStock.tsx:166
+#: src/paths/admin/create/CreatePage.tsx:110
+#: src/paths/admin/create/CreatePage.tsx:127
+#: src/paths/instance/orders/create/CreatePage.tsx:319
+#: src/paths/instance/update/UpdatePage.tsx:129
+#: src/paths/instance/update/UpdatePage.tsx:146
+#, c-format
+msgid "Town"
+msgstr "Ciudad"
+
+#: src/components/form/InputStock.tsx:167
+#: src/paths/admin/create/CreatePage.tsx:111
+#: src/paths/admin/create/CreatePage.tsx:128
+#: src/paths/instance/orders/create/CreatePage.tsx:320
+#: src/paths/instance/update/UpdatePage.tsx:130
+#: src/paths/instance/update/UpdatePage.tsx:147
+#, c-format
+msgid "District"
+msgstr "Distrito"
+
+#: src/components/form/InputStock.tsx:168
+#: src/paths/admin/create/CreatePage.tsx:112
+#: src/paths/admin/create/CreatePage.tsx:129
+#: src/paths/instance/orders/create/CreatePage.tsx:321
+#: src/paths/instance/update/UpdatePage.tsx:131
+#: src/paths/instance/update/UpdatePage.tsx:148
+#, c-format
+msgid "Country subdivision"
+msgstr "Provincia"
+
+#: src/components/form/InputTaxes.tsx:73
+#, c-format
+msgid "this product has no taxes"
+msgstr "este producto no tiene impuestos"
+
+#: src/components/form/InputTaxes.tsx:77
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#: src/paths/instance/orders/details/DetailPage.tsx:296
+#: src/paths/instance/orders/list/Table.tsx:116
+#, c-format
+msgid "Amount"
+msgstr "Monto"
+
+#: src/components/form/InputTaxes.tsx:78
+#, c-format
+msgid "currency and value separated with colon"
+msgstr "Moneda y valor separado por dos puntos"
+
+#: src/components/form/InputTaxes.tsx:84
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:78
+#, c-format
+msgid "Add"
+msgstr "Agregar"
+
+#: src/components/menu/SideBar.tsx:53
+#, c-format
+msgid "Instance"
+msgstr "Instancia"
+
+#: src/components/menu/SideBar.tsx:59
+#, c-format
+msgid "Settings"
+msgstr "Configuración"
+
+#: src/components/menu/SideBar.tsx:65
+#: src/paths/instance/orders/list/Table.tsx:60
+#, fuzzy, c-format
+msgid "Orders"
+msgstr "Ordenes"
+
+#: src/components/menu/SideBar.tsx:71
+#: src/paths/instance/orders/create/CreatePage.tsx:257
+#: src/paths/instance/products/list/Table.tsx:48
+#, c-format
+msgid "Products"
+msgstr "Productos"
+
+#: src/components/menu/SideBar.tsx:77
+#: src/paths/instance/transfers/list/Table.tsx:59
+#, c-format
+msgid "Transfers"
+msgstr "Transferencias"
+
+#: src/components/menu/SideBar.tsx:87
+#, fuzzy, c-format
+msgid "Connection"
+msgstr "Conexión"
+
+#: src/components/menu/SideBar.tsx:112 src/paths/admin/list/Table.tsx:57
+#, c-format
+msgid "Instances"
+msgstr "Instancias"
+
+#: src/components/menu/SideBar.tsx:116
+#, fuzzy, c-format
+msgid "New"
+msgstr "Nuevo"
+
+#: src/components/menu/SideBar.tsx:122
+#, c-format
+msgid "List"
+msgstr "Lista"
+
+#: src/components/menu/SideBar.tsx:129
+#, c-format
+msgid "Log out"
+msgstr "Salir"
+
+#: src/components/modal/index.tsx:74
+#, c-format
+msgid "Clear"
+msgstr "Limpiar"
+
+#: src/components/modal/index.tsx:110 src/components/modal/index.tsx:111
+#, c-format
+msgid "should be the same"
+msgstr "deberían ser iguales"
+
+#: src/components/modal/index.tsx:111
+#, c-format
+msgid "cannot be the same as before"
+msgstr "no puede ser igual al anterior"
+
+#: src/components/modal/index.tsx:114
+#, c-format
+msgid ""
+"You are updating the authorization token from instance %1$s with id %2$s"
+msgstr ""
+"Está actualizando el token de autorización para la instancia %1$s con id %2$s"
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Old token"
+msgstr "Viejo token"
+
+#: src/components/modal/index.tsx:125
+#, c-format
+msgid "New token"
+msgstr "Nuevo token"
+
+#: src/components/modal/index.tsx:127
+#, c-format
+msgid "Clearing the auth token will mean public access to the instance"
+msgstr ""
+"Limpiar el token de autorización significa acceso publico a la instancia"
+
+#: src/components/product/ProductForm.tsx:96
+#: src/paths/admin/create/CreatePage.tsx:84 src/paths/admin/list/Table.tsx:109
+#: src/paths/instance/transfers/list/Table.tsx:111
+#, c-format
+msgid "ID"
+msgstr "ID"
+
+#: src/components/product/ProductForm.tsx:98
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:121
+#: src/paths/instance/products/list/Table.tsx:85
+#, c-format
+msgid "Image"
+msgstr "Imagen"
+
+#: src/components/product/ProductForm.tsx:100
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:123
+#, c-format
+msgid "Unit"
+msgstr "Unidad"
+
+#: src/components/product/ProductForm.tsx:101
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:124
+#: src/paths/instance/products/list/Table.tsx:162
+#: src/paths/instance/products/list/Table.tsx:214
+#, c-format
+msgid "Price"
+msgstr "Precio"
+
+#: src/components/product/ProductForm.tsx:103
+#: src/paths/instance/products/list/Table.tsx:90
+#, c-format
+msgid "Stock"
+msgstr "Stock"
+
+#: src/components/product/ProductForm.tsx:105
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:128
+#: src/paths/instance/products/list/Table.tsx:88
+#, c-format
+msgid "Taxes"
+msgstr "Impuesto"
+
+#: src/index.tsx:75
+#, c-format
+msgid "Server not found"
+msgstr "Servidor no encontrado"
+
+#: src/index.tsx:85
+#, c-format
+msgid "Couldn't access the server"
+msgstr "No se pudo aceder al servidor"
+
+#: src/index.tsx:87 src/index.tsx:99
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr "Recivimos el mensaje %1$s desde %2$s"
+
+#: src/index.tsx:97
+#, c-format
+msgid "Unexpected Error"
+msgstr "Error inesperado"
+
+#: src/paths/admin/create/CreatePage.tsx:88
+#: src/paths/instance/update/UpdatePage.tsx:107
+#, c-format
+msgid "Auth token"
+msgstr "Token de autorización"
+
+#: src/paths/admin/create/CreatePage.tsx:90
+#: src/paths/instance/details/DetailPage.tsx:77
+#: src/paths/instance/update/UpdatePage.tsx:109
+#, c-format
+msgid "Account address"
+msgstr "Dirección de cuenta"
+
+#: src/paths/admin/create/CreatePage.tsx:92
+#: src/paths/instance/update/UpdatePage.tsx:111
+#, c-format
+msgid "Default max deposit fee"
+msgstr "Impuesto máximo de deposito por omisión"
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#: src/paths/instance/update/UpdatePage.tsx:113
+#, c-format
+msgid "Default max wire fee"
+msgstr "Impuesto máximo de transferencia por omisión"
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#: src/paths/instance/update/UpdatePage.tsx:115
+#, c-format
+msgid "Default wire fee amortization"
+msgstr "Amortización de impuesto de transferencia por omisión"
+
+#: src/paths/admin/create/CreatePage.tsx:115
+#: src/paths/instance/update/UpdatePage.tsx:134
+#, c-format
+msgid "Jurisdiction"
+msgstr "Jurisdicción"
+
+#: src/paths/admin/create/CreatePage.tsx:132
+#: src/paths/instance/update/UpdatePage.tsx:151
+#, c-format
+msgid "Default pay delay"
+msgstr "Retrazo de pago por omisión"
+
+#: src/paths/admin/create/CreatePage.tsx:134
+#: src/paths/instance/update/UpdatePage.tsx:153
+#, c-format
+msgid "Default wire transfer delay"
+msgstr "Retrazo de transferencia por omisión"
+
+#: src/paths/admin/create/index.tsx:58
+#, c-format
+msgid "could not create instance"
+msgstr "no se pudo crear la instancia"
+
+#: src/paths/admin/list/Table.tsx:63 src/paths/admin/list/Table.tsx:131
+#, fuzzy, c-format
+msgid "Delete"
+msgstr "Borrando"
+
+#: src/paths/admin/list/Table.tsx:128
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:149
+#: src/paths/instance/products/list/Table.tsx:245
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr "No hay instancias todavían, agregue mas presionando el signo +"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:236
+#, c-format
+msgid "Inventory products"
+msgstr "Productos de inventario"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:285
+#, c-format
+msgid "Total price"
+msgstr "Precio total"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:286
+#, c-format
+msgid "Total tax"
+msgstr "Impuesto total"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:288
+#: src/paths/instance/orders/create/CreatePage.tsx:296
+#, c-format
+msgid "Order price"
+msgstr "Precio de la orden"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:294
+#, fuzzy, c-format
+msgid "Net"
+msgstr "Neto"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#: src/paths/instance/orders/details/DetailPage.tsx:295
+#: src/paths/instance/orders/list/Table.tsx:117
+#, c-format
+msgid "Summary"
+msgstr "Resumen"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:301
+#, c-format
+msgid "Payments options"
+msgstr "Opciones de pago"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:302
+#, c-format
+msgid "Auto refund deadline"
+msgstr "Plazo de reembolso automático"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:303
+#, c-format
+msgid "Refund deadline"
+msgstr "Plazo de reembolso"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:304
+#, c-format
+msgid "Pay deadline"
+msgstr "Plazo de pago"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:306
+#, c-format
+msgid "Delivery date"
+msgstr "Fecha de entrega"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:307
+#, fuzzy, c-format
+msgid "Location"
+msgstr "Ubicación"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:324
+#, c-format
+msgid "Max fee"
+msgstr "Impuesto máximo"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:325
+#, c-format
+msgid "Max wire fee"
+msgstr "Impuesto de transferencia máximo"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:326
+#, c-format
+msgid "Wire fee amortization"
+msgstr "Amortización de impuesto de transferencia"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:327
+#, c-format
+msgid "Fullfilment url"
+msgstr "URL de completitud"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:330
+#, c-format
+msgid "Extra information"
+msgstr "Información extra"
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:44
+#, c-format
+msgid "select a product first"
+msgstr "seleccione un producto primero"
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:51
+#, fuzzy, c-format
+msgid "should be greater than 0"
+msgstr "La imagen debe ser mas chica que 1 MB"
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:58
+#, c-format
+msgid ""
+"cannot be greater than current stock and quantity previously added. max: %1$s"
+msgstr ""
+"no puede ser mayor al stock actual y la cantidad previamente agregada. "
+"máximo: %1$s"
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:64
+#, c-format
+msgid "cannot be greater than current stock %1$s"
+msgstr "no puede ser mayor al stock actual %1$s"
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:76
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:126
+#, c-format
+msgid "Quantity"
+msgstr "Cantidad"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:92
+#: src/paths/instance/orders/details/DetailPage.tsx:235
+#: src/paths/instance/orders/details/DetailPage.tsx:333
+#, c-format
+msgid "Order"
+msgstr "Orden"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "claimed"
+msgstr "reclamado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:110
+#: src/paths/instance/orders/details/DetailPage.tsx:261
+#: src/paths/instance/orders/list/Table.tsx:136
+#, c-format
+msgid "copy url"
+msgstr "copiar url"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:126
+#: src/paths/instance/orders/details/DetailPage.tsx:349
+#, c-format
+msgid "pay at"
+msgstr "pagar en"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:127
+#: src/paths/instance/orders/details/DetailPage.tsx:350
+#, c-format
+msgid "created at"
+msgstr "creado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:138
+#: src/paths/instance/orders/details/DetailPage.tsx:289
+#, c-format
+msgid "Timeline"
+msgstr "Cronología"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:142
+#: src/paths/instance/orders/details/DetailPage.tsx:293
+#, c-format
+msgid "Payment details"
+msgstr "Detalles de pago"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:146
+#: src/paths/instance/orders/details/DetailPage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:363
+#, fuzzy, c-format
+msgid "Order status"
+msgstr "Estado de orden"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:156
+#: src/paths/instance/orders/details/DetailPage.tsx:308
+#, fuzzy, c-format
+msgid "Product list"
+msgstr "Lista de producto"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:236
+#, c-format
+msgid "paid"
+msgstr "pagados"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:238
+#, c-format
+msgid "wired"
+msgstr "transferido"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:241
+#, c-format
+msgid "refunded"
+msgstr "reembolzado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:258
+#, c-format
+msgid "refund"
+msgstr "reembolzar"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:297
+#, c-format
+msgid "Refunded amount"
+msgstr "Monto reembolzado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:298
+#, c-format
+msgid "Deposit total"
+msgstr "Total depositado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:336
+#, c-format
+msgid "unpaid"
+msgstr "impago"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:364
+#, c-format
+msgid "Order status URL"
+msgstr "URL de estado de orden"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:365
+#, c-format
+msgid "Pay URI"
+msgstr "URI de pago"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:383
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+"Estado de orden desconocido. Esto es un error, por favor contacte a su "
+"administrador"
+
+#: src/paths/instance/orders/details/index.tsx:56
+#: src/paths/instance/orders/list/index.tsx:147
+#, c-format
+msgid "refund created successfully"
+msgstr "reembolzo creado satisfactoriamente"
+
+#: src/paths/instance/orders/details/index.tsx:59
+#: src/paths/instance/orders/list/index.tsx:150
+#, fuzzy, c-format
+msgid "could not create the refund"
+msgstr "No se pudo aceder al servidor"
+
+#: src/paths/instance/orders/list/Table.tsx:111
+#, c-format
+msgid "load newer orders"
+msgstr "cargar nuevas ordenes"
+
+#: src/paths/instance/orders/list/Table.tsx:115
+#, c-format
+msgid "Date"
+msgstr "Fecha"
+
+#: src/paths/instance/orders/list/Table.tsx:131
+#: src/paths/instance/orders/list/Table.tsx:223
+#, c-format
+msgid "Refund"
+msgstr "Reembolzar"
+
+#: src/paths/instance/orders/list/Table.tsx:145
+#, c-format
+msgid "load older orders"
+msgstr "cargar viejas ordenes"
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "No orders has been found"
+msgstr "No se enconraron ordenes"
+
+#: src/paths/instance/orders/list/Table.tsx:202
+#, c-format
+msgid "date"
+msgstr "fecha"
+
+#: src/paths/instance/orders/list/Table.tsx:203
+#, c-format
+msgid "amount"
+msgstr "monto"
+
+#: src/paths/instance/orders/list/Table.tsx:204
+#, c-format
+msgid "reason"
+msgstr "razón"
+
+#: src/paths/instance/orders/list/Table.tsx:224
+#, c-format
+msgid "Max refundable:"
+msgstr "Máximo reembolzable:"
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "Reason"
+msgstr "Razón"
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "duplicated"
+msgstr "duplicado"
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "requested by the customer"
+msgstr "pedido por el consumidor"
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "other"
+msgstr "otro"
+
+#: src/paths/instance/orders/list/index.tsx:91
+#, c-format
+msgid "go to order id"
+msgstr "ir a id de orden"
+
+#: src/paths/instance/orders/list/index.tsx:107
+#, c-format
+msgid "Paid"
+msgstr "Pagado"
+
+#: src/paths/instance/orders/list/index.tsx:108
+#, fuzzy, c-format
+msgid "Refunded"
+msgstr "Reembolzado"
+
+#: src/paths/instance/orders/list/index.tsx:109
+#, fuzzy, c-format
+msgid "Not wired"
+msgstr "No transferido"
+
+#: src/paths/instance/orders/list/index.tsx:110
+#, c-format
+msgid "All"
+msgstr "Todo"
+
+#: src/paths/instance/products/create/index.tsx:48
+#: src/paths/instance/products/update/index.tsx:64
+#, c-format
+msgid "could not create product"
+msgstr "no se pudo crear el producto"
+
+#: src/paths/instance/products/list/Table.tsx:87
+#, c-format
+msgid "Sell"
+msgstr "Venta"
+
+#: src/paths/instance/products/list/Table.tsx:89
+#, c-format
+msgid "Profit"
+msgstr "Ganancia"
+
+#: src/paths/instance/products/list/Table.tsx:91
+#, c-format
+msgid "Sold"
+msgstr "Vendido"
+
+#: src/paths/instance/products/list/index.tsx:59
+#, c-format
+msgid "product updated successfully"
+msgstr "producto actualizado correctamente"
+
+#: src/paths/instance/products/list/index.tsx:62
+#, c-format
+msgid "could not update the product"
+msgstr "no se pudo actualizar el producto"
+
+#: src/paths/instance/products/list/index.tsx:70
+#, c-format
+msgid "product delete successfully"
+msgstr "producto fue eliminado correctamente"
+
+#: src/paths/instance/products/list/index.tsx:73
+#, c-format
+msgid "could not delete the product"
+msgstr "no se pudo eliminar el producto"
+
+#: src/paths/instance/tips/list/Table.tsx:59
+#, c-format
+msgid "Tips"
+msgstr "Propinas"
+
+#: src/paths/instance/tips/list/Table.tsx:111
+#, c-format
+msgid "Committed amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:112
+#, c-format
+msgid "Exchange initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:113
+#, c-format
+msgid "Merchant initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:148
+#, c-format
+msgid "There is no tips yet, add more pressing the + sign"
+msgstr "No hay propinas todavía, agregar mas presionando el signo +"
+
+#: src/paths/instance/transfers/list/Table.tsx:147
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr "No hay transferencias todavía, agregar mas presionando el signo +"
diff --git a/packages/frontend/src/i18n/fr.po b/packages/frontend/src/i18n/fr.po
new file mode 100644
index 0000000..694798f
--- /dev/null
+++ b/packages/frontend/src/i18n/fr.po
@@ -0,0 +1,1010 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/ApplicationReadyRoutes.tsx:50 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:293
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:51 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:294
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:72
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:73
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:108
+#, c-format
+msgid "HTTP status #%1$s: Server reported a problem"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:109
+#, c-format
+msgid "Got message: \"%1$s\" from: %2$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:126
+#, c-format
+msgid "No default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:127
+#, c-format
+msgid ""
+"in order to use merchant backoffice, you should create the default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:282
+#, c-format
+msgid "Server reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:283
+#, c-format
+msgid "Got message: %1$s from: %2$s"
+msgstr ""
+
+#: src/components/exception/login.tsx:46
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:49
+#, c-format
+msgid ""
+"Please enter your auth token. Token should have \"secret-token:\" and start "
+"with Bearer or ApiKey"
+msgstr ""
+
+#: src/components/exception/login.tsx:86 src/components/modal/index.tsx:53
+#: src/components/modal/index.tsx:75 src/paths/admin/create/CreatePage.tsx:140
+#: src/paths/instance/orders/create/CreatePage.tsx:337
+#: src/paths/instance/products/create/CreatePage.tsx:51
+#: src/paths/instance/products/list/Table.tsx:174
+#: src/paths/instance/products/list/Table.tsx:228
+#: src/paths/instance/products/update/UpdatePage.tsx:55
+#: src/paths/instance/update/UpdatePage.tsx:159
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:72
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:67
+#: src/paths/instance/orders/list/index.tsx:123
+#, c-format
+msgid "pick a date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:81
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:83
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:80
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:59
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:60
+#: src/components/product/ProductForm.tsx:99
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:122
+#: src/paths/instance/orders/list/Table.tsx:227
+#: src/paths/instance/products/list/Table.tsx:86
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:73
+#: src/components/form/InputTaxes.tsx:81
+#: src/paths/admin/create/CreatePage.tsx:86 src/paths/admin/list/Table.tsx:110
+#: src/paths/instance/details/DetailPage.tsx:76
+#: src/paths/instance/transfers/list/Table.tsx:112
+#: src/paths/instance/update/UpdatePage.tsx:105
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:102
+#, c-format
+msgid "loading..."
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:108
+#, c-format
+msgid "no products found"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:116
+#, c-format
+msgid "no results"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:33
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:34
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:60
+#, c-format
+msgid "Manage token"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:83
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:100
+#: src/paths/instance/orders/create/CreatePage.tsx:251
+#: src/paths/instance/orders/create/CreatePage.tsx:272
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:106 src/components/modal/index.tsx:52
+#: src/components/modal/index.tsx:73 src/paths/admin/create/CreatePage.tsx:139
+#: src/paths/instance/orders/create/CreatePage.tsx:336
+#: src/paths/instance/products/create/CreatePage.tsx:50
+#: src/paths/instance/products/list/Table.tsx:166
+#: src/paths/instance/products/list/Table.tsx:218
+#: src/paths/instance/products/update/UpdatePage.tsx:54
+#: src/paths/instance/update/UpdatePage.tsx:158
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:90
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:92
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:104
+#, c-format
+msgid "lost cannot be greater that current + incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:110
+#, c-format
+msgid "current stock will change from %1$s to %2$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:111
+#, c-format
+msgid "current stock will stay at %1$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:128
+#: src/paths/instance/products/list/Table.tsx:204
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:129
+#: src/paths/instance/products/list/Table.tsx:205
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:141
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:144
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:149
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:151
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:153
+#: src/paths/admin/create/CreatePage.tsx:99
+#: src/paths/admin/create/CreatePage.tsx:116
+#: src/paths/instance/orders/create/CreatePage.tsx:308
+#: src/paths/instance/update/UpdatePage.tsx:118
+#: src/paths/instance/update/UpdatePage.tsx:135
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:156
+#: src/paths/admin/create/CreatePage.tsx:98
+#: src/paths/admin/create/CreatePage.tsx:101
+#: src/paths/admin/create/CreatePage.tsx:118
+#: src/paths/instance/orders/create/CreatePage.tsx:310
+#: src/paths/instance/update/UpdatePage.tsx:117
+#: src/paths/instance/update/UpdatePage.tsx:120
+#: src/paths/instance/update/UpdatePage.tsx:137
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:161
+#: src/paths/admin/create/CreatePage.tsx:105
+#: src/paths/admin/create/CreatePage.tsx:122
+#: src/paths/instance/orders/create/CreatePage.tsx:314
+#: src/paths/instance/update/UpdatePage.tsx:124
+#: src/paths/instance/update/UpdatePage.tsx:141
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:162
+#: src/paths/admin/create/CreatePage.tsx:106
+#: src/paths/admin/create/CreatePage.tsx:123
+#: src/paths/instance/orders/create/CreatePage.tsx:315
+#: src/paths/instance/update/UpdatePage.tsx:125
+#: src/paths/instance/update/UpdatePage.tsx:142
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:163
+#: src/paths/admin/create/CreatePage.tsx:107
+#: src/paths/admin/create/CreatePage.tsx:124
+#: src/paths/instance/orders/create/CreatePage.tsx:316
+#: src/paths/instance/update/UpdatePage.tsx:126
+#: src/paths/instance/update/UpdatePage.tsx:143
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:164
+#: src/paths/admin/create/CreatePage.tsx:108
+#: src/paths/admin/create/CreatePage.tsx:125
+#: src/paths/instance/orders/create/CreatePage.tsx:317
+#: src/paths/instance/update/UpdatePage.tsx:127
+#: src/paths/instance/update/UpdatePage.tsx:144
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:165
+#: src/paths/admin/create/CreatePage.tsx:109
+#: src/paths/admin/create/CreatePage.tsx:126
+#: src/paths/instance/orders/create/CreatePage.tsx:318
+#: src/paths/instance/update/UpdatePage.tsx:128
+#: src/paths/instance/update/UpdatePage.tsx:145
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:166
+#: src/paths/admin/create/CreatePage.tsx:110
+#: src/paths/admin/create/CreatePage.tsx:127
+#: src/paths/instance/orders/create/CreatePage.tsx:319
+#: src/paths/instance/update/UpdatePage.tsx:129
+#: src/paths/instance/update/UpdatePage.tsx:146
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:167
+#: src/paths/admin/create/CreatePage.tsx:111
+#: src/paths/admin/create/CreatePage.tsx:128
+#: src/paths/instance/orders/create/CreatePage.tsx:320
+#: src/paths/instance/update/UpdatePage.tsx:130
+#: src/paths/instance/update/UpdatePage.tsx:147
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:168
+#: src/paths/admin/create/CreatePage.tsx:112
+#: src/paths/admin/create/CreatePage.tsx:129
+#: src/paths/instance/orders/create/CreatePage.tsx:321
+#: src/paths/instance/update/UpdatePage.tsx:131
+#: src/paths/instance/update/UpdatePage.tsx:148
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:73
+#, c-format
+msgid "this product has no taxes"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:77
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#: src/paths/instance/orders/details/DetailPage.tsx:296
+#: src/paths/instance/orders/list/Table.tsx:116
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:78
+#, c-format
+msgid "currency and value separated with colon"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:84
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:78
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:53
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:59
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:65
+#: src/paths/instance/orders/list/Table.tsx:60
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:71
+#: src/paths/instance/orders/create/CreatePage.tsx:257
+#: src/paths/instance/products/list/Table.tsx:48
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:77
+#: src/paths/instance/transfers/list/Table.tsx:59
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:87
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:112 src/paths/admin/list/Table.tsx:57
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:116
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:122
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:129
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/components/modal/index.tsx:74
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:110 src/components/modal/index.tsx:111
+#, c-format
+msgid "should be the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:111
+#, c-format
+msgid "cannot be the same as before"
+msgstr ""
+
+#: src/components/modal/index.tsx:114
+#, c-format
+msgid ""
+"You are updating the authorization token from instance %1$s with id %2$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:125
+#, c-format
+msgid "New token"
+msgstr ""
+
+#: src/components/modal/index.tsx:127
+#, c-format
+msgid "Clearing the auth token will mean public access to the instance"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:96
+#: src/paths/admin/create/CreatePage.tsx:84 src/paths/admin/list/Table.tsx:109
+#: src/paths/instance/transfers/list/Table.tsx:111
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:98
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:121
+#: src/paths/instance/products/list/Table.tsx:85
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:100
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:123
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:101
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:124
+#: src/paths/instance/products/list/Table.tsx:162
+#: src/paths/instance/products/list/Table.tsx:214
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:103
+#: src/paths/instance/products/list/Table.tsx:90
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:105
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:128
+#: src/paths/instance/products/list/Table.tsx:88
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/index.tsx:75
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/index.tsx:85
+#, c-format
+msgid "Couldn't access the server"
+msgstr ""
+
+#: src/index.tsx:87 src/index.tsx:99
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/index.tsx:97
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:88
+#: src/paths/instance/update/UpdatePage.tsx:107
+#, c-format
+msgid "Auth token"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:90
+#: src/paths/instance/details/DetailPage.tsx:77
+#: src/paths/instance/update/UpdatePage.tsx:109
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:92
+#: src/paths/instance/update/UpdatePage.tsx:111
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#: src/paths/instance/update/UpdatePage.tsx:113
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#: src/paths/instance/update/UpdatePage.tsx:115
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:115
+#: src/paths/instance/update/UpdatePage.tsx:134
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:132
+#: src/paths/instance/update/UpdatePage.tsx:151
+#, c-format
+msgid "Default pay delay"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:134
+#: src/paths/instance/update/UpdatePage.tsx:153
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/paths/admin/create/index.tsx:58
+#, c-format
+msgid "could not create instance"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:63 src/paths/admin/list/Table.tsx:131
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:128
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:149
+#: src/paths/instance/products/list/Table.tsx:245
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:236
+#, c-format
+msgid "Inventory products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:285
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:286
+#, c-format
+msgid "Total tax"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:288
+#: src/paths/instance/orders/create/CreatePage.tsx:296
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:294
+#, c-format
+msgid "Net"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#: src/paths/instance/orders/details/DetailPage.tsx:295
+#: src/paths/instance/orders/list/Table.tsx:117
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:301
+#, c-format
+msgid "Payments options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:302
+#, c-format
+msgid "Auto refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:303
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:304
+#, c-format
+msgid "Pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:306
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:307
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:324
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:325
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:326
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:327
+#, c-format
+msgid "Fullfilment url"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:330
+#, c-format
+msgid "Extra information"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:44
+#, c-format
+msgid "select a product first"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:51
+#, c-format
+msgid "should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:58
+#, c-format
+msgid ""
+"cannot be greater than current stock and quantity previously added. max: %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:64
+#, c-format
+msgid "cannot be greater than current stock %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:76
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:126
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:92
+#: src/paths/instance/orders/details/DetailPage.tsx:235
+#: src/paths/instance/orders/details/DetailPage.tsx:333
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:110
+#: src/paths/instance/orders/details/DetailPage.tsx:261
+#: src/paths/instance/orders/list/Table.tsx:136
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:126
+#: src/paths/instance/orders/details/DetailPage.tsx:349
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:127
+#: src/paths/instance/orders/details/DetailPage.tsx:350
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:138
+#: src/paths/instance/orders/details/DetailPage.tsx:289
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:142
+#: src/paths/instance/orders/details/DetailPage.tsx:293
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:146
+#: src/paths/instance/orders/details/DetailPage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:363
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:156
+#: src/paths/instance/orders/details/DetailPage.tsx:308
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:236
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:238
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:241
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:258
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:297
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:298
+#, c-format
+msgid "Deposit total"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:336
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:364
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:365
+#, c-format
+msgid "Pay URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:383
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:56
+#: src/paths/instance/orders/list/index.tsx:147
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:59
+#: src/paths/instance/orders/list/index.tsx:150
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:111
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:115
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:131
+#: src/paths/instance/orders/list/Table.tsx:223
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:145
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "No orders has been found"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:202
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:203
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:204
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:224
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:91
+#, c-format
+msgid "go to order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:107
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:108
+#, c-format
+msgid "Refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:109
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:110
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:48
+#: src/paths/instance/products/update/index.tsx:64
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:87
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:89
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:91
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:59
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:62
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:70
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:73
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:59
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:111
+#, c-format
+msgid "Committed amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:112
+#, c-format
+msgid "Exchange initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:113
+#, c-format
+msgid "Merchant initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:148
+#, c-format
+msgid "There is no tips yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:147
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
diff --git a/packages/frontend/src/i18n/index.tsx 
b/packages/frontend/src/i18n/index.tsx
new file mode 100644
index 0000000..3a304a0
--- /dev/null
+++ b/packages/frontend/src/i18n/index.tsx
@@ -0,0 +1,204 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 { Component, ComponentChild, ComponentChildren, h, Fragment, VNode } 
from "preact";
+
+import { useTranslationContext } from "../context/translation";
+
+export function useTranslator() {
+  const ctx = useTranslationContext();
+  const jed = ctx.handler
+  return function str(stringSeq: TemplateStringsArray, ...values: any[]): 
string {
+    const s = toI18nString(stringSeq);
+    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();
+  // console.log("translation lookup", JSON.stringify(s));
+  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 <>{result}</>;
+}
+
+/**
+ * Switch translation based on singular or plural based on the target prop.
+ * Should only contain TranslateSingular and TransplatePlural as children.
+ *
+ * Example:
+ * ```
+ * <TranslateSwitch target={n}>
+ *  <TranslateSingular>I have {n} apple.</TranslateSingular>
+ *  <TranslatePlural>I have {n} apples.</TranslatePlural>
+ * </TranslateSwitch>
+ * ```
+ */
+export 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 <>{result}</>;
+}
+
+/**
+ * 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 <>{result}</>;
+
+}
diff --git a/packages/frontend/src/i18n/it.po b/packages/frontend/src/i18n/it.po
new file mode 100644
index 0000000..694798f
--- /dev/null
+++ b/packages/frontend/src/i18n/it.po
@@ -0,0 +1,1010 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/ApplicationReadyRoutes.tsx:50 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:293
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:51 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:294
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:72
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:73
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:108
+#, c-format
+msgid "HTTP status #%1$s: Server reported a problem"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:109
+#, c-format
+msgid "Got message: \"%1$s\" from: %2$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:126
+#, c-format
+msgid "No default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:127
+#, c-format
+msgid ""
+"in order to use merchant backoffice, you should create the default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:282
+#, c-format
+msgid "Server reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:283
+#, c-format
+msgid "Got message: %1$s from: %2$s"
+msgstr ""
+
+#: src/components/exception/login.tsx:46
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:49
+#, c-format
+msgid ""
+"Please enter your auth token. Token should have \"secret-token:\" and start "
+"with Bearer or ApiKey"
+msgstr ""
+
+#: src/components/exception/login.tsx:86 src/components/modal/index.tsx:53
+#: src/components/modal/index.tsx:75 src/paths/admin/create/CreatePage.tsx:140
+#: src/paths/instance/orders/create/CreatePage.tsx:337
+#: src/paths/instance/products/create/CreatePage.tsx:51
+#: src/paths/instance/products/list/Table.tsx:174
+#: src/paths/instance/products/list/Table.tsx:228
+#: src/paths/instance/products/update/UpdatePage.tsx:55
+#: src/paths/instance/update/UpdatePage.tsx:159
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:72
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:67
+#: src/paths/instance/orders/list/index.tsx:123
+#, c-format
+msgid "pick a date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:81
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:83
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:80
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:59
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:60
+#: src/components/product/ProductForm.tsx:99
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:122
+#: src/paths/instance/orders/list/Table.tsx:227
+#: src/paths/instance/products/list/Table.tsx:86
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:73
+#: src/components/form/InputTaxes.tsx:81
+#: src/paths/admin/create/CreatePage.tsx:86 src/paths/admin/list/Table.tsx:110
+#: src/paths/instance/details/DetailPage.tsx:76
+#: src/paths/instance/transfers/list/Table.tsx:112
+#: src/paths/instance/update/UpdatePage.tsx:105
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:102
+#, c-format
+msgid "loading..."
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:108
+#, c-format
+msgid "no products found"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:116
+#, c-format
+msgid "no results"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:33
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:34
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:60
+#, c-format
+msgid "Manage token"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:83
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:100
+#: src/paths/instance/orders/create/CreatePage.tsx:251
+#: src/paths/instance/orders/create/CreatePage.tsx:272
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:106 src/components/modal/index.tsx:52
+#: src/components/modal/index.tsx:73 src/paths/admin/create/CreatePage.tsx:139
+#: src/paths/instance/orders/create/CreatePage.tsx:336
+#: src/paths/instance/products/create/CreatePage.tsx:50
+#: src/paths/instance/products/list/Table.tsx:166
+#: src/paths/instance/products/list/Table.tsx:218
+#: src/paths/instance/products/update/UpdatePage.tsx:54
+#: src/paths/instance/update/UpdatePage.tsx:158
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:90
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:92
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:104
+#, c-format
+msgid "lost cannot be greater that current + incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:110
+#, c-format
+msgid "current stock will change from %1$s to %2$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:111
+#, c-format
+msgid "current stock will stay at %1$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:128
+#: src/paths/instance/products/list/Table.tsx:204
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:129
+#: src/paths/instance/products/list/Table.tsx:205
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:141
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:144
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:149
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:151
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:153
+#: src/paths/admin/create/CreatePage.tsx:99
+#: src/paths/admin/create/CreatePage.tsx:116
+#: src/paths/instance/orders/create/CreatePage.tsx:308
+#: src/paths/instance/update/UpdatePage.tsx:118
+#: src/paths/instance/update/UpdatePage.tsx:135
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:156
+#: src/paths/admin/create/CreatePage.tsx:98
+#: src/paths/admin/create/CreatePage.tsx:101
+#: src/paths/admin/create/CreatePage.tsx:118
+#: src/paths/instance/orders/create/CreatePage.tsx:310
+#: src/paths/instance/update/UpdatePage.tsx:117
+#: src/paths/instance/update/UpdatePage.tsx:120
+#: src/paths/instance/update/UpdatePage.tsx:137
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:161
+#: src/paths/admin/create/CreatePage.tsx:105
+#: src/paths/admin/create/CreatePage.tsx:122
+#: src/paths/instance/orders/create/CreatePage.tsx:314
+#: src/paths/instance/update/UpdatePage.tsx:124
+#: src/paths/instance/update/UpdatePage.tsx:141
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:162
+#: src/paths/admin/create/CreatePage.tsx:106
+#: src/paths/admin/create/CreatePage.tsx:123
+#: src/paths/instance/orders/create/CreatePage.tsx:315
+#: src/paths/instance/update/UpdatePage.tsx:125
+#: src/paths/instance/update/UpdatePage.tsx:142
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:163
+#: src/paths/admin/create/CreatePage.tsx:107
+#: src/paths/admin/create/CreatePage.tsx:124
+#: src/paths/instance/orders/create/CreatePage.tsx:316
+#: src/paths/instance/update/UpdatePage.tsx:126
+#: src/paths/instance/update/UpdatePage.tsx:143
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:164
+#: src/paths/admin/create/CreatePage.tsx:108
+#: src/paths/admin/create/CreatePage.tsx:125
+#: src/paths/instance/orders/create/CreatePage.tsx:317
+#: src/paths/instance/update/UpdatePage.tsx:127
+#: src/paths/instance/update/UpdatePage.tsx:144
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:165
+#: src/paths/admin/create/CreatePage.tsx:109
+#: src/paths/admin/create/CreatePage.tsx:126
+#: src/paths/instance/orders/create/CreatePage.tsx:318
+#: src/paths/instance/update/UpdatePage.tsx:128
+#: src/paths/instance/update/UpdatePage.tsx:145
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:166
+#: src/paths/admin/create/CreatePage.tsx:110
+#: src/paths/admin/create/CreatePage.tsx:127
+#: src/paths/instance/orders/create/CreatePage.tsx:319
+#: src/paths/instance/update/UpdatePage.tsx:129
+#: src/paths/instance/update/UpdatePage.tsx:146
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:167
+#: src/paths/admin/create/CreatePage.tsx:111
+#: src/paths/admin/create/CreatePage.tsx:128
+#: src/paths/instance/orders/create/CreatePage.tsx:320
+#: src/paths/instance/update/UpdatePage.tsx:130
+#: src/paths/instance/update/UpdatePage.tsx:147
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:168
+#: src/paths/admin/create/CreatePage.tsx:112
+#: src/paths/admin/create/CreatePage.tsx:129
+#: src/paths/instance/orders/create/CreatePage.tsx:321
+#: src/paths/instance/update/UpdatePage.tsx:131
+#: src/paths/instance/update/UpdatePage.tsx:148
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:73
+#, c-format
+msgid "this product has no taxes"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:77
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#: src/paths/instance/orders/details/DetailPage.tsx:296
+#: src/paths/instance/orders/list/Table.tsx:116
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:78
+#, c-format
+msgid "currency and value separated with colon"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:84
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:78
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:53
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:59
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:65
+#: src/paths/instance/orders/list/Table.tsx:60
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:71
+#: src/paths/instance/orders/create/CreatePage.tsx:257
+#: src/paths/instance/products/list/Table.tsx:48
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:77
+#: src/paths/instance/transfers/list/Table.tsx:59
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:87
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:112 src/paths/admin/list/Table.tsx:57
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:116
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:122
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:129
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/components/modal/index.tsx:74
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:110 src/components/modal/index.tsx:111
+#, c-format
+msgid "should be the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:111
+#, c-format
+msgid "cannot be the same as before"
+msgstr ""
+
+#: src/components/modal/index.tsx:114
+#, c-format
+msgid ""
+"You are updating the authorization token from instance %1$s with id %2$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:125
+#, c-format
+msgid "New token"
+msgstr ""
+
+#: src/components/modal/index.tsx:127
+#, c-format
+msgid "Clearing the auth token will mean public access to the instance"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:96
+#: src/paths/admin/create/CreatePage.tsx:84 src/paths/admin/list/Table.tsx:109
+#: src/paths/instance/transfers/list/Table.tsx:111
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:98
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:121
+#: src/paths/instance/products/list/Table.tsx:85
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:100
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:123
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:101
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:124
+#: src/paths/instance/products/list/Table.tsx:162
+#: src/paths/instance/products/list/Table.tsx:214
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:103
+#: src/paths/instance/products/list/Table.tsx:90
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:105
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:128
+#: src/paths/instance/products/list/Table.tsx:88
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/index.tsx:75
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/index.tsx:85
+#, c-format
+msgid "Couldn't access the server"
+msgstr ""
+
+#: src/index.tsx:87 src/index.tsx:99
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/index.tsx:97
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:88
+#: src/paths/instance/update/UpdatePage.tsx:107
+#, c-format
+msgid "Auth token"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:90
+#: src/paths/instance/details/DetailPage.tsx:77
+#: src/paths/instance/update/UpdatePage.tsx:109
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:92
+#: src/paths/instance/update/UpdatePage.tsx:111
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#: src/paths/instance/update/UpdatePage.tsx:113
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#: src/paths/instance/update/UpdatePage.tsx:115
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:115
+#: src/paths/instance/update/UpdatePage.tsx:134
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:132
+#: src/paths/instance/update/UpdatePage.tsx:151
+#, c-format
+msgid "Default pay delay"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:134
+#: src/paths/instance/update/UpdatePage.tsx:153
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/paths/admin/create/index.tsx:58
+#, c-format
+msgid "could not create instance"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:63 src/paths/admin/list/Table.tsx:131
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:128
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:149
+#: src/paths/instance/products/list/Table.tsx:245
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:236
+#, c-format
+msgid "Inventory products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:285
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:286
+#, c-format
+msgid "Total tax"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:288
+#: src/paths/instance/orders/create/CreatePage.tsx:296
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:294
+#, c-format
+msgid "Net"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#: src/paths/instance/orders/details/DetailPage.tsx:295
+#: src/paths/instance/orders/list/Table.tsx:117
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:301
+#, c-format
+msgid "Payments options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:302
+#, c-format
+msgid "Auto refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:303
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:304
+#, c-format
+msgid "Pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:306
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:307
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:324
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:325
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:326
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:327
+#, c-format
+msgid "Fullfilment url"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:330
+#, c-format
+msgid "Extra information"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:44
+#, c-format
+msgid "select a product first"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:51
+#, c-format
+msgid "should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:58
+#, c-format
+msgid ""
+"cannot be greater than current stock and quantity previously added. max: %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:64
+#, c-format
+msgid "cannot be greater than current stock %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:76
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:126
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:92
+#: src/paths/instance/orders/details/DetailPage.tsx:235
+#: src/paths/instance/orders/details/DetailPage.tsx:333
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:110
+#: src/paths/instance/orders/details/DetailPage.tsx:261
+#: src/paths/instance/orders/list/Table.tsx:136
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:126
+#: src/paths/instance/orders/details/DetailPage.tsx:349
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:127
+#: src/paths/instance/orders/details/DetailPage.tsx:350
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:138
+#: src/paths/instance/orders/details/DetailPage.tsx:289
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:142
+#: src/paths/instance/orders/details/DetailPage.tsx:293
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:146
+#: src/paths/instance/orders/details/DetailPage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:363
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:156
+#: src/paths/instance/orders/details/DetailPage.tsx:308
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:236
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:238
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:241
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:258
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:297
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:298
+#, c-format
+msgid "Deposit total"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:336
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:364
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:365
+#, c-format
+msgid "Pay URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:383
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:56
+#: src/paths/instance/orders/list/index.tsx:147
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:59
+#: src/paths/instance/orders/list/index.tsx:150
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:111
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:115
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:131
+#: src/paths/instance/orders/list/Table.tsx:223
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:145
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "No orders has been found"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:202
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:203
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:204
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:224
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:91
+#, c-format
+msgid "go to order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:107
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:108
+#, c-format
+msgid "Refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:109
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:110
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:48
+#: src/paths/instance/products/update/index.tsx:64
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:87
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:89
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:91
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:59
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:62
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:70
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:73
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:59
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:111
+#, c-format
+msgid "Committed amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:112
+#, c-format
+msgid "Exchange initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:113
+#, c-format
+msgid "Merchant initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:148
+#, c-format
+msgid "There is no tips yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:147
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
diff --git a/packages/frontend/src/i18n/poheader 
b/packages/frontend/src/i18n/poheader
new file mode 100644
index 0000000..ee3fcd7
--- /dev/null
+++ b/packages/frontend/src/i18n/poheader
@@ -0,0 +1,27 @@
+#  This file is part of GNU Taler
+#  (C) 2021 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/>
+
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: taler@gnu.org\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
diff --git a/packages/frontend/src/messages/index.ts 
b/packages/frontend/src/i18n/strings-prelude
similarity index 87%
rename from packages/frontend/src/messages/index.ts
rename to packages/frontend/src/i18n/strings-prelude
index f060157..cca13af 100644
--- a/packages/frontend/src/messages/index.ts
+++ b/packages/frontend/src/i18n/strings-prelude
@@ -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/>
  */
-export * as en from './en.po'
-export * as es from './es.po'
+
+/*eslint quote-props: ["error", "consistent"]*/
+export const strings: {[s: string]: any} = {};
 
diff --git a/packages/frontend/src/i18n/strings.ts 
b/packages/frontend/src/i18n/strings.ts
new file mode 100644
index 0000000..a167540
--- /dev/null
+++ b/packages/frontend/src/i18n/strings.ts
@@ -0,0 +1,3139 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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/>
+ */
+
+/*eslint quote-props: ["error", "consistent"]*/
+export const strings: {[s: string]: any} = {};
+
+strings['de'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Access denied": [
+        ""
+      ],
+      "Check your token is valid": [
+        ""
+      ],
+      "Couldn't access the server.": [
+        ""
+      ],
+      "Could not infer instance id from url %1$s": [
+        ""
+      ],
+      "HTTP status #%1$s: Server reported a problem": [
+        ""
+      ],
+      "Got message: \"%1$s\" from: %2$s": [
+        ""
+      ],
+      "No default instance": [
+        ""
+      ],
+      "in order to use merchant backoffice, you should create the default 
instance": [
+        ""
+      ],
+      "Server reported a problem: HTTP status #%1$s": [
+        ""
+      ],
+      "Got message: %1$s from: %2$s": [
+        ""
+      ],
+      "Login required": [
+        ""
+      ],
+      "Please enter your auth token. Token should have \"secret-token:\" and 
start with Bearer or ApiKey": [
+        ""
+      ],
+      "Confirm": [
+        ""
+      ],
+      "The value %1$s is invalid for a payment url": [
+        ""
+      ],
+      "pick a date": [
+        ""
+      ],
+      "clear": [
+        ""
+      ],
+      "never": [
+        ""
+      ],
+      "Image should be smaller than 1 MB": [
+        ""
+      ],
+      "Product id": [
+        ""
+      ],
+      "Description": [
+        ""
+      ],
+      "Name": [
+        ""
+      ],
+      "loading...": [
+        ""
+      ],
+      "no products found": [
+        ""
+      ],
+      "no results": [
+        ""
+      ],
+      "Deleting": [
+        ""
+      ],
+      "Changing": [
+        ""
+      ],
+      "Manage token": [
+        ""
+      ],
+      "Update": [
+        ""
+      ],
+      "Remove": [
+        ""
+      ],
+      "Cancel": [
+        ""
+      ],
+      "Manage stock": [
+        ""
+      ],
+      "Infinite": [
+        ""
+      ],
+      "lost cannot be greater that current + incoming (max %1$s)": [
+        ""
+      ],
+      "current stock will change from %1$s to %2$s": [
+        ""
+      ],
+      "current stock will stay at %1$s": [
+        ""
+      ],
+      "Incoming": [
+        ""
+      ],
+      "Lost": [
+        ""
+      ],
+      "Current": [
+        ""
+      ],
+      "without stock": [
+        ""
+      ],
+      "Next restock": [
+        ""
+      ],
+      "Delivery address": [
+        ""
+      ],
+      "Country": [
+        ""
+      ],
+      "Address": [
+        ""
+      ],
+      "Building number": [
+        ""
+      ],
+      "Building name": [
+        ""
+      ],
+      "Street": [
+        ""
+      ],
+      "Post code": [
+        ""
+      ],
+      "Town location": [
+        ""
+      ],
+      "Town": [
+        ""
+      ],
+      "District": [
+        ""
+      ],
+      "Country subdivision": [
+        ""
+      ],
+      "this product has no taxes": [
+        ""
+      ],
+      "Amount": [
+        ""
+      ],
+      "currency and value separated with colon": [
+        ""
+      ],
+      "Add": [
+        ""
+      ],
+      "Instance": [
+        ""
+      ],
+      "Settings": [
+        ""
+      ],
+      "Orders": [
+        ""
+      ],
+      "Products": [
+        ""
+      ],
+      "Transfers": [
+        ""
+      ],
+      "Connection": [
+        ""
+      ],
+      "Instances": [
+        ""
+      ],
+      "New": [
+        ""
+      ],
+      "List": [
+        ""
+      ],
+      "Log out": [
+        ""
+      ],
+      "Clear": [
+        ""
+      ],
+      "should be the same": [
+        ""
+      ],
+      "cannot be the same as before": [
+        ""
+      ],
+      "You are updating the authorization token from instance %1$s with id 
%2$s": [
+        ""
+      ],
+      "Old token": [
+        ""
+      ],
+      "New token": [
+        ""
+      ],
+      "Clearing the auth token will mean public access to the instance": [
+        ""
+      ],
+      "ID": [
+        ""
+      ],
+      "Image": [
+        ""
+      ],
+      "Unit": [
+        ""
+      ],
+      "Price": [
+        ""
+      ],
+      "Stock": [
+        ""
+      ],
+      "Taxes": [
+        ""
+      ],
+      "Server not found": [
+        ""
+      ],
+      "Couldn't access the server": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        ""
+      ],
+      "Auth token": [
+        ""
+      ],
+      "Account address": [
+        ""
+      ],
+      "Default max deposit fee": [
+        ""
+      ],
+      "Default max wire fee": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        ""
+      ],
+      "Jurisdiction": [
+        ""
+      ],
+      "Default pay delay": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        ""
+      ],
+      "could not create instance": [
+        ""
+      ],
+      "Delete": [
+        ""
+      ],
+      "Edit": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        ""
+      ],
+      "Inventory products": [
+        ""
+      ],
+      "Total price": [
+        ""
+      ],
+      "Total tax": [
+        ""
+      ],
+      "Order price": [
+        ""
+      ],
+      "Net": [
+        ""
+      ],
+      "Summary": [
+        ""
+      ],
+      "Payments options": [
+        ""
+      ],
+      "Auto refund deadline": [
+        ""
+      ],
+      "Refund deadline": [
+        ""
+      ],
+      "Pay deadline": [
+        ""
+      ],
+      "Delivery date": [
+        ""
+      ],
+      "Location": [
+        ""
+      ],
+      "Max fee": [
+        ""
+      ],
+      "Max wire fee": [
+        ""
+      ],
+      "Wire fee amortization": [
+        ""
+      ],
+      "Fullfilment url": [
+        ""
+      ],
+      "Extra information": [
+        ""
+      ],
+      "select a product first": [
+        ""
+      ],
+      "should be greater than 0": [
+        ""
+      ],
+      "cannot be greater than current stock and quantity previously added. 
max: %1$s": [
+        ""
+      ],
+      "cannot be greater than current stock %1$s": [
+        ""
+      ],
+      "Quantity": [
+        ""
+      ],
+      "Order": [
+        ""
+      ],
+      "claimed": [
+        ""
+      ],
+      "copy url": [
+        ""
+      ],
+      "pay at": [
+        ""
+      ],
+      "created at": [
+        ""
+      ],
+      "Timeline": [
+        ""
+      ],
+      "Payment details": [
+        ""
+      ],
+      "Order status": [
+        ""
+      ],
+      "Product list": [
+        ""
+      ],
+      "paid": [
+        ""
+      ],
+      "wired": [
+        ""
+      ],
+      "refunded": [
+        ""
+      ],
+      "refund": [
+        ""
+      ],
+      "Refunded amount": [
+        ""
+      ],
+      "Deposit total": [
+        ""
+      ],
+      "unpaid": [
+        ""
+      ],
+      "Order status URL": [
+        ""
+      ],
+      "Pay URI": [
+        ""
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        ""
+      ],
+      "refund created successfully": [
+        ""
+      ],
+      "could not create the refund": [
+        ""
+      ],
+      "load newer orders": [
+        ""
+      ],
+      "Date": [
+        ""
+      ],
+      "Refund": [
+        ""
+      ],
+      "load older orders": [
+        ""
+      ],
+      "No orders has been found": [
+        ""
+      ],
+      "date": [
+        ""
+      ],
+      "amount": [
+        ""
+      ],
+      "reason": [
+        ""
+      ],
+      "Max refundable:": [
+        ""
+      ],
+      "Reason": [
+        ""
+      ],
+      "duplicated": [
+        ""
+      ],
+      "requested by the customer": [
+        ""
+      ],
+      "other": [
+        ""
+      ],
+      "go to order id": [
+        ""
+      ],
+      "Paid": [
+        ""
+      ],
+      "Refunded": [
+        ""
+      ],
+      "Not wired": [
+        ""
+      ],
+      "All": [
+        ""
+      ],
+      "could not create product": [
+        ""
+      ],
+      "Sell": [
+        ""
+      ],
+      "Profit": [
+        ""
+      ],
+      "Sold": [
+        ""
+      ],
+      "product updated successfully": [
+        ""
+      ],
+      "could not update the product": [
+        ""
+      ],
+      "product delete successfully": [
+        ""
+      ],
+      "could not delete the product": [
+        ""
+      ],
+      "Tips": [
+        ""
+      ],
+      "Committed amount": [
+        ""
+      ],
+      "Exchange initial amount": [
+        ""
+      ],
+      "Merchant initial amount": [
+        ""
+      ],
+      "There is no tips yet, add more pressing the + sign": [
+        ""
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        ""
+      ]
+    }
+  }
+};
+
+strings['en'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Access denied": [
+        ""
+      ],
+      "Check your token is valid": [
+        ""
+      ],
+      "Couldn't access the server.": [
+        ""
+      ],
+      "Could not infer instance id from url %1$s": [
+        ""
+      ],
+      "HTTP status #%1$s: Server reported a problem": [
+        ""
+      ],
+      "Got message: \"%1$s\" from: %2$s": [
+        ""
+      ],
+      "No default instance": [
+        ""
+      ],
+      "in order to use merchant backoffice, you should create the default 
instance": [
+        ""
+      ],
+      "Server reported a problem: HTTP status #%1$s": [
+        ""
+      ],
+      "Got message: %1$s from: %2$s": [
+        ""
+      ],
+      "Login required": [
+        ""
+      ],
+      "Please enter your auth token. Token should have \"secret-token:\" and 
start with Bearer or ApiKey": [
+        ""
+      ],
+      "Confirm": [
+        ""
+      ],
+      "The value %1$s is invalid for a payment url": [
+        ""
+      ],
+      "pick a date": [
+        ""
+      ],
+      "clear": [
+        ""
+      ],
+      "never": [
+        ""
+      ],
+      "Image should be smaller than 1 MB": [
+        ""
+      ],
+      "Product id": [
+        ""
+      ],
+      "Description": [
+        ""
+      ],
+      "Name": [
+        ""
+      ],
+      "loading...": [
+        ""
+      ],
+      "no products found": [
+        ""
+      ],
+      "no results": [
+        ""
+      ],
+      "Deleting": [
+        ""
+      ],
+      "Changing": [
+        ""
+      ],
+      "Manage token": [
+        ""
+      ],
+      "Update": [
+        ""
+      ],
+      "Remove": [
+        ""
+      ],
+      "Cancel": [
+        ""
+      ],
+      "Manage stock": [
+        ""
+      ],
+      "Infinite": [
+        ""
+      ],
+      "lost cannot be greater that current + incoming (max %1$s)": [
+        ""
+      ],
+      "current stock will change from %1$s to %2$s": [
+        ""
+      ],
+      "current stock will stay at %1$s": [
+        ""
+      ],
+      "Incoming": [
+        ""
+      ],
+      "Lost": [
+        ""
+      ],
+      "Current": [
+        ""
+      ],
+      "without stock": [
+        ""
+      ],
+      "Next restock": [
+        ""
+      ],
+      "Delivery address": [
+        ""
+      ],
+      "Country": [
+        ""
+      ],
+      "Address": [
+        ""
+      ],
+      "Building number": [
+        ""
+      ],
+      "Building name": [
+        ""
+      ],
+      "Street": [
+        ""
+      ],
+      "Post code": [
+        ""
+      ],
+      "Town location": [
+        ""
+      ],
+      "Town": [
+        ""
+      ],
+      "District": [
+        ""
+      ],
+      "Country subdivision": [
+        ""
+      ],
+      "this product has no taxes": [
+        ""
+      ],
+      "Amount": [
+        ""
+      ],
+      "currency and value separated with colon": [
+        ""
+      ],
+      "Add": [
+        ""
+      ],
+      "Instance": [
+        ""
+      ],
+      "Settings": [
+        ""
+      ],
+      "Orders": [
+        ""
+      ],
+      "Products": [
+        ""
+      ],
+      "Transfers": [
+        ""
+      ],
+      "Connection": [
+        ""
+      ],
+      "Instances": [
+        ""
+      ],
+      "New": [
+        ""
+      ],
+      "List": [
+        ""
+      ],
+      "Log out": [
+        ""
+      ],
+      "Clear": [
+        ""
+      ],
+      "should be the same": [
+        ""
+      ],
+      "cannot be the same as before": [
+        ""
+      ],
+      "You are updating the authorization token from instance %1$s with id 
%2$s": [
+        ""
+      ],
+      "Old token": [
+        ""
+      ],
+      "New token": [
+        ""
+      ],
+      "Clearing the auth token will mean public access to the instance": [
+        ""
+      ],
+      "ID": [
+        ""
+      ],
+      "Image": [
+        ""
+      ],
+      "Unit": [
+        ""
+      ],
+      "Price": [
+        ""
+      ],
+      "Stock": [
+        ""
+      ],
+      "Taxes": [
+        ""
+      ],
+      "Server not found": [
+        ""
+      ],
+      "Couldn't access the server": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        ""
+      ],
+      "Auth token": [
+        ""
+      ],
+      "Account address": [
+        ""
+      ],
+      "Default max deposit fee": [
+        ""
+      ],
+      "Default max wire fee": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        ""
+      ],
+      "Jurisdiction": [
+        ""
+      ],
+      "Default pay delay": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        ""
+      ],
+      "could not create instance": [
+        ""
+      ],
+      "Delete": [
+        ""
+      ],
+      "Edit": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        ""
+      ],
+      "Inventory products": [
+        ""
+      ],
+      "Total price": [
+        ""
+      ],
+      "Total tax": [
+        ""
+      ],
+      "Order price": [
+        ""
+      ],
+      "Net": [
+        ""
+      ],
+      "Summary": [
+        ""
+      ],
+      "Payments options": [
+        ""
+      ],
+      "Auto refund deadline": [
+        ""
+      ],
+      "Refund deadline": [
+        ""
+      ],
+      "Pay deadline": [
+        ""
+      ],
+      "Delivery date": [
+        ""
+      ],
+      "Location": [
+        ""
+      ],
+      "Max fee": [
+        ""
+      ],
+      "Max wire fee": [
+        ""
+      ],
+      "Wire fee amortization": [
+        ""
+      ],
+      "Fullfilment url": [
+        ""
+      ],
+      "Extra information": [
+        ""
+      ],
+      "select a product first": [
+        ""
+      ],
+      "should be greater than 0": [
+        ""
+      ],
+      "cannot be greater than current stock and quantity previously added. 
max: %1$s": [
+        ""
+      ],
+      "cannot be greater than current stock %1$s": [
+        ""
+      ],
+      "Quantity": [
+        ""
+      ],
+      "Order": [
+        ""
+      ],
+      "claimed": [
+        ""
+      ],
+      "copy url": [
+        ""
+      ],
+      "pay at": [
+        ""
+      ],
+      "created at": [
+        ""
+      ],
+      "Timeline": [
+        ""
+      ],
+      "Payment details": [
+        ""
+      ],
+      "Order status": [
+        ""
+      ],
+      "Product list": [
+        ""
+      ],
+      "paid": [
+        ""
+      ],
+      "wired": [
+        ""
+      ],
+      "refunded": [
+        ""
+      ],
+      "refund": [
+        ""
+      ],
+      "Refunded amount": [
+        ""
+      ],
+      "Deposit total": [
+        ""
+      ],
+      "unpaid": [
+        ""
+      ],
+      "Order status URL": [
+        ""
+      ],
+      "Pay URI": [
+        ""
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        ""
+      ],
+      "refund created successfully": [
+        ""
+      ],
+      "could not create the refund": [
+        ""
+      ],
+      "load newer orders": [
+        ""
+      ],
+      "Date": [
+        ""
+      ],
+      "Refund": [
+        ""
+      ],
+      "load older orders": [
+        ""
+      ],
+      "No orders has been found": [
+        ""
+      ],
+      "date": [
+        ""
+      ],
+      "amount": [
+        ""
+      ],
+      "reason": [
+        ""
+      ],
+      "Max refundable:": [
+        ""
+      ],
+      "Reason": [
+        ""
+      ],
+      "duplicated": [
+        ""
+      ],
+      "requested by the customer": [
+        ""
+      ],
+      "other": [
+        ""
+      ],
+      "go to order id": [
+        ""
+      ],
+      "Paid": [
+        ""
+      ],
+      "Refunded": [
+        ""
+      ],
+      "Not wired": [
+        ""
+      ],
+      "All": [
+        ""
+      ],
+      "could not create product": [
+        ""
+      ],
+      "Sell": [
+        ""
+      ],
+      "Profit": [
+        ""
+      ],
+      "Sold": [
+        ""
+      ],
+      "product updated successfully": [
+        ""
+      ],
+      "could not update the product": [
+        ""
+      ],
+      "product delete successfully": [
+        ""
+      ],
+      "could not delete the product": [
+        ""
+      ],
+      "Tips": [
+        ""
+      ],
+      "Committed amount": [
+        ""
+      ],
+      "Exchange initial amount": [
+        ""
+      ],
+      "Merchant initial amount": [
+        ""
+      ],
+      "There is no tips yet, add more pressing the + sign": [
+        ""
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        ""
+      ]
+    }
+  }
+};
+
+strings['es'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Access denied": [
+        "Acceso denegado"
+      ],
+      "Check your token is valid": [
+        "Verifica que el token sea valido"
+      ],
+      "Couldn't access the server.": [
+        "No se pudo acceder al servidor"
+      ],
+      "Could not infer instance id from url %1$s": [
+        "No se pudo inferir el id de la instancia con la url %1$s"
+      ],
+      "HTTP status #%1$s: Server reported a problem": [
+        "HTTP status #%1$s: Servidor reporto un problema"
+      ],
+      "Got message: \"%1$s\" from: %2$s": [
+        "Recivimos el mensaje %1$s desde %2$s"
+      ],
+      "No default instance": [
+        "Sin instancia default"
+      ],
+      "in order to use merchant backoffice, you should create the default 
instance": [
+        "para usar el merchant backoffice, debería crear la instancia default"
+      ],
+      "Server reported a problem: HTTP status #%1$s": [
+        "Servidir reporto un problema: HTTP status #%1$s"
+      ],
+      "Got message: %1$s from: %2$s": [
+        "Recivimos el mensaje %1$s desde %2$s"
+      ],
+      "Login required": [
+        "Login necesario"
+      ],
+      "Please enter your auth token. Token should have \"secret-token:\" and 
start with Bearer or ApiKey": [
+        "Por favor ingrese su token de autorización. El token debe tener 
\"secret-token\" y comenzar con Bearer o ApiKey"
+      ],
+      "Confirm": [
+        "Confirmar"
+      ],
+      "The value %1$s is invalid for a payment url": [
+        "El valor %1$s es invalido para una URL de pago"
+      ],
+      "pick a date": [
+        "elegir una fecha"
+      ],
+      "clear": [
+        "Limpiar"
+      ],
+      "never": [
+        "nunca"
+      ],
+      "Image should be smaller than 1 MB": [
+        "La imagen debe ser mas chica que 1 MB"
+      ],
+      "Product id": [
+        "Id de producto"
+      ],
+      "Description": [
+        "Descripcion"
+      ],
+      "Name": [
+        "Nombre"
+      ],
+      "loading...": [
+        "Cargando..."
+      ],
+      "no products found": [
+        "No se encontraron productos"
+      ],
+      "no results": [
+        "Sin resultados"
+      ],
+      "Deleting": [
+        "Borrando"
+      ],
+      "Changing": [
+        "Cambiando"
+      ],
+      "Manage token": [
+        "Administrar token"
+      ],
+      "Update": [
+        "Actualizar"
+      ],
+      "Remove": [
+        "Eliminar"
+      ],
+      "Cancel": [
+        "Cancelar"
+      ],
+      "Manage stock": [
+        "Administrar stock"
+      ],
+      "Infinite": [
+        "Inifinito"
+      ],
+      "lost cannot be greater that current + incoming (max %1$s)": [
+        "no puede ser mayor al stock actual %1$s"
+      ],
+      "current stock will change from %1$s to %2$s": [
+        "stock actual cambiará desde %1$s a %2$s"
+      ],
+      "current stock will stay at %1$s": [
+        "stock actual seguirá en %1$s"
+      ],
+      "Incoming": [
+        "Ingresando"
+      ],
+      "Lost": [
+        "Perdido"
+      ],
+      "Current": [
+        "Actual"
+      ],
+      "without stock": [
+        "sin stock"
+      ],
+      "Next restock": [
+        "Próximo reabastecimiento"
+      ],
+      "Delivery address": [
+        "Dirección de entrega"
+      ],
+      "Country": [
+        "País"
+      ],
+      "Address": [
+        "Dirección"
+      ],
+      "Building number": [
+        "Número de edificio"
+      ],
+      "Building name": [
+        "Nombre de edificio"
+      ],
+      "Street": [
+        "Calle"
+      ],
+      "Post code": [
+        "Código postal"
+      ],
+      "Town location": [
+        "Ubicación de ciudad"
+      ],
+      "Town": [
+        "Ciudad"
+      ],
+      "District": [
+        "Distrito"
+      ],
+      "Country subdivision": [
+        "Provincia"
+      ],
+      "this product has no taxes": [
+        "este producto no tiene impuestos"
+      ],
+      "Amount": [
+        "Monto"
+      ],
+      "currency and value separated with colon": [
+        "Moneda y valor separado por dos puntos"
+      ],
+      "Add": [
+        "Agregar"
+      ],
+      "Instance": [
+        "Instancia"
+      ],
+      "Settings": [
+        "Configuración"
+      ],
+      "Orders": [
+        "Ordenes"
+      ],
+      "Products": [
+        "Productos"
+      ],
+      "Transfers": [
+        "Transferencias"
+      ],
+      "Connection": [
+        "Conexión"
+      ],
+      "Instances": [
+        "Instancias"
+      ],
+      "New": [
+        "Nuevo"
+      ],
+      "List": [
+        "Lista"
+      ],
+      "Log out": [
+        "Salir"
+      ],
+      "Clear": [
+        "Limpiar"
+      ],
+      "should be the same": [
+        "deberían ser iguales"
+      ],
+      "cannot be the same as before": [
+        "no puede ser igual al anterior"
+      ],
+      "You are updating the authorization token from instance %1$s with id 
%2$s": [
+        "Está actualizando el token de autorización para la instancia %1$s con 
id %2$s"
+      ],
+      "Old token": [
+        "Viejo token"
+      ],
+      "New token": [
+        "Nuevo token"
+      ],
+      "Clearing the auth token will mean public access to the instance": [
+        "Limpiar el token de autorización significa acceso publico a la 
instancia"
+      ],
+      "ID": [
+        "ID"
+      ],
+      "Image": [
+        "Imagen"
+      ],
+      "Unit": [
+        "Unidad"
+      ],
+      "Price": [
+        "Precio"
+      ],
+      "Stock": [
+        "Stock"
+      ],
+      "Taxes": [
+        "Impuesto"
+      ],
+      "Server not found": [
+        "Servidor no encontrado"
+      ],
+      "Couldn't access the server": [
+        "No se pudo aceder al servidor"
+      ],
+      "Got message %1$s from %2$s": [
+        "Recivimos el mensaje %1$s desde %2$s"
+      ],
+      "Unexpected Error": [
+        "Error inesperado"
+      ],
+      "Auth token": [
+        "Token de autorización"
+      ],
+      "Account address": [
+        "Dirección de cuenta"
+      ],
+      "Default max deposit fee": [
+        "Impuesto máximo de deposito por omisión"
+      ],
+      "Default max wire fee": [
+        "Impuesto máximo de transferencia por omisión"
+      ],
+      "Default wire fee amortization": [
+        "Amortización de impuesto de transferencia por omisión"
+      ],
+      "Jurisdiction": [
+        "Jurisdicción"
+      ],
+      "Default pay delay": [
+        "Retrazo de pago por omisión"
+      ],
+      "Default wire transfer delay": [
+        "Retrazo de transferencia por omisión"
+      ],
+      "could not create instance": [
+        "no se pudo crear la instancia"
+      ],
+      "Delete": [
+        "Borrando"
+      ],
+      "Edit": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        "No hay instancias todavían, agregue mas presionando el signo +"
+      ],
+      "Inventory products": [
+        "Productos de inventario"
+      ],
+      "Total price": [
+        "Precio total"
+      ],
+      "Total tax": [
+        "Impuesto total"
+      ],
+      "Order price": [
+        "Precio de la orden"
+      ],
+      "Net": [
+        "Neto"
+      ],
+      "Summary": [
+        "Resumen"
+      ],
+      "Payments options": [
+        "Opciones de pago"
+      ],
+      "Auto refund deadline": [
+        "Plazo de reembolso automático"
+      ],
+      "Refund deadline": [
+        "Plazo de reembolso"
+      ],
+      "Pay deadline": [
+        "Plazo de pago"
+      ],
+      "Delivery date": [
+        "Fecha de entrega"
+      ],
+      "Location": [
+        "Ubicación"
+      ],
+      "Max fee": [
+        "Impuesto máximo"
+      ],
+      "Max wire fee": [
+        "Impuesto de transferencia máximo"
+      ],
+      "Wire fee amortization": [
+        "Amortización de impuesto de transferencia"
+      ],
+      "Fullfilment url": [
+        "URL de completitud"
+      ],
+      "Extra information": [
+        "Información extra"
+      ],
+      "select a product first": [
+        "seleccione un producto primero"
+      ],
+      "should be greater than 0": [
+        "La imagen debe ser mas chica que 1 MB"
+      ],
+      "cannot be greater than current stock and quantity previously added. 
max: %1$s": [
+        "no puede ser mayor al stock actual y la cantidad previamente 
agregada. máximo: %1$s"
+      ],
+      "cannot be greater than current stock %1$s": [
+        "no puede ser mayor al stock actual %1$s"
+      ],
+      "Quantity": [
+        "Cantidad"
+      ],
+      "Order": [
+        "Orden"
+      ],
+      "claimed": [
+        "reclamado"
+      ],
+      "copy url": [
+        "copiar url"
+      ],
+      "pay at": [
+        "pagar en"
+      ],
+      "created at": [
+        "creado"
+      ],
+      "Timeline": [
+        "Cronología"
+      ],
+      "Payment details": [
+        "Detalles de pago"
+      ],
+      "Order status": [
+        "Estado de orden"
+      ],
+      "Product list": [
+        "Lista de producto"
+      ],
+      "paid": [
+        "pagados"
+      ],
+      "wired": [
+        "transferido"
+      ],
+      "refunded": [
+        "reembolzado"
+      ],
+      "refund": [
+        "reembolzar"
+      ],
+      "Refunded amount": [
+        "Monto reembolzado"
+      ],
+      "Deposit total": [
+        "Total depositado"
+      ],
+      "unpaid": [
+        "impago"
+      ],
+      "Order status URL": [
+        "URL de estado de orden"
+      ],
+      "Pay URI": [
+        "URI de pago"
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        "Estado de orden desconocido. Esto es un error, por favor contacte a 
su administrador"
+      ],
+      "refund created successfully": [
+        "reembolzo creado satisfactoriamente"
+      ],
+      "could not create the refund": [
+        "No se pudo aceder al servidor"
+      ],
+      "load newer orders": [
+        "cargar nuevas ordenes"
+      ],
+      "Date": [
+        "Fecha"
+      ],
+      "Refund": [
+        "Reembolzar"
+      ],
+      "load older orders": [
+        "cargar viejas ordenes"
+      ],
+      "No orders has been found": [
+        "No se enconraron ordenes"
+      ],
+      "date": [
+        "fecha"
+      ],
+      "amount": [
+        "monto"
+      ],
+      "reason": [
+        "razón"
+      ],
+      "Max refundable:": [
+        "Máximo reembolzable:"
+      ],
+      "Reason": [
+        "Razón"
+      ],
+      "duplicated": [
+        "duplicado"
+      ],
+      "requested by the customer": [
+        "pedido por el consumidor"
+      ],
+      "other": [
+        "otro"
+      ],
+      "go to order id": [
+        "ir a id de orden"
+      ],
+      "Paid": [
+        "Pagado"
+      ],
+      "Refunded": [
+        "Reembolzado"
+      ],
+      "Not wired": [
+        "No transferido"
+      ],
+      "All": [
+        "Todo"
+      ],
+      "could not create product": [
+        "no se pudo crear el producto"
+      ],
+      "Sell": [
+        "Venta"
+      ],
+      "Profit": [
+        "Ganancia"
+      ],
+      "Sold": [
+        "Vendido"
+      ],
+      "product updated successfully": [
+        "producto actualizado correctamente"
+      ],
+      "could not update the product": [
+        "no se pudo actualizar el producto"
+      ],
+      "product delete successfully": [
+        "producto fue eliminado correctamente"
+      ],
+      "could not delete the product": [
+        "no se pudo eliminar el producto"
+      ],
+      "Tips": [
+        "Propinas"
+      ],
+      "Committed amount": [
+        ""
+      ],
+      "Exchange initial amount": [
+        ""
+      ],
+      "Merchant initial amount": [
+        ""
+      ],
+      "There is no tips yet, add more pressing the + sign": [
+        "No hay propinas todavía, agregar mas presionando el signo +"
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        "No hay transferencias todavía, agregar mas presionando el signo +"
+      ]
+    }
+  }
+};
+
+strings['fr'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Access denied": [
+        ""
+      ],
+      "Check your token is valid": [
+        ""
+      ],
+      "Couldn't access the server.": [
+        ""
+      ],
+      "Could not infer instance id from url %1$s": [
+        ""
+      ],
+      "HTTP status #%1$s: Server reported a problem": [
+        ""
+      ],
+      "Got message: \"%1$s\" from: %2$s": [
+        ""
+      ],
+      "No default instance": [
+        ""
+      ],
+      "in order to use merchant backoffice, you should create the default 
instance": [
+        ""
+      ],
+      "Server reported a problem: HTTP status #%1$s": [
+        ""
+      ],
+      "Got message: %1$s from: %2$s": [
+        ""
+      ],
+      "Login required": [
+        ""
+      ],
+      "Please enter your auth token. Token should have \"secret-token:\" and 
start with Bearer or ApiKey": [
+        ""
+      ],
+      "Confirm": [
+        ""
+      ],
+      "The value %1$s is invalid for a payment url": [
+        ""
+      ],
+      "pick a date": [
+        ""
+      ],
+      "clear": [
+        ""
+      ],
+      "never": [
+        ""
+      ],
+      "Image should be smaller than 1 MB": [
+        ""
+      ],
+      "Product id": [
+        ""
+      ],
+      "Description": [
+        ""
+      ],
+      "Name": [
+        ""
+      ],
+      "loading...": [
+        ""
+      ],
+      "no products found": [
+        ""
+      ],
+      "no results": [
+        ""
+      ],
+      "Deleting": [
+        ""
+      ],
+      "Changing": [
+        ""
+      ],
+      "Manage token": [
+        ""
+      ],
+      "Update": [
+        ""
+      ],
+      "Remove": [
+        ""
+      ],
+      "Cancel": [
+        ""
+      ],
+      "Manage stock": [
+        ""
+      ],
+      "Infinite": [
+        ""
+      ],
+      "lost cannot be greater that current + incoming (max %1$s)": [
+        ""
+      ],
+      "current stock will change from %1$s to %2$s": [
+        ""
+      ],
+      "current stock will stay at %1$s": [
+        ""
+      ],
+      "Incoming": [
+        ""
+      ],
+      "Lost": [
+        ""
+      ],
+      "Current": [
+        ""
+      ],
+      "without stock": [
+        ""
+      ],
+      "Next restock": [
+        ""
+      ],
+      "Delivery address": [
+        ""
+      ],
+      "Country": [
+        ""
+      ],
+      "Address": [
+        ""
+      ],
+      "Building number": [
+        ""
+      ],
+      "Building name": [
+        ""
+      ],
+      "Street": [
+        ""
+      ],
+      "Post code": [
+        ""
+      ],
+      "Town location": [
+        ""
+      ],
+      "Town": [
+        ""
+      ],
+      "District": [
+        ""
+      ],
+      "Country subdivision": [
+        ""
+      ],
+      "this product has no taxes": [
+        ""
+      ],
+      "Amount": [
+        ""
+      ],
+      "currency and value separated with colon": [
+        ""
+      ],
+      "Add": [
+        ""
+      ],
+      "Instance": [
+        ""
+      ],
+      "Settings": [
+        ""
+      ],
+      "Orders": [
+        ""
+      ],
+      "Products": [
+        ""
+      ],
+      "Transfers": [
+        ""
+      ],
+      "Connection": [
+        ""
+      ],
+      "Instances": [
+        ""
+      ],
+      "New": [
+        ""
+      ],
+      "List": [
+        ""
+      ],
+      "Log out": [
+        ""
+      ],
+      "Clear": [
+        ""
+      ],
+      "should be the same": [
+        ""
+      ],
+      "cannot be the same as before": [
+        ""
+      ],
+      "You are updating the authorization token from instance %1$s with id 
%2$s": [
+        ""
+      ],
+      "Old token": [
+        ""
+      ],
+      "New token": [
+        ""
+      ],
+      "Clearing the auth token will mean public access to the instance": [
+        ""
+      ],
+      "ID": [
+        ""
+      ],
+      "Image": [
+        ""
+      ],
+      "Unit": [
+        ""
+      ],
+      "Price": [
+        ""
+      ],
+      "Stock": [
+        ""
+      ],
+      "Taxes": [
+        ""
+      ],
+      "Server not found": [
+        ""
+      ],
+      "Couldn't access the server": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        ""
+      ],
+      "Auth token": [
+        ""
+      ],
+      "Account address": [
+        ""
+      ],
+      "Default max deposit fee": [
+        ""
+      ],
+      "Default max wire fee": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        ""
+      ],
+      "Jurisdiction": [
+        ""
+      ],
+      "Default pay delay": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        ""
+      ],
+      "could not create instance": [
+        ""
+      ],
+      "Delete": [
+        ""
+      ],
+      "Edit": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        ""
+      ],
+      "Inventory products": [
+        ""
+      ],
+      "Total price": [
+        ""
+      ],
+      "Total tax": [
+        ""
+      ],
+      "Order price": [
+        ""
+      ],
+      "Net": [
+        ""
+      ],
+      "Summary": [
+        ""
+      ],
+      "Payments options": [
+        ""
+      ],
+      "Auto refund deadline": [
+        ""
+      ],
+      "Refund deadline": [
+        ""
+      ],
+      "Pay deadline": [
+        ""
+      ],
+      "Delivery date": [
+        ""
+      ],
+      "Location": [
+        ""
+      ],
+      "Max fee": [
+        ""
+      ],
+      "Max wire fee": [
+        ""
+      ],
+      "Wire fee amortization": [
+        ""
+      ],
+      "Fullfilment url": [
+        ""
+      ],
+      "Extra information": [
+        ""
+      ],
+      "select a product first": [
+        ""
+      ],
+      "should be greater than 0": [
+        ""
+      ],
+      "cannot be greater than current stock and quantity previously added. 
max: %1$s": [
+        ""
+      ],
+      "cannot be greater than current stock %1$s": [
+        ""
+      ],
+      "Quantity": [
+        ""
+      ],
+      "Order": [
+        ""
+      ],
+      "claimed": [
+        ""
+      ],
+      "copy url": [
+        ""
+      ],
+      "pay at": [
+        ""
+      ],
+      "created at": [
+        ""
+      ],
+      "Timeline": [
+        ""
+      ],
+      "Payment details": [
+        ""
+      ],
+      "Order status": [
+        ""
+      ],
+      "Product list": [
+        ""
+      ],
+      "paid": [
+        ""
+      ],
+      "wired": [
+        ""
+      ],
+      "refunded": [
+        ""
+      ],
+      "refund": [
+        ""
+      ],
+      "Refunded amount": [
+        ""
+      ],
+      "Deposit total": [
+        ""
+      ],
+      "unpaid": [
+        ""
+      ],
+      "Order status URL": [
+        ""
+      ],
+      "Pay URI": [
+        ""
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        ""
+      ],
+      "refund created successfully": [
+        ""
+      ],
+      "could not create the refund": [
+        ""
+      ],
+      "load newer orders": [
+        ""
+      ],
+      "Date": [
+        ""
+      ],
+      "Refund": [
+        ""
+      ],
+      "load older orders": [
+        ""
+      ],
+      "No orders has been found": [
+        ""
+      ],
+      "date": [
+        ""
+      ],
+      "amount": [
+        ""
+      ],
+      "reason": [
+        ""
+      ],
+      "Max refundable:": [
+        ""
+      ],
+      "Reason": [
+        ""
+      ],
+      "duplicated": [
+        ""
+      ],
+      "requested by the customer": [
+        ""
+      ],
+      "other": [
+        ""
+      ],
+      "go to order id": [
+        ""
+      ],
+      "Paid": [
+        ""
+      ],
+      "Refunded": [
+        ""
+      ],
+      "Not wired": [
+        ""
+      ],
+      "All": [
+        ""
+      ],
+      "could not create product": [
+        ""
+      ],
+      "Sell": [
+        ""
+      ],
+      "Profit": [
+        ""
+      ],
+      "Sold": [
+        ""
+      ],
+      "product updated successfully": [
+        ""
+      ],
+      "could not update the product": [
+        ""
+      ],
+      "product delete successfully": [
+        ""
+      ],
+      "could not delete the product": [
+        ""
+      ],
+      "Tips": [
+        ""
+      ],
+      "Committed amount": [
+        ""
+      ],
+      "Exchange initial amount": [
+        ""
+      ],
+      "Merchant initial amount": [
+        ""
+      ],
+      "There is no tips yet, add more pressing the + sign": [
+        ""
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        ""
+      ]
+    }
+  }
+};
+
+strings['it'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Access denied": [
+        ""
+      ],
+      "Check your token is valid": [
+        ""
+      ],
+      "Couldn't access the server.": [
+        ""
+      ],
+      "Could not infer instance id from url %1$s": [
+        ""
+      ],
+      "HTTP status #%1$s: Server reported a problem": [
+        ""
+      ],
+      "Got message: \"%1$s\" from: %2$s": [
+        ""
+      ],
+      "No default instance": [
+        ""
+      ],
+      "in order to use merchant backoffice, you should create the default 
instance": [
+        ""
+      ],
+      "Server reported a problem: HTTP status #%1$s": [
+        ""
+      ],
+      "Got message: %1$s from: %2$s": [
+        ""
+      ],
+      "Login required": [
+        ""
+      ],
+      "Please enter your auth token. Token should have \"secret-token:\" and 
start with Bearer or ApiKey": [
+        ""
+      ],
+      "Confirm": [
+        ""
+      ],
+      "The value %1$s is invalid for a payment url": [
+        ""
+      ],
+      "pick a date": [
+        ""
+      ],
+      "clear": [
+        ""
+      ],
+      "never": [
+        ""
+      ],
+      "Image should be smaller than 1 MB": [
+        ""
+      ],
+      "Product id": [
+        ""
+      ],
+      "Description": [
+        ""
+      ],
+      "Name": [
+        ""
+      ],
+      "loading...": [
+        ""
+      ],
+      "no products found": [
+        ""
+      ],
+      "no results": [
+        ""
+      ],
+      "Deleting": [
+        ""
+      ],
+      "Changing": [
+        ""
+      ],
+      "Manage token": [
+        ""
+      ],
+      "Update": [
+        ""
+      ],
+      "Remove": [
+        ""
+      ],
+      "Cancel": [
+        ""
+      ],
+      "Manage stock": [
+        ""
+      ],
+      "Infinite": [
+        ""
+      ],
+      "lost cannot be greater that current + incoming (max %1$s)": [
+        ""
+      ],
+      "current stock will change from %1$s to %2$s": [
+        ""
+      ],
+      "current stock will stay at %1$s": [
+        ""
+      ],
+      "Incoming": [
+        ""
+      ],
+      "Lost": [
+        ""
+      ],
+      "Current": [
+        ""
+      ],
+      "without stock": [
+        ""
+      ],
+      "Next restock": [
+        ""
+      ],
+      "Delivery address": [
+        ""
+      ],
+      "Country": [
+        ""
+      ],
+      "Address": [
+        ""
+      ],
+      "Building number": [
+        ""
+      ],
+      "Building name": [
+        ""
+      ],
+      "Street": [
+        ""
+      ],
+      "Post code": [
+        ""
+      ],
+      "Town location": [
+        ""
+      ],
+      "Town": [
+        ""
+      ],
+      "District": [
+        ""
+      ],
+      "Country subdivision": [
+        ""
+      ],
+      "this product has no taxes": [
+        ""
+      ],
+      "Amount": [
+        ""
+      ],
+      "currency and value separated with colon": [
+        ""
+      ],
+      "Add": [
+        ""
+      ],
+      "Instance": [
+        ""
+      ],
+      "Settings": [
+        ""
+      ],
+      "Orders": [
+        ""
+      ],
+      "Products": [
+        ""
+      ],
+      "Transfers": [
+        ""
+      ],
+      "Connection": [
+        ""
+      ],
+      "Instances": [
+        ""
+      ],
+      "New": [
+        ""
+      ],
+      "List": [
+        ""
+      ],
+      "Log out": [
+        ""
+      ],
+      "Clear": [
+        ""
+      ],
+      "should be the same": [
+        ""
+      ],
+      "cannot be the same as before": [
+        ""
+      ],
+      "You are updating the authorization token from instance %1$s with id 
%2$s": [
+        ""
+      ],
+      "Old token": [
+        ""
+      ],
+      "New token": [
+        ""
+      ],
+      "Clearing the auth token will mean public access to the instance": [
+        ""
+      ],
+      "ID": [
+        ""
+      ],
+      "Image": [
+        ""
+      ],
+      "Unit": [
+        ""
+      ],
+      "Price": [
+        ""
+      ],
+      "Stock": [
+        ""
+      ],
+      "Taxes": [
+        ""
+      ],
+      "Server not found": [
+        ""
+      ],
+      "Couldn't access the server": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        ""
+      ],
+      "Auth token": [
+        ""
+      ],
+      "Account address": [
+        ""
+      ],
+      "Default max deposit fee": [
+        ""
+      ],
+      "Default max wire fee": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        ""
+      ],
+      "Jurisdiction": [
+        ""
+      ],
+      "Default pay delay": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        ""
+      ],
+      "could not create instance": [
+        ""
+      ],
+      "Delete": [
+        ""
+      ],
+      "Edit": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        ""
+      ],
+      "Inventory products": [
+        ""
+      ],
+      "Total price": [
+        ""
+      ],
+      "Total tax": [
+        ""
+      ],
+      "Order price": [
+        ""
+      ],
+      "Net": [
+        ""
+      ],
+      "Summary": [
+        ""
+      ],
+      "Payments options": [
+        ""
+      ],
+      "Auto refund deadline": [
+        ""
+      ],
+      "Refund deadline": [
+        ""
+      ],
+      "Pay deadline": [
+        ""
+      ],
+      "Delivery date": [
+        ""
+      ],
+      "Location": [
+        ""
+      ],
+      "Max fee": [
+        ""
+      ],
+      "Max wire fee": [
+        ""
+      ],
+      "Wire fee amortization": [
+        ""
+      ],
+      "Fullfilment url": [
+        ""
+      ],
+      "Extra information": [
+        ""
+      ],
+      "select a product first": [
+        ""
+      ],
+      "should be greater than 0": [
+        ""
+      ],
+      "cannot be greater than current stock and quantity previously added. 
max: %1$s": [
+        ""
+      ],
+      "cannot be greater than current stock %1$s": [
+        ""
+      ],
+      "Quantity": [
+        ""
+      ],
+      "Order": [
+        ""
+      ],
+      "claimed": [
+        ""
+      ],
+      "copy url": [
+        ""
+      ],
+      "pay at": [
+        ""
+      ],
+      "created at": [
+        ""
+      ],
+      "Timeline": [
+        ""
+      ],
+      "Payment details": [
+        ""
+      ],
+      "Order status": [
+        ""
+      ],
+      "Product list": [
+        ""
+      ],
+      "paid": [
+        ""
+      ],
+      "wired": [
+        ""
+      ],
+      "refunded": [
+        ""
+      ],
+      "refund": [
+        ""
+      ],
+      "Refunded amount": [
+        ""
+      ],
+      "Deposit total": [
+        ""
+      ],
+      "unpaid": [
+        ""
+      ],
+      "Order status URL": [
+        ""
+      ],
+      "Pay URI": [
+        ""
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        ""
+      ],
+      "refund created successfully": [
+        ""
+      ],
+      "could not create the refund": [
+        ""
+      ],
+      "load newer orders": [
+        ""
+      ],
+      "Date": [
+        ""
+      ],
+      "Refund": [
+        ""
+      ],
+      "load older orders": [
+        ""
+      ],
+      "No orders has been found": [
+        ""
+      ],
+      "date": [
+        ""
+      ],
+      "amount": [
+        ""
+      ],
+      "reason": [
+        ""
+      ],
+      "Max refundable:": [
+        ""
+      ],
+      "Reason": [
+        ""
+      ],
+      "duplicated": [
+        ""
+      ],
+      "requested by the customer": [
+        ""
+      ],
+      "other": [
+        ""
+      ],
+      "go to order id": [
+        ""
+      ],
+      "Paid": [
+        ""
+      ],
+      "Refunded": [
+        ""
+      ],
+      "Not wired": [
+        ""
+      ],
+      "All": [
+        ""
+      ],
+      "could not create product": [
+        ""
+      ],
+      "Sell": [
+        ""
+      ],
+      "Profit": [
+        ""
+      ],
+      "Sold": [
+        ""
+      ],
+      "product updated successfully": [
+        ""
+      ],
+      "could not update the product": [
+        ""
+      ],
+      "product delete successfully": [
+        ""
+      ],
+      "could not delete the product": [
+        ""
+      ],
+      "Tips": [
+        ""
+      ],
+      "Committed amount": [
+        ""
+      ],
+      "Exchange initial amount": [
+        ""
+      ],
+      "Merchant initial amount": [
+        ""
+      ],
+      "There is no tips yet, add more pressing the + sign": [
+        ""
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        ""
+      ]
+    }
+  }
+};
+
+strings['sv'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Access denied": [
+        ""
+      ],
+      "Check your token is valid": [
+        ""
+      ],
+      "Couldn't access the server.": [
+        ""
+      ],
+      "Could not infer instance id from url %1$s": [
+        ""
+      ],
+      "HTTP status #%1$s: Server reported a problem": [
+        ""
+      ],
+      "Got message: \"%1$s\" from: %2$s": [
+        ""
+      ],
+      "No default instance": [
+        ""
+      ],
+      "in order to use merchant backoffice, you should create the default 
instance": [
+        ""
+      ],
+      "Server reported a problem: HTTP status #%1$s": [
+        ""
+      ],
+      "Got message: %1$s from: %2$s": [
+        ""
+      ],
+      "Login required": [
+        ""
+      ],
+      "Please enter your auth token. Token should have \"secret-token:\" and 
start with Bearer or ApiKey": [
+        ""
+      ],
+      "Confirm": [
+        ""
+      ],
+      "The value %1$s is invalid for a payment url": [
+        ""
+      ],
+      "pick a date": [
+        ""
+      ],
+      "clear": [
+        ""
+      ],
+      "never": [
+        ""
+      ],
+      "Image should be smaller than 1 MB": [
+        ""
+      ],
+      "Product id": [
+        ""
+      ],
+      "Description": [
+        ""
+      ],
+      "Name": [
+        ""
+      ],
+      "loading...": [
+        ""
+      ],
+      "no products found": [
+        ""
+      ],
+      "no results": [
+        ""
+      ],
+      "Deleting": [
+        ""
+      ],
+      "Changing": [
+        ""
+      ],
+      "Manage token": [
+        ""
+      ],
+      "Update": [
+        ""
+      ],
+      "Remove": [
+        ""
+      ],
+      "Cancel": [
+        ""
+      ],
+      "Manage stock": [
+        ""
+      ],
+      "Infinite": [
+        ""
+      ],
+      "lost cannot be greater that current + incoming (max %1$s)": [
+        ""
+      ],
+      "current stock will change from %1$s to %2$s": [
+        ""
+      ],
+      "current stock will stay at %1$s": [
+        ""
+      ],
+      "Incoming": [
+        ""
+      ],
+      "Lost": [
+        ""
+      ],
+      "Current": [
+        ""
+      ],
+      "without stock": [
+        ""
+      ],
+      "Next restock": [
+        ""
+      ],
+      "Delivery address": [
+        ""
+      ],
+      "Country": [
+        ""
+      ],
+      "Address": [
+        ""
+      ],
+      "Building number": [
+        ""
+      ],
+      "Building name": [
+        ""
+      ],
+      "Street": [
+        ""
+      ],
+      "Post code": [
+        ""
+      ],
+      "Town location": [
+        ""
+      ],
+      "Town": [
+        ""
+      ],
+      "District": [
+        ""
+      ],
+      "Country subdivision": [
+        ""
+      ],
+      "this product has no taxes": [
+        ""
+      ],
+      "Amount": [
+        ""
+      ],
+      "currency and value separated with colon": [
+        ""
+      ],
+      "Add": [
+        ""
+      ],
+      "Instance": [
+        ""
+      ],
+      "Settings": [
+        ""
+      ],
+      "Orders": [
+        ""
+      ],
+      "Products": [
+        ""
+      ],
+      "Transfers": [
+        ""
+      ],
+      "Connection": [
+        ""
+      ],
+      "Instances": [
+        ""
+      ],
+      "New": [
+        ""
+      ],
+      "List": [
+        ""
+      ],
+      "Log out": [
+        ""
+      ],
+      "Clear": [
+        ""
+      ],
+      "should be the same": [
+        ""
+      ],
+      "cannot be the same as before": [
+        ""
+      ],
+      "You are updating the authorization token from instance %1$s with id 
%2$s": [
+        ""
+      ],
+      "Old token": [
+        ""
+      ],
+      "New token": [
+        ""
+      ],
+      "Clearing the auth token will mean public access to the instance": [
+        ""
+      ],
+      "ID": [
+        ""
+      ],
+      "Image": [
+        ""
+      ],
+      "Unit": [
+        ""
+      ],
+      "Price": [
+        ""
+      ],
+      "Stock": [
+        ""
+      ],
+      "Taxes": [
+        ""
+      ],
+      "Server not found": [
+        ""
+      ],
+      "Couldn't access the server": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        ""
+      ],
+      "Auth token": [
+        ""
+      ],
+      "Account address": [
+        ""
+      ],
+      "Default max deposit fee": [
+        ""
+      ],
+      "Default max wire fee": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        ""
+      ],
+      "Jurisdiction": [
+        ""
+      ],
+      "Default pay delay": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        ""
+      ],
+      "could not create instance": [
+        ""
+      ],
+      "Delete": [
+        ""
+      ],
+      "Edit": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        ""
+      ],
+      "Inventory products": [
+        ""
+      ],
+      "Total price": [
+        ""
+      ],
+      "Total tax": [
+        ""
+      ],
+      "Order price": [
+        ""
+      ],
+      "Net": [
+        ""
+      ],
+      "Summary": [
+        ""
+      ],
+      "Payments options": [
+        ""
+      ],
+      "Auto refund deadline": [
+        ""
+      ],
+      "Refund deadline": [
+        ""
+      ],
+      "Pay deadline": [
+        ""
+      ],
+      "Delivery date": [
+        ""
+      ],
+      "Location": [
+        ""
+      ],
+      "Max fee": [
+        ""
+      ],
+      "Max wire fee": [
+        ""
+      ],
+      "Wire fee amortization": [
+        ""
+      ],
+      "Fullfilment url": [
+        ""
+      ],
+      "Extra information": [
+        ""
+      ],
+      "select a product first": [
+        ""
+      ],
+      "should be greater than 0": [
+        ""
+      ],
+      "cannot be greater than current stock and quantity previously added. 
max: %1$s": [
+        ""
+      ],
+      "cannot be greater than current stock %1$s": [
+        ""
+      ],
+      "Quantity": [
+        ""
+      ],
+      "Order": [
+        ""
+      ],
+      "claimed": [
+        ""
+      ],
+      "copy url": [
+        ""
+      ],
+      "pay at": [
+        ""
+      ],
+      "created at": [
+        ""
+      ],
+      "Timeline": [
+        ""
+      ],
+      "Payment details": [
+        ""
+      ],
+      "Order status": [
+        ""
+      ],
+      "Product list": [
+        ""
+      ],
+      "paid": [
+        ""
+      ],
+      "wired": [
+        ""
+      ],
+      "refunded": [
+        ""
+      ],
+      "refund": [
+        ""
+      ],
+      "Refunded amount": [
+        ""
+      ],
+      "Deposit total": [
+        ""
+      ],
+      "unpaid": [
+        ""
+      ],
+      "Order status URL": [
+        ""
+      ],
+      "Pay URI": [
+        ""
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        ""
+      ],
+      "refund created successfully": [
+        ""
+      ],
+      "could not create the refund": [
+        ""
+      ],
+      "load newer orders": [
+        ""
+      ],
+      "Date": [
+        ""
+      ],
+      "Refund": [
+        ""
+      ],
+      "load older orders": [
+        ""
+      ],
+      "No orders has been found": [
+        ""
+      ],
+      "date": [
+        ""
+      ],
+      "amount": [
+        ""
+      ],
+      "reason": [
+        ""
+      ],
+      "Max refundable:": [
+        ""
+      ],
+      "Reason": [
+        ""
+      ],
+      "duplicated": [
+        ""
+      ],
+      "requested by the customer": [
+        ""
+      ],
+      "other": [
+        ""
+      ],
+      "go to order id": [
+        ""
+      ],
+      "Paid": [
+        ""
+      ],
+      "Refunded": [
+        ""
+      ],
+      "Not wired": [
+        ""
+      ],
+      "All": [
+        ""
+      ],
+      "could not create product": [
+        ""
+      ],
+      "Sell": [
+        ""
+      ],
+      "Profit": [
+        ""
+      ],
+      "Sold": [
+        ""
+      ],
+      "product updated successfully": [
+        ""
+      ],
+      "could not update the product": [
+        ""
+      ],
+      "product delete successfully": [
+        ""
+      ],
+      "could not delete the product": [
+        ""
+      ],
+      "Tips": [
+        ""
+      ],
+      "Committed amount": [
+        ""
+      ],
+      "Exchange initial amount": [
+        ""
+      ],
+      "Merchant initial amount": [
+        ""
+      ],
+      "There is no tips yet, add more pressing the + sign": [
+        ""
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        ""
+      ]
+    }
+  }
+};
+
diff --git a/packages/frontend/src/i18n/sv.po b/packages/frontend/src/i18n/sv.po
new file mode 100644
index 0000000..694798f
--- /dev/null
+++ b/packages/frontend/src/i18n/sv.po
@@ -0,0 +1,1010 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/ApplicationReadyRoutes.tsx:50 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:293
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:51 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:294
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:72
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:73
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:108
+#, c-format
+msgid "HTTP status #%1$s: Server reported a problem"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:109
+#, c-format
+msgid "Got message: \"%1$s\" from: %2$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:126
+#, c-format
+msgid "No default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:127
+#, c-format
+msgid ""
+"in order to use merchant backoffice, you should create the default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:282
+#, c-format
+msgid "Server reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:283
+#, c-format
+msgid "Got message: %1$s from: %2$s"
+msgstr ""
+
+#: src/components/exception/login.tsx:46
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:49
+#, c-format
+msgid ""
+"Please enter your auth token. Token should have \"secret-token:\" and start "
+"with Bearer or ApiKey"
+msgstr ""
+
+#: src/components/exception/login.tsx:86 src/components/modal/index.tsx:53
+#: src/components/modal/index.tsx:75 src/paths/admin/create/CreatePage.tsx:140
+#: src/paths/instance/orders/create/CreatePage.tsx:337
+#: src/paths/instance/products/create/CreatePage.tsx:51
+#: src/paths/instance/products/list/Table.tsx:174
+#: src/paths/instance/products/list/Table.tsx:228
+#: src/paths/instance/products/update/UpdatePage.tsx:55
+#: src/paths/instance/update/UpdatePage.tsx:159
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:72
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:67
+#: src/paths/instance/orders/list/index.tsx:123
+#, c-format
+msgid "pick a date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:81
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:83
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:80
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:59
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:60
+#: src/components/product/ProductForm.tsx:99
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:122
+#: src/paths/instance/orders/list/Table.tsx:227
+#: src/paths/instance/products/list/Table.tsx:86
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:73
+#: src/components/form/InputTaxes.tsx:81
+#: src/paths/admin/create/CreatePage.tsx:86 src/paths/admin/list/Table.tsx:110
+#: src/paths/instance/details/DetailPage.tsx:76
+#: src/paths/instance/transfers/list/Table.tsx:112
+#: src/paths/instance/update/UpdatePage.tsx:105
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:102
+#, c-format
+msgid "loading..."
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:108
+#, c-format
+msgid "no products found"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:116
+#, c-format
+msgid "no results"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:33
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:34
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:60
+#, c-format
+msgid "Manage token"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:83
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:100
+#: src/paths/instance/orders/create/CreatePage.tsx:251
+#: src/paths/instance/orders/create/CreatePage.tsx:272
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:106 src/components/modal/index.tsx:52
+#: src/components/modal/index.tsx:73 src/paths/admin/create/CreatePage.tsx:139
+#: src/paths/instance/orders/create/CreatePage.tsx:336
+#: src/paths/instance/products/create/CreatePage.tsx:50
+#: src/paths/instance/products/list/Table.tsx:166
+#: src/paths/instance/products/list/Table.tsx:218
+#: src/paths/instance/products/update/UpdatePage.tsx:54
+#: src/paths/instance/update/UpdatePage.tsx:158
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:90
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:92
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:104
+#, c-format
+msgid "lost cannot be greater that current + incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:110
+#, c-format
+msgid "current stock will change from %1$s to %2$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:111
+#, c-format
+msgid "current stock will stay at %1$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:128
+#: src/paths/instance/products/list/Table.tsx:204
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:129
+#: src/paths/instance/products/list/Table.tsx:205
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:141
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:144
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:149
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:151
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:153
+#: src/paths/admin/create/CreatePage.tsx:99
+#: src/paths/admin/create/CreatePage.tsx:116
+#: src/paths/instance/orders/create/CreatePage.tsx:308
+#: src/paths/instance/update/UpdatePage.tsx:118
+#: src/paths/instance/update/UpdatePage.tsx:135
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:156
+#: src/paths/admin/create/CreatePage.tsx:98
+#: src/paths/admin/create/CreatePage.tsx:101
+#: src/paths/admin/create/CreatePage.tsx:118
+#: src/paths/instance/orders/create/CreatePage.tsx:310
+#: src/paths/instance/update/UpdatePage.tsx:117
+#: src/paths/instance/update/UpdatePage.tsx:120
+#: src/paths/instance/update/UpdatePage.tsx:137
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:161
+#: src/paths/admin/create/CreatePage.tsx:105
+#: src/paths/admin/create/CreatePage.tsx:122
+#: src/paths/instance/orders/create/CreatePage.tsx:314
+#: src/paths/instance/update/UpdatePage.tsx:124
+#: src/paths/instance/update/UpdatePage.tsx:141
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:162
+#: src/paths/admin/create/CreatePage.tsx:106
+#: src/paths/admin/create/CreatePage.tsx:123
+#: src/paths/instance/orders/create/CreatePage.tsx:315
+#: src/paths/instance/update/UpdatePage.tsx:125
+#: src/paths/instance/update/UpdatePage.tsx:142
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:163
+#: src/paths/admin/create/CreatePage.tsx:107
+#: src/paths/admin/create/CreatePage.tsx:124
+#: src/paths/instance/orders/create/CreatePage.tsx:316
+#: src/paths/instance/update/UpdatePage.tsx:126
+#: src/paths/instance/update/UpdatePage.tsx:143
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:164
+#: src/paths/admin/create/CreatePage.tsx:108
+#: src/paths/admin/create/CreatePage.tsx:125
+#: src/paths/instance/orders/create/CreatePage.tsx:317
+#: src/paths/instance/update/UpdatePage.tsx:127
+#: src/paths/instance/update/UpdatePage.tsx:144
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:165
+#: src/paths/admin/create/CreatePage.tsx:109
+#: src/paths/admin/create/CreatePage.tsx:126
+#: src/paths/instance/orders/create/CreatePage.tsx:318
+#: src/paths/instance/update/UpdatePage.tsx:128
+#: src/paths/instance/update/UpdatePage.tsx:145
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:166
+#: src/paths/admin/create/CreatePage.tsx:110
+#: src/paths/admin/create/CreatePage.tsx:127
+#: src/paths/instance/orders/create/CreatePage.tsx:319
+#: src/paths/instance/update/UpdatePage.tsx:129
+#: src/paths/instance/update/UpdatePage.tsx:146
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:167
+#: src/paths/admin/create/CreatePage.tsx:111
+#: src/paths/admin/create/CreatePage.tsx:128
+#: src/paths/instance/orders/create/CreatePage.tsx:320
+#: src/paths/instance/update/UpdatePage.tsx:130
+#: src/paths/instance/update/UpdatePage.tsx:147
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:168
+#: src/paths/admin/create/CreatePage.tsx:112
+#: src/paths/admin/create/CreatePage.tsx:129
+#: src/paths/instance/orders/create/CreatePage.tsx:321
+#: src/paths/instance/update/UpdatePage.tsx:131
+#: src/paths/instance/update/UpdatePage.tsx:148
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:73
+#, c-format
+msgid "this product has no taxes"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:77
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#: src/paths/instance/orders/details/DetailPage.tsx:296
+#: src/paths/instance/orders/list/Table.tsx:116
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:78
+#, c-format
+msgid "currency and value separated with colon"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:84
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:78
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:53
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:59
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:65
+#: src/paths/instance/orders/list/Table.tsx:60
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:71
+#: src/paths/instance/orders/create/CreatePage.tsx:257
+#: src/paths/instance/products/list/Table.tsx:48
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:77
+#: src/paths/instance/transfers/list/Table.tsx:59
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:87
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:112 src/paths/admin/list/Table.tsx:57
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:116
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:122
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:129
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/components/modal/index.tsx:74
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:110 src/components/modal/index.tsx:111
+#, c-format
+msgid "should be the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:111
+#, c-format
+msgid "cannot be the same as before"
+msgstr ""
+
+#: src/components/modal/index.tsx:114
+#, c-format
+msgid ""
+"You are updating the authorization token from instance %1$s with id %2$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:125
+#, c-format
+msgid "New token"
+msgstr ""
+
+#: src/components/modal/index.tsx:127
+#, c-format
+msgid "Clearing the auth token will mean public access to the instance"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:96
+#: src/paths/admin/create/CreatePage.tsx:84 src/paths/admin/list/Table.tsx:109
+#: src/paths/instance/transfers/list/Table.tsx:111
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:98
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:121
+#: src/paths/instance/products/list/Table.tsx:85
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:100
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:123
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:101
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:124
+#: src/paths/instance/products/list/Table.tsx:162
+#: src/paths/instance/products/list/Table.tsx:214
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:103
+#: src/paths/instance/products/list/Table.tsx:90
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:105
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:128
+#: src/paths/instance/products/list/Table.tsx:88
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/index.tsx:75
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/index.tsx:85
+#, c-format
+msgid "Couldn't access the server"
+msgstr ""
+
+#: src/index.tsx:87 src/index.tsx:99
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/index.tsx:97
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:88
+#: src/paths/instance/update/UpdatePage.tsx:107
+#, c-format
+msgid "Auth token"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:90
+#: src/paths/instance/details/DetailPage.tsx:77
+#: src/paths/instance/update/UpdatePage.tsx:109
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:92
+#: src/paths/instance/update/UpdatePage.tsx:111
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#: src/paths/instance/update/UpdatePage.tsx:113
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#: src/paths/instance/update/UpdatePage.tsx:115
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:115
+#: src/paths/instance/update/UpdatePage.tsx:134
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:132
+#: src/paths/instance/update/UpdatePage.tsx:151
+#, c-format
+msgid "Default pay delay"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:134
+#: src/paths/instance/update/UpdatePage.tsx:153
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/paths/admin/create/index.tsx:58
+#, c-format
+msgid "could not create instance"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:63 src/paths/admin/list/Table.tsx:131
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:128
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:149
+#: src/paths/instance/products/list/Table.tsx:245
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:236
+#, c-format
+msgid "Inventory products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:285
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:286
+#, c-format
+msgid "Total tax"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:288
+#: src/paths/instance/orders/create/CreatePage.tsx:296
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:294
+#, c-format
+msgid "Net"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#: src/paths/instance/orders/details/DetailPage.tsx:295
+#: src/paths/instance/orders/list/Table.tsx:117
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:301
+#, c-format
+msgid "Payments options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:302
+#, c-format
+msgid "Auto refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:303
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:304
+#, c-format
+msgid "Pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:306
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:307
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:324
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:325
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:326
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:327
+#, c-format
+msgid "Fullfilment url"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:330
+#, c-format
+msgid "Extra information"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:44
+#, c-format
+msgid "select a product first"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:51
+#, c-format
+msgid "should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:58
+#, c-format
+msgid ""
+"cannot be greater than current stock and quantity previously added. max: %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:64
+#, c-format
+msgid "cannot be greater than current stock %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:76
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:126
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:92
+#: src/paths/instance/orders/details/DetailPage.tsx:235
+#: src/paths/instance/orders/details/DetailPage.tsx:333
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:110
+#: src/paths/instance/orders/details/DetailPage.tsx:261
+#: src/paths/instance/orders/list/Table.tsx:136
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:126
+#: src/paths/instance/orders/details/DetailPage.tsx:349
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:127
+#: src/paths/instance/orders/details/DetailPage.tsx:350
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:138
+#: src/paths/instance/orders/details/DetailPage.tsx:289
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:142
+#: src/paths/instance/orders/details/DetailPage.tsx:293
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:146
+#: src/paths/instance/orders/details/DetailPage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:363
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:156
+#: src/paths/instance/orders/details/DetailPage.tsx:308
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:236
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:238
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:241
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:258
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:297
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:298
+#, c-format
+msgid "Deposit total"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:336
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:364
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:365
+#, c-format
+msgid "Pay URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:383
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:56
+#: src/paths/instance/orders/list/index.tsx:147
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:59
+#: src/paths/instance/orders/list/index.tsx:150
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:111
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:115
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:131
+#: src/paths/instance/orders/list/Table.tsx:223
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:145
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "No orders has been found"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:202
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:203
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:204
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:224
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:91
+#, c-format
+msgid "go to order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:107
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:108
+#, c-format
+msgid "Refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:109
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:110
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:48
+#: src/paths/instance/products/update/index.tsx:64
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:87
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:89
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:91
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:59
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:62
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:70
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:73
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:59
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:111
+#, c-format
+msgid "Committed amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:112
+#, c-format
+msgid "Exchange initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:113
+#, c-format
+msgid "Merchant initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:148
+#, c-format
+msgid "There is no tips yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:147
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
diff --git a/packages/frontend/src/i18n/taler-merchant-backoffice.pot 
b/packages/frontend/src/i18n/taler-merchant-backoffice.pot
new file mode 100644
index 0000000..50c9939
--- /dev/null
+++ b/packages/frontend/src/i18n/taler-merchant-backoffice.pot
@@ -0,0 +1,1007 @@
+#  This file is part of GNU Taler
+#  (C) 2021 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/>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/ApplicationReadyRoutes.tsx:50 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:293
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:51 src/InstanceRoutes.tsx:117
+#: src/InstanceRoutes.tsx:294
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:72
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:73
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:108
+#, c-format
+msgid "HTTP status #%1$s: Server reported a problem"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:109
+#, c-format
+msgid "Got message: \"%1$s\" from: %2$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:126
+#, c-format
+msgid "No default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:127
+#, c-format
+msgid ""
+"in order to use merchant backoffice, you should create the default instance"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:282
+#, c-format
+msgid "Server reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:283
+#, c-format
+msgid "Got message: %1$s from: %2$s"
+msgstr ""
+
+#: src/components/exception/login.tsx:46
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:49
+#, c-format
+msgid ""
+"Please enter your auth token. Token should have \"secret-token:\" and start "
+"with Bearer or ApiKey"
+msgstr ""
+
+#: src/components/exception/login.tsx:86 src/components/modal/index.tsx:53
+#: src/components/modal/index.tsx:75 src/paths/admin/create/CreatePage.tsx:140
+#: src/paths/instance/orders/create/CreatePage.tsx:337
+#: src/paths/instance/products/create/CreatePage.tsx:51
+#: src/paths/instance/products/list/Table.tsx:174
+#: src/paths/instance/products/list/Table.tsx:228
+#: src/paths/instance/products/update/UpdatePage.tsx:55
+#: src/paths/instance/update/UpdatePage.tsx:159
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:72
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:67
+#: src/paths/instance/orders/list/index.tsx:123
+#, c-format
+msgid "pick a date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:81
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:83
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:80
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:59
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:60
+#: src/components/product/ProductForm.tsx:99
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:122
+#: src/paths/instance/orders/list/Table.tsx:227
+#: src/paths/instance/products/list/Table.tsx:86
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:73
+#: src/components/form/InputTaxes.tsx:81
+#: src/paths/admin/create/CreatePage.tsx:86 src/paths/admin/list/Table.tsx:110
+#: src/paths/instance/details/DetailPage.tsx:76
+#: src/paths/instance/transfers/list/Table.tsx:112
+#: src/paths/instance/update/UpdatePage.tsx:105
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:102
+#, c-format
+msgid "loading..."
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:108
+#, c-format
+msgid "no products found"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:116
+#, c-format
+msgid "no results"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:33
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:34
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:60
+#, c-format
+msgid "Manage token"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:83
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:100
+#: src/paths/instance/orders/create/CreatePage.tsx:251
+#: src/paths/instance/orders/create/CreatePage.tsx:272
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:106 src/components/modal/index.tsx:52
+#: src/components/modal/index.tsx:73 src/paths/admin/create/CreatePage.tsx:139
+#: src/paths/instance/orders/create/CreatePage.tsx:336
+#: src/paths/instance/products/create/CreatePage.tsx:50
+#: src/paths/instance/products/list/Table.tsx:166
+#: src/paths/instance/products/list/Table.tsx:218
+#: src/paths/instance/products/update/UpdatePage.tsx:54
+#: src/paths/instance/update/UpdatePage.tsx:158
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:90
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:92
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:104
+#, c-format
+msgid "lost cannot be greater that current + incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:110
+#, c-format
+msgid "current stock will change from %1$s to %2$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:111
+#, c-format
+msgid "current stock will stay at %1$s"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:128
+#: src/paths/instance/products/list/Table.tsx:204
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:129
+#: src/paths/instance/products/list/Table.tsx:205
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:141
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:144
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:149
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:151
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:153
+#: src/paths/admin/create/CreatePage.tsx:99
+#: src/paths/admin/create/CreatePage.tsx:116
+#: src/paths/instance/orders/create/CreatePage.tsx:308
+#: src/paths/instance/update/UpdatePage.tsx:118
+#: src/paths/instance/update/UpdatePage.tsx:135
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:156
+#: src/paths/admin/create/CreatePage.tsx:98
+#: src/paths/admin/create/CreatePage.tsx:101
+#: src/paths/admin/create/CreatePage.tsx:118
+#: src/paths/instance/orders/create/CreatePage.tsx:310
+#: src/paths/instance/update/UpdatePage.tsx:117
+#: src/paths/instance/update/UpdatePage.tsx:120
+#: src/paths/instance/update/UpdatePage.tsx:137
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:161
+#: src/paths/admin/create/CreatePage.tsx:105
+#: src/paths/admin/create/CreatePage.tsx:122
+#: src/paths/instance/orders/create/CreatePage.tsx:314
+#: src/paths/instance/update/UpdatePage.tsx:124
+#: src/paths/instance/update/UpdatePage.tsx:141
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:162
+#: src/paths/admin/create/CreatePage.tsx:106
+#: src/paths/admin/create/CreatePage.tsx:123
+#: src/paths/instance/orders/create/CreatePage.tsx:315
+#: src/paths/instance/update/UpdatePage.tsx:125
+#: src/paths/instance/update/UpdatePage.tsx:142
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:163
+#: src/paths/admin/create/CreatePage.tsx:107
+#: src/paths/admin/create/CreatePage.tsx:124
+#: src/paths/instance/orders/create/CreatePage.tsx:316
+#: src/paths/instance/update/UpdatePage.tsx:126
+#: src/paths/instance/update/UpdatePage.tsx:143
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:164
+#: src/paths/admin/create/CreatePage.tsx:108
+#: src/paths/admin/create/CreatePage.tsx:125
+#: src/paths/instance/orders/create/CreatePage.tsx:317
+#: src/paths/instance/update/UpdatePage.tsx:127
+#: src/paths/instance/update/UpdatePage.tsx:144
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:165
+#: src/paths/admin/create/CreatePage.tsx:109
+#: src/paths/admin/create/CreatePage.tsx:126
+#: src/paths/instance/orders/create/CreatePage.tsx:318
+#: src/paths/instance/update/UpdatePage.tsx:128
+#: src/paths/instance/update/UpdatePage.tsx:145
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:166
+#: src/paths/admin/create/CreatePage.tsx:110
+#: src/paths/admin/create/CreatePage.tsx:127
+#: src/paths/instance/orders/create/CreatePage.tsx:319
+#: src/paths/instance/update/UpdatePage.tsx:129
+#: src/paths/instance/update/UpdatePage.tsx:146
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:167
+#: src/paths/admin/create/CreatePage.tsx:111
+#: src/paths/admin/create/CreatePage.tsx:128
+#: src/paths/instance/orders/create/CreatePage.tsx:320
+#: src/paths/instance/update/UpdatePage.tsx:130
+#: src/paths/instance/update/UpdatePage.tsx:147
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:168
+#: src/paths/admin/create/CreatePage.tsx:112
+#: src/paths/admin/create/CreatePage.tsx:129
+#: src/paths/instance/orders/create/CreatePage.tsx:321
+#: src/paths/instance/update/UpdatePage.tsx:131
+#: src/paths/instance/update/UpdatePage.tsx:148
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:73
+#, c-format
+msgid "this product has no taxes"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:77
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#: src/paths/instance/orders/details/DetailPage.tsx:296
+#: src/paths/instance/orders/list/Table.tsx:116
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:78
+#, c-format
+msgid "currency and value separated with colon"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:84
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:78
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:53
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:59
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:65
+#: src/paths/instance/orders/list/Table.tsx:60
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:71
+#: src/paths/instance/orders/create/CreatePage.tsx:257
+#: src/paths/instance/products/list/Table.tsx:48
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:77
+#: src/paths/instance/transfers/list/Table.tsx:59
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:87
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:112 src/paths/admin/list/Table.tsx:57
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:116
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:122
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:129
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/components/modal/index.tsx:74
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:110 src/components/modal/index.tsx:111
+#, c-format
+msgid "should be the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:111
+#, c-format
+msgid "cannot be the same as before"
+msgstr ""
+
+#: src/components/modal/index.tsx:114
+#, c-format
+msgid ""
+"You are updating the authorization token from instance %1$s with id %2$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:125
+#, c-format
+msgid "New token"
+msgstr ""
+
+#: src/components/modal/index.tsx:127
+#, c-format
+msgid "Clearing the auth token will mean public access to the instance"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:96
+#: src/paths/admin/create/CreatePage.tsx:84 src/paths/admin/list/Table.tsx:109
+#: src/paths/instance/transfers/list/Table.tsx:111
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:98
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:121
+#: src/paths/instance/products/list/Table.tsx:85
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:100
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:123
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:101
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:124
+#: src/paths/instance/products/list/Table.tsx:162
+#: src/paths/instance/products/list/Table.tsx:214
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:103
+#: src/paths/instance/products/list/Table.tsx:90
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:105
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:128
+#: src/paths/instance/products/list/Table.tsx:88
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/index.tsx:75
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/index.tsx:85
+#, c-format
+msgid "Couldn't access the server"
+msgstr ""
+
+#: src/index.tsx:87 src/index.tsx:99
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/index.tsx:97
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:88
+#: src/paths/instance/update/UpdatePage.tsx:107
+#, c-format
+msgid "Auth token"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:90
+#: src/paths/instance/details/DetailPage.tsx:77
+#: src/paths/instance/update/UpdatePage.tsx:109
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:92
+#: src/paths/instance/update/UpdatePage.tsx:111
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#: src/paths/instance/update/UpdatePage.tsx:113
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#: src/paths/instance/update/UpdatePage.tsx:115
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:115
+#: src/paths/instance/update/UpdatePage.tsx:134
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:132
+#: src/paths/instance/update/UpdatePage.tsx:151
+#, c-format
+msgid "Default pay delay"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:134
+#: src/paths/instance/update/UpdatePage.tsx:153
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/paths/admin/create/index.tsx:58
+#, c-format
+msgid "could not create instance"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:63 src/paths/admin/list/Table.tsx:131
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:128
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/Table.tsx:149
+#: src/paths/instance/products/list/Table.tsx:245
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:236
+#, c-format
+msgid "Inventory products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:285
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:286
+#, c-format
+msgid "Total tax"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:288
+#: src/paths/instance/orders/create/CreatePage.tsx:296
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:294
+#, c-format
+msgid "Net"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#: src/paths/instance/orders/details/DetailPage.tsx:295
+#: src/paths/instance/orders/list/Table.tsx:117
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:301
+#, c-format
+msgid "Payments options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:302
+#, c-format
+msgid "Auto refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:303
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:304
+#, c-format
+msgid "Pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:306
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:307
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:324
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:325
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:326
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:327
+#, c-format
+msgid "Fullfilment url"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:330
+#, c-format
+msgid "Extra information"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:44
+#, c-format
+msgid "select a product first"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:51
+#, c-format
+msgid "should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:58
+#, c-format
+msgid ""
+"cannot be greater than current stock and quantity previously added. max: %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:64
+#, c-format
+msgid "cannot be greater than current stock %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/InventoryProductForm.tsx:76
+#: src/paths/instance/orders/create/NonInventoryProductForm.tsx:126
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:92
+#: src/paths/instance/orders/details/DetailPage.tsx:235
+#: src/paths/instance/orders/details/DetailPage.tsx:333
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:110
+#: src/paths/instance/orders/details/DetailPage.tsx:261
+#: src/paths/instance/orders/list/Table.tsx:136
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:126
+#: src/paths/instance/orders/details/DetailPage.tsx:349
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:127
+#: src/paths/instance/orders/details/DetailPage.tsx:350
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:138
+#: src/paths/instance/orders/details/DetailPage.tsx:289
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:142
+#: src/paths/instance/orders/details/DetailPage.tsx:293
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:146
+#: src/paths/instance/orders/details/DetailPage.tsx:299
+#: src/paths/instance/orders/details/DetailPage.tsx:363
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:156
+#: src/paths/instance/orders/details/DetailPage.tsx:308
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:236
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:238
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:241
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:258
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:297
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:298
+#, c-format
+msgid "Deposit total"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:336
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:364
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:365
+#, c-format
+msgid "Pay URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:383
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:56
+#: src/paths/instance/orders/list/index.tsx:147
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:59
+#: src/paths/instance/orders/list/index.tsx:150
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:111
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:115
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:131
+#: src/paths/instance/orders/list/Table.tsx:223
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:145
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "No orders has been found"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:202
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:203
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:204
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:224
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:226
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:91
+#, c-format
+msgid "go to order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:107
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:108
+#, c-format
+msgid "Refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:109
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:110
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:48
+#: src/paths/instance/products/update/index.tsx:64
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:87
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:89
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:91
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:59
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:62
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:70
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:73
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:59
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:111
+#, c-format
+msgid "Committed amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:112
+#, c-format
+msgid "Exchange initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:113
+#, c-format
+msgid "Merchant initial amount"
+msgstr ""
+
+#: src/paths/instance/tips/list/Table.tsx:148
+#, c-format
+msgid "There is no tips yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:147
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
diff --git a/packages/frontend/src/index.tsx b/packages/frontend/src/index.tsx
index babc2d1..5c2df2f 100644
--- a/packages/frontend/src/index.tsx
+++ b/packages/frontend/src/index.tsx
@@ -20,31 +20,25 @@
 */
 
 import { h, VNode } from 'preact';
-import { MessageProvider, useMessageTemplate } from 'preact-messages';
 import { route } from 'preact-router';
 import { useMemo } from "preact/hooks";
 import { ApplicationReadyRoutes } from "./ApplicationReadyRoutes";
 import { Loading } from "./components/exception/loading";
 import { NotificationCard, NotYetReadyAppMenu } from "./components/menu";
-import { BackendContextProvider, ConfigContextProvider, useBackendContext } 
from './context/backend';
-import { useBackendContextState } from './hooks';
+import { BackendContextProvider, useBackendContext } from './context/backend';
+import { ConfigContextProvider } from './context/config';
+import { TranslationProvider } from './context/translation';
 import { useBackendConfig } from "./hooks/backend";
-import * as messages from './messages';
+import { useTranslator } from './i18n';
 import LoginPage from './paths/login';
 import "./scss/main.scss";
-import { hasKey, onTranslationError } from "./utils/functions";
-
-
-
 
 export default function Application(): VNode {
-  const state = useBackendContextState()
-
   return (
-    <BackendContextProvider value={state}>
-      <MessageProvider locale={state.lang} onError={onTranslationError} 
messages={hasKey(messages, state.lang) ? messages[state.lang] : messages.en} 
pathSep={null as any} >
+    <BackendContextProvider>
+      <TranslationProvider>
         <ApplicationStatusRoutes />
-      </MessageProvider >
+      </TranslationProvider>
     </BackendContextProvider>
   );
 }
@@ -52,7 +46,7 @@ export default function Application(): VNode {
 function ApplicationStatusRoutes(): VNode {
   const { changeBackend, triedToLog, updateToken } = useBackendContext()
   const result = useBackendConfig();
-  const i18n = useMessageTemplate()
+  const i18n = useTranslator()
 
   const updateLoginInfoAndGoToRoot = (url: string, token?: string) => {
     changeBackend(url)
diff --git a/packages/frontend/src/messages/en.po 
b/packages/frontend/src/messages/en.po
deleted file mode 100644
index 32a78a1..0000000
--- a/packages/frontend/src/messages/en.po
+++ /dev/null
@@ -1,627 +0,0 @@
-#   This file is part of GNU Taler
-#   (C) 2021 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/>
-
-# Examples from http://pology.nedohodnik.net/doc/user/en_US/ch-poformat.html
-msgid ""
-msgstr ""
-"Content-Type: text/plain; charset=UTF-8\n"
-"Language: en\n"
-"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 
|| n%100>=20) ? 1 : 2);\n"
- 
-msgid "Time: %1 second"
-msgid_plural "Time: %1 seconds"
-msgstr[0] "Czas: %1 sekunda"
-msgstr[1] "Czas: %1 sekundy"
-msgstr[2] "Czas: %1 sekund"
- 
-msgid "Hi"
-msgstr "Hello"
-
-msgid "List of configured instances"
-msgstr "List of configured instances"
-
-msgid "There is no instances yet, add more pressing the + sign"
-msgstr "There is no instances yet, add more pressing the + sign"
-
-msgid "Invalid payment address"
-msgstr "Invalid payment address"
-
-msgid "Problem reaching the server"
-msgstr "Problem reaching the server"
-
-msgid "The value %s is invalid for a payment url"
-msgstr "The value \"%s\" is invalid for a payment url"
-
-#  msgctxt "fields.instance.name"
-#  msgid "placeholder"
-#  msgstr ""
-
-#  |msgctxt "fields"
-#  |msgctxt "instance"
-#  msgctxt "fields.instance.id.label"
-
-msgid "fields.instance.id.label"
-msgstr "Id"
-
-msgid "fields.instance.name.label"
-msgstr "Name"
-
-msgid "fields.instance.merchant.pub.label"
-msgstr "Public key"
-
-msgid "fields.instance.payment.targets.label"
-msgstr "Payment targets"
-
-msgid "fields.instance.auth_token.label"
-msgstr "Auth token"
-
-msgid "fields.instance.auth_token.tooltip"
-msgstr "Use this token to secure an instance with a password"
-
-msgid "fields.instance.payto_uris.label"
-msgstr "Account address"
-
-msgid "fields.instance.payto_uris.help"
-msgstr "x-taler-bank/bank.taler:5882/blogger"
-
-msgid "fields.instance.default_max_deposit_fee.label"
-msgstr "Max deposit fee label"
-
-msgid "fields.instance.default_max_wire_fee.label"
-msgstr "Max wire fee label"
-
-msgid "fields.instance.default_wire_fee_amortization.label"
-msgstr "Wire fee Amortization"
-
-msgid "fields.instance.address.label"
-msgstr "Address"
-
-msgid "Could not infer instance id from url %s"
-msgstr "Could not infer instance id from url %s"
-
-msgid "fields.instance.address.country.label"
-msgstr "Country"
-
-msgid "fields.instance.address.country_subdivision.label"
-msgstr "Country Subdivision"
-
-msgid "fields.instance.address.district.label"
-msgstr "District"
-
-msgid "fields.instance.address.town.label"
-msgstr "Town"
-
-msgid "fields.instance.address.town_location.label"
-msgstr "Town Location"
-
-msgid "fields.instance.address.post_code.label"
-msgstr "Post code"
-
-msgid "fields.instance.address.street.label"
-msgstr "Street"
-
-msgid "fields.instance.address.building_name.label"
-msgstr "Building Name"
-
-msgid "fields.instance.address.building_number.label"
-msgstr "Building Number"
-
-msgid "fields.instance.address.address_lines.label"
-msgstr "Address"
-
-msgid "fields.instance.jurisdiction.label"
-msgstr "Jurisdiction"
-
-msgid "fields.instance.jurisdiction.country.label"
-msgstr "Country"
-
-msgid "fields.instance.jurisdiction.country_subdivision.label"
-msgstr "Country Subdivision"
-
-msgid "fields.instance.jurisdiction.district.label"
-msgstr "District"
-
-msgid "fields.instance.jurisdiction.town.label"
-msgstr "Town"
-
-msgid "fields.instance.jurisdiction.town_location.label"
-msgstr "Town Location"
-
-msgid "fields.instance.jurisdiction.post_code.label"
-msgstr "Post code"
-
-msgid "fields.instance.jurisdiction.street.label"
-msgstr "Street"
-
-msgid "fields.instance.jurisdiction.building_name.label"
-msgstr "Building Name"
-
-msgid "fields.instance.jurisdiction.building_number.label"
-msgstr "Building Number"
-
-msgid "fields.instance.jurisdiction.address_lines.label"
-msgstr "Address"
-
-msgid "fields.instance.default_pay_delay.label"
-msgstr "Pay delay"
-
-msgid "fields.instance.default_wire_transfer_delay.label"
-msgstr "Wire transfer delay"
-
-msgid "Couldn't access the server"
-msgstr "Couldn't access the server"
-
-msgid "Unexpected Error"
-msgstr "Unexpected Error"
-
-msgid "Got message %s from %s"
-msgstr "Got message \"%s\" from %s"
-
-msgid "Merchant"
-msgstr "Merchant"
-
-msgid "Instances"
-msgstr "Instances"
-
-msgid "Update this instance"
-msgstr "Update this instance"
-
-msgid "Cancel"
-msgstr "Cancel"
-
-msgid "Clear"
-msgstr "Clear"
-
-msgid "Confirm"
-msgstr "Confirm"
-
-msgid "en"
-msgstr "English [en]"
-
-msgid "es"
-msgstr "Español [es]"
-
-
-msgid "fields.instance.old_token.label"
-msgstr "Old token"
-
-msgid "fields.instance.new_token.label"
-msgstr "New token"
-
-msgid "validations."
-msgstr "New token"
-
-msgid "fields.instance.id.label"
-msgstr "Id"
-
-msgid "fields.instance.name.label"
-msgstr "Business Name"
-
-msgid "fields.instance.merchant_pub.label"
-msgstr "Public Key"
-
-msgid "fields.instance.payment_targets.label"
-msgstr "Payment targets"
-
-msgid "Access denied"
-msgstr "Access denied"
-
-msgid "Check your token is valid"
-msgstr "Check your token is valid"
-
-msgid "delete"
-msgstr "Delete"
-
-msgid "update"
-msgstr "Update"
-
-msgid "Instance details"
-msgstr "Instance details"
-
-msgid "Login required"
-msgstr "Login required"
-
-msgid "Please enter your auth token. Token should have \"secret-token:\" and 
start with Bearer or ApiKey"
-msgstr "Please enter your auth token. Token should have \"secret-token:\" and 
start with Bearer or ApiKey"
-
-msgid "Orders"
-msgstr "Orders"
-
-msgid "fields.order.amount.label"
-msgstr "Amount"
-
-msgid "fields.order.summary.label"
-msgstr "Summary"
-
-msgid "fields.order.date.label"
-msgstr "Date"
-
-msgid "Products"
-msgstr "Products"
-
-msgid "fields.product.id.label"
-msgstr "Id"
-
-msgid "Transfers"
-msgstr "Transfers"
-
-msgid "Tips"
-msgstr "Tips"
-
-msgid "fields.tips.committed_amount.label"
-msgstr "Commited Amount"
-
-msgid "fields.tips.exchange_initial_amount.label"
-msgstr "Exchange Initial Amount"
-
-msgid "fields.tips.merchant_initial_amount.label"
-msgstr "Merchant Initial Amount"
-
-msgid "fields.instance.paid.tooltip"
-msgstr "three state boolean"
-
-msgid "fields.instance.paid.label"
-msgstr "Paid"
-
-#  msgid "fields.instance.refunded.tooltip"
-#  msgstr ""
-
-msgid "fields.instance.refunded.label"
-msgstr "Refunded"
-
-#  msgid "fields.instance.wired.tooltip"
-#  msgstr ""
-
-msgid "fields.instance.wired.label"
-msgstr "Wired"
-
-msgid "create_success"
-msgstr "Creation succeed"
-
-msgid "create_error"
-msgstr "Creation failed"
-
-msgid "delete_instance"
-msgstr "Delete instance"
-
-#  msgid "fields.instance.refund.placeholder"
-#  msgstr ""
-
-#  msgid "fields.instance.refund.tooltip"
-#  msgstr ""
-
-msgid "fields.instance.refund.label"
-msgstr "Amount"
-
-msgid "fields.instance.mainReason.placeholder"
-msgstr "select an option"
-
-#  msgid "fields.instance.reason.tooltip"
-#  msgstr ""
-
-msgid "fields.instance.mainReason.label"
-msgstr "Reason"
-
-msgid "fields.instance.description.label"
-msgstr "Description"
-
-msgid "fields.instance.description.placeholder"
-msgstr "add more information about the refund"
-
-msgid "fields.instance.order_status.label"
-msgstr "Order status"
-
-msgid "fields.instance.order_status_url.label"
-msgstr "Order status URL"
-
-msgid "fields.instance.taler_pay_uri.label"
-msgstr "Taler Pay URI"
-
-
-msgid "fields.instance.amount.label"
-msgstr "Amount"
-
-msgid "fields.instance.summary.label"
-msgstr "Summary"
-
-
-msgid "fields.instance.contract_terms.amount.label"
-msgstr "Amount"
-
-msgid "fields.instance.contract_terms.summary.label"
-msgstr "Summary"
-
-msgid "fields.instance.refund_amount.label"
-msgstr "Refunded"
-
-msgid "fields.instance.deposit_total.label"
-msgstr "Deposit Total"
-
-msgid "fields.instance.contract_terms.max_fee.label"
-msgstr "Max Fee"
-
-msgid "fields.instance.contract_terms.max_wire_fee.label"
-msgstr "Max Wire Fee"
-
-
-msgid "fields.instance.fee.label"
-msgstr "Fee"
-
-msgid "fields.product.image.label"
-msgstr "Image"
-
-msgid "fields.product.description.label"
-msgstr "Description"
-
-msgid "fields.product.sell.label"
-msgstr "Sell"
-
-msgid "fields.product.taxes.label"
-msgstr "Taxes"
-
-msgid "fields.product.profit.label"
-msgstr "Profit"
-
-msgid "fields.product.stock.label"
-msgstr "Stock"
-
-msgid "fields.product.quantity.label"
-msgstr "Quantity"
-
-msgid "fields.product.sold.label"
-msgstr "Sold"
-
-msgid "fields.instance.inventory_products.label"
-msgstr "Products from inventory"
-
-msgid "fields.instance.products.label"
-msgstr "Products outside inventory"
-
-msgid "fields.instance.quantity.label"
-msgstr "Quantity"
-
-
-msgid "fields.instance.pricing.order_price.label"
-msgstr "Order Price"
-
-msgid "fields.instance.pricing.summary.label"
-msgstr "Summary"
-
-msgid "fields.instance.pricing.products_price.label"
-msgstr "Products Price"
-
-msgid "fields.instance.pricing.products_taxes.label"
-msgstr "Products Taxes"
-
-msgid "fields.instance.pricing.net.label"
-msgstr "Net"
-
-
-msgid "fields.instance.payments.label"
-msgstr "Payments"
-
-
-
-msgid "fields.instance.payments.auto_refund_deadline.label"
-msgstr "Auto Refund Deadline"
-
-
-
-msgid "fields.instance.payments.refund_deadline.label"
-msgstr "Refund Deadline"
-
-
-
-msgid "fields.instance.payments.pay_deadline.label"
-msgstr "Pay Deadline"
-
-
-
-msgid "fields.instance.payments.delivery_date.label"
-msgstr "Delivery Date"
-
-msgid "fields.instance.payments.delivery_location.label"
-msgstr "Delivery Location"
-
-
-
-msgid "fields.instance.payments.max_fee.label"
-msgstr "Max Fee"
-
-
-
-msgid "fields.instance.payments.max_wire_fee.label"
-msgstr "Max Wire Fee"
-
-
-
-msgid "fields.instance.payments.wire_fee_amortization.label"
-msgstr "Wire Fee Amortization"
-
-
-
-msgid "fields.instance.payments.fullfilment_url.label"
-msgstr "Fillfilment URL"
-
-
-
-msgid "fields.instance.payments.delivery_location.country.label"
-msgstr "Country"
-
-
-
-msgid "fields.instance.payments.delivery_location.address_lines.label"
-msgstr "Adress Lines"
-
-
-
-msgid "fields.instance.payments.delivery_location.building_number.label"
-msgstr "Building Number"
-
-
-
-msgid "fields.instance.payments.delivery_location.building_name.label"
-msgstr "Building Name"
-
-
-
-msgid "fields.instance.payments.delivery_location.street.label"
-msgstr "Stree"
-
-
-
-msgid "fields.instance.payments.delivery_location.post_code.label"
-msgstr "Post Code"
-
-
-
-msgid "fields.instance.payments.delivery_location.town_location.label"
-msgstr "Town Location"
-
-msgid "fields.instance.payments.delivery_location.town.label"
-msgstr "Town"
-
-msgid "fields.instance.payments.delivery_location.district.label"
-msgstr "District"
-
-msgid "fields.instance.payments.delivery_location.country_subdivision.label"
-msgstr "Country Subdivision"
-
-msgid "fields.instance.extra.label"
-msgstr "Extra information"
-
-msgid "fields.instance.extra.tooltip"
-msgstr "Must be a JSON formatted string"
-
-
-msgid "fields.instance.product_id.label"
-msgstr "ID"
-
-
-msgid "fields.instance.image.label"
-msgstr "Image"
-
-
-msgid "fields.instance.unit.label"
-msgstr "Unit"
-
-
-
-msgid "fields.instance.total_stock.label"
-msgstr "Total Stock"
-
-
-msgid "fields.product.description.label"
-msgstr "Description"
-
-msgid "fields.product.unit.label"
-msgstr "Unit"
-
-msgid "fields.product.total_stock.label"
-msgstr "Total Stock"
-
-msgid "fields.product.product_id.label"
-msgstr "ID"
-
-msgid "fields.product.price.label"
-msgstr "Price"
-
-msgid "fields.tax.name.label"
-msgstr "Name"
-
-msgid "fields.tax.tax.label"
-msgstr "Amount"
-
-msgid "fields.groups.address.label"
-msgstr "Storage address"
-
-msgid "fields.stock.current.label"
-msgstr "Current stock"
-
-msgid "fields.stock.lost.label"
-msgstr "Lost stock"
-
-msgid "fields.stock.nextRestock.label"
-msgstr "Next Restock"
-
-
-msgid "fields.stock.address.country.label"
-msgstr "Country"
-
-msgid "fields.stock.address.country_subdivision.label"
-msgstr "Country Subdivision"
-
-msgid "fields.stock.address.district.label"
-msgstr "District"
-
-msgid "fields.stock.address.town.label"
-msgstr "Town"
-
-msgid "fields.stock.address.town_location.label"
-msgstr "Town Location"
-
-msgid "fields.stock.address.post_code.label"
-msgstr "Post code"
-
-msgid "fields.stock.address.street.label"
-msgstr "Street"
-
-msgid "fields.stock.address.building_name.label"
-msgstr "Building Name"
-
-msgid "fields.stock.address.building_number.label"
-msgstr "Building Number"
-
-msgid "fields.stock.address.address_lines.label"
-msgstr "Address"
-
-msgid "fields.groups.jurisdiction.label"
-msgstr "Jurisdiction"
-
-msgid "fields.groups.inventory_products.label"
-msgstr "Inventory Products"
-
-msgid "fields.groups.products.label"
-msgstr "Products"
-
-msgid "fields.groups.payments.label"
-msgstr "Payments"
-
-msgid "fields.groups.extra.label"
-msgstr "Extra"
-
-
-msgid "fields.instance.stock.label"
-msgstr "Stock"
-
-msgid "fields.instance.lost.label"
-msgstr "Lost"
-
-msgid "fields.instance.price.label"
-msgstr "Price"
-
-msgid "fields.groups.tax.label"
-msgstr "Taxes"
-
-msgid "validation.imageSizeLimit"
-msgstr "Image max size is 1 MB"
-
-msgid "fields.added.incoming.label"
-msgstr "Incoming"
-
-msgid "fields.added.lost.label"
-msgstr "Notify Lost"
-
-msgid "fields.added.price.label"
-msgstr "New Price"
diff --git a/packages/frontend/src/messages/es.po 
b/packages/frontend/src/messages/es.po
deleted file mode 100644
index 545b8a5..0000000
--- a/packages/frontend/src/messages/es.po
+++ /dev/null
@@ -1,202 +0,0 @@
-#   This file is part of GNU Taler
-#   (C) 2021 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/>
-
-# Examples from http://pology.nedohodnik.net/doc/user/en_US/ch-poformat.html
-msgid ""
-msgstr ""
-"Content-Type: text/plain; charset=UTF-8\n"
-"Language: es\n"
-"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 
|| n%100>=20) ? 1 : 2);\n"
- 
-msgid "Hi"
-msgstr "Hola"
-
-msgid "List of configured instances"
-msgstr "Lista de instancias configuradas"
-
-msgid "There is no instances yet, add more pressing the + sign"
-msgstr "Lodavía no hay instancias, puedes agregar mas presionando el signo +"
-
-msgid "Invalid payment address"
-msgstr "Dirección de pago invalido"
-
-msgid "Problem reaching the server"
-msgstr "Hubo problemas intentando llegar al servidor"
-
-msgid "The value %s is invalid for a payment url"
-msgstr "El valor \"%s\" es una dirección de pago invalido"
-
-#  msgctxt "fields.instance.name"
-#  msgid "placeholder"
-#  msgstr ""
-
-#  |msgctxt "fields"
-#  |msgctxt "instance"
-#  msgctxt "fields.instance.id.label"
-
-msgid "fields.instance.id.label"
-msgstr "Id"
-
-msgid "fields.instance.name.label"
-msgstr "Nombre"
-
-msgid "fields.instance.merchant_pub.label"
-msgstr "Clave publica"
-
-msgid "fields.instance.payment_targets.label"
-msgstr "Dirección de pago"
-
-msgid "fields.instance.auth_token.label"
-msgstr "Token de autorización"
-
-msgid "fields.instance.auth_token.tooltip"
-msgstr "Use this token to secure an instance with a password"
-
-msgid "fields.instance.payto_uris.label"
-msgstr "Dirección de cuenta"
-
-msgid "fields.instance.payto_uris.help"
-msgstr "x-taler-bank/bank.taler:5882/blogger"
-
-msgid "fields.instance.default_max_deposit_fee.label"
-msgstr "Máximo cobro por deposito"
-
-msgid "fields.instance.default_max_wire_fee.label"
-msgstr "Máximo cobro por transferencia bancaria"
-
-msgid "fields.instance.default_wire_fee_amortization.label"
-msgstr "Cobro por transferencia"
-
-msgid "fields.instance.address.label"
-msgstr "Dirección"
-
-msgid "fields.instance.address.country.label"
-msgstr "País"
-
-msgid "fields.instance.address.country_subdivision.label"
-msgstr "País suvdivisión"
-
-msgid "fields.instance.address.district.label"
-msgstr "Distrito"
-
-msgid "fields.instance.address.town.label"
-msgstr "Ciudad"
-
-msgid "fields.instance.address.town_location.label"
-msgstr "Ubicación"
-
-msgid "fields.instance.address.post_code.label"
-msgstr "Código postal"
-
-msgid "fields.instance.address.street.label"
-msgstr "Calle"
-
-msgid "fields.instance.address.building_name.label"
-msgstr "Nombre de edificio"
-
-msgid "fields.instance.address.building_number.label"
-msgstr "Numero de edificio"
-
-msgid "fields.instance.address.address_lines.label"
-msgstr "Linea de dirección"
-
-msgid "fields.instance.jurisdiction.label"
-msgstr "Juridiscción"
-
-msgid "fields.instance.jurisdiction.country.label"
-msgstr "País"
-
-msgid "fields.instance.jurisdiction.country_subdivision.label"
-msgstr "Country Subdivision"
-
-msgid "fields.instance.jurisdiction.district.label"
-msgstr "District"
-
-msgid "fields.instance.jurisdiction.town.label"
-msgstr "Town"
-
-msgid "fields.instance.jurisdiction.town_location.label"
-msgstr "Town Location"
-
-msgid "fields.instance.jurisdiction.post_code.label"
-msgstr "Post code"
-
-msgid "fields.instance.jurisdiction.street.label"
-msgstr "Street"
-
-msgid "fields.instance.jurisdiction.building_name.label"
-msgstr "Building Name"
-
-msgid "fields.instance.jurisdiction.building_number.label"
-msgstr "Building Number"
-
-msgid "fields.instance.jurisdiction.address_lines.label"
-msgstr "Adress Line"
-
-msgid "fields.instance.default_pay_delay.label"
-msgstr "Demora de pago"
-
-msgid "fields.instance.default_wire_transfer_delay.label"
-msgstr "Demora de transferencia"
-
-msgid "Couldnt access the server"
-msgstr "Sin acceso a servidor"
-
-msgid "Got message: %s from: %s (hasToken: %s)"
-msgstr "Se recibió el mensaje \"%s\" desde %s"
-
-msgid "Merchant"
-msgstr "Mercader"
-
-msgid "Instances"
-msgstr "Instancias"
-
-msgid "Update this instance"
-msgstr "Actualizar esta instancia"
-
-msgid "Cancel"
-msgstr "Cancelar"
-
-msgid "Clear"
-msgstr "Limpiar"
-
-msgid "Confirm"
-msgstr "Confirmar"
-
-msgid "fields.instance.old_token.label"
-msgstr "Token previo"
-
-msgid "fields.instance.new_token.label"
-msgstr "Token nuevo"
-
-
-msgid "Access denied"
-msgstr "Acceso denegado"
-
-msgid "Check your token is valid"
-msgstr "Verifica que el token sea válido"
-
-msgid "delete"
-msgstr "Borrar"
-
-msgid "update"
-msgstr "Actualizar"
-
-msgid "Login required"
-msgstr "Login requerido"
-
-msgid "Please enter your auth token. Token should have \"secret-token:\" and 
start with Bearer or ApiKey"
-msgstr "Por favor, ingrese su token de autorización. El token debe contender 
\"secret-token:\" y comenzar con Bearer o ApiKey"
-
-
diff --git a/packages/frontend/src/paths/admin/create/CreatePage.tsx 
b/packages/frontend/src/paths/admin/create/CreatePage.tsx
index 5da8c72..58a294e 100644
--- a/packages/frontend/src/paths/admin/create/CreatePage.tsx
+++ b/packages/frontend/src/paths/admin/create/CreatePage.tsx
@@ -20,7 +20,6 @@
 */
 
 import { h, VNode } from "preact";
-import { Message } from "preact-messages";
 import { useState } from "preact/hooks";
 import * as yup from 'yup';
 import { FormErrors, FormProvider } from 
"../../../components/form/FormProvider";
@@ -33,6 +32,7 @@ import { InputSecured } from 
"../../../components/form/InputSecured";
 import { InputWithAddon } from "../../../components/form/InputWithAddon";
 import { useBackendContext } from "../../../context/backend";
 import { MerchantBackend } from "../../../declaration";
+import { Translate, useTranslator } from "../../../i18n";
 import { InstanceCreateSchema as schema } from '../../../schemas';
 
 type Entity = MerchantBackend.Instances.InstanceConfigurationMessage & { 
auth_token?: string }
@@ -46,9 +46,9 @@ interface Props {
 function with_defaults(id?: string): Partial<Entity> {
   return {
     id,
-    default_pay_delay: { d_ms: 1000*60*5 },
+    default_pay_delay: { d_ms: 1000 * 60 * 5 },
     default_wire_fee_amortization: 1,
-    default_wire_transfer_delay: { d_ms: 2000*60*5 },
+    default_wire_transfer_delay: { d_ms: 2000 * 60 * 5 },
   };
 }
 
@@ -67,12 +67,12 @@ export function CreatePage({ onCreate, onBack, forceId }: 
Props): VNode {
       onCreate(schema.cast(value) as Entity);
     } catch (err) {
       const errors = err.inner as yup.ValidationError[]
-      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: { type: cur.type, params: cur.params, message: cur.message 
} }), {})
+      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: cur.message }), {})
       setErrors(pathMessages)
     }
   }
   const backend = useBackendContext()
-
+  const i18n = useTranslator()
   return <div>
 
     <section class="section is-main-section">
@@ -81,61 +81,63 @@ export function CreatePage({ onCreate, onBack, forceId }: 
Props): VNode {
         <div class="column is-two-thirds">
           <FormProvider<Entity> errors={errors} object={value} 
valueHandler={valueHandler} >
 
-            <InputWithAddon<Entity> name="id" 
addonBefore={`${backend.url}/private/instances/`} readonly={!!forceId} />
+            <InputWithAddon<Entity> name="id" label={i18n`ID`} 
addonBefore={`${backend.url}/private/instances/`} readonly={!!forceId} />
 
-            <Input<Entity> name="name" />
+            <Input<Entity> name="name" label={i18n`Name`} />
 
-            <InputSecured<Entity> name="auth_token" />
+            <InputSecured<Entity> name="auth_token" label={i18n`Auth token`} />
 
-            <InputPayto<Entity> name="payto_uris" />
+            <InputPayto<Entity> name="payto_uris" label={i18n`Account 
address`} />
 
-            <InputCurrency<Entity> name="default_max_deposit_fee" />
+            <InputCurrency<Entity> name="default_max_deposit_fee" 
label={i18n`Default max deposit fee`} />
 
-            <InputCurrency<Entity> name="default_max_wire_fee" />
+            <InputCurrency<Entity> name="default_max_wire_fee" 
label={i18n`Default max wire fee`} />
 
-            <Input<Entity> name="default_wire_fee_amortization" />
+            <Input<Entity> name="default_wire_fee_amortization" 
label={i18n`Default wire fee amortization`} />
 
-            <InputGroup name="address">
-              <Input name="address.country" />
+            <InputGroup name="address" label={i18n`Address`}>
+              <Input name="address.country" label={i18n`Country`} />
               <Input name="address.address_lines" inputType="multiline"
+                label={i18n`Address`}
                 toStr={(v: string[] | undefined) => !v ? '' : v.join('\n')}
                 fromStr={(v: string) => v.split('\n')}
               />
-              <Input name="address.building_number" />
-              <Input name="address.building_name" />
-              <Input name="address.street" />
-              <Input name="address.post_code" />
-              <Input name="address.town_location" />
-              <Input name="address.town" />
-              <Input name="address.district" />
-              <Input name="address.country_subdivision" />
+              <Input name="address.building_number" label={i18n`Building 
number`} />
+              <Input name="address.building_name" label={i18n`Building name`} 
/>
+              <Input name="address.street" label={i18n`Street`} />
+              <Input name="address.post_code" label={i18n`Post code`} />
+              <Input name="address.town_location" label={i18n`Town location`} 
/>
+              <Input name="address.town" label={i18n`Town`} />
+              <Input name="address.district" label={i18n`District`} />
+              <Input name="address.country_subdivision" label={i18n`Country 
subdivision`} />
             </InputGroup>
 
-            <InputGroup name="jurisdiction">
-              <Input name="jurisdiction.country" />
+            <InputGroup name="jurisdiction" label={i18n`Jurisdiction`}>
+              <Input name="jurisdiction.country" label={i18n`Country`} />
               <Input name="jurisdiction.address_lines" inputType="multiline"
+                label={i18n`Address`}
                 toStr={(v: string[] | undefined) => !v ? '' : v.join('\n')}
                 fromStr={(v: string) => v.split('\n')}
               />
-              <Input name="jurisdiction.building_number" />
-              <Input name="jurisdiction.building_name" />
-              <Input name="jurisdiction.street" />
-              <Input name="jurisdiction.post_code" />
-              <Input name="jurisdiction.town_location" />
-              <Input name="jurisdiction.town" />
-              <Input name="jurisdiction.district" />
-              <Input name="jurisdiction.country_subdivision" />
+              <Input name="jurisdiction.building_number" label={i18n`Building 
number`} />
+              <Input name="jurisdiction.building_name" label={i18n`Building 
name`} />
+              <Input name="jurisdiction.street" label={i18n`Street`} />
+              <Input name="jurisdiction.post_code" label={i18n`Post code`} />
+              <Input name="jurisdiction.town_location" label={i18n`Town 
location`} />
+              <Input name="jurisdiction.town" label={i18n`Town`} />
+              <Input name="jurisdiction.district" label={i18n`District`} />
+              <Input name="jurisdiction.country_subdivision" 
label={i18n`Country subdivision`} />
             </InputGroup>
 
-            <InputDuration<Entity> name="default_pay_delay" />
+            <InputDuration<Entity> name="default_pay_delay" 
label={i18n`Default pay delay`} />
 
-            <InputDuration<Entity> name="default_wire_transfer_delay" />
+            <InputDuration<Entity> name="default_wire_transfer_delay" 
label={i18n`Default wire transfer delay`} />
 
           </FormProvider>
 
           <div class="buttons is-right mt-5">
-            {onBack && <button class="button" onClick={onBack} ><Message 
id="Cancel" /></button>}
-            <button class="button is-success" onClick={submit} ><Message 
id="Confirm" /></button>
+            {onBack && <button class="button" onClick={onBack} 
><Translate>Cancel</Translate></button>}
+            <button class="button is-success" onClick={submit} 
><Translate>Confirm</Translate></button>
           </div>
 
         </div>
diff --git a/packages/frontend/src/paths/admin/create/index.tsx 
b/packages/frontend/src/paths/admin/create/index.tsx
index 852ce34..1480a27 100644
--- a/packages/frontend/src/paths/admin/create/index.tsx
+++ b/packages/frontend/src/paths/admin/create/index.tsx
@@ -22,6 +22,7 @@ import { useState } from "preact/hooks";
 import { NotificationCard } from "../../../components/menu";
 import { MerchantBackend } from "../../../declaration";
 import { useAdminAPI } from "../../../hooks/admin";
+import { useTranslator } from "../../../i18n";
 import { Notification } from "../../../utils/types";
 import { CreatePage } from "./CreatePage";
 import { InstanceCreatedSuccessfully } from "./InstanceCreatedSuccessfully";
@@ -37,6 +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()
 
   if (createdOk) {
     return <InstanceCreatedSuccessfully entity={createdOk} 
onConfirm={onConfirm} />
@@ -53,7 +55,7 @@ export default function Create({ onBack, onConfirm, forceId 
}: Props): VNode {
           setCreatedOk(d)
         }).catch((error) => {
           setNotif({
-            message: 'could not create instance',
+            message: i18n`could not create instance`,
             type: "ERROR",
             description: error.message
           })
diff --git a/packages/frontend/src/paths/admin/list/Table.tsx 
b/packages/frontend/src/paths/admin/list/Table.tsx
index 5b08ad9..2886014 100644
--- a/packages/frontend/src/paths/admin/list/Table.tsx
+++ b/packages/frontend/src/paths/admin/list/Table.tsx
@@ -20,10 +20,10 @@
 */
 
 import { h, VNode } from "preact";
-import { Message } from "preact-messages";
 import { StateUpdater, useEffect, useState } from "preact/hooks";
 import { MerchantBackend } from "../../../declaration";
 import { calculateRootPath } from "../../../hooks";
+import { Translate } from "../../../i18n";
 
 interface Props {
   instances: MerchantBackend.Instances.Instance[];
@@ -54,13 +54,13 @@ export function CardTable({ instances, onCreate, onUpdate, 
onDelete, selected }:
 
   return <div class="card has-table">
     <header class="card-header">
-      <p class="card-header-title"><span class="icon"><i class="mdi 
mdi-desktop-mac" /></span><Message id="Instances" /></p>
+      <p class="card-header-title"><span class="icon"><i class="mdi 
mdi-desktop-mac" /></span><Translate>Instances</Translate></p>
 
       <div class="card-header-icon" aria-label="more options">
 
         <button class={rowSelection.length > 0 ? "button is-danger" : 
"is-hidden"}
           type="button" onClick={(): void => 
actionQueueHandler(buildActions(instances, rowSelection, 'DELETE'))} >
-          Delete
+          <Translate>Delete</Translate>
         </button>
       </div>
       <div class="card-header-icon" aria-label="more options">
@@ -106,8 +106,8 @@ function Table({ rowSelection, rowSelectionHandler, 
instances, onUpdate, onDelet
               <span class="check" />
             </label>
           </th>
-          <th><Message id="fields.instance.id.label" /></th>
-          <th><Message id="fields.instance.name.label" /></th>
+          <th><Translate>ID</Translate></th>
+          <th><Translate>Name</Translate></th>
           <th />
         </tr>
       </thead>
@@ -125,10 +125,10 @@ function Table({ rowSelection, rowSelectionHandler, 
instances, onUpdate, onDelet
             <td class="is-actions-cell right-sticky">
               <div class="buttons is-right">
                 <button class="button is-small is-success jb-modal" 
type="button" onClick={(): void => onUpdate(i.id)}>
-                  Edit
+                  <Translate>Edit</Translate>
                 </button>
                 <button class="button is-small is-danger jb-modal" 
type="button" onClick={(): void => onDelete(i)}>
-                  Delete
+                  <Translate>Delete</Translate>
                 </button>
               </div>
             </td>
@@ -146,7 +146,7 @@ function EmptyTable(): VNode {
     <p>
       <span class="icon is-large"><i class="mdi mdi-emoticon-sad mdi-48px" 
/></span>
     </p>
-    <p><Message id="There is no instances yet, add more pressing the + sign" 
/></p>
+    <p><Translate>There is no instances yet, add more pressing the + 
sign</Translate></p>
   </div>
 }
 
diff --git a/packages/frontend/src/paths/admin/list/View.tsx 
b/packages/frontend/src/paths/admin/list/View.tsx
index 26c2eca..61ed109 100644
--- a/packages/frontend/src/paths/admin/list/View.tsx
+++ b/packages/frontend/src/paths/admin/list/View.tsx
@@ -29,10 +29,9 @@ interface Props {
   onUpdate: (id: string) => void;
   onDelete: (id: MerchantBackend.Instances.Instance) => void;
   selected?: boolean;
-  isLoading: boolean;
 }
 
-export function View({ instances, isLoading, onCreate, onDelete, onUpdate, 
selected }: Props): VNode {
+export function View({ instances, onCreate, onDelete, onUpdate, selected }: 
Props): VNode {
 
   return <div id="app">
 
diff --git a/packages/frontend/src/paths/admin/list/index.tsx 
b/packages/frontend/src/paths/admin/list/index.tsx
index 074163c..d23288c 100644
--- a/packages/frontend/src/paths/admin/list/index.tsx
+++ b/packages/frontend/src/paths/admin/list/index.tsx
@@ -50,7 +50,6 @@ export default function Instances({ onUnauthorized, 
onLoadError, onNotFound, onC
 
   return <Fragment>
     <View instances={result.data.instances}
-      isLoading={false}
       onDelete={setDeleting}
       onCreate={onCreate}
       onUpdate={onUpdate}
diff --git a/packages/frontend/src/paths/instance/details/DetailPage.tsx 
b/packages/frontend/src/paths/instance/details/DetailPage.tsx
index 419e420..cc177f3 100644
--- a/packages/frontend/src/paths/instance/details/DetailPage.tsx
+++ b/packages/frontend/src/paths/instance/details/DetailPage.tsx
@@ -24,6 +24,7 @@ import { useState } from "preact/hooks";
 import { FormProvider } from "../../../components/form/FormProvider";
 import { Input } from "../../../components/form/Input";
 import { MerchantBackend } from "../../../declaration";
+import { useTranslator } from "../../../i18n";
 
 type Entity = MerchantBackend.Instances.InstanceReconfigurationMessage;
 interface Props {
@@ -46,6 +47,8 @@ function convert(from: 
MerchantBackend.Instances.QueryInstancesResponse): Entity
 export function DetailPage({ selected }: Props): VNode {
   const [value, valueHandler] = useState<Partial<Entity>>(convert(selected))
 
+  const i18n = useTranslator()
+  
   return <div>
     <section class="hero is-hero-bar">
       <div class="hero-body">
@@ -70,8 +73,8 @@ export function DetailPage({ selected }: Props): VNode {
         <div class="column is-6">
           <FormProvider<Entity> object={value} valueHandler={valueHandler} >
 
-            <Input<Entity> name="name" readonly />
-            <Input<Entity> name="payto_uris" readonly />
+            <Input<Entity> name="name" readonly label={i18n`Name`} />
+            <Input<Entity> name="payto_uris" readonly label={i18n`Account 
address`} />
 
           </FormProvider>
         </div>
diff --git a/packages/frontend/src/paths/instance/details/index.tsx 
b/packages/frontend/src/paths/instance/details/index.tsx
index 5e9fc7a..cda56a4 100644
--- a/packages/frontend/src/paths/instance/details/index.tsx
+++ b/packages/frontend/src/paths/instance/details/index.tsx
@@ -17,7 +17,7 @@ import { Fragment, h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { Loading } from "../../../components/exception/loading";
 import { DeleteModal } from "../../../components/modal";
-import { useInstanceContext } from "../../../context/backend";
+import { useInstanceContext } from "../../../context/instance";
 import { HttpError } from "../../../hooks/backend";
 import { useInstanceAPI, useInstanceDetails } from "../../../hooks/instance";
 import { DetailPage } from "./DetailPage";
diff --git a/packages/frontend/src/paths/instance/orders/create/CreatePage.tsx 
b/packages/frontend/src/paths/instance/orders/create/CreatePage.tsx
index 22ec9e6..a8bdd18 100644
--- a/packages/frontend/src/paths/instance/orders/create/CreatePage.tsx
+++ b/packages/frontend/src/paths/instance/orders/create/CreatePage.tsx
@@ -21,7 +21,6 @@
 
 import { add } from "date-fns";
 import { Fragment, h, VNode } from "preact";
-import { Message } from "preact-messages";
 import { useEffect, useState } from "preact/hooks";
 import * as yup from 'yup';
 import { FormProvider, FormErrors } from 
"../../../../components/form/FormProvider";
@@ -30,9 +29,10 @@ import { InputCurrency } from 
"../../../../components/form/InputCurrency";
 import { InputDate } from "../../../../components/form/InputDate";
 import { InputGroup } from "../../../../components/form/InputGroup";
 import { ProductList } from "../../../../components/product/ProductList";
-import { useConfigContext } from "../../../../context/backend";
+import { useConfigContext } from "../../../../context/config";
 import { MerchantBackend, WithId } from "../../../../declaration";
 import { useInstanceDetails } from "../../../../hooks/instance";
+import { Translate, useTranslator } from "../../../../i18n";
 import { OrderCreateSchema as schema } from '../../../../schemas/index';
 import { multiplyPrice, rate, subtractPrices, sumPrices } from 
"../../../../utils/amount";
 import { InventoryProductForm } from "./InventoryProductForm";
@@ -105,9 +105,9 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
           summary: order.pricing.summary,
           products: productList,
           extra: value.extra,
-          pay_deadline: value.payments.pay_deadline ? { t_ms: 
Math.floor(value.payments.pay_deadline.getTime()/1000)*1000 } : undefined,
-          wire_transfer_deadline: value.payments.pay_deadline ? { t_ms: 
Math.floor(value.payments.pay_deadline.getTime()/1000)*1000 } : undefined,
-          refund_deadline: value.payments.refund_deadline ? { t_ms: 
Math.floor(value.payments.refund_deadline.getTime()/1000)*1000 } : undefined,
+          pay_deadline: value.payments.pay_deadline ? { t_ms: 
Math.floor(value.payments.pay_deadline.getTime() / 1000) * 1000 } : undefined,
+          wire_transfer_deadline: value.payments.pay_deadline ? { t_ms: 
Math.floor(value.payments.pay_deadline.getTime() / 1000) * 1000 } : undefined,
+          refund_deadline: value.payments.refund_deadline ? { t_ms: 
Math.floor(value.payments.refund_deadline.getTime() / 1000) * 1000 } : 
undefined,
           max_fee: value.payments.max_fee,
           max_wire_fee: value.payments.max_wire_fee,
           delivery_date: value.payments.delivery_date ? { t_ms: 
value.payments.delivery_date.getTime() } : undefined,
@@ -122,7 +122,7 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
       onCreate(request);
     } catch (err) {
       const errors = err.inner as yup.ValidationError[]
-      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: { type: cur.type, params: cur.params, message: cur.message 
} }), {})
+      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: cur.message }), {})
       setErrors(pathMessages)
     }
   }
@@ -188,7 +188,7 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
 
 
   const discountOrRise = rate(value.pricing.order_price, totalPrice)
-  
+
   useEffect(() => {
     valueHandler(v => {
       return ({
@@ -205,7 +205,7 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
   const dmwf = !details_response.ok ? undefined : 
details_response.data.default_max_wire_fee;
   const dmdf = !details_response.ok ? undefined : 
details_response.data.default_max_deposit_fee;
   const dwfa = !details_response.ok ? undefined : 
details_response.data.default_wire_fee_amortization;
-  const dpd  = !details_response.ok ? undefined : 
details_response.data.default_pay_delay;
+  const dpd = !details_response.ok ? undefined : 
details_response.data.default_pay_delay;
   useEffect(() => {
     if (details_response.ok) {
       valueHandler(v => {
@@ -224,6 +224,8 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
     }
   }, [details_response.ok, dmwf, dmdf, dwfa, dpd])
 
+  const i18n = useTranslator()
+
   return <div>
 
     <section class="section is-main-section">
@@ -231,7 +233,7 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
         <div class="column" />
         <div class="column is-four-fifths">
 
-          <InputGroup name="inventory_products" alternative={
+          <InputGroup name="inventory_products" label={i18n`Inventory 
products`} alternative={
             inventoryList.length > 0 && <p>
               {inventoryList.length} products,
               in {inventoryList.reduce((prev, cur) => cur.quantity + prev, 0)} 
units,
@@ -246,13 +248,13 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
             {inventoryList.length > 0 &&
               <ProductList list={inventoryList.map(asProduct)}
                 actions={[{
-                  name: 'Remove', handler: (e) => 
removeProductFromTheInventoryList(e.product_id!)
+                  name: i18n`Remove`, handler: (e) => 
removeProductFromTheInventoryList(e.product_id!)
                 }]}
               />
             }
           </InputGroup>
 
-          <InputGroup name="products" alternative={
+          <InputGroup name="products" label={i18n`Products`} alternative={
             productList.length > 0 && <p>
               {productList.length} products,
               in {productList.reduce((prev, cur) => cur.quantity + prev, 0)} 
units,
@@ -267,7 +269,7 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
             {productList.length > 0 &&
               <ProductList list={productList}
                 actions={[{
-                  name: 'Remove', handler: (e, index) => {
+                  name: i18n`Remove`, handler: (e, index) => {
                     removeFromNewProduct(index);
                     setEditingProduct(e);
                   }
@@ -280,57 +282,59 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
           <FormProvider<Entity> errors={errors} object={value} 
valueHandler={valueHandler as any}>
             {hasProducts ?
               <Fragment>
-                <InputCurrency name="pricing.products_price" readonly />
-                <InputCurrency name="pricing.products_taxes" readonly />
+                <InputCurrency name="pricing.products_price" label={i18n`Total 
price`} readonly />
+                <InputCurrency name="pricing.products_taxes" label={i18n`Total 
tax`} readonly />
                 <InputCurrency name="pricing.order_price"
+                  label={i18n`Order price`}
                   addonAfter={value.pricing.order_price !== totalPrice && 
(discountOrRise < 1 ?
                     `discount of %${Math.round((1 - discountOrRise) * 100)}` :
                     `rise of %${Math.round((discountOrRise - 1) * 100)}`)
                   }
                 />
-                <InputCurrency name="pricing.net" readonly />
+                <InputCurrency name="pricing.net" label={i18n`Net`} readonly />
               </Fragment> :
-              <InputCurrency name="pricing.order_price" />
+              <InputCurrency name="pricing.order_price" label={i18n`Order 
price`} />
             }
 
-            <Input name="pricing.summary" inputType="multiline" />
+            <Input name="pricing.summary" inputType="multiline" 
label={i18n`Summary`} />
 
-            <InputGroup name="payments">
-              <InputDate name="payments.auto_refund_deadline" />
-              <InputDate name="payments.refund_deadline" />
-              <InputDate name="payments.pay_deadline" />
+            <InputGroup name="payments" label={i18n`Payments options`}>
+              <InputDate name="payments.auto_refund_deadline" label={i18n`Auto 
refund deadline`} />
+              <InputDate name="payments.refund_deadline" label={i18n`Refund 
deadline`} />
+              <InputDate name="payments.pay_deadline" label={i18n`Pay 
deadline`} />
 
-              <InputDate name="payments.delivery_date" />
-              {value.payments.delivery_date && <InputGroup 
name="payments.delivery_location" >
-                <Input name="payments.delivery_location.country" />
+              <InputDate name="payments.delivery_date" label={i18n`Delivery 
date`} />
+              {value.payments.delivery_date && <InputGroup 
name="payments.delivery_location" label={i18n`Location`} >
+                <Input name="payments.delivery_location.country" 
label={i18n`Country`} />
                 <Input name="payments.delivery_location.address_lines" 
inputType="multiline"
+                  label={i18n`Address`}
                   toStr={(v: string[] | undefined) => !v ? '' : v.join('\n')}
                   fromStr={(v: string) => v.split('\n')}
                 />
-                <Input name="payments.delivery_location.building_number" />
-                <Input name="payments.delivery_location.building_name" />
-                <Input name="payments.delivery_location.street" />
-                <Input name="payments.delivery_location.post_code" />
-                <Input name="payments.delivery_location.town_location" />
-                <Input name="payments.delivery_location.town" />
-                <Input name="payments.delivery_location.district" />
-                <Input name="payments.delivery_location.country_subdivision" />
+                <Input name="payments.delivery_location.building_number" 
label={i18n`Building number`} />
+                <Input name="payments.delivery_location.building_name" 
label={i18n`Building name`} />
+                <Input name="payments.delivery_location.street" 
label={i18n`Street`} />
+                <Input name="payments.delivery_location.post_code" 
label={i18n`Post code`} />
+                <Input name="payments.delivery_location.town_location" 
label={i18n`Town location`} />
+                <Input name="payments.delivery_location.town" 
label={i18n`Town`} />
+                <Input name="payments.delivery_location.district" 
label={i18n`District`} />
+                <Input name="payments.delivery_location.country_subdivision" 
label={i18n`Country subdivision`} />
               </InputGroup>}
 
-              <InputCurrency name="payments.max_fee" />
-              <InputCurrency name="payments.max_wire_fee" />
-              <Input name="payments.wire_fee_amortization" />
-              <Input name="payments.fullfilment_url" />
+              <InputCurrency name="payments.max_fee" label={i18n`Max fee`} />
+              <InputCurrency name="payments.max_wire_fee" label={i18n`Max wire 
fee`} />
+              <Input name="payments.wire_fee_amortization" label={i18n`Wire 
fee amortization`} />
+              <Input name="payments.fullfilment_url" label={i18n`Fullfilment 
url`} />
             </InputGroup>
 
-            <InputGroup name="extra">
-              <Input name="extra" inputType="multiline" />
+            <InputGroup name="extra" label={i18n`Extra information`}>
+              <Input name="extra" inputType="multiline" label={`JSON value`} />
             </InputGroup>
           </FormProvider>
 
           <div class="buttons is-right mt-5">
-            {onBack && <button class="button" onClick={onBack} ><Message 
id="Cancel" /></button>}
-            <button class="button is-success" onClick={submit} ><Message 
id="Confirm" /></button>
+            {onBack && <button class="button" onClick={onBack} 
><Translate>Cancel</Translate></button>}
+            <button class="button is-success" onClick={submit} 
><Translate>Confirm</Translate></button>
           </div>
 
         </div>
diff --git 
a/packages/frontend/src/paths/instance/orders/create/InventoryProductForm.tsx 
b/packages/frontend/src/paths/instance/orders/create/InventoryProductForm.tsx
index 274a66f..5dcebeb 100644
--- 
a/packages/frontend/src/paths/instance/orders/create/InventoryProductForm.tsx
+++ 
b/packages/frontend/src/paths/instance/orders/create/InventoryProductForm.tsx
@@ -19,6 +19,7 @@ import { FormProvider, FormErrors } from 
"../../../../components/form/FormProvid
 import { InputNumber } from "../../../../components/form/InputNumber";
 import { InputSearchProduct } from 
"../../../../components/form/InputSearchProduct";
 import { MerchantBackend, WithId } from "../../../../declaration";
+import { Translate, useTranslator } from "../../../../i18n";
 import { ProductMap } from "./CreatePage";
 
 type Form = {
@@ -36,29 +37,31 @@ export function InventoryProductForm({ currentProducts, 
onAddProduct }: Props):
   const [state, setState] = useState<Partial<Form>>(initialState)
   const [errors, setErrors] = useState<FormErrors<Form>>({})
 
+  const i18n = useTranslator()
+
   const submit = (): void => {
     if (!state.product) {
-      setErrors({ product: { message: 'select a product first' } });
+      setErrors({ product: i18n`select a product first` });
       return;
     }
     if (state.product.total_stock === -1) {
       onAddProduct(state.product, 1)
     } else {
       if (!state.quantity || state.quantity <= 0) {
-        setErrors({ quantity: { message: 'should be greater than 0' } });
+        setErrors({ quantity: i18n`should be greater than 0` });
         return;
       }
       const currentStock = state.product.total_stock - 
state.product.total_lost - state.product.total_sold
       const p = currentProducts[state.product.id]
       if (p) {
         if (state.quantity + p.quantity > currentStock) {
-          setErrors({ quantity: { message: `cannot be greater than current 
stock and quantity previously added. max: ${currentStock - p.quantity}` } });
+          setErrors({ quantity: i18n`cannot be greater than current stock and 
quantity previously added. max: ${currentStock - p.quantity}` });
           return;
         }
         onAddProduct(state.product, state.quantity + p.quantity)
       } else {
         if (state.quantity > currentStock) {
-          setErrors({ quantity: { message: `cannot be greater than current 
stock ${currentStock}` } });
+          setErrors({ quantity: i18n`cannot be greater than current stock 
${currentStock}` });
           return;
         }
         onAddProduct(state.product, state.quantity)
@@ -70,9 +73,9 @@ export function InventoryProductForm({ currentProducts, 
onAddProduct }: Props):
 
   return <FormProvider<Form> errors={errors} object={state} 
valueHandler={setState}>
     <InputSearchProduct selected={state.product} onChange={(p) => setState(v 
=> ({ ...v, product: p }))} />
-    <InputNumber<Form> name="quantity" />
+    <InputNumber<Form> name="quantity" label={i18n`Quantity`} />
     <div class="buttons is-right mt-5">
-      <button class="button is-success" onClick={submit}>add</button>
+      <button class="button is-success" 
onClick={submit}><Translate>Add</Translate></button>
     </div>
   </FormProvider>
 }
\ No newline at end of file
diff --git 
a/packages/frontend/src/paths/instance/orders/create/NonInventoryProductForm.tsx
 
b/packages/frontend/src/paths/instance/orders/create/NonInventoryProductForm.tsx
index 7edf6fb..e94892a 100644
--- 
a/packages/frontend/src/paths/instance/orders/create/NonInventoryProductForm.tsx
+++ 
b/packages/frontend/src/paths/instance/orders/create/NonInventoryProductForm.tsx
@@ -20,7 +20,6 @@ import { Input } from "../../../../components/form/Input";
 import { InputCurrency } from "../../../../components/form/InputCurrency";
 import { InputImage } from "../../../../components/form/InputImage";
 import { InputNumber } from "../../../../components/form/InputNumber";
-import { Stock } from "../../../../components/form/InputStock";
 import { InputTaxes } from "../../../../components/form/InputTaxes";
 import { ConfirmModal } from "../../../../components/modal";
 import { MerchantBackend } from "../../../../declaration";
@@ -29,6 +28,7 @@ import {
   NonInventoryProductSchema as schema
 } from '../../../../schemas';
 import * as yup from 'yup';
+import { useTranslator } from "../../../../i18n";
 
 type Entity = MerchantBackend.Product
 
@@ -104,7 +104,7 @@ export function ProductForm({ onSubscribe, initial }: 
ProductProps) {
       return result
     } catch (err) {
       const errors = err.inner as yup.ValidationError[]
-      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: { type: cur.type, params: cur.params, message: cur.message 
} }), {})
+      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: cur.message }), {})
       setErrors(pathMessages)
     }
   }, [value])
@@ -113,17 +113,19 @@ export function ProductForm({ onSubscribe, initial }: 
ProductProps) {
     onSubscribe(submit)
   }, [submit])
 
+  const i18n = useTranslator()
+
   return <div>
     <FormProvider<NonInventoryProduct> name="product" errors={errors} 
object={value} valueHandler={valueHandler} >
 
-      <InputImage<NonInventoryProduct> name="image" />
-      <Input<NonInventoryProduct> name="description" inputType="multiline" />
-      <Input<NonInventoryProduct> name="unit" />
-      <InputCurrency<NonInventoryProduct> name="price" />
+      <InputImage<NonInventoryProduct> name="image" label={i18n`Image`}  />
+      <Input<NonInventoryProduct> name="description" inputType="multiline" 
label={i18n`Description`} />
+      <Input<NonInventoryProduct> name="unit" label={i18n`Unit`} />
+      <InputCurrency<NonInventoryProduct> name="price" label={i18n`Price`} />
 
-      <InputNumber<NonInventoryProduct> name="quantity" />
+      <InputNumber<NonInventoryProduct> name="quantity" label={i18n`Quantity`} 
/>
 
-      <InputTaxes<NonInventoryProduct> name="taxes" />
+      <InputTaxes<NonInventoryProduct> name="taxes" label={i18n`Taxes`} />
 
     </FormProvider>
   </div>
diff --git a/packages/frontend/src/paths/instance/orders/details/DetailPage.tsx 
b/packages/frontend/src/paths/instance/orders/details/DetailPage.tsx
index 6e9fbec..a34bb27 100644
--- a/packages/frontend/src/paths/instance/orders/details/DetailPage.tsx
+++ b/packages/frontend/src/paths/instance/orders/details/DetailPage.tsx
@@ -28,8 +28,8 @@ import { InputCurrency } from 
"../../../../components/form/InputCurrency";
 import { NotificationCard } from "../../../../components/menu";
 import { ProductList } from "../../../../components/product/ProductList";
 import { MerchantBackend } from "../../../../declaration";
+import { Translate, useTranslator } from "../../../../i18n";
 import { mergeRefunds } from "../../../../utils/amount";
-import { copyToClipboard } from "../../../../utils/functions";
 import { RefundModal } from "../list/Table";
 import { Event, Timeline } from "./Timeline";
 
@@ -75,6 +75,7 @@ function ClaimedPage({ id, order }: { id: string; order: 
MerchantBackend.Orders.
   })
 
   const [value, valueHandler] = useState<Partial<Claimed>>(order)
+  const i18n = useTranslator()
 
   return <div>
     <section class="section">
@@ -88,8 +89,8 @@ function ClaimedPage({ id, order }: { id: string; order: 
MerchantBackend.Orders.
               <div class="level">
                 <div class="level-left">
                   <div class="level-item">
-                    Order #{id}
-                    <div class="tag is-info ml-4">claimed</div>
+                    <Translate>Order</Translate> #{id}
+                    <div class="tag is-info 
ml-4"><Translate>claimed</Translate></div>
                   </div>
                 </div>
               </div>
@@ -106,7 +107,7 @@ function ClaimedPage({ id, order }: { id: string; order: 
MerchantBackend.Orders.
                     <h1 class="title">
                       <button class="button is-info" onClick={() => {
                         if (order.contract_terms.fulfillment_url) 
copyToClipboard(order.contract_terms.fulfillment_url)
-                      }}>copy url</button>
+                      }}><Translate>copy url</Translate></button>
                     </h1>
                   </div>
                 </div>
@@ -122,8 +123,8 @@ function ClaimedPage({ id, order }: { id: string; order: 
MerchantBackend.Orders.
                       // maxWidth: '100%',
                     }}>
                       {/* <a href={order.order_status_url} rel="nofollow" 
target="new">{order.order_status_url}</a> */}
-                      <p>pay at:  <b>missing value, there is no 
order_status_url</b></p>
-                      <p>created at: {format(new 
Date(order.contract_terms.timestamp.t_ms), 'yyyy-MM-dd HH:mm:ss')}</p>
+                      <p><Translate>pay at</Translate>:  <b>missing value, 
there is no order_status_url</b></p>
+                      <p><Translate>created at</Translate>: {format(new 
Date(order.contract_terms.timestamp.t_ms), 'yyyy-MM-dd HH:mm:ss')}</p>
                     </div>
                   </div>
                 </div>
@@ -134,15 +135,15 @@ function ClaimedPage({ id, order }: { id: string; order: 
MerchantBackend.Orders.
           <section class="section">
             <div class="columns">
               <div class="column is-4">
-                <div class="title">Timeline</div>
+                <div class="title"><Translate>Timeline</Translate></div>
                 <Timeline events={events} />
               </div>
               <div class="column is-8" >
-                <div class="title">Payment details</div>
+                <div class="title"><Translate>Payment details</Translate></div>
                 <FormProvider<Claimed> object={value} 
valueHandler={valueHandler} >
-                  <Input name="contract_terms.summary" readonly 
inputType="multiline" />
-                  <InputCurrency name="contract_terms.amount" readonly />
-                  <Input<Claimed> name="order_status" readonly />
+                  <Input name="contract_terms.summary" readonly 
inputType="multiline" label={i18n`Summary`} />
+                  <InputCurrency name="contract_terms.amount" readonly 
label={i18n`Amount`} />
+                  <Input<Claimed> name="order_status" readonly 
label={i18n`Order status`} />
                 </FormProvider>
               </div>
             </div>
@@ -152,7 +153,7 @@ function ClaimedPage({ id, order }: { id: string; order: 
MerchantBackend.Orders.
             <section class="section">
               <div class="columns">
                 <div class="column is-12" >
-                  <div class="title">Product list</div>
+                  <div class="title"><Translate>Product list</Translate></div>
                   <ProductList list={order.contract_terms.products} />
                 </div>
                 <div class="column" />
@@ -217,6 +218,7 @@ function PaidPage({ id, order, onRefund }: { id: string; 
order: MerchantBackend.
   const [value, valueHandler] = useState<Partial<Paid>>(order)
 
   const refundable = new Date().getTime() < 
order.contract_terms.refund_deadline.t_ms
+  const i18n = useTranslator()
 
   return <div>
     <section class="section">
@@ -230,13 +232,13 @@ function PaidPage({ id, order, onRefund }: { id: string; 
order: MerchantBackend.
               <div class="level">
                 <div class="level-left">
                   <div class="level-item">
-                    Order #{id}
-                    <div class="tag is-success ml-4">paid</div>
+                    <Translate>Order</Translate> #{id}
+                    <div class="tag is-success 
ml-4"><Translate>paid</Translate></div>
                     {order.wired ?
-                      <div class="tag is-success ml-4">wired</div> : null
+                      <div class="tag is-success 
ml-4"><Translate>wired</Translate></div> : null
                     }
                     {order.refunded ?
-                      <div class="tag is-danger ml-4">refunded</div> : null
+                      <div class="tag is-danger 
ml-4"><Translate>refunded</Translate></div> : null
                     }
                   </div>
                 </div>
@@ -253,10 +255,10 @@ function PaidPage({ id, order, onRefund }: { id: string; 
order: MerchantBackend.
                   <div class="level-item">
                     <h1 class="title">
                       <div class="buttons">
-                        {refundable && <button class="button is-danger" 
onClick={() => onRefund(id)}>refund</button>}
+                        {refundable && <button class="button is-danger" 
onClick={() => onRefund(id)}><Translate>refund</Translate></button>}
                         <button class="button is-info" onClick={() => {
                           if (order.contract_terms.fulfillment_url) 
copyToClipboard(order.contract_terms.fulfillment_url)
-                        }}>copy url</button>
+                        }}><Translate>copy url</Translate></button>
                       </div>
                     </h1>
                   </div>
@@ -284,17 +286,17 @@ function PaidPage({ id, order, onRefund }: { id: string; 
order: MerchantBackend.
           <section class="section">
             <div class="columns">
               <div class="column is-4">
-                <div class="title">Timeline</div>
+                <div class="title"><Translate>Timeline</Translate></div>
                 <Timeline events={events} />
               </div>
               <div class="column is-8" >
-                <div class="title">Payment details</div>
+                <div class="title"><Translate>Payment details</Translate></div>
                 <FormProvider<Paid> object={value} valueHandler={valueHandler} 
>
-                  <Input name="contract_terms.summary" readonly 
inputType="multiline" />
-                  <InputCurrency name="contract_terms.amount" readonly />
-                  {order.refunded && <InputCurrency<Paid> name="refund_amount" 
readonly />}
-                  <InputCurrency<Paid> name="deposit_total" readonly />
-                  <Input<Paid> name="order_status" readonly />
+                  <Input name="contract_terms.summary" readonly 
inputType="multiline" label={i18n`Summary`} />
+                  <InputCurrency name="contract_terms.amount" readonly 
label={i18n`Amount`} />
+                  {order.refunded && <InputCurrency<Paid> name="refund_amount" 
readonly label={i18n`Refunded amount`} />}
+                  <InputCurrency<Paid> name="deposit_total" readonly 
label={i18n`Deposit total`} />
+                  <Input<Paid> name="order_status" readonly label={i18n`Order 
status`} />
                 </FormProvider>
               </div>
             </div>
@@ -303,7 +305,7 @@ function PaidPage({ id, order, onRefund }: { id: string; 
order: MerchantBackend.
           {order.contract_terms.products.length ? <section class="section">
             <div class="columns">
               <div class="column is-12" >
-                <div class="title">Product list</div>
+                <div class="title"><Translate>Product list</Translate></div>
                 <ProductList list={order.contract_terms.products} />
               </div>
               <div class="column" />
@@ -319,6 +321,7 @@ function PaidPage({ id, order, onRefund }: { id: string; 
order: MerchantBackend.
 
 function UnpaidPage({ id, order }: { id: string; order: 
MerchantBackend.Orders.CheckPaymentUnpaidResponse }) {
   const [value, valueHandler] = useState<Partial<Unpaid>>(order)
+  const i18n = useTranslator()
   return <div>
 
     <section class="hero is-hero-bar">
@@ -327,10 +330,10 @@ function UnpaidPage({ id, order }: { id: string; order: 
MerchantBackend.Orders.C
           <div class="level-left">
             <div class="level-item">
               <h1 class="title">
-                Order #{id}
+                <Translate>Order</Translate> #{id}
               </h1>
             </div>
-            <div class="tag is-dark">unpaid</div>
+            <div class="tag is-dark"><Translate>unpaid</Translate></div>
           </div>
         </div>
 
@@ -343,8 +346,8 @@ function UnpaidPage({ id, order }: { id: string; order: 
MerchantBackend.Orders.C
                 textOverflow: 'ellipsis',
                 // maxWidth: '100%',
               }}>
-                <p>pay at: <a href={order.order_status_url} rel="nofollow" 
target="new">{order.order_status_url}</a></p>
-                <p>created at: <b>missing value, there is no contract term 
yet</b></p>
+                <p><Translate>pay at</Translate>: <a 
href={order.order_status_url} rel="nofollow" 
target="new">{order.order_status_url}</a></p>
+                <p><Translate>created at</Translate>: <b>missing value, there 
is no contract term yet</b></p>
               </div>
             </div>
           </div>
@@ -357,9 +360,9 @@ function UnpaidPage({ id, order }: { id: string; order: 
MerchantBackend.Orders.C
         <div class="column" />
         <div class="column is-6">
           <FormProvider<Unpaid> object={value} valueHandler={valueHandler} >
-            <Input<Unpaid> name="order_status" readonly />
-            <Input<Unpaid> name="order_status_url" readonly />
-            <Input<Unpaid> name="taler_pay_uri" readonly />
+            <Input<Unpaid> name="order_status" readonly label={i18n`Order 
status`} />
+            <Input<Unpaid> name="order_status_url" readonly label={i18n`Order 
status URL`} />
+            <Input<Unpaid> name="taler_pay_uri" readonly label={i18n`Pay URI`} 
/>
           </FormProvider>
         </div>
         <div class="column" />
@@ -377,7 +380,7 @@ export function DetailPage({ id, selected, onRefund }: 
Props): VNode {
       case 'claimed': return <ClaimedPage id={id} order={selected} />
       case 'paid': return <PaidPage id={id} order={selected} 
onRefund={setShowRefund} />
       case 'unpaid': return <UnpaidPage id={id} order={selected} />
-      default: return <div>unknown order status</div>
+      default: return <div><Translate>Unknown order status. This is an error, 
please contact the administrator.</Translate></div>
     }
   }
 
@@ -401,4 +404,10 @@ export function DetailPage({ id, selected, onRefund }: 
Props): VNode {
       }}
     />}
   </Fragment>
-}
\ No newline at end of file
+}
+
+async function copyToClipboard(text: string) {
+  return navigator.clipboard.writeText(text)
+}
+
+
diff --git a/packages/frontend/src/paths/instance/orders/details/index.tsx 
b/packages/frontend/src/paths/instance/orders/details/index.tsx
index 28f7818..cd4e163 100644
--- a/packages/frontend/src/paths/instance/orders/details/index.tsx
+++ b/packages/frontend/src/paths/instance/orders/details/index.tsx
@@ -19,6 +19,7 @@ import { Loading } from 
"../../../../components/exception/loading";
 import { NotificationCard } from "../../../../components/menu";
 import { HttpError } from "../../../../hooks/backend";
 import { useOrderDetails, useOrderAPI } from "../../../../hooks/order";
+import { useTranslator } from "../../../../i18n";
 import { Notification } from "../../../../utils/types";
 import { DetailPage } from "./DetailPage";
 
@@ -36,6 +37,8 @@ export default function Update({ oid, onBack, onLoadError, 
onNotFound, onUnautho
   const result = useOrderDetails(oid)
   const [notif, setNotif] = useState<Notification | undefined>(undefined)
 
+  const i18n = useTranslator()
+
   if (result.clientError && result.isUnauthorized) return onUnauthorized()
   if (result.clientError && result.isNotfound) return onNotFound()
   if (result.loading) return <Loading />
@@ -50,10 +53,10 @@ export default function Update({ oid, onBack, onLoadError, 
onNotFound, onUnautho
       id={oid}
       onRefund={(id, value) => refundOrder(id, value)
         .then(() => setNotif({
-          message: 'refund created successfully',
+          message: i18n`refund created successfully`,
           type: "SUCCESS"
         })).catch((error) => setNotif({
-          message: 'could not create the refund',
+          message: i18n`could not create the refund`,
           type: "ERROR",
           description: error.message
         }))
diff --git a/packages/frontend/src/paths/instance/orders/list/Table.tsx 
b/packages/frontend/src/paths/instance/orders/list/Table.tsx
index e4706e9..d54e3b7 100644
--- a/packages/frontend/src/paths/instance/orders/list/Table.tsx
+++ b/packages/frontend/src/paths/instance/orders/list/Table.tsx
@@ -21,7 +21,6 @@
 
 import { format } from "date-fns";
 import { h, VNode } from "preact";
-import { Message } from "preact-messages";
 import { StateUpdater, useState } from "preact/hooks";
 import { FormProvider, FormErrors } from 
"../../../../components/form/FormProvider";
 import { Input } from "../../../../components/form/Input";
@@ -31,6 +30,7 @@ import { InputSelector } from 
"../../../../components/form/InputSelector";
 import { ConfirmModal } from "../../../../components/modal";
 import { MerchantBackend, WithId } from "../../../../declaration";
 import { useOrderDetails } from "../../../../hooks/order";
+import { Translate, useTranslator } from "../../../../i18n";
 import { RefoundSchema } from "../../../../schemas";
 import { mergeRefunds, subtractPrices, sumPrices } from 
"../../../../utils/amount";
 import { AMOUNT_ZERO_REGEX } from "../../../../utils/constants";
@@ -57,7 +57,7 @@ export function CardTable({ instances, onCreate, onRefund, 
onCopyURL, onSelect,
 
   return <div class="card has-table">
     <header class="card-header">
-      <p class="card-header-title"><span class="icon"><i class="mdi 
mdi-cash-register" /></span><Message id="Orders" /></p>
+      <p class="card-header-title"><span class="icon"><i class="mdi 
mdi-cash-register" /></span><Translate>Orders</Translate></p>
 
       <div class="card-header-icon" aria-label="more options" />
 
@@ -108,13 +108,13 @@ interface TableProps {
 
 function Table({ instances, onSelect, onRefund, onCopyURL, onLoadMoreAfter, 
onLoadMoreBefore, hasMoreAfter, hasMoreBefore }: TableProps): VNode {
   return <div class="table-container">
-    {onLoadMoreBefore && <button class="button is-fullwidth" 
disabled={!hasMoreBefore} onClick={onLoadMoreBefore}> load newer orders 
</button>}
+    {onLoadMoreBefore && <button class="button is-fullwidth" 
disabled={!hasMoreBefore} onClick={onLoadMoreBefore}><Translate>load newer 
orders</Translate></button>}
     <table class="table is-striped is-hoverable is-fullwidth">
       <thead>
         <tr>
-          <th style={{ minWidth: 100 }}><Message id="fields.order.date.label" 
/></th>
-          <th style={{ minWidth: 100 }}><Message 
id="fields.order.amount.label" /></th>
-          <th style={{ minWidth: 500 }}><Message 
id="fields.order.summary.label" /></th>
+          <th style={{ minWidth: 100 }}><Translate>Date</Translate></th>
+          <th style={{ minWidth: 100 }}><Translate>Amount</Translate></th>
+          <th style={{ minWidth: 500 }}><Translate>Summary</Translate></th>
           <th style={{ minWidth: 50 }} />
         </tr>
       </thead>
@@ -128,12 +128,12 @@ function Table({ instances, onSelect, onRefund, 
onCopyURL, onLoadMoreAfter, onLo
               <div class="buttons is-right">
                 {(i.refundable) &&
                   <button class="button is-small is-danger jb-modal" 
type="button" onClick={(): void => onRefund(i)}>
-                    Refund
+                    <Translate>Refund</Translate>
                   </button>
                 }
                 {(!i.paid) &&
                   <button class="button is-small is-info jb-modal" 
type="button" onClick={(): void => onCopyURL(i)}>
-                    copy url
+                    <Translate>copy url</Translate>
                   </button>
                 }
               </div>
@@ -142,7 +142,7 @@ function Table({ instances, onSelect, onRefund, onCopyURL, 
onLoadMoreAfter, onLo
         })}
       </tbody>
     </table>
-    {onLoadMoreAfter && <button class="button is-fullwidth" 
disabled={!hasMoreAfter} onClick={onLoadMoreAfter}> load older orders </button>}
+    {onLoadMoreAfter && <button class="button is-fullwidth" 
disabled={!hasMoreAfter} onClick={onLoadMoreAfter}><Translate>load older 
orders</Translate></button>}
   </div>
 }
 
@@ -151,7 +151,7 @@ function EmptyTable(): VNode {
     <p>
       <span class="icon is-large"><i class="mdi mdi-emoticon-sad mdi-48px" 
/></span>
     </p>
-    <p>No orders has been found</p>
+    <p><Translate>No orders has been found</Translate></p>
   </div>
 }
 
@@ -165,7 +165,7 @@ export function RefundModal({ id, onCancel, onConfirm }: 
RefundModalProps): VNod
   const result = useOrderDetails(id)
   type State = { mainReason?: string, description?: string, refund?: string }
   const [form, setValue] = useState<State>({})
-
+  const i18n = useTranslator();
   const [errors, setErrors] = useState<FormErrors<State>>({})
 
   const validateAndConfirm = () => {
@@ -178,7 +178,7 @@ export function RefundModal({ id, onCancel, onConfirm }: 
RefundModalProps): VNod
       })
     } catch (err) {
       const errors = err.inner as any[]
-      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: { type: cur.type, params: cur.params, message: cur.message 
} }), {})
+      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: cur.message }), {})
       setErrors(pathMessages)
     }
   }
@@ -190,18 +190,18 @@ export function RefundModal({ id, onCancel, onConfirm }: 
RefundModalProps): VNod
   const totalRefundable = !orderPrice ? undefined : (refunds.length ? 
subtractPrices(orderPrice, totalRefunded) : orderPrice)
 
   const isRefundable = totalRefundable && 
!AMOUNT_ZERO_REGEX.test(totalRefundable)
-
+  //FIXME: parameters in the translation
   return <ConfirmModal description="refund" danger active onCancel={onCancel} 
onConfirm={validateAndConfirm}>
     {refunds.length > 0 && <div class="columns">
       <div class="column is-2" />
       <div class="column is-8">
-        <InputGroup name="asd" description={`${totalRefunded} was already 
refunded`}>
+        <InputGroup name="asd" label={`${totalRefunded} was already refunded`}>
           <table class="table is-fullwidth">
             <thead>
               <tr>
-                <th>date</th>
-                <th>amount</th>
-                <th>reason</th>
+                <th><Translate>date</Translate></th>
+                <th><Translate>amount</Translate></th>
+                <th><Translate>reason</Translate></th>
               </tr>
             </thead>
             <tbody>
@@ -219,13 +219,13 @@ export function RefundModal({ id, onCancel, onConfirm }: 
RefundModalProps): VNod
       <div class="column is-2" />
     </div>}
 
-    { isRefundable && <FormProvider<State> errors={errors} object={form} 
valueHandler={(d) => setValue(d as any)}>
-      <InputCurrency<State> name="refund">
-        Max refundable: {totalRefundable}
+    {isRefundable && <FormProvider<State> errors={errors} object={form} 
valueHandler={(d) => setValue(d as any)}>
+      <InputCurrency<State> name="refund" label={i18n`Refund`}>
+        <Translate>Max refundable:</Translate> {totalRefundable}
       </InputCurrency>
-      <InputSelector name="mainReason" values={['duplicated', 'requested by 
the customer', 'other']} />
-      {form.mainReason && <Input<State> name="description" />}
-    </FormProvider> }
+      <InputSelector name="mainReason" label={i18n`Reason`} 
values={[i18n`duplicated`, i18n`requested by the customer`, i18n`other`]} />
+      {form.mainReason && <Input<State> label={i18n`Description`} 
name="description" />}
+    </FormProvider>}
 
   </ConfirmModal>
 }
diff --git a/packages/frontend/src/paths/instance/orders/list/index.tsx 
b/packages/frontend/src/paths/instance/orders/list/index.tsx
index 6026e7b..aeba05b 100644
--- a/packages/frontend/src/paths/instance/orders/list/index.tsx
+++ b/packages/frontend/src/paths/instance/orders/list/index.tsx
@@ -27,7 +27,7 @@ import { DatePicker } from 
'../../../../components/form/DatePicker';
 import { NotificationCard } from '../../../../components/menu';
 import { HttpError } from '../../../../hooks/backend';
 import { InstanceOrderFilter, useInstanceOrders, useOrderAPI } from 
'../../../../hooks/order';
-import { copyToClipboard } from '../../../../utils/functions';
+import { Translate, useTranslator } from '../../../../i18n';
 import { Notification } from '../../../../utils/types';
 import { CardTable } from './Table';
 
@@ -78,6 +78,8 @@ export default function ({ onUnauthorized, onLoadError, 
onCreate, onSelect, onNo
     }
   }
 
+  const i18n = useTranslator()
+
   return <section class="section is-main-section">
     <NotificationCard notification={notif} />
 
@@ -86,7 +88,7 @@ export default function ({ onUnauthorized, onLoadError, 
onCreate, onSelect, onNo
         <div class="level-item">
           <div class="field has-addons">
             <div class="control">
-              <input class={errorOrderId ? "input is-danger" : "input"} 
type="text" value={orderId} onChange={e => setOrderId(e.currentTarget.value)} 
placeholder="go to order id" />
+              <input class={errorOrderId ? "input is-danger" : "input"} 
type="text" value={orderId} onChange={e => setOrderId(e.currentTarget.value)} 
placeholder={i18n`go to order id`} />
               {errorOrderId && <p class="help is-danger">{errorOrderId}</p>}
             </div>
             <div class="control">
@@ -102,10 +104,10 @@ export default function ({ onUnauthorized, onLoadError, 
onCreate, onSelect, onNo
       <div class="column">
         <div class="tabs">
           <ul>
-            <li class={isPaidActive}><a onClick={() => setFilter({ paid: 'yes' 
})}>Paid</a></li>
-            <li class={isRefundedActive}><a onClick={() => setFilter({ 
refunded: 'yes' })}>Refunded</a></li>
-            <li class={isNotWiredActive}><a onClick={() => setFilter({ wired: 
'no' })}>Not wired</a></li>
-            <li class={isAllActive}><a onClick={() => 
setFilter({})}>All</a></li>
+            <li class={isPaidActive}><a onClick={() => setFilter({ paid: 'yes' 
})}><Translate>Paid</Translate></a></li>
+            <li class={isRefundedActive}><a onClick={() => setFilter({ 
refunded: 'yes' })}><Translate>Refunded</Translate></a></li>
+            <li class={isNotWiredActive}><a onClick={() => setFilter({ wired: 
'no' })}><Translate>Not wired</Translate></a></li>
+            <li class={isAllActive}><a onClick={() => 
setFilter({})}><Translate>All</Translate></a></li>
           </ul>
         </div>
       </div>
@@ -118,7 +120,7 @@ export default function ({ onUnauthorized, onLoadError, 
onCreate, onSelect, onNo
               </a>
             </div>}
             <div class="control">
-              <input class="input" type="text" readonly value={!filter.date ? 
'' : format(filter.date, 'yyyy/MM/dd')} placeholder="pick a date" />
+              <input class="input" type="text" readonly value={!filter.date ? 
'' : format(filter.date, 'yyyy/MM/dd')} placeholder={i18n`pick a date`} />
             </div>
             <div class="control">
               <a class="button" onClick={() => { setPickDate(true) }}>
@@ -142,10 +144,10 @@ export default function ({ onUnauthorized, onLoadError, 
onCreate, onSelect, onNo
       onCopyURL={(id) => getPaymentURL(id).then((resp) => 
copyToClipboard(resp.data))}
       onRefund={(id, value) => refundOrder(id, value)
         .then(() => setNotif({
-          message: 'refund created successfully',
+          message: i18n`refund created successfully`,
           type: "SUCCESS"
         })).catch((error) => setNotif({
-          message: 'could not create the refund',
+          message: i18n`could not create the refund`,
           type: "ERROR",
           description: error.message
         }))
@@ -154,4 +156,8 @@ export default function ({ onUnauthorized, onLoadError, 
onCreate, onSelect, onNo
       onLoadMoreAfter={result.loadMore} hasMoreAfter={!result.isReachingEnd}
     />
   </section>
-}
\ No newline at end of file
+}
+
+async function copyToClipboard(text: string) {
+  return navigator.clipboard.writeText(text)
+}
diff --git 
a/packages/frontend/src/paths/instance/products/create/CreatePage.tsx 
b/packages/frontend/src/paths/instance/products/create/CreatePage.tsx
index 427ebc0..de33564 100644
--- a/packages/frontend/src/paths/instance/products/create/CreatePage.tsx
+++ b/packages/frontend/src/paths/instance/products/create/CreatePage.tsx
@@ -20,10 +20,10 @@
 */
 
 import { h, VNode } from "preact";
-import { Message } from "preact-messages";
 import { ProductForm } from "../../../../components/product/ProductForm";
 import { MerchantBackend } from "../../../../declaration";
 import { useListener } from "../../../../hooks";
+import { Translate } from "../../../../i18n";
 
 type Entity = MerchantBackend.Products.ProductAddDetail & { product_id: string}
 
@@ -47,8 +47,8 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
           <ProductForm onSubscribe={addFormSubmitter} />
 
           <div class="buttons is-right mt-5">
-            {onBack && <button class="button" onClick={onBack} ><Message 
id="Cancel" /></button>}
-            <button class="button is-success" onClick={submitForm} ><Message 
id="Confirm" /></button>
+            {onBack && <button class="button" onClick={onBack} 
><Translate>Cancel</Translate></button>}
+            <button class="button is-success" onClick={submitForm} 
><Translate>Confirm</Translate></button>
           </div>
 
         </div>
diff --git a/packages/frontend/src/paths/instance/products/create/index.tsx 
b/packages/frontend/src/paths/instance/products/create/index.tsx
index ed997c4..6e81a04 100644
--- a/packages/frontend/src/paths/instance/products/create/index.tsx
+++ b/packages/frontend/src/paths/instance/products/create/index.tsx
@@ -24,6 +24,7 @@ import { useState } from 'preact/hooks';
 import { NotificationCard } from '../../../../components/menu';
 import { MerchantBackend } from '../../../../declaration';
 import { useProductAPI } from '../../../../hooks/product';
+import { useTranslator } from '../../../../i18n';
 import { Notification } from '../../../../utils/types';
 import { CreatePage } from './CreatePage';
 
@@ -35,7 +36,8 @@ interface Props {
 export default function CreateProduct({ onConfirm, onBack }: Props): VNode {
   const { createProduct } = useProductAPI()
   const [notif, setNotif] = useState<Notification | undefined>(undefined)
-
+  const i18n = useTranslator()
+  
   return <Fragment>
     <NotificationCard notification={notif} />
     <CreatePage
@@ -43,7 +45,7 @@ export default function CreateProduct({ onConfirm, onBack }: 
Props): VNode {
       onCreate={(request: MerchantBackend.Products.ProductAddDetail) => {
         createProduct(request).then(() => onConfirm()).catch((error) => {
           setNotif({
-            message: 'could not create product',
+            message: i18n`could not create product`,
             type: "ERROR",
             description: error.message
           })
diff --git a/packages/frontend/src/paths/instance/products/list/Table.tsx 
b/packages/frontend/src/paths/instance/products/list/Table.tsx
index 65f6c6a..44418e9 100644
--- a/packages/frontend/src/paths/instance/products/list/Table.tsx
+++ b/packages/frontend/src/paths/instance/products/list/Table.tsx
@@ -21,13 +21,13 @@
 
 import { format } from "date-fns"
 import { ComponentChildren, Fragment, h, VNode } from "preact"
-import { Message } from "preact-messages"
 import { StateUpdater, useState } from "preact/hooks"
 import { FormProvider, FormErrors } from 
"../../../../components/form/FormProvider"
 import { InputCurrency } from "../../../../components/form/InputCurrency"
 import { InputNumber } from "../../../../components/form/InputNumber"
 import { MerchantBackend, WithId } from "../../../../declaration"
 import emptyImage from "../../../../assets/empty.png";
+import { Translate, useTranslator } from "../../../../i18n"
 
 type Entity = MerchantBackend.Products.ProductDetail & WithId
 
@@ -45,7 +45,7 @@ export function CardTable({ instances, onCreate, onSelect, 
onUpdate, onDelete }:
 
   return <div class="card has-table">
     <header class="card-header">
-      <p class="card-header-title"><span class="icon"><i class="mdi 
mdi-shopping" /></span><Message id="Products" /></p>
+      <p class="card-header-title"><span class="icon"><i class="mdi 
mdi-shopping" /></span><Translate>Products</Translate></p>
 
       <div class="card-header-icon" aria-label="more options" />
       <div class="card-header-icon" aria-label="more options">
@@ -82,13 +82,13 @@ function Table({ rowSelection, rowSelectionHandler, 
instances, onSelect, onUpdat
       <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
         <thead>
           <tr>
-            <th><Message id="fields.product.image.label" style={{ with: 100 }} 
/></th>
-            <th><Message id="fields.product.description.label" /></th>
-            <th><Message id="fields.product.sell.label" /></th>
-            <th><Message id="fields.product.taxes.label" /></th>
-            <th><Message id="fields.product.profit.label" /></th>
-            <th><Message id="fields.product.stock.label" /></th>
-            <th><Message id="fields.product.sold.label" /></th>
+            <th><Translate>Image</Translate></th>
+            <th><Translate>Description</Translate></th>
+            <th><Translate>Sell</Translate></th>
+            <th><Translate>Taxes</Translate></th>
+            <th><Translate>Profit</Translate></th>
+            <th><Translate>Stock</Translate></th>
+            <th><Translate>Sold</Translate></th>
             <th />
           </tr>
         </thead>
@@ -154,15 +154,16 @@ interface FastProductUpdate {
 }
 
 function FastProductWithInfiniteStockUpdateForm({ product, onUpdate, onCancel 
}: FastProductUpdateFormProps) {
-  const [value, valueHandler] = useState<{price:string}>({price: 
product.price})
+  const [value, valueHandler] = useState<{ price: string }>({ price: 
product.price })
+  const i18n = useTranslator()
 
   return <Fragment>
     <FormProvider<FastProductUpdate> name="added" object={value} 
valueHandler={valueHandler as any} >
-      <InputCurrency<FastProductUpdate> name="price" />
+      <InputCurrency<FastProductUpdate> name="price" label={i18n`Price`} />
     </FormProvider>
 
     <div class="buttons is-right mt-5">
-      <button class="button" onClick={onCancel} ><Message id="Cancel" 
/></button>
+      <button class="button" onClick={onCancel} 
><Translate>Cancel</Translate></button>
       <button class="button is-info" onClick={() => {
 
         return onUpdate({
@@ -170,7 +171,7 @@ function FastProductWithInfiniteStockUpdateForm({ product, 
onUpdate, onCancel }:
           price: value.price,
         })
 
-      }}><Message id="Confirm" /></button>
+      }}><Translate>Confirm</Translate></button>
     </div>
 
   </Fragment>
@@ -184,9 +185,9 @@ function FastProductWithManagedStockUpdateForm({ product, 
onUpdate, onCancel }:
   const currentStock = product.total_stock - product.total_sold - 
product.total_lost
 
   const errors: FormErrors<FastProductUpdate> = {
-    lost: currentStock + value.incoming < value.lost ? {
-      message: `lost cannot be greater that current + incoming (max 
${currentStock + value.incoming})`
-    } : undefined
+    lost: currentStock + value.incoming < value.lost ?
+      `lost cannot be greater that current + incoming (max ${currentStock + 
value.incoming})`
+      : undefined
   }
 
   const stockUpdateDescription = errors.lost ? '' : (
@@ -196,11 +197,12 @@ function FastProductWithManagedStockUpdateForm({ product, 
onUpdate, onCancel }:
   )
 
   const hasErrors = Object.keys(errors).some(k => (errors as any)[k] !== 
undefined)
+  const i18n = useTranslator()
 
   return <Fragment>
     <FormProvider<FastProductUpdate> name="added" errors={errors} 
object={value} valueHandler={valueHandler as any} >
-      <InputNumber<FastProductUpdate> name="incoming" />
-      <InputNumber<FastProductUpdate> name="lost" />
+      <InputNumber<FastProductUpdate> name="incoming" label={i18n`Incoming`} />
+      <InputNumber<FastProductUpdate> name="lost" label={i18n`Lost`} />
       <div class="field is-horizontal">
         <div class="field-label is-normal" />
         <div class="field-body is-flex-grow-3">
@@ -209,11 +211,11 @@ function FastProductWithManagedStockUpdateForm({ product, 
onUpdate, onCancel }:
           </div>
         </div>
       </div>
-      <InputCurrency<FastProductUpdate> name="price" />
+      <InputCurrency<FastProductUpdate> name="price" label={i18n`Price`} />
     </FormProvider>
 
     <div class="buttons is-right mt-5">
-      <button class="button" onClick={onCancel} ><Message id="Cancel" 
/></button>
+      <button class="button" onClick={onCancel} 
><Translate>Cancel</Translate></button>
       <button class="button is-info" disabled={hasErrors} onClick={() => {
 
         return onUpdate({
@@ -223,7 +225,7 @@ function FastProductWithManagedStockUpdateForm({ product, 
onUpdate, onCancel }:
           price: value.price,
         })
 
-      }}><Message id="Confirm" /></button>
+      }}><Translate>Confirm</Translate></button>
     </div>
 
   </Fragment>
@@ -240,7 +242,7 @@ function EmptyTable(): VNode {
     <p>
       <span class="icon is-large"><i class="mdi mdi-emoticon-sad mdi-48px" 
/></span>
     </p>
-    <p><Message id="There is no instances yet, add more pressing the + sign" 
/></p>
+    <p><Translate>There is no instances yet, add more pressing the + 
sign</Translate></p>
   </div>
 }
 
diff --git a/packages/frontend/src/paths/instance/products/list/index.tsx 
b/packages/frontend/src/paths/instance/products/list/index.tsx
index a77b22e..63e440d 100644
--- a/packages/frontend/src/paths/instance/products/list/index.tsx
+++ b/packages/frontend/src/paths/instance/products/list/index.tsx
@@ -26,6 +26,7 @@ import { NotificationCard } from 
'../../../../components/menu';
 import { MerchantBackend, WithId } from '../../../../declaration';
 import { HttpError } from '../../../../hooks/backend';
 import { useInstanceProducts, useProductAPI } from "../../../../hooks/product";
+import { useTranslator } from '../../../../i18n';
 import { Notification } from '../../../../utils/types';
 import { CardTable } from './Table';
 
@@ -41,6 +42,8 @@ export default function ProductList({ onUnauthorized, 
onLoadError, onCreate, onS
   const { deleteProduct, updateProduct } = useProductAPI()
   const [notif, setNotif] = useState<Notification | undefined>(undefined)
 
+  const i18n = useTranslator()
+
   if (result.clientError && result.isUnauthorized) return onUnauthorized()
   if (result.clientError && result.isNotfound) return onNotFound()
   if (result.loading) return <Loading />
@@ -53,10 +56,10 @@ export default function ProductList({ onUnauthorized, 
onLoadError, onCreate, onS
       onCreate={onCreate}
       onUpdate={(id, prod) => updateProduct(id, prod)
         .then(() => setNotif({
-          message: 'product updated successfully',
+          message: i18n`product updated successfully`,
           type: "SUCCESS"
         })).catch((error) => setNotif({
-          message: 'could not update the product',
+          message: i18n`could not update the product`,
           type: "ERROR",
           description: error.message
         }))
@@ -64,10 +67,10 @@ export default function ProductList({ onUnauthorized, 
onLoadError, onCreate, onS
       onSelect={(product) => onSelect(product.id)}
       onDelete={(prod: (MerchantBackend.Products.ProductDetail & WithId)) => 
deleteProduct(prod.id)
         .then(() => setNotif({
-          message: 'product delete successfully',
+          message: i18n`product delete successfully`,
           type: "SUCCESS"
         })).catch((error) => setNotif({
-          message: 'could not delete the product',
+          message: i18n`could not delete the product`,
           type: "ERROR",
           description: error.message
         }))
diff --git 
a/packages/frontend/src/paths/instance/products/update/UpdatePage.tsx 
b/packages/frontend/src/paths/instance/products/update/UpdatePage.tsx
index 89fc05e..4a6248d 100644
--- a/packages/frontend/src/paths/instance/products/update/UpdatePage.tsx
+++ b/packages/frontend/src/paths/instance/products/update/UpdatePage.tsx
@@ -20,10 +20,10 @@
 */
 
 import { h, VNode } from "preact";
-import { Message } from "preact-messages";
 import { ProductForm } from "../../../../components/product/ProductForm";
 import { MerchantBackend, WithId } from "../../../../declaration";
 import { useListener } from "../../../../hooks";
+import { Translate } from "../../../../i18n";
 
 type Entity = MerchantBackend.Products.ProductDetail & WithId
 
@@ -51,8 +51,8 @@ export function UpdatePage({ product, onUpdate, onBack }: 
Props): VNode {
           }} alreadyExist />
 
           <div class="buttons is-right mt-5">
-            {onBack && <button class="button" onClick={onBack} ><Message 
id="Cancel" /></button>}
-            <button class="button is-success" onClick={submitForm} ><Message 
id="Confirm" /></button>
+            {onBack && <button class="button" onClick={onBack} 
><Translate>Cancel</Translate></button>}
+            <button class="button is-success" onClick={submitForm} 
><Translate>Confirm</Translate></button>
           </div>
 
         </div>
diff --git a/packages/frontend/src/paths/instance/products/update/index.tsx 
b/packages/frontend/src/paths/instance/products/update/index.tsx
index 22a60f8..338924f 100644
--- a/packages/frontend/src/paths/instance/products/update/index.tsx
+++ b/packages/frontend/src/paths/instance/products/update/index.tsx
@@ -26,6 +26,7 @@ import { NotificationCard } from 
'../../../../components/menu';
 import { MerchantBackend } from '../../../../declaration';
 import { HttpError } from '../../../../hooks/backend';
 import { useProductAPI, useProductDetails } from '../../../../hooks/product';
+import { useTranslator } from '../../../../i18n';
 import { Notification } from '../../../../utils/types';
 import { UpdatePage } from './UpdatePage';
 
@@ -43,6 +44,8 @@ export default function UpdateProduct({ pid, onConfirm, 
onBack, onUnauthorized,
   const result = useProductDetails(pid)
   const [notif, setNotif] = useState<Notification | undefined>(undefined)
 
+  const i18n = useTranslator()
+
   if (result.clientError && result.isUnauthorized) return onUnauthorized()
   if (result.clientError && result.isNotfound) return onNotFound()
   if (result.loading) return <Loading />
@@ -58,7 +61,7 @@ export default function UpdateProduct({ pid, onConfirm, 
onBack, onUnauthorized,
           .then(onConfirm)
           .catch((error) => {
             setNotif({
-              message: 'could not create product',
+              message: i18n`could not create product`,
               type: "ERROR",
               description: error.message
             })
diff --git a/packages/frontend/src/paths/instance/tips/list/Table.tsx 
b/packages/frontend/src/paths/instance/tips/list/Table.tsx
index 92c067e..722b013 100644
--- a/packages/frontend/src/paths/instance/tips/list/Table.tsx
+++ b/packages/frontend/src/paths/instance/tips/list/Table.tsx
@@ -20,9 +20,9 @@
  */
 
 import { h, VNode } from "preact"
-import { Message } from "preact-messages"
 import { StateUpdater, useEffect, useState } from "preact/hooks"
 import { MerchantBackend, WithId } from "../../../../declaration"
+import { Translate } from "../../../../i18n"
 import { Actions, buildActions } from "../../../../utils/table"
 
 type Entity = MerchantBackend.Tips.ReserveStatusEntry & WithId
@@ -56,7 +56,7 @@ export function CardTable({ instances, onCreate, onUpdate, 
onDelete, selected }:
 
   return <div class="card has-table">
     <header class="card-header">
-      <p class="card-header-title"><span class="icon"><i class="mdi mdi-cash" 
/></span><Message id="Tips" /></p>
+      <p class="card-header-title"><span class="icon"><i class="mdi mdi-cash" 
/></span><Translate>Tips</Translate></p>
 
       <div class="card-header-icon" aria-label="more options">
 
@@ -108,9 +108,9 @@ function Table({ rowSelection, rowSelectionHandler, 
instances, onUpdate, onDelet
               <span class="check" />
             </label>
           </th>
-          <th><Message id="fields.tips.committed_amount.label" /></th>
-          <th><Message id="fields.tips.exchange_initial_amount.label" /></th>
-          <th><Message id="fields.tips.merchant_initial_amount.label" /></th>
+          <th><Translate>Committed amount</Translate></th>
+          <th><Translate>Exchange initial amount</Translate></th>
+          <th><Translate>Merchant initial amount</Translate></th>
           <th />
         </tr>
       </thead>
@@ -145,6 +145,6 @@ function EmptyTable(): VNode {
     <p>
       <span class="icon is-large"><i class="mdi mdi-emoticon-sad mdi-48px" 
/></span>
     </p>
-    <p><Message id="There is no tips yet, add more pressing the + sign" /></p>
+    <p><Translate>There is no tips yet, add more pressing the + 
sign</Translate></p>
   </div>
 }
diff --git a/packages/frontend/src/paths/instance/tips/list/index.tsx 
b/packages/frontend/src/paths/instance/tips/list/index.tsx
index 3adeb44..e1afcca 100644
--- a/packages/frontend/src/paths/instance/tips/list/index.tsx
+++ b/packages/frontend/src/paths/instance/tips/list/index.tsx
@@ -21,7 +21,7 @@
 
 import { h, VNode } from 'preact';
 import { Loading } from '../../../../components/exception/loading';
-import { useConfigContext } from '../../../../context/backend';
+import { useConfigContext } from '../../../../context/config';
 import { MerchantBackend } from '../../../../declaration';
 import { HttpError } from '../../../../hooks/backend';
 import { useInstanceTips, useTipsMutateAPI } from "../../../../hooks/tips";
diff --git a/packages/frontend/src/paths/instance/transfers/list/Table.tsx 
b/packages/frontend/src/paths/instance/transfers/list/Table.tsx
index 22282f5..52fbb4d 100644
--- a/packages/frontend/src/paths/instance/transfers/list/Table.tsx
+++ b/packages/frontend/src/paths/instance/transfers/list/Table.tsx
@@ -20,9 +20,9 @@
  */
 
 import { h, VNode } from "preact"
-import { Message } from "preact-messages"
 import { StateUpdater, useEffect, useState } from "preact/hooks"
 import { MerchantBackend, WithId } from "../../../../declaration"
+import { Translate } from "../../../../i18n"
 import { Actions, buildActions } from "../../../../utils/table"
 
 type Entity = MerchantBackend.Transfers.TransferDetails & WithId
@@ -56,7 +56,7 @@ export function CardTable({ instances, onCreate, onUpdate, 
onDelete, selected }:
 
   return <div class="card has-table">
     <header class="card-header">
-      <p class="card-header-title"><span class="icon"><i class="mdi mdi-bank" 
/></span><Message id="Transfers" /></p>
+      <p class="card-header-title"><span class="icon"><i class="mdi mdi-bank" 
/></span><Translate>Transfers</Translate></p>
 
       <div class="card-header-icon" aria-label="more options">
 
@@ -108,8 +108,8 @@ function Table({ rowSelection, rowSelectionHandler, 
instances, onUpdate, onDelet
               <span class="check" />
             </label>
           </th>
-          <th><Message id="fields.instance.id.label" /></th>
-          <th><Message id="fields.instance.name.label" /></th>
+          <th><Translate>ID</Translate></th>
+          <th><Translate>Name</Translate></th>
           <th />
         </tr>
       </thead>
@@ -144,7 +144,7 @@ function EmptyTable(): VNode {
     <p>
       <span class="icon is-large"><i class="mdi mdi-emoticon-sad mdi-48px" 
/></span>
     </p>
-    <p><Message id="There is no transfer yet, add more pressing the + sign" 
/></p>
+    <p><Translate>There is no transfer yet, add more pressing the + 
sign</Translate></p>
   </div>
 }
 
diff --git a/packages/frontend/src/paths/instance/update/UpdatePage.tsx 
b/packages/frontend/src/paths/instance/update/UpdatePage.tsx
index 2a79195..86432fa 100644
--- a/packages/frontend/src/paths/instance/update/UpdatePage.tsx
+++ b/packages/frontend/src/paths/instance/update/UpdatePage.tsx
@@ -20,7 +20,6 @@
 */
 
 import { h, VNode } from "preact";
-import { Message } from "preact-messages";
 import { useState } from "preact/hooks";
 import * as yup from 'yup';
 import { FormProvider, FormErrors } from 
"../../../components/form/FormProvider";
@@ -30,8 +29,9 @@ import { InputDuration } from 
"../../../components/form/InputDuration";
 import { InputGroup } from "../../../components/form/InputGroup";
 import { InputPayto } from "../../../components/form/InputPayto";
 import { InputSecured } from "../../../components/form/InputSecured";
-import { useInstanceContext } from "../../../context/backend";
+import { useInstanceContext } from "../../../context/instance";
 import { MerchantBackend } from "../../../declaration";
+import { Translate, useTranslator } from "../../../i18n";
 import { InstanceUpdateSchema as schema } from '../../../schemas';
 
 
@@ -88,11 +88,13 @@ export function UpdatePage({ onUpdate, selected, onBack }: 
Props): VNode {
       onBack()
     } catch (err) {
       const errors = err.inner as yup.ValidationError[]
-      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: { type: cur.type, params: cur.params, message: cur.message 
} }), {})
+      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: cur.message }), {})
       setErrors(pathMessages)
     }
   }
 
+  const i18n = useTranslator()
+
   return <div>
     <section class="section is-main-section">
       <div class="columns">
@@ -100,59 +102,61 @@ export function UpdatePage({ onUpdate, selected, onBack 
}: Props): VNode {
         <div class="column is-four-fifths">
           <FormProvider<Entity> errors={errors} object={value} 
valueHandler={valueHandler} >
 
-            <Input<Entity> name="name" />
+            <Input<Entity> name="name" label={i18n`Name`} />
 
-            <InputSecured<Entity> name="auth_token" />
+            <InputSecured<Entity> name="auth_token" label={i18n`Auth token`} />
 
-            <InputPayto<Entity> name="payto_uris" />
+            <InputPayto<Entity> name="payto_uris" label={i18n`Account 
address`} />
 
-            <InputCurrency<Entity> name="default_max_deposit_fee" />
+            <InputCurrency<Entity> name="default_max_deposit_fee" 
label={i18n`Default max deposit fee`} />
 
-            <InputCurrency<Entity> name="default_max_wire_fee" />
+            <InputCurrency<Entity> name="default_max_wire_fee" 
label={i18n`Default max wire fee`} />
 
-            <Input<Entity> name="default_wire_fee_amortization" 
inputType="number" />
+            <Input<Entity> name="default_wire_fee_amortization" 
inputType="number" label={i18n`Default wire fee amortization`} />
 
-            <InputGroup name="address">
-              <Input name="address.country" />
+            <InputGroup name="address" label={i18n`Address`}>
+              <Input name="address.country" label={i18n`Country`} />
               <Input name="address.address_lines" inputType="multiline"
+                label={i18n`Address`}
                 toStr={(v: string[] | undefined) => !v ? '' : v.join('\n')}
                 fromStr={(v: string) => v.split('\n')}
               />
-              <Input name="address.building_number" />
-              <Input name="address.building_name" />
-              <Input name="address.street" />
-              <Input name="address.post_code" />
-              <Input name="address.town_location" />
-              <Input name="address.town" />
-              <Input name="address.district" />
-              <Input name="address.country_subdivision" />
+              <Input name="address.building_number" label={i18n`Building 
number`} />
+              <Input name="address.building_name" label={i18n`Building name`} 
/>
+              <Input name="address.street" label={i18n`Street`} />
+              <Input name="address.post_code" label={i18n`Post code`} />
+              <Input name="address.town_location" label={i18n`Town location`} 
/>
+              <Input name="address.town" label={i18n`Town`} />
+              <Input name="address.district" label={i18n`District`} />
+              <Input name="address.country_subdivision" label={i18n`Country 
subdivision`} />
             </InputGroup>
 
-            <InputGroup name="jurisdiction">
-              <Input name="jurisdiction.country" />
+            <InputGroup name="jurisdiction" label={i18n`Jurisdiction`}>
+              <Input name="jurisdiction.country" label={i18n`Country`} />
               <Input name="jurisdiction.address_lines" inputType="multiline"
+                label={i18n`Address`}
                 toStr={(v: string[] | undefined) => !v ? '' : v.join('\n')}
                 fromStr={(v: string) => v.split('\n')}
               />
-              <Input name="jurisdiction.building_number" />
-              <Input name="jurisdiction.building_name" />
-              <Input name="jurisdiction.street" />
-              <Input name="jurisdiction.post_code" />
-              <Input name="jurisdiction.town_location" />
-              <Input name="jurisdiction.town" />
-              <Input name="jurisdiction.district" />
-              <Input name="jurisdiction.country_subdivision" />
+              <Input name="jurisdiction.building_number" label={i18n`Building 
number`} />
+              <Input name="jurisdiction.building_name" label={i18n`Building 
name`} />
+              <Input name="jurisdiction.street" label={i18n`Street`} />
+              <Input name="jurisdiction.post_code" label={i18n`Post code`} />
+              <Input name="jurisdiction.town_location" label={i18n`Town 
location`} />
+              <Input name="jurisdiction.town" label={i18n`Town`} />
+              <Input name="jurisdiction.district" label={i18n`District`} />
+              <Input name="jurisdiction.country_subdivision" 
label={i18n`Country subdivision`} />
             </InputGroup>
 
-            <InputDuration<Entity> name="default_pay_delay" />
+            <InputDuration<Entity> name="default_pay_delay" 
label={i18n`Default pay delay`} />
 
-            <InputDuration<Entity> name="default_wire_transfer_delay" />
+            <InputDuration<Entity> name="default_wire_transfer_delay" 
label={i18n`Default wire transfer delay`} />
 
           </FormProvider>
 
           <div class="buttons is-right mt-4">
-            <button class="button" onClick={onBack} ><Message id="Cancel" 
/></button>
-            <button class="button is-success" onClick={submit} ><Message 
id="Confirm" /></button>
+            <button class="button" onClick={onBack} 
><Translate>Cancel</Translate></button>
+            <button class="button is-success" onClick={submit} 
><Translate>Confirm</Translate></button>
           </div>
         </div>
         <div class="column" />
diff --git a/packages/frontend/src/utils/functions.ts 
b/packages/frontend/src/utils/functions.ts
deleted file mode 100644
index 4fc2815..0000000
--- a/packages/frontend/src/utils/functions.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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/>
- */
-
-import { MessageError } from "preact-messages";
-
-export function hasKey<O>(obj: O, key: string | number | symbol): key is keyof 
O {
-  return key in obj
-}
-
-declare global {
-  interface Window { MerchantBackoffice: any; }
-}
-
-if (typeof window !== "undefined") {
-  window.MerchantBackoffice = window.MerchantBackoffice || {
-    missing_locales: [],
-    getMissingTranslation: () => Array.from(new 
Set(window.MerchantBackoffice.missing_locales)).filter(i => i).map(i => `msgid 
"${i}"\nmsgstr ""\n`).join('\n')
-  };
-}
-
-export function onTranslationError(error: MessageError) {
-  if (typeof window === "undefined") return;
-  window.MerchantBackoffice.missing_locales = 
window.MerchantBackoffice.missing_locales.concat(error.path.join())
-}
-
-export async function copyToClipboard(text:string) {
-  return navigator.clipboard.writeText(text)
-}
-
diff --git a/packages/frontend/tests/header.test.tsx 
b/packages/frontend/tests/header.test.tsx
index 9a69adc..c4cbfce 100644
--- a/packages/frontend/tests/header.test.tsx
+++ b/packages/frontend/tests/header.test.tsx
@@ -23,7 +23,7 @@ import { h } from 'preact';
 import { ProductList } from '../src/components/product/ProductList';
 // See: https://github.com/preactjs/enzyme-adapter-preact-pure
 import { shallow } from 'enzyme';
-import * as backend from '../src/context/backend';
+import * as backend from '../src/context/config';
 
 describe('Initial Test of the Sidebar', () => {
     beforeEach(() => {
diff --git a/packages/frontend/tests/hooks/swr/order-create.test.tsx 
b/packages/frontend/tests/hooks/swr/order-create.test.tsx
index 201999c..d80f815 100644
--- a/packages/frontend/tests/hooks/swr/order-create.test.tsx
+++ b/packages/frontend/tests/hooks/swr/order-create.test.tsx
@@ -21,8 +21,8 @@
 
 import { renderHook } from '@testing-library/preact-hooks';
 import * as axios from 'axios';
-// import { cache,  } from "swr";
-import * as ctx from '../../../src/context/backend';
+import * as backend from '../../../src/context/backend';
+import * as instance from '../../../src/context/instance';
 import { MerchantBackend } from '../../../src/declaration';
 import { useInstanceOrders, useOrderAPI } from '../../../src/hooks/order';
 import { simulateBackendResponse } from '../../util'
@@ -33,8 +33,8 @@ jest.mock('axios');
 describe('order api', () => {
 
   beforeEach(() => {
-    jest.spyOn(ctx, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
-    jest.spyOn(ctx, 'useInstanceContext').mockImplementation(() => ({ token: 
'token', id: 'default', admin: true, } as any));
+    jest.spyOn(backend, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
+    jest.spyOn(instance, 'useInstanceContext').mockImplementation(() => ({ 
token: 'token', id: 'default', admin: true, } as any));
   })
 
   it('should not have problem with cache after an creation', async () => {
diff --git a/packages/frontend/tests/hooks/swr/order-pagination.test.tsx 
b/packages/frontend/tests/hooks/swr/order-pagination.test.tsx
index c80770c..f99b52d 100644
--- a/packages/frontend/tests/hooks/swr/order-pagination.test.tsx
+++ b/packages/frontend/tests/hooks/swr/order-pagination.test.tsx
@@ -21,8 +21,8 @@
 
 import { act, renderHook } from '@testing-library/preact-hooks';
 import * as axios from 'axios';
-// import { cache,  } from "swr";
-import * as ctx from '../../../src/context/backend';
+import * as backend from '../../../src/context/backend';
+import * as instance from '../../../src/context/instance';
 import { MerchantBackend } from '../../../src/declaration';
 import { useInstanceOrders } from '../../../src/hooks/order';
 import { simulateBackendResponse } from '../../util'
@@ -33,8 +33,8 @@ jest.mock('axios');
 describe('order pagination', () => {
 
   beforeEach(() => {
-    jest.spyOn(ctx, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
-    jest.spyOn(ctx, 'useInstanceContext').mockImplementation(() => ({ token: 
'token', id: 'default', admin: true, } as any));
+    jest.spyOn(backend, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
+    jest.spyOn(instance, 'useInstanceContext').mockImplementation(() => ({ 
token: 'token', id: 'default', admin: true, } as any));
   })
 
   it('should change pagination', async () => {
diff --git a/packages/frontend/tests/hooks/swr/product-create.test.tsx 
b/packages/frontend/tests/hooks/swr/product-create.test.tsx
index 19a0df0..318c93b 100644
--- a/packages/frontend/tests/hooks/swr/product-create.test.tsx
+++ b/packages/frontend/tests/hooks/swr/product-create.test.tsx
@@ -21,8 +21,8 @@
 
 import { renderHook } from '@testing-library/preact-hooks';
 import * as axios from 'axios';
-// import { cache,  } from "swr";
-import * as ctx from '../../../src/context/backend';
+import * as backend from '../../../src/context/backend';
+import * as instance from '../../../src/context/instance';
 import { MerchantBackend } from '../../../src/declaration';
 import { useInstanceProducts, useProductAPI } from 
'../../../src/hooks/product';
 import { simulateBackendResponse } from '../../util'
@@ -33,8 +33,8 @@ jest.mock('axios');
 describe('product api', () => {
 
   beforeEach(() => {
-    jest.spyOn(ctx, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
-    jest.spyOn(ctx, 'useInstanceContext').mockImplementation(() => ({ token: 
'token', id: 'default', admin: true, } as any));
+    jest.spyOn(backend, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
+    jest.spyOn(instance, 'useInstanceContext').mockImplementation(() => ({ 
token: 'token', id: 'default', admin: true, } as any));
   })
 
   it('should not have problem with cache after an creation', async () => {
diff --git a/packages/frontend/tests/hooks/swr/product-delete.test.tsx 
b/packages/frontend/tests/hooks/swr/product-delete.test.tsx
index 4109db9..7fdf24b 100644
--- a/packages/frontend/tests/hooks/swr/product-delete.test.tsx
+++ b/packages/frontend/tests/hooks/swr/product-delete.test.tsx
@@ -20,7 +20,8 @@
 */
 
 import { renderHook } from '@testing-library/preact-hooks';
-import * as ctx from '../../../src/context/backend';
+import * as backend from '../../../src/context/backend';
+import * as instance from '../../../src/context/instance';
 import { MerchantBackend } from '../../../src/declaration';
 import { useInstanceProducts, useProductAPI } from 
'../../../src/hooks/product';
 import { simulateBackendResponse } from '../../util'
@@ -35,8 +36,8 @@ axios.default
 describe('product api', () => {
 
   beforeEach(() => {
-    jest.spyOn(ctx, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
-    jest.spyOn(ctx, 'useInstanceContext').mockImplementation(() => ({ token: 
'token', id: 'default', admin: true, } as any));
+    jest.spyOn(backend, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
+    jest.spyOn(instance, 'useInstanceContext').mockImplementation(() => ({ 
token: 'token', id: 'default', admin: true, } as any));
     // console.log("CLEAR")
   })
 
diff --git a/packages/frontend/tests/hooks/swr/product-details-update.test.tsx 
b/packages/frontend/tests/hooks/swr/product-details-update.test.tsx
index 277e27a..eb4e2ed 100644
--- a/packages/frontend/tests/hooks/swr/product-details-update.test.tsx
+++ b/packages/frontend/tests/hooks/swr/product-details-update.test.tsx
@@ -21,9 +21,10 @@
 
 import { renderHook } from '@testing-library/preact-hooks';
 import * as axios from 'axios';
-import * as ctx from '../../../src/context/backend';
+import * as backend from '../../../src/context/backend';
+import * as instance from '../../../src/context/instance';
 import { MerchantBackend } from '../../../src/declaration';
-import { useInstanceProducts, useProductAPI, useProductDetails } from 
'../../../src/hooks/product';
+import { useProductAPI, useProductDetails } from '../../../src/hooks/product';
 import { simulateBackendResponse } from '../../util'
 
 
@@ -32,9 +33,8 @@ jest.mock('axios');
 describe('product api', () => {
 
   beforeEach(() => {
-    jest.spyOn(ctx, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
-    jest.spyOn(ctx, 'useInstanceContext').mockImplementation(() => ({ token: 
'token', id: 'default', admin: true, } as any));
-    // console.log("CLEAR")
+    jest.spyOn(backend, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
+    jest.spyOn(instance, 'useInstanceContext').mockImplementation(() => ({ 
token: 'token', id: 'default', admin: true, } as any));
   })
 
   it('should not have problem with cache after an update', async () => {
diff --git a/packages/frontend/tests/hooks/swr/product-update.test.tsx 
b/packages/frontend/tests/hooks/swr/product-update.test.tsx
index d1e1e0b..daaafbd 100644
--- a/packages/frontend/tests/hooks/swr/product-update.test.tsx
+++ b/packages/frontend/tests/hooks/swr/product-update.test.tsx
@@ -21,7 +21,8 @@
 
 import { renderHook } from '@testing-library/preact-hooks';
 import * as axios from 'axios';
-import * as ctx from '../../../src/context/backend';
+import * as backend from '../../../src/context/backend';
+import * as instance from '../../../src/context/instance';
 import { MerchantBackend } from '../../../src/declaration';
 import { useInstanceProducts, useProductAPI } from 
'../../../src/hooks/product';
 import { simulateBackendResponse } from '../../util'
@@ -32,8 +33,8 @@ jest.mock('axios');
 describe('product api', () => {
 
   beforeEach(() => {
-    jest.spyOn(ctx, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
-    jest.spyOn(ctx, 'useInstanceContext').mockImplementation(() => ({ token: 
'token', id: 'default', admin: true, } as any));
+    jest.spyOn(backend, 'useBackendContext').mockImplementation(() => ({ url: 
'http://backend', token: 'token' } as any));
+    jest.spyOn(instance, 'useInstanceContext').mockImplementation(() => ({ 
token: 'token', id: 'default', admin: true, } as any));
     // console.log("CLEAR")
   })
 
diff --git a/packages/frontend/tests/stories.test.tsx 
b/packages/frontend/tests/stories.test.tsx
index 1fbdb4a..996aebb 100644
--- a/packages/frontend/tests/stories.test.tsx
+++ b/packages/frontend/tests/stories.test.tsx
@@ -20,7 +20,7 @@
 */
 import { mount } from 'enzyme';
 import { h } from 'preact';
-import * as ctx from '../src/context/backend';
+import * as ctx from '../src/context/config';
 
 import fs from 'fs';
 
diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json
index 14d4d04..dfb8758 100644
--- a/packages/frontend/tsconfig.json
+++ b/packages/frontend/tsconfig.json
@@ -8,6 +8,7 @@
         // "checkJs": true,                       /* Report errors in .js 
files. */
         "jsx": "react",                           /* Specify JSX code 
generation: 'preserve', 'react-native', or 'react'. */
         "jsxFactory": "h",                        /* Specify the JSX factory 
function to use when targeting react JSX emit, e.g. React.createElement or h. */
+        "jsxFragmentFactory": "Fragment",         // 
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html#custom-jsx-factories
         // "declaration": true,                   /* Generates corresponding 
'.d.ts' file. */
         // "sourceMap": true,                     /* Generates corresponding 
'.map' file. */
         // "outFile": "./",                       /* Concatenate and emit 
output to single file. */
diff --git a/packages/preact-messages/.gitignore 
b/packages/preact-messages/.gitignore
deleted file mode 100644
index ad09c5f..0000000
--- a/packages/preact-messages/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/example/dist/
-/lib/
diff --git a/packages/preact-messages/CHANGELOG.md 
b/packages/preact-messages/CHANGELOG.md
deleted file mode 100644
index 4681441..0000000
--- a/packages/preact-messages/CHANGELOG.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Change Log
-
-All notable changes to this project will be documented in this file.
-See [Conventional Commits](https://conventionalcommits.org) for commit 
guidelines.
-
-# 1.0.0-beta.1 (2020-11-29)
-
-
-### Features
-
-* Add @messageformat/react (was react-message-context) 
([#292](https://github.com/messageformat/messageformat/issues/292)) 
([9089f0a](https://github.com/messageformat/messageformat/commit/9089f0ad52f21f8ab6c356fd4f51bb140dc36855))
-
-
-# 0.6.2 and earlier
-
-For earlier changes, see 
https://github.com/eemeli/react-message-context/releases
diff --git a/packages/preact-messages/LICENSE b/packages/preact-messages/LICENSE
deleted file mode 100644
index 78918d5..0000000
--- a/packages/preact-messages/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright OpenJS Foundation and contributors, https://openjsf.org/
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/packages/preact-messages/README.md 
b/packages/preact-messages/README.md
deleted file mode 100644
index a52d5b3..0000000
--- a/packages/preact-messages/README.md
+++ /dev/null
@@ -1,126 +0,0 @@
-# @messageformat/react
-
-An efficient React front-end for message formatting libraries.
-Designed in particular for use with [messageformat], but will work with any 
messages.
-Provides the best possible API for a front-end developer, without making the 
back end any more difficult than it needs to be either.
-Should add at most about 1kB to your compiled & minified bundle size.
-
-This package was previously named 
[react-message-context](https://www.npmjs.com/package/react-message-context).
-
-[messageformat]: https://messageformat.github.io
-
-## Installation
-
-```
-npm install @messageformat/react
-```
-
-The library has React 16.8 or later as a peer dependency.
-It is published as an **ES module** only, which should work directly with 
almost all tools and environments that support modern development targeting 
browser environments.
-For tools such as Jest that define their own import methods, you may need to 
add something like `transformIgnorePatterns: 
['node_modules/(?!@messageformat/react)']` to your configuration.
-
-## [API Documentation]
-
-- [`<MessageProvider messages [locale] [onError] 
[pathSep]>`](http://messageformat.github.io/messageformat/api/react.messageprovider/)
-- [`<Message id [locale] [props] 
[...msgProps]>`](http://messageformat.github.io/messageformat/api/react.message/)
-- 
[`useLocales()`](http://messageformat.github.io/messageformat/api/react.uselocales/)
-- [`useMessage(id, [params], 
[locale])`](http://messageformat.github.io/messageformat/api/react.usemessage/)
-- [`useMessageGetter(rootId, [{ baseParams, locale 
}])`](http://messageformat.github.io/messageformat/api/react.usemessagegetter/)
-
-## Usage Examples
-
-In addition to the examples included below and in the [API documentation], see 
the [example] for a simple, but fully functional example of using this library 
along with [@messageformat/core] and [@messageformat/loader] to handle 
localized messages, with dynamic loading of non-default locales.
-
-[api documentation]: http://messageformat.github.io/messageformat/api/react/
-[example]: 
https://github.com/messageformat/messageformat/tree/master/packages/react/example
-[@messageformat/core]: https://www.npmjs.com/package/@messageformat/core
-[@messageformat/loader]: https://www.npmjs.com/package/@messageformat/loader
-
----
-
-Within a `MessageProvider`, access to the messages is possible using either 
the `Message` component, or via custom hooks such as `useMessageGetter`:
-
-```js
-import React from 'preact';
-import {
-  Message,
-  MessageProvider,
-  useMessageGetter
-} from '@messageformat/react';
-
-const messages = {
-  message: 'Your message is important',
-  answers: {
-    sixByNine: ({ base }) => (6 * 9).toString(base),
-    universe: 42
-  }
-};
-
-function Equality() {
-  const getAnswer = useMessageGetter('answers');
-  const foo = getAnswer('sixByNine', { base: 13 });
-  const bar = getAnswer('universe');
-  return `${foo} and ${bar} are equal`;
-}
-
-export const Example = () => (
-  <MessageProvider messages={messages}>
-    <ul>
-      <li>
-        <Message id="message" />
-      </li>
-      <li>
-        <Equality />
-      </li>
-    </ul>
-  </MessageProvider>
-);
-
-// Will render as:
-//   - Your message is important
-//   - 42 and 42 are equal
-```
-
----
-
-Using MessageProviders within each other allows for multiple locales and 
namespaces:
-
-```jsx
-import React from 'preact';
-import { Message, MessageProvider } from '@messageformat/react';
-
-export const Example = () => (
-  <MessageProvider locale="en" messages={{ foo: 'FOO', qux: 'QUX' }}>
-    <MessageProvider locale="fi" messages={{ foo: 'FÖÖ', bar: 'BÄR' }}>
-      <ul>
-        <li>
-          <Message id="foo" />
-        </li>
-        <li>
-          <Message id="foo" locale="en" />
-        </li>
-        <li>
-          <Message id="bar" />
-        </li>
-        <li>
-          <Message id="bar" locale="en" />
-        </li>
-        <li>
-          <Message id="qux" />
-        </li>
-        <li>
-          <Message id="quux">xyzzy</Message>
-        </li>
-      </ul>
-    </MessageProvider>
-  </MessageProvider>
-);
-
-// Will render as:
-// - FÖÖ
-// - FOO
-// - BÄR
-// - bar  (uses fallback to key)
-// - QUX  (uses fallback to "en" locale)
-// - xyzzy  (uses fallback to child node)
-```
diff --git a/packages/preact-messages/package.json 
b/packages/preact-messages/package.json
deleted file mode 100644
index 3e924d9..0000000
--- a/packages/preact-messages/package.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
-  "name": "preact-messages",
-  "version": "1.0.0-beta.1",
-  "description": "PReact hooks and other bindings for messages",
-  "keywords": [
-    "i18n",
-    "preact",
-    "context",
-    "messages",
-    "messageformat",
-    "provider"
-  ],
-  "contributors": [
-    "Eemeli Aro <eemeli@gmail.com>"
-  ],
-  "license": "MIT",
-  "homepage": "http://messageformat.github.io/messageformat/api/react/";,
-  "main": "lib/index.js",
-  "types": "lib/index.d.ts",
-  "exports": {
-    ".": "./lib/index.js",
-    "./package.json": "./package.json"
-  },
-  "files": [
-    "lib/"
-  ],
-  "sideEffects": false,
-  "scripts": {
-    "build": "tsc",
-    "compile": "tsc",
-    "clean": "rimraf lib",
-    "extract-api": "api-extractor run --local --verbose"
-  },
-  "peerDependencies": {
-    "preact": ">=10.3.0"
-  },
-  "dependencies": {
-    "preact": "^10.5.13",
-    "typescript": "^4.2.3"
-  },
-  "devDependencies": {
-    "rimraf": "^3.0.2"
-  }
-}
diff --git a/packages/preact-messages/src/MessageProvider.ts 
b/packages/preact-messages/src/MessageProvider.ts
deleted file mode 100644
index cb72622..0000000
--- a/packages/preact-messages/src/MessageProvider.ts
+++ /dev/null
@@ -1,183 +0,0 @@
-import { createElement } from 'preact';
-import { useContext, useMemo } from 'preact/hooks';
-import { MessageContext, MessageObject, defaultValue } from 
'./message-context';
-// import { MessageProviderProps, getPathSep, getLocales, getMessages, 
getOnError } from './message-provider';
-import { MessageError, ErrorCode, errorMessages } from './message-error';
-
-/**
- * `<MessageProvider messages [locale] [merge] [onError] [pathSep]>`
- *
- * Makes the messages available for its descendants via a React Context.
- * To support multiple locales and/or namespaces, MessageProviders may be used 
within each other, merging each provider's messages with those of its parents.
- * The locale preference order is also set similarly, from nearest to furthest.
- *
- * @public
- *
- * @example
- * ```js
- * import React from 'preact'
- * import { Message, MessageProvider } from '@messageformat/react'
- *
- * const messages = { example: { key: 'Your message here' } }
- * const extended = { other: { key: 'Another message' } }
- *
- * const Example = () => (
- *   <span>
- *     <Message id={['example', 'key']} />
- *     {' | '}
- *     <Message id="other/key" />
- *   </span>
- * ) // 'Your message here | Another message'
- *
- * export const App = () => (
- *   <MessageProvider messages={messages} pathSep="/">
- *     <MessageProvider messages={extended}>
- *       <Example />
- *     </MessageProvider>
- *   </MessageProvider>
- * )
- * ```
- */
-
-export function MessageProvider(props: MessageProviderProps) {
-  const {
-    children,
-    context: propContext,
-    debug,
-    locale = '',
-    merge,
-    messages,
-    onError,
-    pathSep
-  } = props;
-  let parent = useContext(MessageContext);
-  if (propContext)
-    parent = propContext;
-  else if (propContext === null)
-    parent = defaultValue;
-  const value: MessageContext = useMemo(() => {
-    const ps = getPathSep(parent, pathSep);
-    return {
-      locales: getLocales(parent, locale),
-      merge: merge || parent.merge,
-      messages: getMessages(parent, locale, messages),
-      onError: getOnError(parent, ps, onError, debug),
-      pathSep: ps
-    };
-  }, [parent, locale, merge, messages, pathSep]);
-  return createElement(MessageContext.Provider, { value } as any, children);
-}
-
-
-
-/** @public */
-export interface MessageProviderProps {
-  children: any;
-
-  /**
-   * A hierarchical object containing the messages as boolean, number, string 
or function values.
-   */
-  messages: MessageObject;
-  context?: MessageContext;
-
-  /** @deprecated Use onError instead */
-  debug?: 'error' | 'warn' | ((msg: string) => any);
-
-  /**
-   * A key for the locale of the given messages.
-   * If uset, will inherit the locale from the parent context, or ultimately 
use en empty string.
-   */
-  locale?: string;
-
-  /**
-   * By default, top-level namespaces defined in a child `MessageProvider` 
overwrite those defined in a parent.
-   * Set this to {@link https://lodash.com/docs/#merge | _.merge} or some 
other function with the same arguments as
-   * {@link 
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
 | Object.assign} to allow for deep merges.
-   */
-  merge?: MessageContext['merge'];
-
-  /**
-   * What to do on errors; most often called if a message is not found.
-   *
-   * - `"silent"`: Ignore the error; use the message's id as the replacement 
message.
-   *
-   * - `"error"`: Throw the error.
-   *
-   * - `"warn"` (default): Print a warning in the console and use the 
message's id as the replacement message.
-   *
-   * - `(error) => any`: A custom function that is called with an `Error` 
object with `code: string` and `path: string[]` fields set.
-   *   The return falue is used as the replacement message.
-   */
-  onError?: 'error' | 'silent' | 'warn' | ((error: MessageError) => any);
-
-  /**
-   * By default, `.` in a `<Message id>` splits the path into parts, such that 
e.g. `'a.b'` is equivalent to `['a', 'b']`.
-   * Use this option to customize or disable this behaviour (by setting it to 
`null`).
-   */
-  pathSep?: string;
-}
-
-export function getOnError(
-  parent: MessageContext,
-  pathSep: string | null,
-  onError: MessageProviderProps['onError'],
-  debug: MessageProviderProps['debug']
-) {
-  const asId = (path: string[]) => path.join(pathSep || ',');
-  function msgError(path: string[], code: ErrorCode) {
-    throw new MessageError(path, code, asId);
-  }
-  function msgWarning(path: string[], code: ErrorCode) {
-    console.warn(errorMessages[code], path);
-    return asId(path);
-  }
-
-  if (onError === undefined) {
-    // debug is deprecated, will be removed later
-    if (typeof debug === 'function')
-      return (path: string[], code: ErrorCode) =>
-        debug(`${errorMessages[code]}: ${asId(path)}`);
-    onError = debug;
-  }
-
-  switch (onError) {
-    case 'silent':
-      return asId;
-    case 'error':
-      return msgError;
-    case 'warn':
-      return msgWarning;
-    default:
-      if (typeof onError === 'function') {
-        const _onError = onError;
-        return (path: string[], code: ErrorCode) =>
-          _onError(new MessageError(path, code, asId));
-      }
-      return parent.onError || msgWarning;
-  }
-}
-
-export function getLocales({ locales }: MessageContext, locale: string) {
-  const fallback = locales.filter(fb => fb !== locale);
-  return [locale].concat(fallback);
-}
-
-export function getMessages(
-  { merge, messages }: MessageContext,
-  locale: string,
-  lcMessages: MessageObject
-) {
-  const res = Object.assign({}, messages);
-  const prev = res[locale];
-  res[locale] =
-    prev && typeof prev === 'object' ? merge({}, prev, lcMessages) : 
lcMessages;
-  return res;
-}
-
-export function getPathSep(context: MessageContext, pathSep?: string | null) {
-  return pathSep === null || typeof pathSep === 'string'
-    ? pathSep
-    : context.pathSep;
-}
-
-
diff --git a/packages/preact-messages/src/declarations.d.ts 
b/packages/preact-messages/src/declarations.d.ts
deleted file mode 100644
index acb8034..0000000
--- a/packages/preact-messages/src/declarations.d.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export module "" {
-  
-}
\ No newline at end of file
diff --git a/packages/preact-messages/src/get-message.ts 
b/packages/preact-messages/src/get-message.ts
deleted file mode 100644
index e04d076..0000000
--- a/packages/preact-messages/src/get-message.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import {
-  MessageContext,
-  MessageObject,
-  MessageValue
-} from './message-context.js';
-
-function getIn(messages: MessageValue | MessageObject, path: string[]) {
-  if (messages) {
-    for (let i = 0; i < path.length; ++i) {
-      if (typeof messages !== 'object') return undefined;
-      messages = messages[path[i]];
-      if (messages === undefined) return undefined;
-    }
-  }
-  return messages;
-}
-
-export function getPath(id?: string | string[], pathSep?: string | null) {
-  if (!id) return [];
-  if (Array.isArray(id)) return id;
-  return pathSep ? id.split(pathSep) : [id];
-}
-
-/**
- * Given a `MessageContext` instance, fetches an entry from the messages 
object of the current or given locale.
- * The returned value will be `undefined` if not found, or otherwise exactly 
as set in the `MessageProvider` props.
- *
- * @public
- * @param id - The key or key path of the message or message object.
- *   If empty or `[]`, matches the root of the messages object
- * @param locale - If set, overrides the current locale precedence as set by 
parent MessageProviders.
- */
-export function getMessage(
-  context: MessageContext,
-  id?: string | string[],
-  locale?: string | string[]
-) {
-  const { locales, messages, onError, pathSep } = context;
-  const lca =
-    locale == null ? locales : Array.isArray(locale) ? locale : [locale];
-  const path = getPath(id, pathSep);
-  for (let i = 0; i < lca.length; ++i) {
-    const lc = lca[i];
-    const msg = getIn(messages[lc], path);
-    if (msg !== undefined) return msg;
-  }
-  return onError ? onError(path, 'ENOMSG') : undefined;
-}
-
-/**
- * @param id - Message identifier; extends the path set by `rootId`
- * @param params - Parameters for a function message
- */
-export interface MessageGetterOptions {
-  baseParams?: any;
-  locale?: string | string[];
-}
-
-/**
- * Given a `MessageContext` instance, returns a message getter function, which 
may have a preset root id path, locale, and/or base parameters for message 
functions.
- *
- * The returned function takes two parameters `(msgId, msgParams)`, which will 
extend any values set by the hook's arguments.
- *
- * @public
- * @param context - The `MessageContext` instance
- * @param rootId - The key or key path of the message or message object.
- *   If empty or `[]`, matches the root of the messages object
- * @param options - If `baseParams` is set, message function parameters will 
be assumed to always be an object, with these values initially set.
- *   `locale` overrides the current locale precedence as set by parent 
MessageProviders.
- */
-export function getMessageGetter(
-  context: MessageContext,
-  rootId?: string | string[],
-  { baseParams, locale }: MessageGetterOptions = {}
-) {
-  const { pathSep } = context;
-  const pathPrefix = getPath(rootId, pathSep);
-  return function message(id?: string | string[], params?: any) {
-    const path = pathPrefix.concat(getPath(id, pathSep));
-    const msg = getMessage(context, path, locale);
-    if (typeof msg !== 'function') return msg;
-    const msgParams = baseParams
-      ? Object.assign({}, baseParams, params)
-      : params;
-    return msg(msgParams);
-  };
-}
diff --git a/packages/preact-messages/src/index.ts 
b/packages/preact-messages/src/index.ts
deleted file mode 100644
index d8dcd69..0000000
--- a/packages/preact-messages/src/index.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * An efficient React front-end for message formatting
- *
- * @packageDocumentation
- * @remarks
- * Designed in particular for use with {@link https://messageformat.github.io 
| messageformat}, but will work with any messages.
- * Provides the best possible API for a front-end developer, without making 
the back end any more difficult than it needs to be either.
- * Should add at most about 1kB to your compiled & minified bundle size.
- *
- * @example
- * ```js
- * import {
- *   MessageContext,
- *   MessageProvider,
- *   Message,
- *   getMessage,
- *   getMessageGetter,
- *   useLocales,
- *   useMessage,
- *   useMessageGetter
- * } from '@messageformat/react'
- * ```
- */
-export { getMessage, getMessageGetter } from './get-message';
-export { Message, MessageProps } from './message';
-export { MessageContext, MessageObject, MessageValue } from 
'./message-context';
-export { MessageError } from './message-error';
-export { MessageProvider } from './MessageProvider';
-export { useLocales } from './use-locales';
-export { useMessage } from './use-message';
-export { useMessageGetter } from './use-message-getter';
-export { useMessageTemplate } from './use-message-template';
diff --git a/packages/preact-messages/src/message-context.ts 
b/packages/preact-messages/src/message-context.ts
deleted file mode 100644
index c344a11..0000000
--- a/packages/preact-messages/src/message-context.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-// @ts-ignore - https://github.com/microsoft/rushstack/issues/1050
-import { createContext } from 'preact';
-import { ErrorCode } from './message-error';
-
-/** @internal */
-export type MessageValue = string | number | boolean | ((props: any) => any);
-
-/** @internal */
-export interface MessageObject {
-  [key: string]: MessageValue | MessageObject;
-}
-
-/** @public */
-export interface MessageContext {
-  locales: string[];
-  merge: (target: MessageObject, ...sources: MessageObject[]) => MessageObject;
-  messages: MessageObject;
-
-  /** Always defined in MessageProvider children */
-  onError?: (path: string[], code: ErrorCode) => any;
-  pathSep: string | null;
-}
-
-export const defaultValue: MessageContext = {
-  locales: [],
-  merge: Object.assign,
-  messages: {},
-  pathSep: '.'
-};
-
-/**
- * The context object used internally by the library.
- * Probably only useful with `Class.contextType` or for building custom hooks.
- *
- * @public
- *
- * @example
- * ```js
- * import React, { Component } from 'preact'
- * import {
- *   getMessage,
- *   getMessageGetter,
- *   MessageContext,
- *   MessageProvider
- * } from '@messageformat/react'
- *
- * const messages = {
- *   example: { key: 'Your message here' },
- *   other: { key: 'Another message' }
- * }
- *
- * class Example extends Component {
- *   render() {
- *     const message = getMessage(this.context, 'example.key')
- *     const otherMsg = getMessageGetter(this.context, 'other')
- *     return (
- *       <span>
- *         {message} | {otherMsg('key')}
- *       </span>
- *     ) // 'Your message here | Another message'
- *   }
- * }
- * Example.contextType = MessageContext
- *
- * export const App = () => (
- *   <MessageProvider messages={messages}>
- *     <Example />
- *   </MessageProvider>
- * )
- * ```
- */
-export const MessageContext = createContext(defaultValue);
diff --git a/packages/preact-messages/src/message-error.ts 
b/packages/preact-messages/src/message-error.ts
deleted file mode 100644
index f641544..0000000
--- a/packages/preact-messages/src/message-error.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-export const errorMessages = {
-  EBADMSG: 'Message with unexpected object value',
-  ENOMSG: 'Message not found'
-};
-
-export type ErrorCode = keyof typeof errorMessages;
-
-/** @internal */
-export class MessageError extends Error {
-  code: ErrorCode;
-  path: string[];
-
-  constructor(
-    path: string[],
-    code: ErrorCode,
-    asId: (path: string[]) => string
-  ) {
-    super(`${errorMessages[code]}: ${asId(path)}`);
-    this.code = code;
-    this.path = path;
-  }
-}
diff --git a/packages/preact-messages/src/message.ts 
b/packages/preact-messages/src/message.ts
deleted file mode 100644
index e64481b..0000000
--- a/packages/preact-messages/src/message.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import { useContext } from 'preact/hooks';
-import { getMessage, getPath } from './get-message';
-import { MessageContext } from './message-context';
-
-/** @public */
-export interface MessageProps {
-  /**
-   * If a function, will be called with the found message.
-   * In this case, `params` will be ignored and `id` is optional.
-   * If some other type of non-empty renderable node, it will be used as a 
fallback value if the message is not found.
-   */
-  children?: any;
-
-  /** The key or key path of the message. */
-  id?: string | string[];
-
-  /** If set, overrides the `locale` of the nearest MessageProvider. */
-  locale?: string | string[];
-
-  /**
-   * Parameters to pass to function messages as their first and only argument.
-   * `params` will override `msgParams`, to allow for data keys such as `key` 
and `locale`.
-   */
-  params?: any;
-
-  /**
-   * Parameters to pass to function messages as their first and only argument.
-   * Overriden by `params`, to allow for data keys such as `key` and `locale`.
-   */
-  [msgParamKey: string]: any;
-}
-
-// Just using { foo, ...bar } adds a polyfill with a boilerplate copyright
-// statement that would add 50% to the minified size of the whole library.
-function rest(props: { [key: string]: any }, exclude: string[]) {
-  const t: typeof props = {};
-  for (const k of Object.keys(props)) if (!exclude.includes(k)) t[k] = 
props[k];
-  return t;
-}
-
-/**
- * `<Message id [locale] [params] [...msgParams]>`
- *
- * The value of a message.
- * May also be used with a render prop: `<Message id={id}>{msg => 
{...}}</Message>`.
- *
- * @public
- *
- * @example
- * ```js
- * import React from 'preact'
- * import { Message, MessageProvider } from '@messageformat/react'
- *
- * const messages = { example: { key: ({ thing }) => `Your ${thing} here` } }
- *
- * const Example = () => (
- *   <span>
- *     <Message id="example.key" thing="message" />
- *   </span>
- * ) // 'Your message here'
- *
- * export const App = () => (
- *   <MessageProvider messages={messages}>
- *     <Example />
- *   </MessageProvider>
- * )
- * ```
- */
-export function Message(props: MessageProps) {
-  const { children, id, locale, params } = props;
-  const msgParams = rest(props, ['children', 'id', 'locale', 'params']);
-  let context = useContext(MessageContext);
-  let fallback = false;
-  if (children && typeof children !== 'function')
-    context = Object.assign({}, context, { onError: () => (fallback = true) });
-  const msg = getMessage(context, id, locale);
-  if (fallback) return children;
-  if (typeof children === 'function') return children(msg);
-  switch (typeof msg) {
-    case 'function':
-      return msg(Object.assign(msgParams, params));
-    case 'boolean':
-      return String(msg);
-    case 'object':
-      if (msg && !Array.isArray(msg))
-        return context.onError ? context.onError(getPath(id), 'EBADMSG') : 
null;
-  }
-  return msg || null;
-}
diff --git a/packages/preact-messages/src/use-locales.ts 
b/packages/preact-messages/src/use-locales.ts
deleted file mode 100644
index 6addd8a..0000000
--- a/packages/preact-messages/src/use-locales.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { useContext } from 'preact/hooks';
-import { MessageContext } from './message-context';
-
-/**
- * A custom React hook providing the current locales as an array of string 
identifiers, with earlier entries taking precedence over latter ones.
- * Undefined locales are identified by an empty string `''`.
- *
- * @public
- *
- * @example
- * ```js
- * import React from 'preact'
- * import { MessageProvider, useLocales } from '@messageformat/react'
- *
- * <MessageProvider locale="en" messages={ { foo: 'FOO' } }>
- *   {() => useLocales().join(',') // 'en'
- *   }
- *   <MessageProvider locale="fi" messages={ { foo: 'FÖÖ' } }>
- *     {() => useLocales().join(',') // 'fi,en'
- *     }
- *   </MessageProvider>
- * </MessageProvider>
- * ```
- *
- * @example
- * ```js
- * import React, { Component } from 'preact'
- * import { MessageContext, MessageProvider, useLocales } from 
'@messageformat/react'
- *
- * // Within a class component, locales are available via the context object
- * class Foo extends Component {
- *   static contextType = MessageContext
- *   declare context: React.ContextType<typeof MessageContext> // TS
- *   render() {
- *     const { locales } = this.context
- *     return locales.join(',')
- *   }
- * }
- * ```
- */
-export function useLocales() {
-  const { locales } = useContext(MessageContext);
-  return locales.slice();
-}
diff --git a/packages/preact-messages/src/use-message-getter.ts 
b/packages/preact-messages/src/use-message-getter.ts
deleted file mode 100644
index a4b08fb..0000000
--- a/packages/preact-messages/src/use-message-getter.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { useContext } from 'preact/hooks';
-import { getMessageGetter, MessageGetterOptions } from './get-message';
-import { MessageContext } from './message-context';
-
-/**
- * A custom [React hook] providing a message getter function, which may have a 
preset root id path, locale, and/or base parameters for message functions.
- *
- * The returned function takes two parameters `(msgId, msgParams)`, which will 
extend any values set by the hook's arguments.
- *
- * @public
- * @param rootId - The key or key path of the message or message object.
- *   If empty or `[]`, matches the root of the messages object
- * @param options - If `baseParams` is set, message function parameters will 
be assumed to always be an object, with these values initially set.
- *   `locale` overrides the current locale precedence as set by parent 
MessageProviders.
- *
- * @example
- * ```js
- * import React from 'preact'
- * import { MessageProvider, useMessageGetter } from '@messageformat/react'
- *
- * const messages = {
- *   example: {
- *     funMsg: ({ thing }) => `Your ${thing} here`,
- *     thing: 'message'
- *   }
- * }
- *
- * function Example() {
- *   const getMsg = useMessageGetter('example')
- *   const thing = getMsg('thing') // 'message'
- *   return getMsg('funMsg', { thing }) // 'Your message here'
- * }
- *
- * export const App = () => (
- *   <MessageProvider messages={messages}>
- *     <Example />
- *   </MessageProvider>
- * )
- * ```
- */
-export function useMessageGetter(
-  rootId: string | string[],
-  opt?: MessageGetterOptions
-) {
-  const context = useContext(MessageContext);
-  return getMessageGetter(context, rootId, opt);
-}
diff --git a/packages/preact-messages/src/use-message-template.ts 
b/packages/preact-messages/src/use-message-template.ts
deleted file mode 100644
index e4de07a..0000000
--- a/packages/preact-messages/src/use-message-template.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { useContext } from 'preact/hooks';
-import { MessageGetterOptions, getPath, getMessage } from './get-message';
-import { MessageContext } from './message-context';
-
-
-export function useMessageTemplate(
-  rootId?: string | string[],
-  opt?: MessageGetterOptions
-) {
-  const context = useContext(MessageContext);
-  return getMessageGetter(context, rootId, opt);
-}
-
-export function getMessageGetter(
-  context: MessageContext,
-  rootId?: string | string[],
-  { baseParams, locale }: MessageGetterOptions = {}
-) {
-  const { pathSep } = context;
-  const pathPrefix = getPath(rootId, pathSep);
-  return function message(id?: TemplateStringsArray, ...params: any) {
-    const path = pathPrefix.concat(getPath(id?.join('%s'), pathSep));
-    const msg = getMessage(context, path, locale);
-    if (typeof msg !== 'function') return msg;
-    const msgParams = baseParams
-      ? Object.assign({}, baseParams, params)
-      : params;
-    return msg(msgParams);
-  };
-}
-
diff --git a/packages/preact-messages/src/use-message.ts 
b/packages/preact-messages/src/use-message.ts
deleted file mode 100644
index c44ec9f..0000000
--- a/packages/preact-messages/src/use-message.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { useContext } from 'preact/hooks';
-import { getMessage } from './get-message';
-import { MessageContext } from './message-context';
-
-/**
- * A custom React hook providing an entry from the messages object of the 
current or given locale.
- * The returned value will be `undefined` if not found.
- *
- * If the identified message value is a function, the returned value will be 
the result of calling it with a single argument `params`, or `{}` if empty.
- * Otherwise the value set in the `MessageProvider` props will be returned 
directly.
- *
- * @public
- * @param id - The key or key path of the message or message object.
- *   If empty or `[]`, matches the root of the messages object
- * @param params - Argument to use if the identified message is a function
- * @param locale - If set, overrides the current locale precedence as set by 
parent MessageProviders.
- *
- * @example
- * ```js
- * import React from 'preact'
- * import { MessageProvider, useLocales, useMessage } from 
'@messageformat/react'
- *
- * const en = { example: { key: 'Your message here' } }
- * const fi = { example: { key: 'Lisää viestisi tähän' } }
- *
- * // Intl.ListFormat may require a polyfill, such as intl-list-format
- * function Example() {
- *   const locales = useLocales() // ['fi', 'en']
- *   const lfOpt = { style: 'long', type: 'conjunction' }
- *   const lf = new Intl.ListFormat(locales, lfOpt)
- *   const lcMsg = lf.format(locales.map(lc => JSON.stringify(lc))) // '"fi" 
ja "en"'
- *   const keyMsg = useMessage('example.key') // 'Lisää viestisi tähän'
- *   return (
- *     <article>
- *       <h1>{lcMsg}</h1>
- *       <p>{keyMsg}</p>
- *     </article>
- *   )
- * }
- *
- * export const App = () => (
- *   <MessageProvider locale="en" messages={en}>
- *     <MessageProvider locale="fi" messages={fi}>
- *       <Example />
- *     </MessageProvider>
- *   </MessageProvider>
- * )
- * ```
- */
-export function useMessage(
-  id: string | string[],
-  params?: any,
-  locale?: string | string[]
-) {
-  const context = useContext(MessageContext);
-  const msg = getMessage(context, id, locale);
-  return typeof msg === 'function' ? msg(params == null ? {} : params) : msg;
-}
diff --git a/packages/preact-messages/tsconfig.json 
b/packages/preact-messages/tsconfig.json
deleted file mode 100644
index 2ae553e..0000000
--- a/packages/preact-messages/tsconfig.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
-  "compilerOptions": {
-      /* Basic Options */
-      "target": "ES5",                          /* Specify ECMAScript target 
version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
-      "module": "ESNext",                       /* Specify module code 
generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
-      // "lib": [],                             /* Specify library files to be 
included in the compilation:  */
-      "allowJs": true,                          /* Allow javascript files to 
be compiled. */
-      // "checkJs": true,                       /* Report errors in .js files. 
*/
-      "jsx": "react",                           /* Specify JSX code 
generation: 'preserve', 'react-native', or 'react'. */
-      "jsxFactory": "h",                        /* Specify the JSX factory 
function to use when targeting react JSX emit, e.g. React.createElement or h. */
-      "declaration": true,                   /* Generates corresponding 
'.d.ts' file. */
-      // "sourceMap": true,                     /* Generates corresponding 
'.map' file. */
-      // "outFile": "./",                       /* Concatenate and emit output 
to single file. */
-      "outDir": "./lib/",                        /* Redirect output structure 
to the directory. */
-      // "rootDir": "./",                       /* Specify the root directory 
of input files. Use to control the output directory structure with --outDir. */
-      // "removeComments": true,                /* Do not emit comments to 
output. */
-      "noEmit": false,                           /* Do not emit outputs. */
-      // "importHelpers": true,                 /* Import emit helpers from 
'tslib'. */
-      // "downlevelIteration": true,            /* Provide full support for 
iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. 
*/
-      // "isolatedModules": true,               /* Transpile each file as a 
separate module (similar to 'ts.transpileModule'). */
-
-      /* Strict Type-Checking Options */
-      "strict": true,                           /* Enable all strict 
type-checking options. */
-      // "noImplicitAny": true,                 /* Raise error on expressions 
and declarations with an implied 'any' type. */
-      // "strictNullChecks": true,              /* Enable strict null checks. 
*/
-      // "noImplicitThis": true,                /* Raise error on 'this' 
expressions with an implied 'any' type. */
-      // "alwaysStrict": true,                  /* Parse in strict mode and 
emit "use strict" for each source file. */
-
-      /* Additional Checks */
-      // "noUnusedLocals": true,                /* Report errors on unused 
locals. */
-      // "noUnusedParameters": true,            /* Report errors on unused 
parameters. */
-      // "noImplicitReturns": true,             /* Report error when not all 
code paths in function return a value. */
-      // "noFallthroughCasesInSwitch": true,    /* Report errors for 
fallthrough cases in switch statement. */
-
-      /* Module Resolution Options */
-      "moduleResolution": "node",               /* Specify module resolution 
strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
-      "esModuleInterop": true,                  /* */
-      // "baseUrl": "./",                       /* Base directory to resolve 
non-absolute module names. */
-      // "paths": {},                           /* A series of entries which 
re-map imports to lookup locations relative to the 'baseUrl'. */
-      // "rootDirs": [],                        /* List of root folders whose 
combined content represents the structure of the project at runtime. */
-      // "typeRoots": [],                       /* List of folders to include 
type definitions from. */
-      // "types": [],                           /* Type declaration files to 
be included in compilation. */
-      // "allowSyntheticDefaultImports": true,  /* Allow default imports from 
modules with no default export. This does not affect code emit, just 
typechecking. */
-      // "preserveSymlinks": true,              /* Do not resolve the real 
path of symlinks. */
-
-      /* Source Map Options */
-      // "sourceRoot": "./",                    /* Specify the location where 
debugger should locate TypeScript files instead of source locations. */
-      // "mapRoot": "./",                       /* Specify the location where 
debugger should locate map files instead of generated locations. */
-      // "inlineSourceMap": true,               /* Emit a single file with 
source maps instead of having a separate file. */
-      // "inlineSources": true,                 /* Emit the source alongside 
the sourcemaps within a single file; requires '--inlineSourceMap' or 
'--sourceMap' to be set. */
-
-      /* Experimental Options */
-      // "experimentalDecorators": true,        /* Enables experimental 
support for ES7 decorators. */
-      // "emitDecoratorMetadata": true,         /* Enables experimental 
support for emitting type metadata for decorators. */
-
-      /* Advanced Options */
-      "skipLibCheck": true                      /* Skip type checking of 
declaration files. */
-  },
-  "include": ["src/**/*", "tests/**/*"]
-}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c27cf57..5279442 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -10,6 +10,8 @@ importers:
       '@babel/core': ^7.13.16
       '@babel/plugin-transform-react-jsx-source': ^7.12.13
       '@creativebulma/bulma-tooltip': ^1.2.0
+      '@gnu-taler/pogen': ^0.0.5
+      '@gnu-taler/taler-util': ^0.8.2
       '@storybook/addon-a11y': ^6.2.9
       '@storybook/addon-actions': ^6.2.9
       '@storybook/addon-essentials': ^6.2.9
@@ -24,7 +26,6 @@ importers:
       '@types/mocha': ^8.2.2
       '@typescript-eslint/eslint-plugin': ^4.22.0
       '@typescript-eslint/parser': ^4.22.0
-      ava: ^3.15.0
       axios: ^0.21.1
       babel-loader: ^8.2.2
       base64-inline-loader: ^1.1.1
@@ -47,14 +48,13 @@ importers:
       html-webpack-inline-source-plugin: 0.0.10
       html-webpack-skip-assets-plugin: ^1.0.1
       inline-chunk-html-plugin: ^1.1.1
+      jed: ^1.1.1
       jest: ^26.6.3
       jest-preset-preact: ^4.0.2
-      messageformat: ^2.3.0
-      messageformat-po-loader: ^0.3.0
       node-sass: ^5.0.0
+      po2json: ^0.4.5
       preact: ^10.5.13
       preact-cli: ^3.0.5
-      preact-messages: workspace:*
       preact-render-to-json: ^3.6.6
       preact-render-to-string: ^5.1.19
       preact-router: ^3.2.1
@@ -67,12 +67,12 @@ importers:
       typescript: ^4.2.4
       yup: ^0.32.9
     dependencies:
+      '@gnu-taler/taler-util': 0.8.2
       axios: 0.21.1
       date-fns: 2.21.1
       history: 4.10.1
-      messageformat: 2.3.0
+      jed: 1.1.1
       preact: 10.5.13
-      preact-messages: link:../preact-messages
       preact-router: 3.2.1_preact@10.5.13
       swr: 0.5.5
       yup: 0.32.9
@@ -80,6 +80,7 @@ importers:
       '@babel/core': 7.13.16
       '@babel/plugin-transform-react-jsx-source': 7.12.13_@babel+core@7.13.16
       '@creativebulma/bulma-tooltip': 1.2.0
+      '@gnu-taler/pogen': 0.0.5
       '@storybook/addon-a11y': 6.2.9
       '@storybook/addon-actions': 6.2.9
       '@storybook/addon-essentials': 6.2.9_472ba1443a3a7dfb9d5f96aaff5418de
@@ -94,7 +95,6 @@ importers:
       '@types/mocha': 8.2.2
       '@typescript-eslint/eslint-plugin': 
4.22.0_e3b52a83531895e7febd6ecd5ba813eb
       '@typescript-eslint/parser': 4.22.0_eslint@7.25.0+typescript@4.2.4
-      ava: 3.15.0
       babel-loader: 8.2.2_@babel+core@7.13.16
       base64-inline-loader: 1.1.1
       bulma: 0.9.2
@@ -116,8 +116,8 @@ importers:
       inline-chunk-html-plugin: 1.1.1
       jest: 26.6.3
       jest-preset-preact: 4.0.2_669f037bdb6c36f0a67e918c516dafdd
-      messageformat-po-loader: 0.3.0_messageformat@2.3.0
       node-sass: 5.0.0
+      po2json: 0.4.5
       preact-cli: 3.0.5_c069246dc1d99535ac277c76f8ef56e0
       preact-render-to-json: 3.6.6_preact@10.5.13
       preact-render-to-string: 5.1.19_preact@10.5.13
@@ -128,17 +128,6 @@ importers:
       typedoc: 0.20.36_typescript@4.2.4
       typescript: 4.2.4
 
-  packages/preact-messages:
-    specifiers:
-      preact: ^10.5.13
-      rimraf: ^3.0.2
-      typescript: ^4.2.3
-    dependencies:
-      preact: 10.5.13
-      typescript: 4.2.3
-    devDependencies:
-      rimraf: 3.0.2
-
 packages:
 
   /@babel/code-frame/7.10.4:
@@ -1421,13 +1410,6 @@ packages:
       minimist: 1.2.5
     dev: true
 
-  /@concordance/react/2.0.0:
-    resolution: {integrity: 
sha512-huLSkUuM2/P+U0uy2WwlKuixMsTODD8p4JVQBI4VKeopkiN0C7M3N9XYVawb4M+4spN5RrO/eLhk7KoQX6nsfA==}
-    engines: {node: '>=6.12.3 <7 || >=8.9.4 <9 || >=10.0.0'}
-    dependencies:
-      arrify: 1.0.1
-    dev: true
-
   /@creativebulma/bulma-tooltip/1.2.0:
     resolution: {integrity: 
sha512-ooImbeXEBxf77cttbzA7X5rC5aAWm9UsXIGViFOnsqB+6M944GkB28S5R4UWRqjFd2iW4zGEkEifAU+q43pt2w==}
     dev: true
@@ -1587,6 +1569,18 @@ packages:
       - supports-color
     dev: true
 
+  /@gnu-taler/pogen/0.0.5:
+    resolution: {integrity: sha1-bB0QCi9T3Yr9o4wvq9EUUnE5R1Y=, tarball: 
https://gitlab.com/api/v4/projects/20136151/packages/npm/@gnu-taler/pogen/-/@gnu-taler/pogen-0.0.5.tgz}
+    dependencies:
+      '@types/node': 14.14.43
+    dev: true
+
+  /@gnu-taler/taler-util/0.8.2:
+    resolution: {integrity: sha1-B6/UuryzdS4wsbBtK1vTn/kNAaM=, tarball: 
https://gitlab.com/api/v4/projects/20136151/packages/npm/@gnu-taler/taler-util/-/@gnu-taler/taler-util-0.8.2.tgz}
+    dependencies:
+      tslib: 2.2.0
+    dev: false
+
   /@hapi/address/2.1.4:
     resolution: {integrity: 
sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==}
     deprecated: Moved to 'npm install @sideway/address'
@@ -4184,11 +4178,6 @@ packages:
     engines: {node: '>=0.4.0'}
     dev: true
 
-  /acorn-walk/8.1.0:
-    resolution: {integrity: 
sha512-mjmzmv12YIG/G8JQdQuz2MUDShEJ6teYpT5bmWA4q7iwoGen8xtt3twF3OvzIUl+Q06aWIjvnwQUKvQ6TtMRjg==}
-    engines: {node: '>=0.4.0'}
-    dev: true
-
   /acorn/5.7.4:
     resolution: {integrity: 
sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==}
     engines: {node: '>=0.4.0'}
@@ -4335,6 +4324,11 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
+  /ansi-styles/1.0.0:
+    resolution: {integrity: sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=}
+    engines: {node: '>=0.8.0'}
+    dev: true
+
   /ansi-styles/2.2.1:
     resolution: {integrity: sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=}
     engines: {node: '>=0.10.0'}
@@ -4354,11 +4348,6 @@ packages:
       color-convert: 2.0.1
     dev: true
 
-  /ansi-styles/5.2.0:
-    resolution: {integrity: 
sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
-    engines: {node: '>=10'}
-    dev: true
-
   /ansi-to-html/0.6.14:
     resolution: {integrity: 
sha512-7ZslfB1+EnFSDO5Ju+ue5Y6It19DRnZXWv8jrGHgIlPna5Mh4jz7BV5jCbQneXNFurQcKoolaaAjHtgSBfOIuA==}
     hasBin: true
@@ -4509,16 +4498,6 @@ packages:
       is-string: 1.0.5
     dev: true
 
-  /arrgv/1.0.2:
-    resolution: {integrity: 
sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==}
-    engines: {node: '>=8.0.0'}
-    dev: true
-
-  /arrify/1.0.1:
-    resolution: {integrity: sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=}
-    engines: {node: '>=0.10.0'}
-    dev: true
-
   /arrify/2.0.1:
     resolution: {integrity: 
sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==}
     engines: {node: '>=8'}
@@ -4611,71 +4590,6 @@ packages:
       postcss-value-parser: 4.1.0
     dev: true
 
-  /ava/3.15.0:
-    resolution: {integrity: 
sha512-HGAnk1SHPk4Sx6plFAUkzV/XC1j9+iQhOzt4vBly18/yo0AV8Oytx7mtJd/CR8igCJ5p160N/Oo/cNJi2uSeWA==}
-    engines: {node: '>=10.18.0 <11 || >=12.14.0 <12.17.0 || >=12.17.0 <13 || 
>=14.0.0 <15 || >=15'}
-    hasBin: true
-    dependencies:
-      '@concordance/react': 2.0.0
-      acorn: 8.2.1
-      acorn-walk: 8.1.0
-      ansi-styles: 5.2.0
-      arrgv: 1.0.2
-      arrify: 2.0.1
-      callsites: 3.1.0
-      chalk: 4.1.1
-      chokidar: 3.5.1
-      chunkd: 2.0.1
-      ci-info: 2.0.0
-      ci-parallel-vars: 1.0.1
-      clean-yaml-object: 0.1.0
-      cli-cursor: 3.1.0
-      cli-truncate: 2.1.0
-      code-excerpt: 3.0.0
-      common-path-prefix: 3.0.0
-      concordance: 5.0.4
-      convert-source-map: 1.7.0
-      currently-unhandled: 0.4.1
-      debug: 4.3.1
-      del: 6.0.0
-      emittery: 0.8.1
-      equal-length: 1.0.1
-      figures: 3.2.0
-      globby: 11.0.3
-      ignore-by-default: 2.0.0
-      import-local: 3.0.2
-      indent-string: 4.0.0
-      is-error: 2.2.2
-      is-plain-object: 5.0.0
-      is-promise: 4.0.0
-      lodash: 4.17.21
-      matcher: 3.0.0
-      md5-hex: 3.0.1
-      mem: 8.1.1
-      ms: 2.1.3
-      ora: 5.4.0
-      p-event: 4.2.0
-      p-map: 4.0.0
-      picomatch: 2.2.3
-      pkg-conf: 3.1.0
-      plur: 4.0.0
-      pretty-ms: 7.0.1
-      read-pkg: 5.2.0
-      resolve-cwd: 3.0.0
-      slash: 3.0.0
-      source-map-support: 0.5.19
-      stack-utils: 2.0.3
-      strip-ansi: 6.0.0
-      supertap: 2.0.0
-      temp-dir: 2.0.0
-      trim-off-newlines: 1.0.1
-      update-notifier: 5.1.0
-      write-file-atomic: 3.0.3
-      yargs: 16.2.0
-    transitivePeerDependencies:
-      - supports-color
-    dev: true
-
   /aws-sign2/0.7.0:
     resolution: {integrity: sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=}
     dev: true
@@ -5058,22 +4972,10 @@ packages:
     dev: true
     optional: true
 
-  /bl/4.1.0:
-    resolution: {integrity: 
sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
-    dependencies:
-      buffer: 5.7.1
-      inherits: 2.0.4
-      readable-stream: 3.6.0
-    dev: true
-
   /bluebird/3.7.2:
     resolution: {integrity: 
sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
     dev: true
 
-  /blueimp-md5/2.18.0:
-    resolution: {integrity: 
sha512-vE52okJvzsVWhcgUHOv+69OG3Mdg151xyn41aVQN/5W5S+S43qZhxECtYLAEHMSFWX6Mv5IZrzj3T5+JqXfj5Q==}
-    dev: true
-
   /bn.js/4.12.0:
     resolution: {integrity: 
sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==}
     dev: true
@@ -5127,20 +5029,6 @@ packages:
       widest-line: 3.1.0
     dev: true
 
-  /boxen/5.0.1:
-    resolution: {integrity: 
sha512-49VBlw+PrWEF51aCmy7QIteYPIFZxSpvqBdP/2itCPPlJ49kj9zg/XPRFrdkne2W+CfwXUls8exMvu1RysZpKA==}
-    engines: {node: '>=10'}
-    dependencies:
-      ansi-align: 3.0.0
-      camelcase: 6.2.0
-      chalk: 4.1.1
-      cli-boxes: 2.2.1
-      string-width: 4.2.2
-      type-fest: 0.20.2
-      widest-line: 3.1.0
-      wrap-ansi: 7.0.0
-    dev: true
-
   /brace-expansion/1.1.11:
     resolution: {integrity: 
sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
     dependencies:
@@ -5283,13 +5171,6 @@ packages:
       isarray: 1.0.0
     dev: true
 
-  /buffer/5.7.1:
-    resolution: {integrity: 
sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
-    dependencies:
-      base64-js: 1.5.1
-      ieee754: 1.2.1
-    dev: true
-
   /builtin-modules/3.2.0:
     resolution: {integrity: 
sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==}
     engines: {node: '>=6'}
@@ -5532,6 +5413,15 @@ packages:
     resolution: {integrity: 
sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==}
     dev: true
 
+  /chalk/0.4.0:
+    resolution: {integrity: sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=}
+    engines: {node: '>=0.8.0'}
+    dependencies:
+      ansi-styles: 1.0.0
+      has-color: 0.1.7
+      strip-ansi: 0.1.1
+    dev: true
+
   /chalk/1.1.3:
     resolution: {integrity: sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=}
     engines: {node: '>=0.10.0'}
@@ -5668,10 +5558,6 @@ packages:
     engines: {node: '>=6.0'}
     dev: true
 
-  /chunkd/2.0.1:
-    resolution: {integrity: 
sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==}
-    dev: true
-
   /ci-env/1.16.0:
     resolution: {integrity: 
sha512-ucF9caQEX5wQlY449KZBIJPx91+kRg9tJ3tWSc4+KzrvC5KNiPm/3g1noP8VhdI3046+Vw3jLmKAD0fjCRJTmw==}
     dev: true
@@ -5680,10 +5566,6 @@ packages:
     resolution: {integrity: 
sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==}
     dev: true
 
-  /ci-parallel-vars/1.0.1:
-    resolution: {integrity: 
sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==}
-    dev: true
-
   /cipher-base/1.0.4:
     resolution: {integrity: 
sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==}
     dependencies:
@@ -5721,11 +5603,6 @@ packages:
     engines: {node: '>=6'}
     dev: true
 
-  /clean-yaml-object/0.1.0:
-    resolution: {integrity: sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g=}
-    engines: {node: '>=0.10.0'}
-    dev: true
-
   /cli-boxes/2.2.1:
     resolution: {integrity: 
sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==}
     engines: {node: '>=6'}
@@ -5753,14 +5630,6 @@ packages:
       colors: 1.4.0
     dev: true
 
-  /cli-truncate/2.1.0:
-    resolution: {integrity: 
sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
-    engines: {node: '>=8'}
-    dependencies:
-      slice-ansi: 3.0.0
-      string-width: 4.2.2
-    dev: true
-
   /clipboard/2.0.8:
     resolution: {integrity: 
sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==}
     dependencies:
@@ -5786,14 +5655,6 @@ packages:
       wrap-ansi: 6.2.0
     dev: true
 
-  /cliui/7.0.4:
-    resolution: {integrity: 
sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
-    dependencies:
-      string-width: 4.2.2
-      strip-ansi: 6.0.0
-      wrap-ansi: 7.0.0
-    dev: true
-
   /clone-deep/4.0.1:
     resolution: {integrity: 
sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
     engines: {node: '>=6'}
@@ -5828,13 +5689,6 @@ packages:
       q: 1.5.1
     dev: true
 
-  /code-excerpt/3.0.0:
-    resolution: {integrity: 
sha512-VHNTVhd7KsLGOqfX3SyeO8RyYPMp1GJOg194VITk04WMYCv4plV68YWe6TJZxd9MhobjtpMRnVky01gqZsalaw==}
-    engines: {node: '>=10'}
-    dependencies:
-      convert-to-spaces: 1.0.2
-    dev: true
-
   /code-point-at/1.1.0:
     resolution: {integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=}
     engines: {node: '>=0.10.0'}
@@ -5933,10 +5787,6 @@ packages:
     engines: {node: '>= 6'}
     dev: true
 
-  /common-path-prefix/3.0.0:
-    resolution: {integrity: 
sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==}
-    dev: true
-
   /common-tags/1.8.0:
     resolution: {integrity: 
sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==}
     engines: {node: '>=4.0.0'}
@@ -6002,20 +5852,6 @@ packages:
       typedarray: 0.0.6
     dev: true
 
-  /concordance/5.0.4:
-    resolution: {integrity: 
sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==}
-    engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'}
-    dependencies:
-      date-time: 3.1.0
-      esutils: 2.0.3
-      fast-diff: 1.2.0
-      js-string-escape: 1.0.1
-      lodash: 4.17.21
-      md5-hex: 3.0.1
-      semver: 7.3.5
-      well-known-symbols: 2.0.0
-    dev: true
-
   /configstore/5.0.1:
     resolution: {integrity: 
sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==}
     engines: {node: '>=8'}
@@ -6068,11 +5904,6 @@ packages:
       safe-buffer: 5.1.2
     dev: true
 
-  /convert-to-spaces/1.0.2:
-    resolution: {integrity: sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU=}
-    engines: {node: '>= 4'}
-    dev: true
-
   /cookie-signature/1.0.6:
     resolution: {integrity: sha1-4wOogrNCzD7oylE6eZmXNNqzriw=}
     dev: true
@@ -6577,13 +6408,6 @@ packages:
     engines: {node: '>=0.11'}
     dev: false
 
-  /date-time/3.1.0:
-    resolution: {integrity: 
sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==}
-    engines: {node: '>=6'}
-    dependencies:
-      time-zone: 1.0.0
-    dev: true
-
   /debug/2.6.9:
     resolution: {integrity: 
sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
     dependencies:
@@ -6737,20 +6561,6 @@ packages:
       rimraf: 2.7.1
     dev: true
 
-  /del/6.0.0:
-    resolution: {integrity: 
sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==}
-    engines: {node: '>=10'}
-    dependencies:
-      globby: 11.0.3
-      graceful-fs: 4.2.6
-      is-glob: 4.0.1
-      is-path-cwd: 2.2.0
-      is-path-inside: 3.0.3
-      p-map: 4.0.0
-      rimraf: 3.0.2
-      slash: 3.0.0
-    dev: true
-
   /delayed-stream/1.0.0:
     resolution: {integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk=}
     engines: {node: '>=0.4.0'}
@@ -7098,11 +6908,6 @@ packages:
     engines: {node: '>=10'}
     dev: true
 
-  /emittery/0.8.1:
-    resolution: {integrity: 
sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==}
-    engines: {node: '>=10'}
-    dev: true
-
   /emoji-regex/6.1.1:
     resolution: {integrity: sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=}
     dev: true
@@ -7247,11 +7052,6 @@ packages:
       string.prototype.trim: 1.2.4
     dev: true
 
-  /equal-length/1.0.1:
-    resolution: {integrity: sha1-IcoRLUirJLTh5//A5TOdMf38J0w=}
-    engines: {node: '>=4'}
-    dev: true
-
   /errno/0.1.8:
     resolution: {integrity: 
sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==}
     hasBin: true
@@ -7346,11 +7146,6 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
-  /escape-string-regexp/4.0.0:
-    resolution: {integrity: 
sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
-    engines: {node: '>=10'}
-    dev: true
-
   /escodegen/1.14.3:
     resolution: {integrity: 
sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==}
     engines: {node: '>=4.0'}
@@ -7772,10 +7567,6 @@ packages:
     resolution: {integrity: 
sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
     dev: true
 
-  /fast-diff/1.2.0:
-    resolution: {integrity: 
sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==}
-    dev: true
-
   /fast-glob/2.2.7:
     resolution: {integrity: 
sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==}
     engines: {node: '>=4.0.0'}
@@ -7837,13 +7628,6 @@ packages:
     resolution: {integrity: 
sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==}
     dev: true
 
-  /figures/3.2.0:
-    resolution: {integrity: 
sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
-    engines: {node: '>=8'}
-    dependencies:
-      escape-string-regexp: 1.0.5
-    dev: true
-
   /file-entry-cache/6.0.1:
     resolution: {integrity: 
sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
     engines: {node: ^10.12.0 || >=12.0.0}
@@ -8303,18 +8087,10 @@ packages:
       assert-plus: 1.0.0
     dev: true
 
-  /gettext-parser/1.4.0:
-    resolution: {integrity: 
sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==}
+  /gettext-parser/1.1.0:
+    resolution: {integrity: sha1-LFpmONiTk0ubVQN9CtgstwBLJnk=}
     dependencies:
       encoding: 0.1.13
-      safe-buffer: 5.2.1
-    dev: true
-
-  /gettext-to-messageformat/0.3.1:
-    resolution: {integrity: 
sha512-UyqIL3Ul4NryU95Wome/qtlcuVIqgEWVIFw0zi7Lv14ACLXfaVDCbrjZ7o+3BZ7u+4NS1mP/2O1eXZoHCoas8g==}
-    engines: {node: '>=6.0'}
-    dependencies:
-      gettext-parser: 1.4.0
     dev: true
 
   /github-slugger/1.3.0:
@@ -8391,13 +8167,6 @@ packages:
       ini: 1.3.7
     dev: true
 
-  /global-dirs/3.0.0:
-    resolution: {integrity: 
sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==}
-    engines: {node: '>=10'}
-    dependencies:
-      ini: 2.0.0
-    dev: true
-
   /global-modules/2.0.0:
     resolution: {integrity: 
sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==}
     engines: {node: '>=6'}
@@ -8608,6 +8377,11 @@ packages:
     resolution: {integrity: 
sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==}
     dev: true
 
+  /has-color/0.1.7:
+    resolution: {integrity: sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
   /has-flag/3.0.0:
     resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=}
     engines: {node: '>=4'}
@@ -9089,11 +8863,6 @@ packages:
     resolution: {integrity: sha1-xg7taebY/bazEEofy8ocGS3FtQE=}
     dev: true
 
-  /ignore-by-default/2.0.0:
-    resolution: {integrity: 
sha512-+mQSgMRiFD3L3AOxLYOCxjIq4OnAmo5CIuC+lj5ehCJcPtV++QacEV7FdpzvYxH6DaOySWzQU6RR0lPLy37ckA==}
-    engines: {node: '>=10 <11 || >=12 <13 || >=14'}
-    dev: true
-
   /ignore/3.3.10:
     resolution: {integrity: 
sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==}
     dev: true
@@ -9217,11 +8986,6 @@ packages:
     resolution: {integrity: 
sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
     dev: true
 
-  /ini/2.0.0:
-    resolution: {integrity: 
sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==}
-    engines: {node: '>=10'}
-    dev: true
-
   /inline-chunk-html-plugin/1.1.1:
     resolution: {integrity: 
sha512-6W1eGIj8z/Yla6xJx5il6jJfCxMZS3kVkbiLQThbbjdsDLRIWkUVmpnhfW2l6WAwCW+qfy0zoXVGBZM1E5XF3g==}
     dev: true
@@ -9277,11 +9041,6 @@ packages:
     engines: {node: '>= 0.10'}
     dev: true
 
-  /irregular-plurals/3.3.0:
-    resolution: {integrity: 
sha512-MVBLKUTangM3EfRPFROhmWQQKRDsrgI83J8GS3jXy+OwYqiR2/aoWndYQ5416jLE3uaGgLH7ncme3X9y09gZ3g==}
-    engines: {node: '>=8'}
-    dev: true
-
   /is-absolute-url/2.1.0:
     resolution: {integrity: sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=}
     engines: {node: '>=0.10.0'}
@@ -9454,10 +9213,6 @@ packages:
       is-window: 1.0.2
     dev: true
 
-  /is-error/2.2.2:
-    resolution: {integrity: 
sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==}
-    dev: true
-
   /is-extendable/0.1.1:
     resolution: {integrity: sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=}
     engines: {node: '>=0.10.0'}
@@ -9544,14 +9299,6 @@ packages:
       is-path-inside: 3.0.3
     dev: true
 
-  /is-installed-globally/0.4.0:
-    resolution: {integrity: 
sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==}
-    engines: {node: '>=10'}
-    dependencies:
-      global-dirs: 3.0.0
-      is-path-inside: 3.0.3
-    dev: true
-
   /is-interactive/1.0.0:
     resolution: {integrity: 
sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
     engines: {node: '>=8'}
@@ -9575,11 +9322,6 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
-  /is-npm/5.0.0:
-    resolution: {integrity: 
sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==}
-    engines: {node: '>=10'}
-    dev: true
-
   /is-number-object/1.0.4:
     resolution: {integrity: 
sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==}
     engines: {node: '>= 0.4'}
@@ -9657,19 +9399,10 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: true
 
-  /is-plain-object/5.0.0:
-    resolution: {integrity: 
sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
-    engines: {node: '>=0.10.0'}
-    dev: true
-
   /is-potential-custom-element-name/1.0.1:
     resolution: {integrity: 
sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
     dev: true
 
-  /is-promise/4.0.0:
-    resolution: {integrity: 
sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
-    dev: true
-
   /is-regex/1.1.2:
     resolution: {integrity: 
sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==}
     engines: {node: '>= 0.4'}
@@ -9726,11 +9459,6 @@ packages:
     resolution: {integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=}
     dev: true
 
-  /is-unicode-supported/0.1.0:
-    resolution: {integrity: 
sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
-    engines: {node: '>=10'}
-    dev: true
-
   /is-utf8/0.2.1:
     resolution: {integrity: sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=}
     dev: true
@@ -9864,6 +9592,10 @@ packages:
       iterate-iterator: 1.0.1
     dev: true
 
+  /jed/1.1.1:
+    resolution: {integrity: sha1-elSbvZ/+FYWwzQoZHiAwVb7ldLQ=}
+    dev: false
+
   /jest-changed-files/26.6.2:
     resolution: {integrity: 
sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==}
     engines: {node: '>= 10.14.2'}
@@ -10659,17 +10391,6 @@ packages:
       strip-bom: 2.0.0
     dev: true
 
-  /load-json-file/5.3.0:
-    resolution: {integrity: 
sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==}
-    engines: {node: '>=6'}
-    dependencies:
-      graceful-fs: 4.2.6
-      parse-json: 4.0.0
-      pify: 4.0.1
-      strip-bom: 3.0.0
-      type-fest: 0.3.1
-    dev: true
-
   /loader-runner/2.4.0:
     resolution: {integrity: 
sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==}
     engines: {node: '>=4.3.0 <5.0.0 || >=5.10'}
@@ -10800,14 +10521,6 @@ packages:
       chalk: 2.4.2
     dev: true
 
-  /log-symbols/4.1.0:
-    resolution: {integrity: 
sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
-    engines: {node: '>=10'}
-    dependencies:
-      chalk: 4.1.1
-      is-unicode-supported: 0.1.0
-    dev: true
-
   /loglevel/1.7.1:
     resolution: {integrity: 
sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==}
     engines: {node: '>= 0.6.0'}
@@ -10904,26 +10617,12 @@ packages:
       semver: 6.3.0
     dev: true
 
-  /make-plural/4.3.0:
-    resolution: {integrity: 
sha512-xTYd4JVHpSCW+aqDof6w/MebaMVNTVYBZhbB/vi513xXdiPT92JMVCo0Jq8W2UZnzYRFeVbQiQ+I25l13JuKvA==}
-    hasBin: true
-    optionalDependencies:
-      minimist: 1.2.5
-    dev: false
-
   /makeerror/1.0.11:
     resolution: {integrity: sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=}
     dependencies:
       tmpl: 1.0.4
     dev: true
 
-  /map-age-cleaner/0.1.3:
-    resolution: {integrity: 
sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==}
-    engines: {node: '>=6'}
-    dependencies:
-      p-defer: 1.0.0
-    dev: true
-
   /map-cache/0.2.2:
     resolution: {integrity: sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=}
     engines: {node: '>=0.10.0'}
@@ -10992,20 +10691,6 @@ packages:
     hasBin: true
     dev: true
 
-  /matcher/3.0.0:
-    resolution: {integrity: 
sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==}
-    engines: {node: '>=10'}
-    dependencies:
-      escape-string-regexp: 4.0.0
-    dev: true
-
-  /md5-hex/3.0.1:
-    resolution: {integrity: 
sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==}
-    engines: {node: '>=8'}
-    dependencies:
-      blueimp-md5: 2.18.0
-    dev: true
-
   /md5.js/1.3.5:
     resolution: {integrity: 
sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==}
     dependencies:
@@ -11060,14 +10745,6 @@ packages:
     engines: {node: '>= 0.6'}
     dev: true
 
-  /mem/8.1.1:
-    resolution: {integrity: 
sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==}
-    engines: {node: '>=10'}
-    dependencies:
-      map-age-cleaner: 0.1.3
-      mimic-fn: 3.1.0
-    dev: true
-
   /memfs/3.2.2:
     resolution: {integrity: 
sha512-RE0CwmIM3CEvpcdK3rZ19BC4E6hv9kADkMN5rPduRak58cNArWLi/9jFLsa4rhsjfVxMP3v0jO7FHXq7SvFY5Q==}
     engines: {node: '>= 4.0.0'}
@@ -11125,33 +10802,6 @@ packages:
     engines: {node: '>= 8'}
     dev: true
 
-  /messageformat-formatters/2.0.1:
-    resolution: {integrity: 
sha512-E/lQRXhtHwGuiQjI7qxkLp8AHbMD5r2217XNe/SREbBlSawe0lOqsFb7rflZJmlQFSULNLIqlcjjsCPlB3m3Mg==}
-    dev: false
-
-  /messageformat-parser/4.1.3:
-    resolution: {integrity: 
sha512-2fU3XDCanRqeOCkn7R5zW5VQHWf+T3hH65SzuqRvjatBK7r4uyFa5mEX+k6F9Bd04LVM5G4/BHBTUJsOdW7uyg==}
-    dev: false
-
-  /messageformat-po-loader/0.3.0_messageformat@2.3.0:
-    resolution: {integrity: 
sha512-thu/A7hNl/iBHsRXUdmiy/nEFJZku3bsBMXL53HgHm+I0JaVU9lSpwuQAe7huCO4INGxgZtDoPAEpeb1ZeI5lg==}
-    engines: {node: '>=6.0'}
-    peerDependencies:
-      messageformat: 1.x | 2.x
-    dependencies:
-      gettext-to-messageformat: 0.3.1
-      loader-utils: 1.4.0
-      messageformat: 2.3.0
-    dev: true
-
-  /messageformat/2.3.0:
-    resolution: {integrity: 
sha512-uTzvsv0lTeQxYI2y1NPa1lItL5VRI8Gb93Y2K2ue5gBPyrbJxfDi/EYWxh2PKv5yO42AJeeqblS9MJSh/IEk4w==}
-    dependencies:
-      make-plural: 4.3.0
-      messageformat-formatters: 2.0.1
-      messageformat-parser: 4.1.3
-    dev: false
-
   /methods/1.1.2:
     resolution: {integrity: sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=}
     engines: {node: '>= 0.6'}
@@ -11225,11 +10875,6 @@ packages:
     engines: {node: '>=6'}
     dev: true
 
-  /mimic-fn/3.1.0:
-    resolution: {integrity: 
sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==}
-    engines: {node: '>=8'}
-    dev: true
-
   /mimic-response/1.0.1:
     resolution: {integrity: 
sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==}
     engines: {node: '>=4'}
@@ -11270,6 +10915,7 @@ packages:
 
   /minimist/1.2.5:
     resolution: {integrity: 
sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==}
+    dev: true
 
   /minipass-collect/1.0.2:
     resolution: {integrity: 
sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
@@ -11606,6 +11252,14 @@ packages:
     resolution: {integrity: 
sha512-4a5FH4WLi+daH/CGD5o/JWRR8W5tlCkd3nrDSkxbOzscJTyTUITltvOJeQjg3HJ1YgEuNyiPhQbvbtRjkQBByQ==}
     dev: true
 
+  /nomnom/1.8.1:
+    resolution: {integrity: sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=}
+    deprecated: Package no longer supported. Contact support@npmjs.com for 
more info.
+    dependencies:
+      chalk: 0.4.0
+      underscore: 1.6.0
+    dev: true
+
   /nopt/5.0.0:
     resolution: {integrity: 
sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
     engines: {node: '>=6'}
@@ -11909,21 +11563,6 @@ packages:
       wcwidth: 1.0.1
     dev: true
 
-  /ora/5.4.0:
-    resolution: {integrity: 
sha512-1StwyXQGoU6gdjYkyVcqOLnVlbKj+6yPNNOxJVgpt9t4eksKjiriiHuxktLYkgllwk+D6MbC4ihH84L1udRXPg==}
-    engines: {node: '>=10'}
-    dependencies:
-      bl: 4.1.0
-      chalk: 4.1.1
-      cli-cursor: 3.1.0
-      cli-spinners: 2.6.0
-      is-interactive: 1.0.0
-      is-unicode-supported: 0.1.0
-      log-symbols: 4.1.0
-      strip-ansi: 6.0.0
-      wcwidth: 1.0.1
-    dev: true
-
   /original/1.0.2:
     resolution: {integrity: 
sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==}
     dependencies:
@@ -11950,11 +11589,6 @@ packages:
     engines: {node: '>=6'}
     dev: true
 
-  /p-defer/1.0.0:
-    resolution: {integrity: sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=}
-    engines: {node: '>=4'}
-    dev: true
-
   /p-each-series/2.2.0:
     resolution: {integrity: 
sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==}
     engines: {node: '>=8'}
@@ -12140,11 +11774,6 @@ packages:
       lines-and-columns: 1.1.6
     dev: true
 
-  /parse-ms/2.1.0:
-    resolution: {integrity: 
sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==}
-    engines: {node: '>=6'}
-    dev: true
-
   /parse5-htmlparser2-tree-adapter/6.0.1:
     resolution: {integrity: 
sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==}
     dependencies:
@@ -12307,14 +11936,6 @@ packages:
       node-modules-regexp: 1.0.0
     dev: true
 
-  /pkg-conf/3.1.0:
-    resolution: {integrity: 
sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==}
-    engines: {node: '>=6'}
-    dependencies:
-      find-up: 3.0.0
-      load-json-file: 5.3.0
-    dev: true
-
   /pkg-dir/3.0.0:
     resolution: {integrity: 
sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==}
     engines: {node: '>=6'}
@@ -12343,13 +11964,6 @@ packages:
       find-up: 3.0.0
     dev: true
 
-  /plur/4.0.0:
-    resolution: {integrity: 
sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==}
-    engines: {node: '>=10'}
-    dependencies:
-      irregular-plurals: 3.3.0
-    dev: true
-
   /pn/1.1.0:
     resolution: {integrity: 
sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==}
     dev: true
@@ -12363,6 +11977,15 @@ packages:
       - typescript
     dev: true
 
+  /po2json/0.4.5:
+    resolution: {integrity: sha1-R7spUtoy1Yob4vJWpZjuvAt0URg=}
+    engines: {node: '>= 0.8.0'}
+    hasBin: true
+    dependencies:
+      gettext-parser: 1.1.0
+      nomnom: 1.8.1
+    dev: true
+
   /polished/4.1.2:
     resolution: {integrity: 
sha512-jq4t3PJUpVRcveC53nnbEX35VyQI05x3tniwp26WFdm1dwaNUBHAi5awa/roBlwQxx1uRhwNSYeAi/aMbfiJCQ==}
     engines: {node: '>=10'}
@@ -12919,13 +12542,6 @@ packages:
     engines: {node: '>= 0.8'}
     dev: true
 
-  /pretty-ms/7.0.1:
-    resolution: {integrity: 
sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==}
-    engines: {node: '>=10'}
-    dependencies:
-      parse-ms: 2.1.0
-    dev: true
-
   /prismjs/1.23.0:
     resolution: {integrity: 
sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==}
     optionalDependencies:
@@ -14263,13 +13879,6 @@ packages:
       statuses: 1.5.0
     dev: true
 
-  /serialize-error/7.0.1:
-    resolution: {integrity: 
sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
-    engines: {node: '>=10'}
-    dependencies:
-      type-fest: 0.13.1
-    dev: true
-
   /serialize-javascript/4.0.0:
     resolution: {integrity: 
sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==}
     dependencies:
@@ -14485,15 +14094,6 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
-  /slice-ansi/3.0.0:
-    resolution: {integrity: 
sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==}
-    engines: {node: '>=8'}
-    dependencies:
-      ansi-styles: 4.3.0
-      astral-regex: 2.0.0
-      is-fullwidth-code-point: 3.0.0
-    dev: true
-
   /slice-ansi/4.0.0:
     resolution: {integrity: 
sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
     engines: {node: '>=10'}
@@ -14891,6 +14491,12 @@ packages:
       is-regexp: 1.0.0
     dev: true
 
+  /strip-ansi/0.1.1:
+    resolution: {integrity: sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=}
+    engines: {node: '>=0.8.0'}
+    hasBin: true
+    dev: true
+
   /strip-ansi/3.0.1:
     resolution: {integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=}
     engines: {node: '>=0.10.0'}
@@ -14919,11 +14525,6 @@ packages:
       is-utf8: 0.2.1
     dev: true
 
-  /strip-bom/3.0.0:
-    resolution: {integrity: sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=}
-    engines: {node: '>=4'}
-    dev: true
-
   /strip-bom/4.0.0:
     resolution: {integrity: 
sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==}
     engines: {node: '>=8'}
@@ -14991,17 +14592,6 @@ packages:
       postcss-selector-parser: 3.1.2
     dev: true
 
-  /supertap/2.0.0:
-    resolution: {integrity: 
sha512-jRzcXlCeDYvKoZGA5oRhYyR3jUIYu0enkSxtmAgHRlD7HwrovTpH4bDSi0py9FtuA8si9cW/fKommJHuaoDHJA==}
-    engines: {node: '>=10'}
-    dependencies:
-      arrify: 2.0.1
-      indent-string: 4.0.0
-      js-yaml: 3.14.1
-      serialize-error: 7.0.1
-      strip-ansi: 6.0.0
-    dev: true
-
   /supports-color/2.0.0:
     resolution: {integrity: sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=}
     engines: {node: '>=0.8.0'}
@@ -15139,11 +14729,6 @@ packages:
     engines: {node: '>=4'}
     dev: true
 
-  /temp-dir/2.0.0:
-    resolution: {integrity: 
sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
-    engines: {node: '>=8'}
-    dev: true
-
   /tempy/0.3.0:
     resolution: {integrity: 
sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ==}
     engines: {node: '>=8'}
@@ -15245,11 +14830,6 @@ packages:
     resolution: {integrity: 
sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==}
     dev: true
 
-  /time-zone/1.0.0:
-    resolution: {integrity: sha1-mcW/VZWJZq9tBtg73zgA3IL67F0=}
-    engines: {node: '>=4'}
-    dev: true
-
   /timers-browserify/2.0.12:
     resolution: {integrity: 
sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==}
     engines: {node: '>=0.6.0'}
@@ -15386,11 +14966,6 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: true
 
-  /trim-off-newlines/1.0.1:
-    resolution: {integrity: sha1-n5up2e+odkw4dpi8v+sshI8RrbM=}
-    engines: {node: '>=0.10.0'}
-    dev: true
-
   /trim-trailing-lines/1.1.4:
     resolution: {integrity: 
sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==}
     dev: true
@@ -15440,7 +15015,6 @@ packages:
 
   /tslib/2.2.0:
     resolution: {integrity: 
sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==}
-    dev: true
 
   /tsutils/3.21.0_typescript@4.2.4:
     resolution: {integrity: 
sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
@@ -15485,11 +15059,6 @@ packages:
     engines: {node: '>=4'}
     dev: true
 
-  /type-fest/0.13.1:
-    resolution: {integrity: 
sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
-    engines: {node: '>=10'}
-    dev: true
-
   /type-fest/0.20.2:
     resolution: {integrity: 
sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
     engines: {node: '>=10'}
@@ -15565,12 +15134,6 @@ packages:
     hasBin: true
     dev: true
 
-  /typescript/4.2.3:
-    resolution: {integrity: 
sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==}
-    engines: {node: '>=4.2.0'}
-    hasBin: true
-    dev: false
-
   /typescript/4.2.4:
     resolution: {integrity: 
sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==}
     engines: {node: '>=4.2.0'}
@@ -15602,6 +15165,10 @@ packages:
       which-boxed-primitive: 1.0.2
     dev: true
 
+  /underscore/1.6.0:
+    resolution: {integrity: sha1-izixDKze9jM3uLJOT/htRa6lKag=}
+    dev: true
+
   /unfetch/4.2.0:
     resolution: {integrity: 
sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==}
     dev: true
@@ -15791,26 +15358,6 @@ packages:
       xdg-basedir: 4.0.0
     dev: true
 
-  /update-notifier/5.1.0:
-    resolution: {integrity: 
sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==}
-    engines: {node: '>=10'}
-    dependencies:
-      boxen: 5.0.1
-      chalk: 4.1.1
-      configstore: 5.0.1
-      has-yarn: 2.1.0
-      import-lazy: 2.1.0
-      is-ci: 2.0.0
-      is-installed-globally: 0.4.0
-      is-npm: 5.0.0
-      is-yarn-global: 0.3.0
-      latest-version: 5.1.0
-      pupa: 2.1.1
-      semver: 7.3.5
-      semver-diff: 3.1.1
-      xdg-basedir: 4.0.0
-    dev: true
-
   /upper-case/1.1.3:
     resolution: {integrity: sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=}
     dev: true
@@ -16334,11 +15881,6 @@ packages:
     engines: {node: '>=0.8.0'}
     dev: true
 
-  /well-known-symbols/2.0.0:
-    resolution: {integrity: 
sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==}
-    engines: {node: '>=6'}
-    dev: true
-
   /whatwg-encoding/1.0.5:
     resolution: {integrity: 
sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==}
     dependencies:
@@ -16593,15 +16135,6 @@ packages:
       strip-ansi: 6.0.0
     dev: true
 
-  /wrap-ansi/7.0.0:
-    resolution: {integrity: 
sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
-    engines: {node: '>=10'}
-    dependencies:
-      ansi-styles: 4.3.0
-      string-width: 4.2.2
-      strip-ansi: 6.0.0
-    dev: true
-
   /wrappy/1.0.2:
     resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
     dev: true
@@ -16656,11 +16189,6 @@ packages:
     resolution: {integrity: 
sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
     dev: true
 
-  /y18n/5.0.8:
-    resolution: {integrity: 
sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
-    engines: {node: '>=10'}
-    dev: true
-
   /yallist/2.1.2:
     resolution: {integrity: sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=}
     dev: true
@@ -16693,11 +16221,6 @@ packages:
       decamelize: 1.2.0
     dev: true
 
-  /yargs-parser/20.2.7:
-    resolution: {integrity: 
sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==}
-    engines: {node: '>=10'}
-    dev: true
-
   /yargs/13.3.2:
     resolution: {integrity: 
sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==}
     dependencies:
@@ -16730,19 +16253,6 @@ packages:
       yargs-parser: 18.1.3
     dev: true
 
-  /yargs/16.2.0:
-    resolution: {integrity: 
sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
-    engines: {node: '>=10'}
-    dependencies:
-      cliui: 7.0.4
-      escalade: 3.1.1
-      get-caller-file: 2.0.5
-      require-directory: 2.1.1
-      string-width: 4.2.2
-      y18n: 5.0.8
-      yargs-parser: 20.2.7
-    dev: true
-
   /yocto-queue/0.1.0:
     resolution: {integrity: 
sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
     engines: {node: '>=10'}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]