diff options
author | Florian Dold <florian.dold@gmail.com> | 2019-12-12 20:53:15 +0100 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2019-12-12 20:53:15 +0100 |
commit | 74433c3e05734aa1194049fcbcaa92c70ce61c74 (patch) | |
tree | d30e79c9ac3fd5720de628f6a9764354ec69c648 /src/i18n.tsx | |
parent | cc137c87394ec34d2f54d69fe896dfdf3feec5ea (diff) | |
download | wallet-core-74433c3e05734aa1194049fcbcaa92c70ce61c74.tar.xz |
refactor: re-structure type definitions
Diffstat (limited to 'src/i18n.tsx')
-rw-r--r-- | src/i18n.tsx | 267 |
1 files changed, 0 insertions, 267 deletions
diff --git a/src/i18n.tsx b/src/i18n.tsx deleted file mode 100644 index 67df6c516..000000000 --- a/src/i18n.tsx +++ /dev/null @@ -1,267 +0,0 @@ -/* - This file is part of TALER - (C) 2016 GNUnet e.V. - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -/** - * Translation helpers for React components and template literals. - */ - -/** - * Imports. - */ -import {strings} from "./i18n/strings"; - -// @ts-ignore: no type decl for this library -import * as jedLib from "jed"; - -import * as React from "react"; - - -const jed = setupJed(); - -let enableTracing = false; - - -/** - * Set up jed library for internationalization, - * based on browser language settings. - */ -function setupJed(): any { - let lang: string; - try { - lang = chrome.i18n.getUILanguage(); - // Chrome gives e.g. "en-US", but Firefox gives us "en_US" - lang = lang.replace("_", "-"); - } catch (e) { - lang = "en"; - console.warn("i18n default language not available"); - } - - if (!strings[lang]) { - lang = "en-US"; - console.log(`language ${lang} not found, defaulting to english`); - } - return new jedLib.Jed(strings[lang]); -} - - -/** - * Convert template strings to a msgid - */ -function toI18nString(stringSeq: ReadonlyArray<string>) { - let s = ""; - for (let i = 0; i < stringSeq.length; i++) { - s += stringSeq[i]; - if (i < stringSeq.length - 1) { - s += `%${i + 1}$s`; - } - } - return s; -} - - -/** - * Internationalize a string template with arbitrary serialized values. - */ -export function str(stringSeq: TemplateStringsArray, ...values: any[]) { - const s = toI18nString(stringSeq); - const tr = jed.translate(s).ifPlural(1, s).fetch(...values); - return tr; -} - - -interface TranslateSwitchProps { - target: number; -} - - -function stringifyChildren(children: any): string { - let n = 1; - const ss = React.Children.map(children, (c) => { - if (typeof c === "string") { - return c; - } - return `%${n++}$s`; - }); - const s = ss.join("").replace(/ +/g, " ").trim(); - enableTracing && console.log("translation lookup", JSON.stringify(s)); - return s; -} - - -interface TranslateProps { - /** - * Component that the translated element should be wrapped in. - * Defaults to "div". - */ - wrap?: any; - - /** - * Props to give to the wrapped component. - */ - wrapProps?: any; -} - - -/** - * 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 class Translate extends React.Component<TranslateProps, {}> { - render(): JSX.Element { - const s = stringifyChildren(this.props.children); - const tr = jed.ngettext(s, s, 1).split(/%(\d+)\$s/).filter((e: any, i: number) => i % 2 === 0); - const childArray = React.Children.toArray(this.props.children!); - for (let i = 0; i < childArray.length - 1; ++i) { - if ((typeof childArray[i]) === "string" && (typeof childArray[i + 1]) === "string") { - childArray[i + 1] = (childArray[i] as string).concat(childArray[i + 1] as string); - childArray.splice(i, 1); - } - } - const result = []; - while (childArray.length > 0) { - const x = childArray.shift(); - if (x === undefined) { - continue; - } - if (typeof x === "string") { - const t = tr.shift(); - result.push(t); - } else { - result.push(x); - } - } - if (!this.props.wrap) { - return <div>{result}</div>; - } - return React.createElement(this.props.wrap, this.props.wrapProps, result); - } -} - - -/** - * Switch translation based on singular or plural based on the target prop. - * Should only contain TranslateSingular and TransplatePlural as children. - * - * Example: - * ``` - * <TranslateSwitch target={n}> - * <TranslateSingular>I have {n} apple.</TranslateSingular> - * <TranslatePlural>I have {n} apples.</TranslatePlural> - * </TranslateSwitch> - * ``` - */ -export class TranslateSwitch extends React.Component<TranslateSwitchProps, void> { - render(): JSX.Element { - let singular: React.ReactElement<TranslationPluralProps> | undefined; - let plural: React.ReactElement<TranslationPluralProps> | undefined; - const children = this.props.children; - if (children) { - React.Children.forEach(children, (child: any) => { - if (child.type === TranslatePlural) { - plural = child; - } - if (child.type === TranslateSingular) { - singular = child; - } - }); - } - if ((!singular) || (!plural)) { - console.error("translation not found"); - return React.createElement("span", {}, ["translation not found"]); - } - singular.props.target = this.props.target; - plural.props.target = this.props.target; - // We're looking up the translation based on the - // singular, even if we must use the plural form. - return singular; - } -} - - -interface TranslationPluralProps { - target: number; -} - -/** - * See [[TranslateSwitch]]. - */ -export class TranslatePlural extends React.Component<TranslationPluralProps, void> { - render(): JSX.Element { - const s = stringifyChildren(this.props.children); - const tr = jed.ngettext(s, s, 1).split(/%(\d+)\$s/).filter((e: any, i: number) => i % 2 === 0); - const childArray = React.Children.toArray(this.props.children!); - for (let i = 0; i < childArray.length - 1; ++i) { - if ((typeof childArray[i]) === "string" && (typeof childArray[i + 1]) === "string") { - childArray[i + i] = childArray[i] as string + childArray[i + 1] as string; - childArray.splice(i, 1); - } - } - const result = []; - while (childArray.length > 0) { - const x = childArray.shift(); - if (x === undefined) { - continue; - } - if (typeof x === "string") { - const t = tr.shift(); - result.push(t); - } else { - result.push(x); - } - } - return <div>{result}</div>; - } -} - - -/** - * See [[TranslateSwitch]]. - */ -export class TranslateSingular extends React.Component<TranslationPluralProps, void> { - render(): JSX.Element { - const s = stringifyChildren(this.props.children); - const tr = jed.ngettext(s, s, 1).split(/%(\d+)\$s/).filter((e: any, i: number) => i % 2 === 0); - const childArray = React.Children.toArray(this.props.children!); - for (let i = 0; i < childArray.length - 1; ++i) { - if ((typeof childArray[i]) === "string" && (typeof childArray[i + 1]) === "string") { - childArray[i + i] = childArray[i] as string + childArray[i + 1] as string; - childArray.splice(i, 1); - } - } - const result = []; - while (childArray.length > 0) { - const x = childArray.shift(); - if (x === undefined) { - continue; - } - if (typeof x === "string") { - const t = tr.shift(); - result.push(t); - } else { - result.push(x); - } - } - return <div>{result}</div>; - } -} |