const languages = require("./languages.js").languages; const phrasebook = require("./phrasebook.js").phrasebook; const selector = require("./selector.js").selector; const autotranslate = require("./autotranslate.js").autotranslate; /** * This class is responsible for saving and loading user language preferences * in the browser localStorage. It is not avairable, when using library in * the NodeJS enviroment. */ class preferences { /** * @var {languages} * This store loaded languages object. */ #languages; /** * @var {?selector} * This store selector for preferences. */ #selector; /** * @var {?autotranslate} * This store autotranslator, or null. */ #autotranslate; /** * This create new language preferences manager from loaded languages * object. * * @throws {Error} - When trying to use it in NodeJS. * * @param {languages} target - loaded languages object. */ constructor(target) { NODE: throw new Error("It could be used only in browser."); this.#selector = null; this.#autotranslate = null; this.#languages = target; } /** * This return name of language key in localStorage. * * @returns {string} - Name of key in localStorage. */ get #setting_name() { return "cx_libtranslate_lang"; } /** * This return current saved language name, or null if any language * is not selected yet. * * @returns {?string} - Saved language or null. */ get #state() { return localStorage.getItem(this.#setting_name); } /** * This return selector, which could being used in the ui. * * @returns {selector} - New UI selector of the languages. */ get selector() { if (this.#selector !== null) { return this.#selector; } this.#selector = new selector(this.#languages) .set_selection(this.current) .add_listener(target => { this.update(target); }) .add_listener(async target => { if (this.#autotranslate === null) { return; } this.#reload_autotranslate(); }); return this.#selector; } async #reload_autotranslate() { const connected = this.#autotranslate.is_connected; if (connected) { this.#autotranslate.disconnect(); } this.#autotranslate = null; const created = await this.get_autotranslate(); if (connected) { created.connect(); } } /** * This load phrasebook for selected language, create autotranslate * for it, and returns it. Autotranslate is cached in this object. * * @returns {autotranslate} - Autotranslate for phrasebook. */ async get_autotranslate() { if (this.#autotranslate !== null) { return this.#autotranslate; } const phrasebook = await this.load_choosen_phrasebook(); this.#autotranslate = new autotranslate(phrasebook); this.#autotranslate.update(); return this.#autotranslate; } /** * This save new selected language name to localStorage, or remove it * from there if null given. * * @param {?string} content - Name of selected language or null. */ set #state(content) { if (content === null) { localStorage.removeItem(this.#setting_name); return; } localStorage.setItem(this.#setting_name, content); } /** * This return current language from localStorage. When any language is * not loaded yet, then return default language. It also check that value * value from localStorage, and if it not avairable in languages storage, * then also return default language. * * @return {string} - Name of the current language. */ get current() { const saved = this.#state; if (saved === null) { return this.#languages.default; } if (this.#languages.has(saved)) { return saved; } return this.#languages.default; } /** * This load phrasebook for current selected language. * * @returns {phrasebook} - Phrasebook for current language. */ async load_choosen_phrasebook() { return await this.#languages.select(this.current); } /** * This return loaded languages container. * * @returns {languages} - Languages container. */ get languages() { return this.#languages; } /** * This set new language for user. It also check that language exists * in the language container. When not exists, throws error. * * @throws {Error} - When language not exists in container. * * @param {string} name - New language to select. * @returns {preferences} - This object to chain. */ update(name) { DEBUG: if (!this.#languages.has(name)) { let error = "Can not set language \"" + name + "\" "; error += "because not exists in languages container."; throw new Error(error); } this.#state = name; return this; } } exports.preferences = preferences;