diff --git a/lib/plankton/plankton.d.ts b/lib/plankton/plankton.d.ts index 64cf666..c677f51 100644 --- a/lib/plankton/plankton.d.ts +++ b/lib/plankton/plankton.d.ts @@ -3325,3 +3325,84 @@ declare namespace lib_plankton.args { }): string; } } +declare namespace lib_plankton.translate { + /** + * @author fenris + */ + type type_package_meta = { + identifier: string; + name?: string; + }; + /** + * @author fenris + */ + type type_package = { + meta: type_package_meta; + tree: { + [id: string]: string; + }; + }; + /** + * @desc the level of verbosity, specifiying how much output the system shall provide about its actions + * @author fenris + */ + var _verbosity: int; + /** + * @desc moves a language to the top of the order, making it the primary one + * @author fenris + */ + function promote(identifier: string): void; + /** + * @desc adds a package to the sytem + * @author fenris + */ + function add(package_: type_package): void; + /** + * @desc integrates a package to the system, i.e. creates a new one if none existed so far or merges with an existing one + * @author fenris + */ + function feed(package_: type_package): void; + /** + * @desc tries to retrieve a translation for a specific package identifier + * @author fenris + */ + function fetch(identifier: string, path: string, args?: { + [id: string]: string; + }): lib_plankton.pod.type_pod; + /** + * @desc retrieves a string by going through the order and trying to fetch it for the current entry + * @author fenris + */ + function get(path: string, args?: { + [id: string]: string; + }, fallback?: string): string; + /** + * @author fenris + */ + function list(): Array; + /** + * @author fenris + * @todo get rid of this; it's currenly needed only for the cdh-internal lib_completion + */ + function paths(): Array; + /** + * @author fenris + */ + function initialize({ "logprefix": logprefix, "verbosity": verbosity, "packages": packages, "order": order, "autopromote": autopromote, }?: { + logprefix?: string; + verbosity?: int; + packages?: Array; + order?: Array; + autopromote?: boolean; + }): Promise; +} +declare namespace lib_plankton.translate { + /** + * @author fenris + */ + function iso_639_1_to_iso_639_2(iso6391: string): string; + /** + * @author fenris + */ + function stance(str: string): string; +} diff --git a/lib/plankton/plankton.js b/lib/plankton/plankton.js index 08be59b..b783764 100644 --- a/lib/plankton/plankton.js +++ b/lib/plankton/plankton.js @@ -11293,3 +11293,346 @@ var lib_plankton; args.class_handler = class_handler; })(args = lib_plankton.args || (lib_plankton.args = {})); })(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:translate«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:translate« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:translate« 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:translate«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var translate; + (function (translate) { + /** + * @desc contains the sets of strings + * @author fenris + */ + var _packages = {}; + /** + * @desc specifies in which order the languages shall be queried; if getting a string from language #0 fails, the + * system tries to get it from language #1, and so on + * @author fenris + */ + var _order = []; + /** + * @desc whether to automatically promote the language of a newly added package + * @author fenris + */ + var _autopromote = false; + /** + * @desc the level of verbosity, specifiying how much output the system shall provide about its actions + * @author fenris + */ + translate._verbosity = 1; + /** + * @desc which initial string to use for log-outputs + * @author fenris + */ + var _logprefix = "[lib_translate]"; + /** + * @desc moves a language to the top of the order, making it the primary one + * @author fenris + */ + function promote(identifier) { + if (Object.keys(_packages).indexOf(identifier) < 0) { + if (translate._verbosity >= 1) { + console.warn(`${_logprefix} package '${identifier}' doesn't exist yet`); + } + } + let position = _order.indexOf(identifier); + if (position >= 0) { + if (translate._verbosity >= 2) { + console.info(`${_logprefix} '${identifier}' already in order; will promote it`); + } + _order.splice(position, 1); + } + _order.unshift(identifier); + if (translate._verbosity >= 2) { + console.info(`${_logprefix} order is now ${_order.toString()}`); + } + } + translate.promote = promote; + /** + * @desc adds a package to the sytem + * @author fenris + */ + function add(package_) { + let identifier = package_.meta.identifier; + if (identifier in _packages) { + if (translate._verbosity >= 1) { + console.warn(`${_logprefix} package '${identifier}' has already been added; will overwrite`); + } + } + else { + if (translate._verbosity >= 2) { + console.log(`${_logprefix} got package '${identifier}'`); + } + } + _packages[identifier] = package_; + if (_autopromote) { + promote(identifier); + } + } + translate.add = add; + /** + * @desc integrates a package to the system, i.e. creates a new one if none existed so far or merges with an existing one + * @author fenris + */ + function feed(package_) { + let identifier = package_.meta.identifier; + if (identifier in _packages) { + lib_plankton.object.patch(_packages[identifier].tree, package_.tree, true); + } + else { + if (translate._verbosity >= 2) { + console.info(`${_logprefix} package '${identifier}' didn't exist so far; will create it now`); + } + add(package_); + } + } + translate.feed = feed; + /** + * @desc tries to retrieve a translation for a specific package identifier + * @author fenris + */ + function fetch(identifier, path, args = {}) { + if (!(identifier in _packages)) { + if (translate._verbosity >= 1) { + console.warn(`${_logprefix} no package '${identifier}'`); + } + return (lib_plankton.pod.make_empty()); + } + else { + // let str : string = lib_plankton.object.path_read(_packages[identifier].tree, path); + let str = _packages[identifier].tree[path]; + if (str == undefined) { + if (translate._verbosity >= 1) { + console.warn(`${_logprefix} string '${path}' missing in package '${identifier}'`); + } + return (lib_plankton.pod.make_empty()); + } + else { + // resolve references + { + let regexp_reference = new RegExp("#\\(([\\w\\.]*)(?:\\?(\\w+)=(\\w+)(?:&(\\w+)=(\\w+))*)?\\)"); + while (true) { + let matching = regexp_reference.exec(str); + if (matching != null) { + let path_ = matching[1]; + let args_ = {}; + if (translate._verbosity >= 2) { + // console.info(`${_logprefix} found reference to '${path_}' with args ${JSON.stringify(args_)}`); + console.info(`${_logprefix} found reference to '${path_}'`); + } + // parse args + { + for (let index = 2; index <= matching.length - 1; index += 2) { + let id = matching[index + 0]; + let value = matching[index + 1]; + if (id != undefined) { + args_[id] = value; + } + } + } + // fetch referenced string + { + let result_ = fetch(identifier, path_, args_); + if (lib_plankton.pod.is_filled(result_)) { + let front = str.slice(0, matching.index); + let back = str.slice(matching.index + matching[0].length); + str = (front + lib_plankton.pod.cull(result_) + back); + } + else { + return (lib_plankton.pod.make_empty()); + break; + } + } + } + else { + break; + } + } + } + // insert arguments + { + str = lib_plankton.string.coin(str, args); + } + return (lib_plankton.pod.make_filled(str)); + } + } + } + translate.fetch = fetch; + /** + * @desc retrieves a string by going through the order and trying to fetch it for the current entry + * @author fenris + */ + function get(path, args = {}, fallback = null) { + if (fallback == null) { + fallback = `{${path}}`; + } + if (translate._verbosity >= 2) { + console.info(`${_logprefix} getting translation for string '${path}' with arguments ${JSON.stringify(args)} …`); + } + let result = lib_plankton.pod.make_empty(); + let found = _order.some(identifier => { + if (translate._verbosity >= 2) { + console.info(`${_logprefix} trying package '${identifier}' …`); + } + let result_ = fetch(identifier, path, args); + if (lib_plankton.pod.is_filled(result_)) { + result = result_; + return true; + } + else { + return false; + } + }); + if (found) { + let str = lib_plankton.pod.cull(result); + if (translate._verbosity >= 3) { + console.info(`${_logprefix} found translation: '${str}'`); + } + return str; + } + else { + let str = fallback; + if (translate._verbosity >= 1) { + console.warn(`${_logprefix} no package provides a translation for string '${path}'; will use the fallback translation '${str}'`); + } + return str; + } + } + translate.get = get; + /** + * @author fenris + */ + function list() { + return lib_plankton.object.to_array(_packages).map(x => x.value.meta); + } + translate.list = list; + /** + * @author fenris + * @todo get rid of this; it's currenly needed only for the cdh-internal lib_completion + */ + function paths() { + return lib_plankton.object.keys(lib_plankton.object.flatten(_packages[_order[0]].tree)); + } + translate.paths = paths; + /** + * @author fenris + */ + function initialize({ "logprefix": logprefix = undefined, "verbosity": verbosity = undefined, "packages": packages = [], "order": order = undefined, "autopromote": autopromote = undefined, } = {}) { + return (Promise.resolve(undefined) + // set variables + .then(_ => { + if (logprefix != undefined) + _logprefix = logprefix; + if (verbosity != undefined) + translate._verbosity = verbosity; + // _packages = {}; + if (order != undefined) + _order = order; + if (autopromote != undefined) + _autopromote = autopromote; + return Promise.resolve(undefined); + }) + // feed + .then(_ => { + packages.forEach(feed); + return Promise.resolve(undefined); + })); + } + translate.initialize = initialize; + })(translate = lib_plankton.translate || (lib_plankton.translate = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:translate«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:translate« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:translate« 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:translate«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var translate; + (function (translate) { + /** + * @author fenris + */ + function iso_639_1_to_iso_639_2(iso6391) { + let mapping = { + "af": "afr", + "ar": "ara", + "bg": "bul", + "cs": "ces", + "da": "dan", + "de": "deu", + "el": "ell", + "en": "eng", + "eo": "epo", + "es": "esp", + "fa": "fas", + "fi": "fin", + "fr": "fra", + "hi": "hin", + "hr": "hrv", + "hu": "hun", + "is": "isl", + "it": "ita", + "ja": "jpn", + "ko": "kor", + "nb": "nob", + "nl": "nld", + "nn": "nno", + "pt": "por", + "pl": "pol", + "ro": "ron", + "ru": "rus", + "sk": "slk", + "sv": "swe", + "zh": "zho", + }; + return mapping[iso6391]; + } + translate.iso_639_1_to_iso_639_2 = iso_639_1_to_iso_639_2; + /** + * @author fenris + */ + function stance(str) { + let regexp = new RegExp("^translate:(.*)$"); + let matching = regexp.exec(str); + if (matching != null) { + return translate.get(matching[1]); + } + else { + return str; + } + } + translate.stance = stance; + })(translate = lib_plankton.translate || (lib_plankton.translate = {})); +})(lib_plankton || (lib_plankton = {})); diff --git a/tools/update-plankton b/tools/update-plankton index 444d997..810be47 100755 --- a/tools/update-plankton +++ b/tools/update-plankton @@ -18,6 +18,7 @@ modules="${modules} rest" modules="${modules} http" modules="${modules} server" modules="${modules} args" +modules="${modules} translate" ## exec