npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

translite

v2.1.0

Published

Small no-db translation library supporting controlled contexts, versioning and plural forms.

Downloads

27

Readme

translite

Small no-db translation library for js, supporting controlled contexts and versioning.

Synopsis

import { getTr, setLanguage, getLanguage } from 'translite';

let pages = {
  form: {
    'This-field-is-required': {
      v: 1,
      en_1: 'This field is required',
      es_0: 'Este campo es obligatorio',
    },

    light: {
      v: 1,
      en_1: 'light',
      es_1: 'ligero',
    },
  },

  welcome: {
    'Hi-user': {
      v: 1,
      en_1: 'Hi ${c.userName}!',
      es_1: 'Hola ${c.userName}!',
    },

    light: {
      v: 1,
      en_1: 'light',
      es_1: 'luz',
    },
  },
};

// Translate identifier to english
setLanguage('en');
let { tr: tr } = getTr(pages['form']);
console.log(tr('This-field-is-required')); // "This field is required"

// Translate identifier to spanish
setLanguage('es');
let { tr: tr } = getTr(pages['form']);
console.log(tr('This-field-is-required')); // "Este campo es obligatorio"

// Translate using context
setLanguage('en');
let { tr: tr, context: context } = getTr(pages['welcome']);
context['userName'] = 'Maximilia';
console.log(tr('Hi-user')); // "Hi Maximilia!"

// Pass in a context
setLanguage('en');
let { tr: tr, context: context } = getTr(pages['welcome'], {
  context: { userName: 'Juan' },
});
console.log(tr('Hi-user')); // "Hi Juan!"

// Mark outdated translation as broken
setLanguage('es');
let { tr: trEs } = getTr(pages['form'], {
  markBroken: function (x) {
    return '??' + x + '??';
  },
});
console.log(trEs('This-field-is-required')); // "??Este campo es obligatorio??"

Features

Below we'll describe the features of this translation library. The examples in the synopsis help to clarify how these features are used. The input to the translation function is a string that we call the "identifier". The output is the translation of the identifier into the selected language. In other words: if you target English as one of the output languages, then you will write an English translation for each identifier. Note that the identifier itself is never used as a translation. My personal preference is to create identifiers by concatenating the first words of the english translation, e.g. "Welcome-to-this-webpage". Of course, you can also use regular english words and sentences as the identifier, but the use of hyphens or underscores makes it clear that it's only used as an input.

No database: all translations are grouped in javascript dictionaries

The use of javascript files for storing the translations allows you to manage the translations and source code together in source control. Typically you should declare multiple translation dictionaries: one for each group of related translations. Think of the group as the usage context: depending on the context, an ambiguous word such as "light" can have a different translation:

```javascript
import { pages } from 'translations'
import { getTr, setLanguage } from 'translite'

setLanguage('es');

let {tr: tr, context: context} = getTr(groups['form']);
// outputs: 'ligero'
console.log(tr('light'))

let {tr: tr2, context: context2} = getTr(group['welcome']);
// outputs: 'luz'
console.log(tr2('light'))
```

Translations are not split per language

Each group (mentioned above) contains the translation of the identifier into all the target languages. This helps to ensure that all the translations carry the same meaning. In addition, having all the translations together makes it easier to find translations that are no longer up-to-date.

Identifiers and their translations have a version number

If the identifier and the translation are at the same version number, then the translation is up-to-date. Note that it's possible for none of the translations to be up-to-date. It's future work to create a tool that automatically flags all translations that are not up-to-date. In the example translations at the bottom of this text, the This-field-is-required identifier is at version 1, as is the english translation, but the spanish translation is lagging behind.

Translations can refer to a context dictionary

The translation of the Hi-user identifier uses the ${c.userName} placeholder. This values comes from the provided context dictionary:

```javascript
let {tr: tr, context: context} = getTr(groups['welcome']);
context['userName'] = 'Maximilia'
// outputs: Hi Maximilia!
console.log(tr('Hi-user'))
```

You can initialize the context as follows:

```javascript
const myContext = {
  userName: 'Juan'
};
let {tr: tr} = getTr(groups['welcome'], {context: myContext});

// outputs: Hi Juan!
console.log(tr('Hi-user'))
```

Spot broken translations

If you supply a markBroken function in the options, then this function will be used to transform the translation output into something that is more easily recognizable as an outdated translation. For example:

```javascript
let {tr: tr} = getTr(groups['welcome'], {
  markBroken: function(x) {return "___" + x + "___"}
});

// outputs: ___Este campo es obligatorio___
console.log(tr('This-field-is-required'))
```

Note: for legacy reasons, it's also supported to set markBroken: true in the options. In this case, broken translations will be shown as !<translated>!.