From fa3f5f14abf34220ff21c5db08a9fa33cdc6cae2 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Mon, 25 Apr 2022 18:42:42 +0300 Subject: [PATCH] initial import Signed-off-by: Vasiliy Tolstov --- .gitignore | 16 + README.md | 37 ++ dist/index.d.ts | 11 + dist/index.js | 34 ++ dist/po.d.ts | 36 ++ dist/po.js | 216 +++++++++++ package-lock.json | 964 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 35 ++ src/index.ts | 53 +++ src/po.ts | 266 +++++++++++++ tsconfig.json | 25 ++ tslint.json | 53 +++ 12 files changed, 1746 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 dist/index.d.ts create mode 100644 dist/index.js create mode 100644 dist/po.d.ts create mode 100644 dist/po.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/index.ts create mode 100644 src/po.ts create mode 100644 tsconfig.json create mode 100644 tslint.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..399b8cd --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# IDE +.vscode +.idea + +# Logs and other files +npm-debug.log* +.DS_Store + +# Compiled files +#dist + +# Dependency directory +node_modules + +# Source maps for JS builds +*.js.map diff --git a/README.md b/README.md new file mode 100644 index 0000000..6303936 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# Description +Load po files for use with `ngx-translate` + +## Installation: + + ``` +npm i @ngx-translate/core --save +npm i @unistack-org/ngx-translate-po-http-loader --save + ``` + +## Usage: +```ts +import { HttpClient, HttpClientModule } from '@angular/common/http'; + +import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; +import { TranslatePoHttpLoader } from '@unistack-org/ngx-translate-po-http-loader'; + +export function createTranslateLoader(http: HttpClient) { + return new TranslatePoHttpLoader(http, 'assets/i18n', '.po'); +} + +@NgModule({ + imports: [ + BrowserModule, + HttpClientModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useFactory: createTranslateLoader, + deps: [HttpClient] + } + }) + ], + bootstrap: [AppComponent] +}) +export class AppModule { } +``` diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..96c056f --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,11 @@ +import { HttpClient } from '@angular/common/http'; +import { TranslateLoader } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +export declare class TranslatePoHttpLoader implements TranslateLoader { + protected _http: HttpClient; + protected _prefix: string; + protected _suffix: string; + constructor(_http: HttpClient, _prefix?: string, _suffix?: string); + getTranslation(lang: string): Observable; + parse(contents: string): any; +} diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..8966a35 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TranslatePoHttpLoader = void 0; +var operators_1 = require("rxjs/operators"); +var po_1 = require("./po"); +var TranslatePoHttpLoader = (function () { + function TranslatePoHttpLoader(_http, _prefix, _suffix) { + if (_prefix === void 0) { _prefix = 'i18n'; } + if (_suffix === void 0) { _suffix = '.po'; } + this._http = _http; + this._prefix = _prefix; + this._suffix = _suffix; + } + TranslatePoHttpLoader.prototype.getTranslation = function (lang) { + var _this = this; + return this._http + .get("".concat(this._prefix, "/").concat(lang).concat(this._suffix), { responseType: 'text' }) + .pipe((0, operators_1.map)(function (contents) { return _this.parse(contents); })); + }; + TranslatePoHttpLoader.prototype.parse = function (contents) { + var translations = {}; + var doc = new po_1.POLoader(); + var po = doc.parse(contents); + po.items.forEach(function (item) { + if (item.msgid.length > 0 && item.msgstr.length > 0) { + translations[item.msgid] = item.msgstr.join('\n'); + } + }); + return translations; + }; + return TranslatePoHttpLoader; +}()); +exports.TranslatePoHttpLoader = TranslatePoHttpLoader; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/po.d.ts b/dist/po.d.ts new file mode 100644 index 0000000..36b215b --- /dev/null +++ b/dist/po.d.ts @@ -0,0 +1,36 @@ +declare interface IHeaders { + 'Project-Id-Version': string; + 'Report-Msgid-Bugs-To': string; + 'POT-Creation-Date': string; + 'PO-Revision-Date': string; + 'Last-Translator': string; + 'Language': string; + 'Language-Team': string; + 'Content-Type': string; + 'Content-Transfer-Encoding': string; + 'Plural-Forms': string; + [name: string]: string; +} +export declare class Item { + msgid: string; + msgctxt?: string; + references: string[]; + msgid_plural?: string; + msgstr: string[]; + comments: string[]; + extractedComments: string[]; + flags: Record; + obsolete: boolean; +} +export declare class PO { + comments: string[]; + extractedComments: string[]; + items: Item[]; + headers: Partial; + headerOrder: any[]; +} +export declare class POLoader { + constructor(); + parse(data: string): PO; +} +export {}; diff --git a/dist/po.js b/dist/po.js new file mode 100644 index 0000000..3ea6e7b --- /dev/null +++ b/dist/po.js @@ -0,0 +1,216 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.POLoader = exports.PO = exports.Item = void 0; +; +var Item = (function () { + function Item() { + this.msgid = ''; + this.msgctxt = ''; + this.references = []; + this.msgid_plural = ''; + this.msgstr = []; + this.comments = []; + this.extractedComments = []; + } + return Item; +}()); +exports.Item = Item; +; +var PO = (function () { + function PO() { + this.comments = []; + this.extractedComments = []; + this.items = []; + this.headerOrder = []; + } + return PO; +}()); +exports.PO = PO; +var POLoader = (function () { + function POLoader() { + } + POLoader.prototype.parse = function (data) { + data = data.replace(/\r\n/g, '\n'); + var po = new PO(); + var sections = data.split(/\n\n/); + var headers; + var theaders = []; + while (sections[0] && (theaders.length === 0 || theaders[theaders.length - 1].indexOf('msgid ""') < 0)) { + if (sections[0].match(/msgid\s+"[^"]/)) { + theaders.push('msgid ""'); + } + else { + theaders.push(sections.shift()); + } + } + headers = theaders.join('\n'); + var lines = sections.join('\n').split(/\n/); + po.headers = { + 'Project-Id-Version': '', + 'Report-Msgid-Bugs-To': '', + 'POT-Creation-Date': '', + 'PO-Revision-Date': '', + 'Last-Translator': '', + 'Language': '', + 'Language-Team': '', + 'Content-Type': '', + 'Content-Transfer-Encoding': '', + 'Plural-Forms': '', + }; + po.headerOrder = []; + headers.split(/\n/).reduce(function (acc, line) { + if (acc.merge) { + line = acc.pop().slice(0, -1) + line.slice(1); + delete acc.merge; + } + if (/^".*"$/.test(line) && !/^".*\\n"$/.test(line)) { + acc.merge = true; + } + acc.push(line); + return acc; + }, []).forEach(function (header) { + if (header.match(/^#\./)) { + po.extractedComments.push(header.replace(/^#\.\s*/, '')); + } + else if (header.match(/^#/)) { + po.comments.push(header.replace(/^#\s*/, '')); + } + else if (header.match(/^"/)) { + header = header.trim().replace(/^"/, '').replace(/\\n"$/, ''); + var p = header.split(/:/); + var name = p.shift().trim(); + var value = p.join(':').trim(); + po.headers[name] = value; + po.headerOrder.push(name); + } + }); + var item = new Item(); + var context = null; + var plural = 0; + var obsoleteCount = 0; + var noCommentLineCount = 0; + function trim(string) { + return string.replace(/^\s+|\s+$/g, ''); + } + function finish() { + if (item.msgid.length > 0) { + if (obsoleteCount >= noCommentLineCount) { + item.obsolete = true; + } + obsoleteCount = 0; + noCommentLineCount = 0; + po.items.push(item); + item = new Item(); + } + } + function extract(string) { + string = trim(string); + string = string.replace(/^[^"]*"|"$/g, ''); + string = string.replace(/\\([abtnvfr'"\\?]|([0-7]{3})|x([0-9a-fA-F]{2}))/g, function (match, esc, oct, hex) { + if (oct) { + return String.fromCharCode(parseInt(oct, 8)); + } + if (hex) { + return String.fromCharCode(parseInt(hex, 16)); + } + switch (esc) { + case 'a': + return '\x07'; + case 'b': + return '\b'; + case 't': + return '\t'; + case 'n': + return '\n'; + case 'v': + return '\v'; + case 'f': + return '\f'; + case 'r': + return '\r'; + default: + return esc; + } + }); + return string; + } + while (lines.length > 0) { + var line = trim(lines.shift()); + var lineObsolete = false; + if (line.match(/^#\~/)) { + line = trim(line.substring(2)); + lineObsolete = true; + } + if (line.match(/^#:/)) { + finish(); + item.references.push(trim(line.replace(/^#:/, ''))); + } + else if (line.match(/^#,/)) { + finish(); + var flags = trim(line.replace(/^#,/, '')).split(','); + for (var i = 0; i < flags.length; i++) { + item.flags[flags[i]] = true; + } + } + else if (line.match(/^#($|\s+)/)) { + finish(); + item.comments.push(trim(line.replace(/^#($|\s+)/, ''))); + } + else if (line.match(/^#\./)) { + finish(); + item.extractedComments.push(trim(line.replace(/^#\./, ''))); + } + else if (line.match(/^msgid_plural/)) { + item.msgid_plural = extract(line); + context = 'msgid_plural'; + noCommentLineCount++; + } + else if (line.match(/^msgid/)) { + finish(); + item.msgid = extract(line); + context = 'msgid'; + noCommentLineCount++; + } + else if (line.match(/^msgstr/)) { + var m = line.match(/^msgstr\[(\d+)\]/); + plural = m && m[1] ? parseInt(m[1]) : 0; + item.msgstr[plural] = extract(line); + context = 'msgstr'; + noCommentLineCount++; + } + else if (line.match(/^msgctxt/)) { + finish(); + item.msgctxt = extract(line); + context = 'msgctxt'; + noCommentLineCount++; + } + else { + if (line.length > 0) { + noCommentLineCount++; + if (context === 'msgstr') { + item.msgstr[plural] += extract(line); + } + else if (context === 'msgid') { + item.msgid += extract(line); + } + else if (context === 'msgid_plural') { + item.msgid_plural += extract(line); + } + else if (context === 'msgctxt') { + item.msgctxt += extract(line); + } + } + } + if (lineObsolete) { + obsoleteCount++; + } + } + finish(); + return po; + }; + ; + return POLoader; +}()); +exports.POLoader = POLoader; +; +//# sourceMappingURL=po.js.map \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b8c4a7d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,964 @@ +{ + "name": "ngx-translate-po-http-loader", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "ngx-translate-po-http-loader", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@angular/common": "^13.3.4", + "@ngx-translate/core": "^14.0.0", + "@types/node": "^17.0.25", + "tslint": "^6.1.3", + "typescript": "^4.1.5" + }, + "engines": { + "node": ">=4.1.1" + } + }, + "node_modules/@angular/common": { + "version": "13.3.4", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-13.3.4.tgz", + "integrity": "sha512-vPZuUGWMXz6r30obBqH+iIG4Feq4YEK/4wUks7PEYGke8MXFPYsNKuHMhKCgYEhabD/4Mo4GEp3i18/3Kk72Mw==", + "dev": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + }, + "peerDependencies": { + "@angular/core": "13.3.4", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/core": { + "version": "13.3.4", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-13.3.4.tgz", + "integrity": "sha512-PqPwx9oaV0Bh0m0fdI2jtXUC6s04jfD4vyzB4sjEuRI9pRUnZ6M5hZ5Vn/KJVZyt411MevbJfqzUVf0W+GDZew==", + "dev": true, + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.11.4" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ngx-translate/core": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-14.0.0.tgz", + "integrity": "sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w==", + "dev": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/core": ">=13.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@types/node": { + "version": "17.0.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz", + "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w==", + "dev": true + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "peer": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/rxjs/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "peer": true + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "node_modules/tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + } + }, + "node_modules/tslint/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/zone.js": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.5.tgz", + "integrity": "sha512-D1/7VxEuQ7xk6z/kAROe4SUbd9CzxY4zOwVGnGHerd/SgLIVU5f4esDzQUsOCeArn933BZfWMKydH7l7dPEp0g==", + "dev": true, + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + } + } + }, + "dependencies": { + "@angular/common": { + "version": "13.3.4", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-13.3.4.tgz", + "integrity": "sha512-vPZuUGWMXz6r30obBqH+iIG4Feq4YEK/4wUks7PEYGke8MXFPYsNKuHMhKCgYEhabD/4Mo4GEp3i18/3Kk72Mw==", + "dev": true, + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/core": { + "version": "13.3.4", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-13.3.4.tgz", + "integrity": "sha512-PqPwx9oaV0Bh0m0fdI2jtXUC6s04jfD4vyzB4sjEuRI9pRUnZ6M5hZ5Vn/KJVZyt411MevbJfqzUVf0W+GDZew==", + "dev": true, + "peer": true, + "requires": { + "tslib": "^2.3.0" + } + }, + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@ngx-translate/core": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-14.0.0.tgz", + "integrity": "sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w==", + "dev": true, + "requires": { + "tslib": "^2.3.0" + } + }, + "@types/node": { + "version": "17.0.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz", + "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "peer": true, + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "peer": true + } + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "typescript": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "zone.js": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.5.tgz", + "integrity": "sha512-D1/7VxEuQ7xk6z/kAROe4SUbd9CzxY4zOwVGnGHerd/SgLIVU5f4esDzQUsOCeArn933BZfWMKydH7l7dPEp0g==", + "dev": true, + "peer": true, + "requires": { + "tslib": "^2.3.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b2a48ec --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "ngx-translate-po-http-loader", + "version": "1.0.0", + "description": "Load po files for use with ngx-translate", + "main": "dist/index.js", + "typings": "dist/index.d.ts", + "scripts": { + "build": "npm run clean && tsc", + "watch": "npm run clean && tsc --watch", + "clean": "rm -rf ./dist", + "lint": "tslint --force '*.ts'" + }, + "repository": { + "type": "git", + "url": "https://github.com/unistack-org/ngx-translate-po-http-loader" + }, + "keywords": [], + "author": "Vasiliy Tolstov ", + "license": "MIT", + "bugs": { + "url": "https://github.com/unistack-org/ngx-translate-po-http-loader/issues" + }, + "homepage": "https://github.com/unistack-org/ngx-translate-po-http-loader", + "engines": { + "node": ">=4.1.1" + }, + "config": {}, + "devDependencies": { + "@angular/common": "^13.3.4", + "@ngx-translate/core": "^14.0.0", + "@types/node": "^17.0.25", + "tslint": "^6.1.3", + "typescript": "^4.1.5" + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..a4b02e0 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,53 @@ +import { HttpClient } from '@angular/common/http'; +import { TranslateLoader } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { POLoader, Item } from './po'; + +export class TranslatePoHttpLoader implements TranslateLoader { + + /** + * Translation domain + */ + //public domain = ''; + + constructor( + protected _http: HttpClient, + protected _prefix: string = 'i18n', + protected _suffix: string = '.po' + ) { + } + + /** + * Gets the translations from file + * @param lang + * @returns {any} + */ + public getTranslation(lang: string): Observable { + return this._http + .get(`${this._prefix}/${lang}${this._suffix}`, { responseType: 'text' }) + .pipe(map((contents: string) => this.parse(contents))); + } + + /** + * Parse po file + * @param contents + * @returns {any} + */ + public parse(contents: string): any { + let translations: { [key: string]: string } = {}; + + let doc = new POLoader(); + let po = doc.parse(contents); + + po.items.forEach((item: Item) => { + if (item.msgid.length > 0 && item.msgstr.length > 0) { + translations[item.msgid] = item.msgstr.join('\n'); + } + }); + + return translations; + } + +} + diff --git a/src/po.ts b/src/po.ts new file mode 100644 index 0000000..94834ae --- /dev/null +++ b/src/po.ts @@ -0,0 +1,266 @@ +declare interface IHeaders { + 'Project-Id-Version': string; + 'Report-Msgid-Bugs-To': string; + 'POT-Creation-Date': string; + 'PO-Revision-Date': string; + 'Last-Translator': string; + 'Language': string; + 'Language-Team': string; + 'Content-Type': string; + 'Content-Transfer-Encoding': string; + 'Plural-Forms': string; + [name: string]: string; +}; + +export class Item { + public msgid: string = ''; + public msgctxt?: string = ''; + public references: string[] = []; + public msgid_plural?: string = ''; + public msgstr: string[] = []; + public comments: string[] = []; + public extractedComments: string[] = []; + public flags: Record; + public obsolete: boolean; + //private nplurals: number = 0; +}; + +export class PO { + public comments: string[] = []; + public extractedComments: string[] = []; + public items: Item[] = []; + public headers: Partial; + headerOrder: any[] = []; +} + +export class POLoader { + constructor() { + } + + public parse(data: string): PO { + //support both unix and windows newline formats. + data = data.replace(/\r\n/g, '\n'); + var po = new PO(); + var sections = data.split(/\n\n/); + var headers: string; + var theaders: string[] = []; + //everything until the first 'msgid ""' is considered header + while (sections[0] && (theaders.length === 0 || theaders[theaders.length - 1].indexOf('msgid ""') < 0)) { + if (sections[0].match(/msgid\s+"[^"]/)) { + //found first real string, adding a dummy header item + theaders.push('msgid ""'); + } else { + theaders.push(sections.shift()); + } + } + headers = theaders.join('\n'); + var lines = sections.join('\n').split(/\n/); + + po.headers = { + 'Project-Id-Version': '', + 'Report-Msgid-Bugs-To': '', + 'POT-Creation-Date': '', + 'PO-Revision-Date': '', + 'Last-Translator': '', + 'Language': '', + 'Language-Team': '', + 'Content-Type': '', + 'Content-Transfer-Encoding': '', + 'Plural-Forms': '', + }; + po.headerOrder = []; + + headers.split(/\n/).reduce(function (acc: any, line:any) { + if (acc.merge) { + //join lines, remove last resp. first " + line = acc.pop().slice(0, -1) + line.slice(1); + delete acc.merge; + } + if (/^".*"$/.test(line) && !/^".*\\n"$/.test(line)) { + acc.merge = true; + } + acc.push(line); + return acc; + }, []).forEach(function (header:string) { + if (header.match(/^#\./)) { + po.extractedComments.push(header.replace(/^#\.\s*/, '')); + } else if (header.match(/^#/)) { + po.comments.push(header.replace(/^#\s*/, '')); + } else if (header.match(/^"/)) { + header = header.trim().replace(/^"/, '').replace(/\\n"$/, ''); + var p = header.split(/:/); + var name = p.shift().trim(); + var value = p.join(':').trim(); + po.headers[name] = value; + po.headerOrder.push(name); + } + }); + + //var parsedPluralForms = PO.parsePluralForms(po.headers['Plural-Forms']); + // var nplurals = parsedPluralForms.nplurals; + // var item = new Item({ nplurals: nplurals }); + var item = new Item(); + var context = null; + var plural = 0; + var obsoleteCount = 0; + var noCommentLineCount = 0; + + function trim(string: string) { + return string.replace(/^\s+|\s+$/g, ''); + } + + function finish() { + if (item.msgid.length > 0) { + if (obsoleteCount >= noCommentLineCount) { + item.obsolete = true; + } + obsoleteCount = 0; + noCommentLineCount = 0; + po.items.push(item); + //item = new Item({ nplurals: nplurals }); + item = new Item(); + } + } + + function extract(string: string) { + string = trim(string); + string = string.replace(/^[^"]*"|"$/g, ''); + string = string.replace(/\\([abtnvfr'"\\?]|([0-7]{3})|x([0-9a-fA-F]{2}))/g, function (match, esc, oct, hex) { + if (oct) { + return String.fromCharCode(parseInt(oct, 8)); + } + if (hex) { + return String.fromCharCode(parseInt(hex, 16)); + } + switch (esc) { + case 'a': + return '\x07'; + case 'b': + return '\b'; + case 't': + return '\t'; + case 'n': + return '\n'; + case 'v': + return '\v'; + case 'f': + return '\f'; + case 'r': + return '\r'; + default: + return esc; + } + }); + return string; + } + + while (lines.length > 0) { + var line = trim(lines.shift()); + var lineObsolete = false; + //var add = false; + + if (line.match(/^#\~/)) { // Obsolete item + //only remove the obsolte comment mark, here + //might be, this is a new item, so + //only remember, this line is marked obsolete, count after line is parsed + line = trim(line.substring(2)); + lineObsolete = true; + } + + if (line.match(/^#:/)) { // Reference + finish(); + item.references.push(trim(line.replace(/^#:/, ''))); + } else if (line.match(/^#,/)) { // Flags + finish(); + var flags = trim(line.replace(/^#,/, '')).split(','); + for (var i = 0; i < flags.length; i++) { + item.flags[flags[i]] = true; + } + } else if (line.match(/^#($|\s+)/)) { // Translator comment + finish(); + item.comments.push(trim(line.replace(/^#($|\s+)/, ''))); + } else if (line.match(/^#\./)) { // Extracted comment + finish(); + item.extractedComments.push(trim(line.replace(/^#\./, ''))); + } else if (line.match(/^msgid_plural/)) { // Plural form + item.msgid_plural = extract(line); + context = 'msgid_plural'; + noCommentLineCount++; + } else if (line.match(/^msgid/)) { // Original + finish(); + item.msgid = extract(line); + context = 'msgid'; + noCommentLineCount++; + } else if (line.match(/^msgstr/)) { // Translation + var m = line.match(/^msgstr\[(\d+)\]/); + plural = m && m[1] ? parseInt(m[1]) : 0; + item.msgstr[plural] = extract(line); + context = 'msgstr'; + noCommentLineCount++; + } else if (line.match(/^msgctxt/)) { // Context + finish(); + item.msgctxt = extract(line); + context = 'msgctxt'; + noCommentLineCount++; + } else { // Probably multiline string or blank + if (line.length > 0) { + noCommentLineCount++; + if (context === 'msgstr') { + item.msgstr[plural] += extract(line); + } else if (context === 'msgid') { + item.msgid += extract(line); + } else if (context === 'msgid_plural') { + item.msgid_plural += extract(line); + } else if (context === 'msgctxt') { + item.msgctxt += extract(line); + } + } + } + + if (lineObsolete) { + // Count obsolete lines for this item + obsoleteCount++; + } + } + finish(); + + return po; + }; +}; +/* +parsePluralForms(pluralFormsString: string) { + var results = (pluralFormsString || '') + .split(';') + .reduce(function (acc, keyValueString) { + var trimmedString = keyValueString.trim(); + var equalsIndex = trimmedString.indexOf('='); + var key = trimmedString.substring(0, equalsIndex).trim(); + var value = trimmedString.substring(equalsIndex + 1).trim(); + acc[key] = value; + return acc; + }, {}); + return { + nplurals: results.nplurals, + plural: results.plural + }; +}; +*/ + +/* +class Item { +public Item(options: any) { + var nplurals = options && options.nplurals; + + this.msgid = ''; + this.msgctxt = null; + this.references = []; + this.msgid_plural = null; + this.msgstr = []; + this.comments = []; // translator comments + this.extractedComments = []; + this.flags = {}; + this.obsolete = false; + var npluralsNumber = Number(nplurals); + this.nplurals = (isNaN(npluralsNumber)) ? 2 : npluralsNumber; +}; +*/ \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4a8545a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "noUnusedLocals": true, + "noImplicitAny": true, + "removeComments": true, + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "outDir": "dist/", + "declaration": true, + "target": "es5", + "lib": [ + "dom", + "es2015" + ], + "types": ["node"] + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000..050ac56 --- /dev/null +++ b/tslint.json @@ -0,0 +1,53 @@ +{ + "rulesDirectory": [ + "node_modules/tslint-eslint-rules/dist/rules" + ], + "rules": { + "indent": [true, "tabs"], + "semicolon": [true, "always", "ignore-interfaces"], + "quotemark": [true, "single", "avoid-escape"], + "only-arrow-functions": true, + "no-duplicate-variable": true, + "member-access": true, + "member-ordering": [ + true, + { + "order": [ + "public-static-field", + "public-static-method", + "protected-static-field", + "protected-static-method", + "private-static-field", + "private-static-method", + "public-instance-field", + "protected-instance-field", + "private-instance-field", + "constructor", + "public-instance-method", + "protected-instance-method", + "private-instance-method" + ] + } + ], + "curly": true, + "eofline": true, + "no-trailing-whitespace": true, + "trailing-comma": [ + true, + { + "multiline": "never", + "singleline": "never" + } + ], + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-module", + "check-separator", + "check-type", + "check-typecast" + ] + } +}