فهرست منبع

Implement i18n service to be used by all LInE projects

Lucas de Souza 5 سال پیش
والد
کامیت
5df687f771
9فایلهای تغییر یافته به همراه4248 افزوده شده و 0 حذف شده
  1. 2 0
      .gitignore
  2. 37 0
      LanguageService.ts
  3. 94 0
      LocalizedStrings.ts
  4. 5 0
      StringTypes.ts
  5. 9 0
      index.ts
  6. 4047 0
      package-lock.json
  7. 22 0
      package.json
  8. 10 0
      tsconfig.json
  9. 22 0
      webpack.config.js

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+/node_modules
+/dist

+ 37 - 0
LanguageService.ts

@@ -0,0 +1,37 @@
+export class LanguageService {
+
+  private listeners: Array<() => void> = [];
+  private document: Document = document;
+
+  constructor (private lsKey: string, private defaultLang = 'pt') {
+    this.setupListener();
+  }
+
+  setupListener (): void {
+    if(this.document !== null) {
+      this.document.addEventListener("storage",(event => {
+        const e = event as StorageEvent;
+        if(e.key === this.lsKey) {
+          this.listeners.forEach(l => l());         
+        }
+      }));
+    }
+  }
+
+  getLang (): string {
+    const lang = localStorage.getItem(this.lsKey);
+    if(lang === null || lang === undefined) {
+      console.warn("Internal Error: User language information has not been set. Returning default...");
+      return this.getDefaultLang();
+    }
+    return lang;
+  }
+
+  getDefaultLang (): string {
+    return this.defaultLang;
+  }
+
+  registerLanguageChangeListener (listener: () => void) {
+    this.listeners.push(listener);
+  }
+}

+ 94 - 0
LocalizedStrings.ts

@@ -0,0 +1,94 @@
+import { LanguageService } from './LanguageService';
+import { StringTypes } from './StringTypes';
+
+type LangInfo = {[id: string]: string};
+type LangData = {[id: string]: LangInfo};
+type LangObject = {[id: string]: LangData}
+
+export class LocalizedStrings {
+
+  private document: Document = document;
+
+  constructor (private service: LanguageService, private i18nData: LangObject, private listenToChange = false) {
+    if(this.listenToChange) {
+      service.registerLanguageChangeListener( () => {
+        this.updateTagText();
+      });
+    }
+  }
+
+  getString (id: string, type: string): string {
+    let i18nObj = this.i18nData[this.service.getLang()];
+    if (!!!i18nObj) {
+      console.warn(`Internal Error. The language set at ivprog.lang is not valid: ${this.service.getLang()}`);
+      i18nObj = this.i18nData[this.service.getDefaultLang()];
+    }
+    if (!!!i18nObj[type]) {
+      return "{MISSING_I18N_TYPE_IDENTIFIER}";
+    } else if (!!!i18nObj[type][id]) {
+      return "{MISSING_I18N_IDENTIFIER}";
+    } else {
+      return i18nObj[type][id];
+    }
+  }
+
+  getOR (): String {
+    return this.getUI('join_or');
+  }
+
+  getError (id: string, context: [] = []) {
+    const text = this.getString(id, StringTypes.ERROR);
+    return this.processString(text, context)
+  }
+
+  getMessage (id: string, context: [] = []) {
+    const text = this.getString(id, StringTypes.MESSAGE);
+    return this.processString(text, context)
+  }
+
+  getUI (id: string, context: [] = []) {
+    const text = this.getString(id, StringTypes.UI);
+    return this.processString(text, context)
+  }
+
+  processString (text: string, context: []) {
+    for (let i = 0; i < context.length; i++) {
+      const v = context[i];
+      text = text.replace('\$' + i, v);
+    }
+    return text;
+  }
+
+  updateTagText (func: ((str: string | null) => string) | null = null): void {
+    if (this.document !== null) {
+      const list = this.document.querySelectorAll("data.i18n");
+      list.forEach(node => {
+        if (func === null) {
+          node.innerHTML = this.processTagTex(node.getAttribute("value"));
+        } else {
+          node.innerHTML = func(node.getAttribute("value"));
+        }
+      })
+    }
+  }
+
+  processTagTex (text: string | null): string {
+    if (text === null) {
+      return "<Invalid i18n identifier>";
+    }
+    const opts = text.split(':');
+    const type = opts[0].toLowerCase();
+    const id = opts[1];
+    if (StringTypes.ERROR === type) {
+      return this.getError(id);
+    } else if (StringTypes.MESSAGE === type) {
+      return this.getMessage(id);
+    } else if (StringTypes.UI === type) {
+      return this.getUI(id);
+    } else {
+      console.warn(" A string has been passed to the i18n helper function that was not in the form type:id -> " + text);
+      return this.getString(id, type);
+    }
+  }
+
+}

+ 5 - 0
StringTypes.ts

@@ -0,0 +1,5 @@
+export enum StringTypes {
+  ERROR = "error",
+  MESSAGE = "message",
+  UI = "ui"
+}

+ 9 - 0
index.ts

@@ -0,0 +1,9 @@
+import { LanguageService } from "./LanguageService";
+import { LocalizedStrings } from "./LocalizedStrings";
+import { StringTypes } from "./StringTypes";
+
+export default {
+  LanguageService,
+  LocalizedStrings,
+  StringTypes
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 4047 - 0
package-lock.json


+ 22 - 0
package.json

@@ -0,0 +1,22 @@
+{
+  "name": "line-i18n",
+  "version": "1.0.0",
+  "description": "Helper library used along side all LInE projects to enable i18n functionalities",
+  "main": "dist/index.js",
+  "scripts": {
+    "build": "tsc",
+    "test": "echo \"Error: no test specified\" && exit 1",
+    "webpack": "webpack"
+  },
+  "keywords": [
+    "i18n"
+  ],
+  "author": "Lucas de Souza",
+  "license": "MIT",
+  "devDependencies": {
+    "ts-loader": "^5.2.1",
+    "typescript": "^3.1.1",
+    "webpack": "^4.20.2",
+    "webpack-cli": "^3.1.2"
+  }
+}

+ 10 - 0
tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "noImplicitAny": true,
+    "module": "es6",
+    "declaration": true,
+    "outDir": "./dist",
+    "strict": true
+  }
+}

+ 22 - 0
webpack.config.js

@@ -0,0 +1,22 @@
+const path = require('path');
+
+module.exports = {
+  entry: './index.ts',
+  mode: 'production',
+  module: {
+    rules: [
+      {
+        test: /\.tsx?$/,
+        use: 'ts-loader',
+        exclude: /node_modules/
+      }
+    ]
+  },
+  resolve: {
+    extensions: [ '.tsx', '.ts', '.js' ]
+  },
+  output: {
+    filename: 'line-i18n.bundle.js',
+    path: path.resolve(__dirname, 'dist')
+  }
+};