gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 01/04: moving i18n into taler util


From: gnunet
Subject: [taler-wallet-core] 01/04: moving i18n into taler util
Date: Tue, 08 Jun 2021 22:18:35 +0200

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

sebasjm pushed a commit to branch master
in repository wallet-core.

commit 2c5612fd63f766ce19a9f885e5142b04bcf11604
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Tue Jun 8 15:56:27 2021 -0300

    moving i18n into taler util
---
 packages/taler-util/package.json   |   1 +
 packages/taler-util/src/i18n.ts    | 147 +++++++++++++++++++++++++++++++++++++
 packages/taler-util/src/index.ts   |   4 +-
 packages/taler-util/src/logging.ts | 100 +++++++++++++++++++++++++
 pnpm-lock.yaml                     |   3 +-
 5 files changed, 253 insertions(+), 2 deletions(-)

diff --git a/packages/taler-util/package.json b/packages/taler-util/package.json
index a1c769e8..977a35c6 100644
--- a/packages/taler-util/package.json
+++ b/packages/taler-util/package.json
@@ -36,6 +36,7 @@
     "typescript": "^4.2.3"
   },
   "dependencies": {
+    "jed": "^1.1.1",
     "tslib": "^2.1.0"
   },
   "ava": {
diff --git a/packages/taler-util/src/i18n.ts b/packages/taler-util/src/i18n.ts
new file mode 100644
index 00000000..4253eb22
--- /dev/null
+++ b/packages/taler-util/src/i18n.ts
@@ -0,0 +1,147 @@
+// @ts-ignore: no type decl for this library
+import * as jedLib from "jed";
+import { Logger } from "./logging";
+
+const logger = new Logger("i18n/index.ts");
+
+export let jed: any = undefined;
+
+/**
+ * Set up jed library for internationalization,
+ * based on browser language settings.
+ */
+export function setupI18n(lang: string, strings: { [s: string]: any }): any {
+  lang = lang.replace("_", "-");
+
+  if (!strings[lang]) {
+    lang = "en-US";
+    logger.warn(`language ${lang} not found, defaulting to english`);
+  }
+  debugger
+  jed = new jedLib.Jed(strings[lang]);
+}
+
+/**
+ * Use different translations for testing.  Should not be used outside
+ * of test cases.
+ */
+export function internalSetStrings(langStrings: any): void {
+  jed = new jedLib.Jed(langStrings);
+}
+
+/**
+ * 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;
+}
+
+/**
+ * Internationalize a string template with arbitrary serialized values.
+ */
+export function str(stringSeq: TemplateStringsArray, ...values: any[]): string 
{
+  const s = toI18nString(stringSeq);
+  const tr = jed
+    .translate(s)
+    .ifPlural(1, s)
+    .fetch(...values);
+  return tr;
+}
+
+/**
+ * Internationalize a string template without serializing
+ */
+export function translate(stringSeq: TemplateStringsArray, ...values: any[]): 
any[] {
+  const s = toI18nString(stringSeq);
+  if (!s) return []
+  const translation: string = jed.ngettext(s, s, 1);
+  return replacePlaceholderWithValues(translation, values)
+}
+
+/**
+ * Internationalize a string template without serializing
+ */
+export function Translate({ children, ...rest }: { children: any }): any {
+  const c = [].concat(children);
+  const s = stringifyArray(c);
+  if (!s) return []
+  const translation: string = jed.ngettext(s, s, 1);
+  return replacePlaceholderWithValues(translation, c)
+}
+
+/**
+ * Get an internationalized string (based on the globally set, current 
language)
+ * from a JSON object.  Fall back to the default language of the JSON object
+ * if no match exists.
+ */
+export function getJsonI18n<K extends string>(
+  obj: Record<K, string>,
+  key: K,
+): string {
+  return obj[key];
+}
+
+export function getTranslatedArray(array: Array<any>) {
+  const s = stringifyArray(array);
+  const translation: string = jed.ngettext(s, s, 1);
+  return replacePlaceholderWithValues(translation, array);
+}
+
+
+function replacePlaceholderWithValues(
+  translation: string,
+  childArray: Array<any>,
+): Array<any> {
+  const tr = translation.split(/%(\d+)\$s/);
+  // const childArray = toChildArray(children);
+  // Merge consecutive string children.
+  const placeholderChildren = [];
+  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 = [];
+  for (let i = 0; i < tr.length; i++) {
+    if (i % 2 == 0) {
+      // Text
+      result.push(tr[i]);
+    } else {
+      const childIdx = Number.parseInt(tr[i]) - 1;
+      result.push(placeholderChildren[childIdx]);
+    }
+  }
+  return result;
+}
+
+function stringifyArray(children: Array<any>): string {
+  let n = 1;
+  const ss = 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;
+}
+
+export const i18n = {
+  str,
+  Translate,
+  translate
+}
+
diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts
index 3416c7d1..25a24fa1 100644
--- a/packages/taler-util/src/index.ts
+++ b/packages/taler-util/src/index.ts
@@ -16,4 +16,6 @@ export * from "./talerTypes.js";
 export * from "./taleruri.js";
 export * from "./time.js";
 export * from "./transactionsTypes.js";
-export * from "./walletTypes.js";
\ No newline at end of file
+export * from "./walletTypes.js";
+export * from "./i18n.js";
+export * from "./logging.js";
\ No newline at end of file
diff --git a/packages/taler-util/src/logging.ts 
b/packages/taler-util/src/logging.ts
new file mode 100644
index 00000000..4f48e24d
--- /dev/null
+++ b/packages/taler-util/src/logging.ts
@@ -0,0 +1,100 @@
+/*
+ This file is part of TALER
+ (C) 2019 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/>
+ */
+
+/**
+ * Check if we are running under nodejs.
+ */
+
+const isNode =
+  typeof process !== "undefined" && typeof process.release !== "undefined" && 
process.release.name === "node";
+
+function writeNodeLog(
+  message: any,
+  tag: string,
+  level: string,
+  args: any[],
+): void {
+  try {
+    process.stderr.write(`${new Date().toISOString()} ${tag} ${level} `);
+    process.stderr.write(`${message}`);
+    if (args.length != 0) {
+      process.stderr.write(" ");
+      process.stderr.write(JSON.stringify(args, undefined, 2));
+    }
+    process.stderr.write("\n");
+  } catch (e) {
+    // This can happen when we're trying to log something that doesn't want to 
be
+    // converted to a string.
+    process.stderr.write(`${new Date().toISOString()} (logger) FATAL `);
+    if (e instanceof Error) {
+      process.stderr.write("failed to write log: ");
+      process.stderr.write(e.message);
+    }
+    process.stderr.write("\n");
+  }
+}
+
+/**
+ * Logger that writes to stderr when running under node,
+ * and uses the corresponding console.* method to log in the browser.
+ */
+export class Logger {
+  constructor(private tag: string) {}
+
+  info(message: string, ...args: any[]): void {
+    if (isNode) {
+      writeNodeLog(message, this.tag, "INFO", args);
+    } else {
+      console.info(
+        `${new Date().toISOString()} ${this.tag} INFO ` + message,
+        ...args,
+      );
+    }
+  }
+
+  warn(message: string, ...args: any[]): void {
+    if (isNode) {
+      writeNodeLog(message, this.tag, "WARN", args);
+    } else {
+      console.warn(
+        `${new Date().toISOString()} ${this.tag} INFO ` + message,
+        ...args,
+      );
+    }
+  }
+
+  error(message: string, ...args: any[]): void {
+    if (isNode) {
+      writeNodeLog(message, this.tag, "ERROR", args);
+    } else {
+      console.info(
+        `${new Date().toISOString()} ${this.tag} ERROR ` + message,
+        ...args,
+      );
+    }
+  }
+
+  trace(message: any, ...args: any[]): void {
+    if (isNode) {
+      writeNodeLog(message, this.tag, "TRACE", args);
+    } else {
+      console.info(
+        `${new Date().toISOString()} ${this.tag} TRACE ` + message,
+        ...args,
+      );
+    }
+  }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1cf013b8..10198d6a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -46,11 +46,13 @@ importers:
       '@types/node': ^14.14.22
       ava: ^3.15.0
       esbuild: ^0.9.2
+      jed: ^1.1.1
       prettier: ^2.2.1
       rimraf: ^3.0.2
       tslib: ^2.1.0
       typescript: ^4.2.3
     dependencies:
+      jed: 1.1.1
       tslib: 2.1.0
     devDependencies:
       '@types/node': 14.14.34
@@ -11583,7 +11585,6 @@ packages:
 
   /jed/1.1.1:
     resolution: {integrity: sha1-elSbvZ/+FYWwzQoZHiAwVb7ldLQ=}
-    dev: true
 
   /jest-changed-files/26.6.2:
     resolution: {integrity: 
sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==}

-- 
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]