{ "version": 3, "sources": ["../source/translation.js", "../source/phrasebook.js", "../source/loader.js", "../source/languages.js", "../source/selector.js", "../source/autotranslate.js", "../source/preferences.js", "../source/core.js"], "sourcesContent": ["class translation {\n /**\n * @var {string}\n * This is translated content.\n */\n #content;\n \n /**\n * @var {bool}\n * This is true, when content is translated from dict, and false\n * when could not being found.\n */\n #translated;\n\n /**\n * This create new translation. Translation store content of the \n * translation, make avairable to format translated phrase and also\n * store that translation was found in the phrasebook.\n * \n * @param {string} content - Content of the translation.\n * @param {bool} translated - True when translation could be found.\n */\n constructor(content, translated = true) {\n if (typeof(content) !== \"string\") {\n throw new TypeError(\"Translated content must be string.\");\n }\n\n if (typeof(translated) !== \"boolean\") {\n throw new TypeError(\"Result of translation must be boolean.\");\n }\n\n this.#content = content;\n this.#translated = translated;\n\n Object.freeze(this);\n }\n\n /**\n * This convert transiation to string.\n * \n * @returns {string} - Content of the translation.\n */\n toString() {\n return this.#content;\n }\n\n /**\n * @returns {string} - Content of the translation.\n */\n get text() {\n return this.#content;\n }\n\n /**\n * @returns {bool} - True when translation was found, false when not.\n */\n get valid() {\n return this.translated;\n }\n\n /**\n * This would format ready translation, with numbers, dats, and \n * other content, which could not being statically places into\n * translation. To use it, place name of content object key into\n * \"#{}\" in translation. \n * \n * @example ```\n * Translation: \"I have more than #{how_many} apples!\"\n * Object: { how_many: 10 }\n * Result: \"I have more than 10 apples!\"\n * ```\n * \n * @param {string} content \n * @returns {string}\n */\n format(content) {\n if (typeof(content) !== \"object\") {\n throw new TypeError(\"Content to format from must be object.\");\n }\n\n if (!this.#translated) {\n return this.#content;\n }\n\n return this.#parse_format(content);\n }\n\n /**\n * This infill prepared translation with data from content \n * object.\n * \n * @see format\n * \n * @param {object} content - Content to load data from. \n * @returns {string} - Formater translation.\n */\n #parse_format(content) {\n let parts = this.#content.split(\"#{\");\n let result = parts[0];\n\n for (let count = 1; count < parts.length; ++count) {\n const part = parts[count];\n const splited = part.split(\"}\");\n\n if (splited.length === 1) {\n return result + splited[0];\n }\n\n const name = splited.splice(0, 1)[0].trim();\n const rest = splited.join(\"}\");\n\n if (!(name in content)) {\n DEBUG: throw new RangeError(\n \"Could not find \\\"\" + name + \"\\\".\"\n );\n \n result += rest;\n continue;\n }\n\n result += content[name] + rest;\n }\n\n return result;\n }\n}\n\nexports.translation = translation;", "const translation = require(\"./translation.js\").translation;\n\n/**\n * This class repesents phrasebook, which is something like dictionary,\n * but not for words, for all phrases in app. It give functions which \n * could find and translates phrases.\n */\nclass phrasebook {\n \n /**\n * @var {Map}\n * This store phrases in flat notation.\n */\n #phrases;\n\n /**\n * @var {?object}\n * This store object for nested object notation.\n */\n #objects;\n\n /**\n * This create new phrasebook from phrases map, and optional object\n * for phrases in object notation.\n * \n * @param {Map} phrases - This contain phrases in flat notation.\n * @param {?object} objects - This contain phrases in object notation. \n */\n constructor(phrases, objects = null) {\n if (!(phrases instanceof Map)) {\n throw new TypeError(\"Phrases must an map.\");\n }\n\n if (objects !== null && typeof(objects) !== \"object\") {\n throw new TypeError(\"Objects must be null or object.\");\n }\n \n this.#phrases = phrases;\n this.#objects = objects;\n }\n\n /**\n * This translate given phrase. When phrase is in the nested object \n * notation, then try to find phrase in objects. When not, try to find\n * phrase in the flat phrases. When could not find phrase, then return \n * not translated phrase. Content always is returned as translation\n * object, which could be also formated wich numbers, dates and\n * much more.\n * \n * @param {string} phrase - Phrase to translate. \n * @returns {translation} - Translated phrase.\n */\n translate(phrase) {\n if (typeof(phrase) !== \"string\") {\n throw new TypeError(\"Phrase to translate must be an string.\");\n }\n\n if (this.#is_nested(phrase)) {\n return this.#translate_nested(phrase);\n }\n\n return this.#translate_flat(phrase);\n }\n\n /**\n * This translate given phrase. When phrase is in the nested object \n * notation, then try to find phrase in objects. When not, try to find\n * phrase in the flat phrases. When could not find phrase, then return \n * not translated phrase. Content always is returned as translation\n * object, which could be also formated wich numbers, dates and\n * much more.\n * \n * @param {string} phrase - Phrase to translate. \n * @returns {translation} - Translated phrase.\n */\n get(phrase) {\n return this.translate(phrase);\n }\n\n /**\n * Check that phrase is nested or not.\n * \n * @param {string} phrase - Phrase to check that is nested\n * @returns {bool} - True when nested, false when not \n */\n #is_nested(phrase) {\n return phrase.indexOf(\".\") !== -1;\n }\n\n /**\n * This translate object notated phrase.\n * \n * @param {string} phrase - Phrase to translate.\n * @returns {translation} - Translated phrase. \n */\n #translate_nested(phrase) {\n if (this.#objects === null) {\n return this.#translate_flat(phrase);\n }\n\n const parts = phrase.trim().split(\".\");\n let current = this.#objects;\n\n for (const count in parts) {\n const part = parts[count];\n \n if (!(part in current)) {\n return new translation(phrase, false);\n }\n\n current = current[part];\n }\n\n if (typeof(current) !== \"string\") {\n return new translation(phrase, false);\n }\n\n return new translation(current, true);\n }\n\n /**\n * This set phrasebook as default. That mean, it would add own translate\n * function to global scope, and create _({string}) function in the global\n * scope. It is useable to minify code with translations. It is not \n * avairable in the NodeJS, only in the browser.\n * \n * @returns {phrasebook} - Object itself to chain loading.\n */\n set_as_default() {\n NODE: throw new Error(\"Could not create global function in NodeJS.\");\n \n const translate = (content) => {\n return this.translate(content);\n };\n\n window._ = translate;\n window.translate = translate;\n }\n\n /**\n * This translate flat phrase.\n * \n * @param {string} phrase - Phrase to translate. \n * @returns {translation} - Translated phrase.\n */\n #translate_flat(phrase) {\n const prepared = phrasebook.prepare(phrase);\n const found = this.#phrases.has(prepared);\n const translated = found ? this.#phrases.get(prepared) : phrase;\n \n return new translation(translated, found);\n }\n\n /**\n * This prepars phrase, that mean replece all spaces with \"_\", trim \n * and also replace all big letters with lowwer. \n * \n * @param {string} content - Phrase to preapre.\n * @return {string} - Prepared phrase.\n */ \n static prepare(content) {\n if (typeof(content) !== \"string\") {\n throw new TypeError(\"Content to prepare must be an string.\");\n }\n \n return content\n .trim()\n .replaceAll(\" \", \"_\")\n .replaceAll(\".\", \"_\")\n .toLowerCase();\n }\n}\n\nexports.phrasebook = phrasebook;", "const phrasebook = require(\"./phrasebook.js\").phrasebook;\n\n/**\n * This class fetch and prepare phrasebook from JSON file. That JSON file \n * could be simple flat JSON, which contain string phrases as keys, and \n * its translatedequivalents as values. Also avalirable is format, where\n * phrases not being used, but JSON contain nested objects. End value must\n * being translated string, but then notation like \"a.b.c\" could being used.\n * \n * @example simple flat phrasebook ```JSON\n * JSON:\n * {\n * \"phrase a\": \"Translated phrase a\",\n * \"phrase b\": \"Translated phrase b\"\n * }\n * \n * Results:\n * \"phrase a\" -> \"Translated phrase a\",\n * \"phrase b\" -> \"Translated phrase b\"\n * ```\n * \n * @example simple nested phrasebook ```JSON\n * JSON:\n * {\n * \"phrases\": {\n * \"phrase a\": \"Translated phrase a\"\n * },\n * \"objects\": {\n * \"a\": {\n * \"b\": {\n * \"c\": \"Second object notation\"\n * }\n * } \n * }\n * }\n * \n * Results:\n * \"phrase a\" -> \"Translated phrase a\",\n * \"a.b.c\" -> \"Second object notation\" \n * ``` \n */\nclass loader {\n /**\n * @var {string}\n * This is location of the phrasebook on the server.\n */\n #path;\n\n /**\n * @var {bool}\n * This is true, when must load local file, or false when fetch.\n */\n #local;\n\n /**\n * This create new loader of the phrasebook.\n * \n * @param {string} path - Location of the phrasebook to fetch.\n * @param {bool} local - False when must fetch from remote.\n */\n constructor(path, local = false) {\n if (typeof(path) !== \"string\") {\n throw new TypeError(\"Path of the file must be string.\");\n }\n\n if (typeof(local) !== \"boolean\") {\n throw new TypeError(\"Local must be bool variable.\");\n }\n\n this.#path = path;\n this.#local = local;\n }\n\n /**\n * This load file from path given in the constructor, parse and return it.\n * \n * @returns {phrasebook} - New phrasebook with content from JSON file.\n */\n async #load_remote() {\n const request = await fetch(this.#path);\n const response = await request.json();\n\n return this.#parse(response);\n }\n\n /**\n * This load file from path given in the constructor, parse and return it.\n * \n * @returns {phrasebook} - New phrasebook with content from JSON file.\n */\n async #load_local() {\n let fs = null;\n NODE: fs = require(\"node:fs/promises\");\n\n if (fs === null) {\n throw new Error(\"Could not use ndoe:fs in browser.\");\n }\n\n const content = await fs.readFile(this.#path, { encoding: 'utf8' });\n const response = JSON.parse(content);\n\n return this.#parse(response);\n }\n\n /**\n * This load file from path given in the constructor, parse and return it.\n * \n * @returns {phrasebook} - New phrasebook with content from JSON file.\n */\n load() {\n if (this.#local) {\n return this.#load_local();\n }\n\n return this.#load_remote();\n }\n\n /**\n * This parse phrasebook. When phrasebook contain \"phrases\" or \"objects\" \n * keys, and also \"objects\" is not string, then parse it as nested file,\n * in the other way parse it as flat.\n * \n * @param {object} content - Fetched object with translations. \n * @returns {phrasebook} - Loaded phrasebook.\n */\n #parse(content) {\n const has_objects = (\n \"objects\" in content &&\n typeof(content[\"objects\"]) === \"object\"\n );\n\n const has_phrases = (\n \"phrases\" in content &&\n typeof(content[\"phrases\"]) === \"object\"\n );\n\n const is_nested = has_objects || has_phrases;\n\n if (is_nested) {\n const phrases = has_phrases ? content[\"phrases\"] : {};\n const objects = has_objects ? content[\"objects\"] : {};\n\n return new phrasebook(\n this.#parse_phrases(phrases),\n objects\n );\n }\n\n return new phrasebook(this.#parse_phrases(content));\n }\n\n /**\n * This parse flat phrases object to map.\n * \n * @param {object} content - Flat phrases object to pase.\n * @returns {Map} - Phrases parsed as Map.\n */\n #parse_phrases(content) {\n const phrases = new Map();\n\n Object.keys(content).forEach(phrase => {\n const name = phrasebook.prepare(phrase);\n const translation = content[phrase];\n\n phrases.set(name, translation);\n });\n\n return phrases;\n }\n}\n\nexports.loader = loader;", "const loader = require(\"./loader.js\").loader;\nconst phrasebook = require(\"./phrasebook.js\").phrasebook;\n\n/**\n * This class represents languages library. This store its location on the \n * server, and create loaders for them. It could also load langiage \n * library from json file.\n */\nclass languages {\n /**\n * @var {string} \n * This represents path to directory where phrasebooks had been stored.\n */\n #path;\n\n /**\n * @var {Map}\n * This store languages and its files on server. \n */\n #libs;\n\n /**\n * @var {bool}\n * This store that directory is in the local file system, or remote\n * server. When true, resources would be loaded by node:fs. When \n * false, resources would be fetched.\n */\n #local;\n\n /**\n * This create new languages library. Next, languages could be added to\n * the library by command, or by loading index file.\n * \n * @throws {TypeError} - When parameters is not in correct format.\n * \n * @param {string} path - Path to phrasebooks on the server or filesystem.\n * @param {bool} local - True when phrasebooks dirs would be loaded by \n * node:fs module. False when would be fetch.\n */\n constructor(path, local = false) {\n if (typeof(path) !== \"string\") {\n throw new TypeError(\"Path to the phrasebooks must be string.\");\n }\n\n if (typeof(local) !== \"boolean\") {\n throw new TypeError(\"Local must be bool variable.\");\n }\n\n this.#local = local;\n this.#path = path;\n this.#libs = new Map();\n }\n\n /**\n * This add new language to the library by name. Name must be in form\n * like POSIX locale, like en_US, or pl_PL. That mean first two letter\n * mest be ISO 639-1 and second two letters mst be in ISO 3166-1 alpha-2\n * 2 letter country code format.\n * \n * @see https://www.loc.gov/standards/iso639-2/php/code_list.php\n * @see https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes\n * @see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2\n * @see https://en.wikipedia.org/wiki/Locale_(computer_software)\n * \n * @throws {TypeError} - When tpes of the parameters is not correct.\n * \n * @param {string} name - Name of the language, like \"en_US\".\n * @param {string} file - Name of the file in the directory.\n * @return {languages} - Instnace of this class to chain.\n */\n add(name, file) {\n if (typeof(name) !== \"string\") {\n throw new TypeError(\"Name of the language must be sting.\");\n }\n\n if (typeof(file) !== \"string\") {\n throw new TypeError(\"File on in the directory must be string.\");\n }\n\n if (this.#libs.has(name)) {\n console.error(\"Language \\\"\" + name + \"\\\" already loaded.\");\n console.error(\"It could not being loaded twice.\");\n return this;\n }\n\n if (!this.#valid_locale(name)) {\n console.error(\"Language name \\\"\" + name + \"\\\" invalid formated.\");\n console.error(\"It could not being loaded.\")\n return this;\n }\n \n this.#libs.set(name, file);\n return this;\n }\n\n /**\n * This load all phrasebook given in the index file. Index must be\n * JSON file, which contain one object. That object properties must be\n * languages names in the notation like in add function. Valus of that\n * properties musts being strings which contains names of the phrasebook\n * files in the path directory.\n * \n * @example ``` { \"pl_PL\": \"polish.json\", \"en_US\": \"english.json\" } ```\n * \n * @see add\n * \n * @param {string} index - Index file in the phrasebook directory.\n * @return {languages} - New languages instance with loaded index.\n */\n async load(index) {\n if (typeof(index) !== \"string\") {\n throw new TypeError(\"Name of index file is not string.\");\n }\n\n const response = await this.#load_index(index);\n this.#libs.clear();\n\n Object.keys(response).forEach(name => {\n if (typeof(name) !== \"string\") {\n console.error(\"Name of the language must be string.\");\n console.error(\"Check languages index.\");\n console.error(\"Skipping it.\")\n return;\n }\n\n if (typeof(response[name]) !== \"string\") {\n console.error(\"Name of phrasebook file must be string.\");\n console.error(\"Check languages index.\");\n console.error(\"Skipping it.\");\n return;\n }\n\n this.add(name, response[name]);\n });\n\n return this;\n }\n\n /**\n * This load index object. That check, and when content must be loaded\n * from local filesystem, it use node:fs, or when it must be fetched from\n * remote, then use fetch API.\n * \n * @param {string} index - Name of the index file in library. \n * @returns {object} - Loaded index file content. \n */\n async #load_index(index) {\n const path = this.#full_path(index);\n\n if (this.#local) {\n let fs = null;\n NODE: fs = require(\"node:fs/promises\"); \n \n if (fs === null) {\n throw new Error(\"Could not use ndoe:fs in browser.\");\n }\n\n return JSON.parse(\n await fs.readFile(path, { encoding: \"utf-8\" })\n );\n }\n\n const request = await fetch(path);\n return await request.json();\n }\n\n /**\n * This check that language exists in languages library.\n * \n * @param {string} name - Name of the language to check.\n * @return {bool} - True when language exists, false when not\n */\n has(name) {\n return this.#libs.has(name);\n }\n\n /**\n * This return all avairable languages.\n * \n * @return {Array} - List of all avairable languages.\n */\n get avairable() {\n const alls = new Array();\n\n this.#libs.keys().forEach(name => {\n alls.push(name);\n });\n\n return alls;\n }\n\n /**\n * @returns {string} - Default \n */\n get default() {\n const avairable = this.avairable;\n\n if (avairable.length === 0) {\n throw new Error(\"Languages list is empty. Can not load default.\");\n }\n\n return avairable[0];\n }\n\n /**\n * This load phrasebook with give name.\n * \n * @throws {TypeError} - Param type is not correct.\n * @throws {RangeError} - Language not exists in libs.\n * \n * @param {string} name - Name of the language to load. \n * @returns {phrasebook} - Phrasebook loaded from the file.\n */\n select(name) {\n if (typeof(name) !== \"string\") {\n throw new TypeError(\"Name of the language must be string.\");\n }\n\n if (!this.has(name)) {\n DEBUG: throw new RangeError(\n \"Not found language \\\"\" + name + \"\\\".\"\n );\n\n return new phrasebook(new Map());\n }\n \n const file = this.#libs.get(name);\n const path = this.#full_path(file);\n\n return new loader(path, this.#local).load();\n }\n\n /**\n * This return full path to the file.\n * \n * @param {string} name - Name of the file to get its path\n * @return {string} - Full path of the file\n */\n #full_path(name) {\n let glue = \"/\";\n\n if (this.#path[this.#path.length - 1] === glue) {\n glue = \"\";\n }\n\n return this.#path + glue + name;\n }\n\n /**\n * This check that format is valid POSIX like locale.\n * \n * @param {string} name - Name to check format of.\n * @return {bool} - True when format is valid, false when not.\n */\n #valid_locale(name) {\n const splited = name.split(\"_\");\n\n if (splited.length !== 2) {\n return false;\n }\n\n const first = splited[0];\n const second = splited[1];\n\n if (first.toLowerCase() !== first || first.length !== 2) {\n return false;\n }\n\n if (second.toUpperCase() !== second || second.length !== 2) {\n return false;\n }\n\n return true;\n }\n}\n\nexports.languages = languages;", "const languages = require(\"./languages.js\").languages;\n\n/**\n * This could be used to setup language selector. This require languages\n * container, and could create functional languages selector from it. This \n * add options to select all avaoidable languages in the container.\n */\nclass selector {\n /**\n * @var {languages}\n * This store languages container.\n */\n #languages;\n\n /**\n * @var {?HTMLElement}\n * This store selector HTML container, or null when not created.\n */\n #container;\n\n /**\n * @var {HTMLElement}\n * This store languages HTML selector object.\n */\n #selector;\n\n /**\n * @var {Array}\n * This is array of callbacks which must being called after change.\n */\n #callbacks;\n\n /**\n * This create new selector object, from languages container.\n * \n * @param {languages} languages - Languages container to work on.\n */\n constructor(languages) {\n NODE: throw new Error(\"This module could not beind used in NodeJS.\");\n \n this.#container = null;\n this.#languages = languages;\n this.#callbacks = new Array();\n this.#selector = this.#create_selector();\n }\n\n /**\n * This check that selector is currently inserted anywhere.\n * \n * @returns {bool} - True when selector is inserted anywhere.\n */\n get is_inserted() {\n return this.#container !== null;\n }\n\n /**\n * This inserts selector into given HTML element, or directly into\n * document body, when any element is not specified. It returns \n * itselt, to call more functions inline.\n * \n * @param {?HTMLElement} where - Place to insert selector, or null.\n * @returns {selector} - This object to chain loading.\n */\n insert(where = null) {\n if (this.is_inserted) {\n return this;\n }\n\n if (where === null) {\n where = document.querySelector(\"body\");\n }\n\n this.#container = this.#create_container();\n where.appendChild(this.#container);\n\n return this;\n }\n\n /**\n * This run all functions which was registered as onChange callback.\n */\n #on_change() {\n this.#callbacks.forEach(count => {\n count(this.current);\n });\n }\n\n /**\n * This function remove selector from HTML element, if it is already\n * inserted anywhere.\n * \n * @returns {selector} - This object to chain loading.\n */\n remove() {\n if (!this.is_inserted) {\n return this;\n }\n\n this.#container.remove();\n this.#container = null;\n\n return this;\n }\n\n /**\n * This create new container with selector inside.\n * \n * @returns {HTMLElement} - New container with selector.\n */\n #create_container() {\n const container = document.createElement(\"div\");\n \n container.classList.add(this.class_name);\n container.appendChild(this.#selector);\n \n return container;\n }\n\n /**\n * This add new callback to selector. All callbacks would be called\n * after language change. Callback would get one parameter, which is\n * name of the location.\n * \n * @param {CallableFunction} callback - Function to call on change.\n * @returns \n */\n add_listener(callback) {\n this.#callbacks.push(callback);\n return this;\n }\n\n /**\n * This return HTML class name of selector container.\n * \n * @returns {string} - HTML class name of selector container.\n */\n get class_name() {\n return 'cx-libtranslate-language-selector';\n }\n\n /**\n * This create HTML option element from language name.\n * \n * @param {string} location - Name of single language. \n * @returns {HTMLElement} - New option element.\n */\n #create_option(location) {\n const name = location.split(\"_\").pop();\n const option = document.createElement(\"option\");\n\n option.innerText = name;\n option.value = location;\n\n return option;\n }\n\n /**\n * This return current selected language name.\n * \n * @returns {string} - Current selected language.\n */\n get current() {\n return this.#selector.value;\n }\n\n /**\n * This set current selected language for the selector.\n * \n * @param {string} name - Name of the language to set.\n * @returns {selector} - This to chain loading.\n */\n set_selection(name) {\n if (!this.#languages.has(name)) {\n DEBUG: throw new Error(\n \"Selector has not \\\"\" + name + \"\\\" \" +\n \"language in the container.\"\n );\n }\n\n this.#selector.value = name;\n return this;\n }\n\n /**\n * This reload languages list in the selector. It could be used\n * after change in the languages container.\n * \n * @returns {selector} - Itself to chain loading.\n */\n reload() {\n while (this.#selector.lastChild) {\n this.#selector.lastChild.remove();\n }\n\n this.#languages.avairable.forEach(count => {\n this.#selector.appendChild(this.#create_option(count));\n });\n\n return this;\n }\n\n /**\n * This create new HTML selector object, witch all languages\n * from container inserted as options.\n * \n * @returns {HTMLElement} - New selector object.\n */\n #create_selector() {\n const selector = document.createElement(\"select\");\n\n selector.addEventListener(\"change\", () => {\n this.#on_change();\n });\n\n this.#languages.avairable.forEach(count => {\n selector.appendChild(this.#create_option(count));\n }); \n\n return selector;\n }\n}\n\nexports.selector = selector;", "const { phrasebook } = require(\"./phrasebook\");\n\n/**\n * This class is responsible for automatic translate site content of the \n * HTML elements. It could automatic translate content for all elements \n * which are in the \"translate\" class, and has \"phrase\" attribute. This \n * attrobite store phrase to translate, and insert into element innerText\n * or placeholder (for inputs). It could also observate HTML Node, and\n * automatic update transltions when any item had been changed.\n */\nclass autotranslate {\n /**\n * @var {?phrasebook}\n * This store phrasebook to get translates from, or store null, to get\n * translate content from global translate function.\n */\n #phrasebook;\n\n /**\n * @var {?MutationObserver}\n * This store observer object, when it is connecter and waiting for \n * changaes, or store null, when observer currently not working.\n */\n #observer;\n\n /**\n * This create new autotranslator. It require phrasebook, to loads \n * translations for phrases from. When null had been given, the it \n * use global translate function.\n * \n * @throws {Error} - When trying to use it in the NodeJS.\n * \n * @param {?phrasebook} phrasebook \n */\n constructor(phrasebook = null) {\n NODE: throw new Error(\"It is not avairable in the NodeJS.\");\n this.#observer = null;\n this.#phrasebook = phrasebook;\n }\n\n /**\n * It return class name for elements, which would be translated by \n * autotranslator.\n * \n * @returns {string} - Class name for autotranslating elements.\n */\n static get_class_name() {\n return \"translate\"; \n }\n\n /**\n * This return selector for choose elements which must be autotranslated.\n * \n * @returns {string} - Selector of the elements to translate.\n */\n get #class_selector() {\n return \".\" + autotranslate.get_class_name();\n }\n\n /**\n * This return name of attribute which store phrase to translate.\n * \n * @returns {string} - Name of attribute which store phrase.\n */\n static get_attribute_name() {\n return \"phrase\";\n }\n\n /**\n * This check that autotranslator is connected and waiting to changes.\n * \n * @returns {bool} - True when observer is connected, fakse when not.\n */\n get is_connected() {\n return this.#observer !== null;\n }\n\n /**\n * This search elements which could be translated in the element given\n * in the parameter. When null given, then it search elements in the \n * all document.\n * \n * @param {?HTMLElement} where - Item to load items from or null.\n * @returns {Array} - Array of elements to translate.\n */\n #get_all_items(where = null) {\n if (where === null) {\n where = document;\n }\n\n return Array.from(\n where.querySelectorAll(this.#class_selector)\n );\n }\n\n /**\n * It translate given phrase, baseed on loaded phrasebook, or when not\n * loaded any, then use global translate function. When it also not \n * exists, then throws error in debug mode, or return not translated\n * phrase on production.\n * \n * @throws {Error} - When any option to translate not exists.\n * \n * @param {string} content - Phrase to translate.\n * @returns {string} - Translated content.\n */\n #translate(content) {\n if (this.#phrasebook !== null) {\n return this.#phrasebook.translate(content);\n }\n\n if (_ === undefined) {\n DEBUG: throw new Error(\"All translate options are unavairable.\");\n return content;\n }\n\n return _(content);\n }\n\n /**\n * This add mutable observer to the body. It wait for DOM modifications,\n * and when any new node had been adder, or any phrase attribute had \n * been changed, then it trying to translate it.\n * \n * @returns {autotranslate} - This object to chain load.\n */\n connect() {\n if (this.is_connected) {\n return this;\n }\n\n const body = document.querySelector(\"body\");\n const callback = (targets) => { this.#process(targets); };\n const options = {\n childList: true,\n attributes: true,\n characterData: false,\n subtree: true,\n attributeFilter: [ autotranslate.get_attribute_name() ],\n attributeOldValue: false,\n characterDataOldValue: false\n };\n\n this.#observer = new MutationObserver(callback);\n this.#observer.observe(body, options);\n\n return this;\n }\n\n /**\n * This prcoess all given in the array mutable records. \n * \n * @param {Array} targets - Array with mutable records. \n */\n #process(targets) {\n targets.forEach(count => {\n if (count.type === \"attributes\") {\n this.#update_single(count.target);\n return;\n }\n\n this.#get_all_items(count.target).forEach(count => {\n this.#update_single(count);\n });\n });\n }\n\n /**\n * This disconnect observer, and remove it.\n * \n * @returns {autotranslate} - This object to chain loading.\n */\n disconnect() {\n if (!this.is_connected) {\n return this;\n }\n\n this.#observer.disconnect();\n this.#observer = null;\n return this;\n }\n\n /**\n * This update single element, based on phrase attribute. When element \n * is standard HTMLElement, then it place translated content into \n * innerText, but when element is input, like HTMLInputElement or\n * HTMLTextAreaElement, then it place result into placeholder. When\n * input is button, or submit, then it put content into value.\n * \n * @param {HTMLElement} target - Element to translate \n */\n #update_single(target) {\n const attrobute_name = autotranslate.get_attribute_name();\n const phrase = target.getAttribute(attrobute_name);\n const result = this.#translate(phrase);\n\n if (target instanceof HTMLInputElement) {\n if (target.type === \"button\" || target.type === \"submit\") {\n target.value = result;\n return;\n }\n \n target.placeholder = result;\n return;\n }\n\n if (target instanceof HTMLTextAreaElement) {\n target.placeholder = result;\n return;\n }\n\n target.innerText = result\n }\n\n /**\n * This update translation of all elements in the document. It is useable\n * when new autotranslator is created. \n * \n * @returns {autotranslate} - Instance of object to chain loading.\n */\n update() {\n this.#get_all_items().forEach(count => {\n this.#update_single(count);\n });\n\n return this;\n }\n}\n\nexports.autotranslate = autotranslate;", "\nconst languages = require(\"./languages.js\").languages;\nconst phrasebook = require(\"./phrasebook.js\").phrasebook;\nconst selector = require(\"./selector.js\").selector;\nconst autotranslate = require(\"./autotranslate.js\").autotranslate;\n\n/**\n * This class is responsible for saving and loading user language preferences\n * in the browser localStorage. It is not avairable, when using library in\n * the NodeJS enviroment.\n */\nclass preferences {\n /**\n * @var {languages}\n * This store loaded languages object.\n */\n #languages;\n\n /**\n * @var {?selector}\n * This store selector for preferences.\n */\n #selector;\n\n /**\n * @var {?autotranslate}\n * This store autotranslator, or null.\n */\n #autotranslate;\n\n /**\n * This create new language preferences manager from loaded languages\n * object.\n *\n * @throws {Error} - When trying to use it in NodeJS.\n * \n * @param {languages} target - loaded languages object.\n */\n constructor(target) {\n NODE: throw new Error(\"It could be used only in browser.\");\n this.#selector = null;\n this.#autotranslate = null;\n this.#languages = target;\n }\n\n /**\n * This return name of language key in localStorage.\n * \n * @returns {string} - Name of key in localStorage.\n */\n get #setting_name() {\n return \"cx_libtranslate_lang\";\n }\n\n /**\n * This return current saved language name, or null if any language\n * is not selected yet.\n * \n * @returns {?string} - Saved language or null.\n */\n get #state() {\n return localStorage.getItem(this.#setting_name);\n }\n\n /**\n * This return selector, which could being used in the ui.\n * \n * @returns {selector} - New UI selector of the languages.\n */\n get selector() {\n if (this.#selector !== null) {\n return this.#selector;\n }\n\n this.#selector = new selector(this.#languages)\n .set_selection(this.current)\n .add_listener(target => {\n this.update(target); \n })\n .add_listener(async target => { \n if (this.#autotranslate === null) {\n return;\n }\n\n this.#reload_autotranslate();\n });\n\n return this.#selector;\n }\n\n async #reload_autotranslate() {\n const connected = this.#autotranslate.is_connected;\n\n if (connected) {\n this.#autotranslate.disconnect();\n }\n\n this.#autotranslate = null;\n const created = await this.get_autotranslate();\n \n if (connected) {\n created.connect();\n }\n }\n\n /**\n * This load phrasebook for selected language, create autotranslate\n * for it, and returns it. Autotranslate is cached in this object.\n * \n * @returns {autotranslate} - Autotranslate for phrasebook.\n */\n async get_autotranslate() {\n if (this.#autotranslate !== null) {\n return this.#autotranslate;\n }\n\n const phrasebook = await this.load_choosen_phrasebook();\n this.#autotranslate = new autotranslate(phrasebook);\n this.#autotranslate.update();\n\n return this.#autotranslate;\n }\n\n /**\n * This save new selected language name to localStorage, or remove it \n * from there if null given.\n * \n * @param {?string} content - Name of selected language or null.\n */\n set #state(content) {\n if (content === null) {\n localStorage.removeItem(this.#setting_name);\n return;\n }\n\n localStorage.setItem(this.#setting_name, content);\n }\n\n /**\n * This return current language from localStorage. When any language is\n * not loaded yet, then return default language. It also check that value\n * value from localStorage, and if it not avairable in languages storage,\n * then also return default language.\n * \n * @return {string} - Name of the current language.\n */\n get current() {\n const saved = this.#state;\n\n if (saved === null) {\n return this.#languages.default;\n }\n\n if (this.#languages.has(saved)) {\n return saved;\n }\n\n return this.#languages.default;\n }\n\n /**\n * This load phrasebook for current selected language.\n * \n * @returns {phrasebook} - Phrasebook for current language.\n */\n async load_choosen_phrasebook() {\n return await this.#languages.select(this.current);\n }\n\n /**\n * This return loaded languages container.\n * \n * @returns {languages} - Languages container.\n */\n get languages() {\n return this.#languages;\n }\n\n /**\n * This set new language for user. It also check that language exists \n * in the language container. When not exists, throws error.\n * \n * @throws {Error} - When language not exists in container.\n * \n * @param {string} name - New language to select.\n * @returns {preferences} - This object to chain.\n */\n update(name) {\n DEBUG: if (!this.#languages.has(name)) {\n let error = \"Can not set language \\\"\" + name + \"\\\" \";\n error += \"because not exists in languages container.\";\n\n throw new Error(error);\n }\n\n this.#state = name;\n return this;\n }\n}\n\nexports.preferences = preferences;", "if (typeof(module) !== \"undefined\" && module.exports) {\n /* Load for NodeJS */\n module.exports.phrasebook = require(\"./phrasebook.js\").phrasebook;\n module.exports.loader = require(\"./loader.js\").loader;\n module.exports.languages = require(\"./languages.js\").languages;\n module.exports.loader = require(\"./loader.js\").loader;\n module.exports.preferences = require(\"./preferences.js\").preferences;\n module.exports.selector = require(\"./selector.js\").selector;\n module.exports.autotranslate = require(\"./autotranslate.js\").autotranslate;\n} else {\n /* Load for web browser */\n window.cx_libtranslate = {\n phrasebook: require(\"./phrasebook.js\").phrasebook,\n loader: require(\"./loader.js\").loader,\n languages: require(\"./languages.js\").languages,\n translation: require(\"./translation.js\").translation,\n preferences: require(\"./preferences.js\").preferences,\n selector: require(\"./selector.js\").selector,\n autotranslate: require(\"./autotranslate.js\").autotranslate\n };\n}\n"], "mappings": "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", "names": ["languages", "selector", "phrasebook", "count", "phrasebook"] }