| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- const loader = require("./loader.js").loader;
- const phrasebook = require("./phrasebook.js").phrasebook;
- /**
- * This class represents languages library. This store its location on the
- * server, and create loaders for them. It could also load langiage
- * library from json file.
- */
- class languages {
- /**
- * @var {string}
- * This represents path to directory where phrasebooks had been stored.
- */
- #path;
- /**
- * @var {Map}
- * This store languages and its files on server.
- */
- #libs;
- /**
- * @var {bool}
- * This store that directory is in the local file system, or remote
- * server. When true, resources would be loaded by node:fs. When
- * false, resources would be fetched.
- */
- #local;
- /**
- * This create new languages library. Next, languages could be added to
- * the library by command, or by loading index file.
- *
- * @throws {TypeError} - When parameters is not in correct format.
- *
- * @param {string} path - Path to phrasebooks on the server or filesystem.
- * @param {bool} local - True when phrasebooks dirs would be loaded by
- * node:fs module. False when would be fetch.
- */
- constructor(path, local = false) {
- if (typeof(path) !== "string") {
- throw new TypeError("Path to the phrasebooks must be string.");
- }
- if (typeof(local) !== "boolean") {
- throw new TypeError("Local must be bool variable.");
- }
- this.#local = local;
- this.#path = path;
- this.#libs = new Map();
- }
- /**
- * This add new language to the library by name. Name must be in form
- * like POSIX locale, like en_US, or pl_PL. That mean first two letter
- * mest be ISO 639-1 and second two letters mst be in ISO 3166-1 alpha-2
- * 2 letter country code format.
- *
- * @see https://www.loc.gov/standards/iso639-2/php/code_list.php
- * @see https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
- * @see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
- * @see https://en.wikipedia.org/wiki/Locale_(computer_software)
- *
- * @throws {TypeError} - When tpes of the parameters is not correct.
- *
- * @param {string} name - Name of the language, like "en_US".
- * @param {string} file - Name of the file in the directory.
- * @return {languages} - Instnace of this class to chain.
- */
- add(name, file) {
- if (typeof(name) !== "string") {
- throw new TypeError("Name of the language must be sting.");
- }
- if (typeof(file) !== "string") {
- throw new TypeError("File on in the directory must be string.");
- }
- if (this.#libs.has(name)) {
- console.error("Language \"" + name + "\" already loaded.");
- console.error("It could not being loaded twice.");
- return this;
- }
- if (!this.#valid_locale(name)) {
- console.error("Language name \"" + name + "\" invalid formated.");
- console.error("It could not being loaded.")
- return this;
- }
-
- this.#libs.set(name, file);
- return this;
- }
- /**
- * This load all phrasebook given in the index file. Index must be
- * JSON file, which contain one object. That object properties must be
- * languages names in the notation like in add function. Valus of that
- * properties musts being strings which contains names of the phrasebook
- * files in the path directory.
- *
- * @example ``` { "pl_PL": "polish.json", "en_US": "english.json" } ```
- *
- * @see add
- *
- * @param {string} index - Index file in the phrasebook directory.
- * @return {languages} - New languages instance with loaded index.
- */
- async load(index) {
- if (typeof(index) !== "string") {
- throw new TypeError("Name of index file is not string.");
- }
- const response = await this.#load_index(index);
- const result = new languages(this.#path, this.#local);
-
- Object.keys(response).forEach(name => {
- if (typeof(name) !== "string") {
- console.error("Name of the language must be string.");
- console.error("Check languages index.");
- console.error("Skipping it.")
- return;
- }
- if (typeof(response[name]) !== "string") {
- console.error("Name of phrasebook file must be string.");
- console.error("Check languages index.");
- console.error("Skipping it.");
- return;
- }
- result.add(name, response[name]);
- });
- return result;
- }
- /**
- * This load index object. That check, and when content must be loaded
- * from local filesystem, it use node:fs, or when it must be fetched from
- * remote, then use fetch API.
- *
- * @param {string} index - Name of the index file in library.
- * @returns {object} - Loaded index file content.
- */
- async #load_index(index) {
- const path = this.#full_path(index);
- if (this.#local) {
- let fs = null;
- NODE: fs = require("node:fs/promises");
-
- if (fs === null) {
- throw new Error("Could not use ndoe:fs in browser.");
- }
- return JSON.parse(
- await fs.readFile(path, { encoding: "utf-8" })
- );
- }
- const request = await fetch(path);
- return await request.json();
- }
- /**
- * This check that language exists in languages library.
- *
- * @param {string} name - Name of the language to check.
- * @return {bool} - True when language exists, false when not
- */
- has(name) {
- return this.#libs.has(name);
- }
- /**
- * This return all avairable languages.
- *
- * @return {Array} - List of all avairable languages.
- */
- get avairable() {
- const alls = new Array();
- this.#libs.keys().forEach(name => {
- alls.push(name);
- });
- return alls;
- }
- /**
- * This load phrasebook with give name.
- *
- * @throws {TypeError} - Param type is not correct.
- * @throws {RangeError} - Language not exists in libs.
- *
- * @param {string} name - Name of the language to load.
- * @returns {phrasebook} - Phrasebook loaded from the file.
- */
- select(name) {
- if (typeof(name) !== "string") {
- throw new TypeError("Name of the language must be string.");
- }
- if (!this.has(name)) {
- DEBUG: throw new RangeError(
- "Not found language \"" + name + "\"."
- );
- return new phrasebook(new Map());
- }
-
- const file = this.#libs.get(name);
- const path = this.#full_path(file);
- return new loader(path, this.#local).load();
- }
- /**
- * This return full path to the file.
- *
- * @param {string} name - Name of the file to get its path
- * @return {string} - Full path of the file
- */
- #full_path(name) {
- let glue = "/";
- if (this.#path[this.#path.length - 1] === glue) {
- glue = "";
- }
- return this.#path + glue + name;
- }
- /**
- * This check that format is valid POSIX like locale.
- *
- * @param {string} name - Name to check format of.
- * @return {bool} - True when format is valid, false when not.
- */
- #valid_locale(name) {
- const splited = name.split("_");
- if (splited.length !== 2) {
- return false;
- }
- const first = splited[0];
- const second = splited[1];
- if (first.toLowerCase() !== first || first.length !== 2) {
- return false;
- }
- if (second.toUpperCase() !== second || second.length !== 2) {
- return false;
- }
- return true;
- }
- }
- exports.languages = languages;
|