| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 | const translation = require("./translation.js").translation;/** * This class repesents phrasebook, which is something like dictionary, * but not for words, for all phrases in app. It give functions which  * could find and translates phrases. */class phrasebook {        /**     * @var {Map}     * This store phrases in flat notation.     */    #phrases;    /**     * @var {?object}     * This store object for nested object notation.     */    #objects;    /**     * This create new phrasebook from phrases map, and optional object     * for phrases in object notation.     *      * @param {Map} phrases - This contain phrases in flat notation.     * @param {?object} objects - This contain phrases in object notation.      */    constructor(phrases, objects = null) {        if (!(phrases instanceof Map)) {            throw new TypeError("Phrases must an map.");        }        if (objects !== null && typeof(objects) !== "object") {            throw new TypeError("Objects must be null or object.");        }            this.#phrases = phrases;        this.#objects = objects;    }    /**     * This translate given phrase. When phrase is in the nested object      * notation, then try to find phrase in objects. When not, try to find     * phrase in the flat phrases. When could not find phrase, then return      * not translated phrase. Content always is returned as translation     * object, which could be also formated wich numbers, dates and     * much more.     *      * @param {string} phrase - Phrase to translate.      * @returns {translation} - Translated phrase.     */    translate(phrase) {        if (typeof(phrase) !== "string") {            throw new TypeError("Phrase to translate must be an string.");        }        if (this.#is_nested(phrase)) {            return this.#translate_nested(phrase);        }        return this.#translate_flat(phrase);    }    /**     * This translate given phrase. When phrase is in the nested object      * notation, then try to find phrase in objects. When not, try to find     * phrase in the flat phrases. When could not find phrase, then return      * not translated phrase. Content always is returned as translation     * object, which could be also formated wich numbers, dates and     * much more.     *      * @param {string} phrase - Phrase to translate.      * @returns {translation} - Translated phrase.     */    get(phrase) {        return this.translate(phrase);    }    /**     * Check that phrase is nested or not.     *      * @param {string} phrase - Phrase to check that is nested     * @returns {bool} - True when nested, false when not      */    #is_nested(phrase) {        return phrase.indexOf(".") !== -1;    }    /**     * This translate object notated phrase.     *      * @param {string} phrase - Phrase to translate.     * @returns {translation} - Translated phrase.      */    #translate_nested(phrase) {        if (this.#objects === null) {            return this.#translate_flat(phrase);        }        const parts = phrase.trim().split(".");        let current = this.#objects;        for (const count in parts) {            const part = parts[count];                        if (!(part in current)) {                return new translation(phrase, false);            }            current = current[part];        }        if (typeof(current) !== "string") {            return new translation(phrase, false);        }        return new translation(current, true);    }    /**     * This set phrasebook as default. That mean, it would add own translate     * function to global scope, and create _({string}) function in the global     * scope. It is useable to minify code with translations. It is not      * avairable in the NodeJS, only in the browser.     *      * @returns {phrasebook} - Object itself to chain loading.     */    set_as_default() {        NODE: throw new Error("Could not create global function in NodeJS.");                const translate = (content) => {            return this.translate(content);        };        window._ = translate;        window.translate = translate;    }    /**     * This translate flat phrase.     *      * @param {string} phrase - Phrase to translate.      * @returns {translation} - Translated phrase.     */    #translate_flat(phrase) {        const prepared = phrasebook.prepare(phrase);        const found = this.#phrases.has(prepared);        const translated = found ? this.#phrases.get(prepared) : phrase;                return new translation(translated, found);    }    /**     * This prepars phrase, that mean replece all spaces with "_", trim      * and also replace all big letters with lowwer.      *      * @param {string} content - Phrase to preapre.     * @return {string} - Prepared phrase.     */     static prepare(content) {        if (typeof(content) !== "string") {            throw new TypeError("Content to prepare must be an string.");        }                return content        .trim()        .replaceAll(" ", "_")        .replaceAll(".", "_")        .toLowerCase();    }}exports.phrasebook = phrasebook;
 |