evalocale

1.0.5 • Public • Published

Evalocale

A library for Node.js and browsers to facilitate dynamic loading of texts in different languages.

Key features

  • Node CLI
  • live binding of a source file
  • mustache-like wildcards
  • Node.js + web apps
  • best-fit language lookup
  • Intl module implementation through various formatters
  • metadata support
  • CSV import/export (consider user Edit csv extension for seamless production if you use VSCode)
  • hands-on Express middleware and pug template

Install

Node.js package instalation:

npm install evalocale

Browser webpack compiled package installation:

<script src="./src/evalocale.min.js">

Getting started

  1. install the package

    npm i evalocale
  2. generate a source file from the CLI

    npx evalocale create -t 100 -m description:string -l en-GB -l es-ES -f csv -n my-words
  3. Add some data to the file

    Add some data to the source file. I find it more user-friendly to use CSV, to which you can install a GUI for your IDE (eg VSCode), but JSON is alright as well. Use {{...custom content}} for dynamic rendering. Wel'll use the example bellow (rendered CSV).

    _id description en-GB es-ES
    47fmJvio welcome Welcome to my site Bienvenido a mi sitio
    uz8PLDtd greeting Hello {{who}} Hola {{who}}
    oOALYYgl human entity human Hombre
    sn25hwRS
    boqkshPL
    rMgVzDXZ
    903lnKPJ
    LgR0Hgnn
    6gMViF4p
    3BRnGImO
    iBdr6oZI
  4. initialize evalocale instance and bind the file

    var evalocale = require("evalocale");
    var $$ = evalocale().bind("./my-words.csv");
    //optionally set the default language
    $$.set("en-GB");
    
  5. go for it!

    console.log($$("47fmJvio")); // "Welcome to my site" (en-GB is set as default);
    console.log($$("uz8PLDtd", {who: "John Doe"}, "es")); // "Hola John Doe"
    console.log($$("uz8PLDtd", {who: $$("oOALYYgl", "es")}, "es")); // "Hola Hombre"
    console.log($$("uz8PLDtd", {who: $$("oOALYYgl")})); // "Hello human"

Basic usage

Evalocale is a plain function with three arguments:

  • code: an id of a concrete text stored in a dictionary
  • data: on object of key-value pairs storing dynamic content for the text
  • language: optionally you may override the global language property of the function - overriding the language is appropriate if one instance is used by multiple clients, e.g. on an HTTP server

Node.js

var $$ = require("evalocale")().set("en-Gb", {"a1b2c3d4": "This is {{quality}} library."});
console.log($$("a1b2c3d4", {quality: "an ugly"}));

CLI

npx evalocale generate -t 500 -c 8 -m '["id", "description"]' -f csv -n myEvalocaleLibrary

Browser

var $$ = window.evalocale().set("en-Gb", {"a1b2c3d4": "This is {{quality}} library."});
console.log($$("a1b2c3d4", {quality: "an ugly"}));

The root function takes two arguments: text code and data object (optional). The data object serves as a container for replacing wildcards, express as {{wildcard}} in a dictionary record (see an example of quality above).

Setting content

Most of the necessary service configuration is possible using the flexible set method. It consumes different types and amounts of arguments, while if only one argument is specified, then the language is set if it is a string type, or if it is an object, the configuration of the evalocale environment is performed. If two arguments (or an even number of arguments) are specified, then the odd argument is taken as a language abbreviation and the even argument as an object with dictionary data. In all cases, the root function evalocale is returned.

The set method always returns the root function.

Setting a single dictionary

$$.set("en-Gb", {"a1b2c3d4": "This is {{quality}} library."});

Setting multiple dictionaries

An even number of arguments indicates that this is a series of name/date pairs. Note that dictionaries have different argument lengths; they can be synchronized later (see below).

$$.set("cs-CZ", {
        "a1b2": "Jmenuji se {{name}}.",
        "c3d4": "Je mi {{age}} let."
    }, "en-GB", {
        "a1b2": "My name is {{name}}.",
        "c3d4": "I am {{age}}.",
        "e5f6": "I am a developer."
});

Setting content by loading a bundle

A bundle is a sort of serializied underlying data, including library, metadata etc. If the first (and one and only) argument is object and contains property library, it is considered to be a bundle.

let bundle = {"library":{"cs-CZ":{"a1b2":"Jmenuji se {{name}}.","c3d4":"Je mi {{age}} let.","e5f6":""},"en-GB":{"a1b2":"My name is {{name}}.","c3d4":"I am {{age}}.","e5f6":"I am a developer."}},"metadata":{"a1b2":{"app":"retusa","version":1},"c3d4":{"app":"retusa","version":1},"e5f6":{"app":"retusa","version":1}},"language":"en-GB"};
$$.set(bundle);

You may also directly load the bundle by the load method:

$$.load(bundle);

Setting an active language

Setting the active language can be done in several ways, all of which have the same effect:

// by means of the set method
$$.set("en-GB");
// by language getter
$$.language = "en-GB";
// by switch method
$$.switch("en-GB");

Configuration

Many configuration methods might be called by the set method as well as by means of direct methods. While using the set method for configuration, mind that the configuration cannot be mixed with dictionary data.

$$.set({
    metadata: {version: 1, group: "A"},
    sync: true
});

Sequential calling of set methods:

let bundle = {"library":{"cs-CZ":{"a1b2":"Jmenuji se {{name}}.","c3d4":"Je mi {{age}} let.","e5f6":""},"en-GB":{"a1b2":"My name is {{name}}.","c3d4":"I am {{age}}.","e5f6":"I am a developer."}},"metadata":{"a1b2":{"app":"retusa","version":1},"c3d4":{"app":"retusa","version":1},"e5f6":{"app":"retusa","version":1}},"language":"en-GB"};
var config = {
    metadata: {version: 1, group: "A"},
    sync: true}
$$.set(bundle).set(config).set("en-GB")("a1b2", {name: "John Doe"});

Methods

method description argument argument property type required default argument role
alias Sets the alias(es) for a particular language and returns itself. nameOrAlias String true Specifies the key under which the entire dictionary is stored (typically, e.g. en-GB).
resolver String / Array / Function [] The resolver is used to compare aliases with the dictionary's own key. It can be a string (eg "en"), an array (eg ["en", "en-GB", "en-US"]) or a function (eg (value) => value.substr(0, 2) == "en").
clean Deletes entries with an empty value from dictionaries. Deletion can be done in two ways. If the separate argument is true, it deletes all empty entries from each dictionary (regardless of whether the same entry in another dictionary is not empty). If false, deletes only those records that are empty across all dictionaries. separate boolean false false If true, removes blank entries in each dictionary regardless of value of the same key in other dictionaries. If false (default), removes only entries with keys of empty value across all dictionaries.
closest Returns the key of a dictionary that is closest to the specified value. If no similar language is found, returns either the default or the system language. what String / Object true Either a string (eg "en-NZ") or an object (eg {code: "en", region: "NZ", script: "en"})
create Appends N new records to each dictionary. Metadata ignored so far length UInt false 1 Number (N) of records to be generated.
chars UInt false - The length of a key. If not specified, either average length of existing keys is calculated, or (if no records exists) is set to 8.
deriveMetadata Generates (or updates) a metadata objec for existing dictionaries. schema Object / Array false {} Specifies the metadata structure.
fromArray Populates the underlying data with an array of key/value pairs, including languages and metadata. arr Array true An array containing the library/metadata values.
config languages Array false null Defines languages present in the arr argument. If empty, the methods tries to identify the languages on its own.
fromCSV Populates the underlying data with a CSV style text. It is suggested to use default CSV settings to avoid errors. content String true A CSV file as a string.
config languages Array false null Defines languages present in the arr argument. If empty, the methods tries to identify the languages on its own.
delimiter String false "\t" Defines the cell delimiter.
generate Generates an entires bundle, containg dictionaries config object total false 1 defines how many elements in each dictionary should be created
chars UInt false 8 defines the lenght of a generated key
language String / Array false 8 Defines the dictionaries to be generated. It can either be a string or an array of strings representing the language i18n code (e.g. en-GB)
metadata Object / Array false {} If not undefined, specifies the schema of metadata; the metadata object is generated with every generated key and a value represented by the schema
load Loads the entire bundle of data, including the library, metadata etc. A workaround for the set method with one object-type argument. bundle library Object false {} Specifies the library element.
metadata Object false {} Specifies the metadata element.
language String false undefined Specifies an active language
save A counterpart of the load method that exports the underlying data. See load for output structure.
set see Setting content.
sync Extends the keys of all language libraries so that they all have the same keys. Ignores existing keys and adds only those that are missing from the given library. writeValues boolean false false If true, assign a non-empty found value for the key from another language where a value is non-empty.
toCSV Converts the underlying library and metadata to a single CSV formatted string.
toArray Converts the underlying library and metadata to a single Array of key/value pair objects.

Examples

Setting language aliases

It makes sense to use some dictionaries for multiple languages (or a combination of languages and regions, e.g. en-GB to be used for en-US, etc.). The alias method makes it possible to extend the validity of the dictionary for other regions or languages, using the so-called resolver.

// define the library content
// then create an aliases
$$.alias("en-GB", ["en-US", "en-AU", "en-BZ"]);
$$("someCode", {}, "en-AU"); // => returns a resut for en-GB
$$("someCode", {}, "en-NZ"); // => returns an empty string as no alias is mathcing
//this might get too long, so better like this:
$$.alias("en-GB", (langCode) => langCode.substr(0,2) == "en");
$$("someCode", {}, "en-XXX"); // => returns a resut for en-GB
//even a single resolver as a alias string might be used:
$$.alias("en-GB", "en-US");
$$("someCode", {}, "en-US"); // => returns a resut for en-GB

Properties

Properties can be get/set by means plain getter/setter, or eventualy by the set method (see bellow). Only method marked "both" can be configured via the set method.

property description type read/write
alertsOn Turns on/off console.warn messages. It is recommend to use alertsOn in the development mode to watch possible drawbacks. boolean both
system Gets the environment language. The value is extracted differently for Node.js and browser environment. String read
default Gets or sets the active language. String both
length Gets the number of entries in the dictionary with the most entries from all dictionaries. Overrides the length property of the base. UInt read
library Gets or sets the underlying library package, containg all the dictionaries. Object both
metadata Get or sets the underlying metadata package. Object both

The two examples below have the same effects.

Configuration by properties

$$.alertsOn = false;
$$.default = "en-GB";

Configuration by set method

$$.set({
    alertsOn: false,
    default: "en-GB"
});

Utils

Generator

Instead of generating unique keys, it is easier to let the job up to the package. Calling the root method generate creates a required language(s) and items. See methods for further information.

var $$ = require("evalocale").generate({total: 500, chars: 8, language: ["en-GB", "cs-CZ"], metadata: {app: "someApp"}});

You can call the generate function without arguments. Default values are

  • total: 1
  • chars: default hash length (8 as of July 2023)
  • language: the system property value (local system language)
var $$ = require("evalocale").generate();

Formatters

The Intl module allows flexible formatting of numbers and data in many languages. Evalocale supports simplified calls for several common user requests. In addition, however, you can use the functions of the Intl module as you wish. The last argument, language, is optional, in case you want to override the global language property.

| method |

  • number(value, decimals, language): converts a number to a locale string; if decimals are not specified, they are set to auto
  • currency(value, currency, language): converts a number to a locale currency string; the currency code is checked against the list of acceplable currency codes (is not case sensitive)
  • time(value, short=false, language): converts a date instance to time string; if short (default false) is set to true, returns only hours and minutes, otherwise hh:mm:ss
  • date(value, short=false, language): converts a date instance to date string; if short (default false) is set to true, returns only hours and minutes, otherwise hh:mm:ss
  • diff(thisTime, thatTime, language): return a humanized time span between the two dates; the unit is automatically guessed from the size of the difference
$$.number(65423.12);
$$.number(65423.12, 3);
$$.currency(15000, "EUR");
$$.time(new Date());
$$.time(new Date(), true);
$$.date(new Date());
$$.date(new Date(), true);
$$.diff(new Date("2023-07-01"),new Date("2023-07-07"));

Extension

Humanize language code

To render language code in its native or other language, use String prototype extension getLanguage(target).

// If the target argument is empty, the language code itself is taken as the target language.
var native = "cs-CZ".getLanguage(); // => čeština;
// Now the same language but in English
var native = "cs-CZ".getLanguage("en"); // => Czech

Package Sidebar

Install

npm i evalocale

Weekly Downloads

1

Version

1.0.5

License

ISC

Unpacked Size

175 kB

Total Files

12

Last publish

Collaborators

  • muzikp