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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dgayerie/tr

v1.1.0

Published

A lightweight library to support i18n

Downloads

132

Readme

tr - A lightweight i18n library for JavaScript

tr is a minimalistic module to handle internationalization in JavaScript. The module provides tr which can be used as a function or a tag function of template literals.

As a function, dynamic parameters can be indicated in the template string with the expression ${}.

import tr from '@dgayerie/tr';

const w = "world";

const translation = tr("Hello the ${}", w);

As a tag function, you can use template parameters as usual:

import tr from '@dgayerie/tr';

const w = "world";

const translation = tr`Hello the ${w}`;

Installation

npm install @dgayerie/tr

Configuring translations

You use the function tr.addTranslations to provide new translations. This function expects an object as parameter. Each key of the object is a template string and the value is the translated message:

tr.addTranslations({
    "hello": "bonjour",
    "hi": "salut"
});

// prints "bonjour"
console.log(tr("hello"));

// prints "bonjour"
console.log(tr`hello`);

You can specify dynamic parameters in the template string and the translation with the expression ${}.

tr.addTranslations({
    "hello ${}": "bonjour ${}"
});

// prints "bonjour john"
console.log(tr("hello ${}", "john"));

// prints "bonjour john"
const name = "john";
console.log(tr`hello ${name}`);

Changing order of the dynamic arguments

If the order of the arguments is not the same in the translated expression, you can specify explicitly the position of the dynamic arguments:

tr.addTranslations({
    "total amount ${}${}": "montant total ${1}${0}"
});

// prints "montant total 2400$"
console.log(tr`total amount ${'$'}${24*100}`);

You can even repeat the same argument several times in the translation:

tr.addTranslations({
    "repeat twice ${}": "${0} ${0}"
});

// prints "zoo zoo"
console.log(tr`repeat twice ${'zoo'}`);

Support for plural form

You can provide an array for the translation. This is useful to support plural form.

tr.addTranslations({
    "${} items": [
        "no item",
        "1 item",
        "${} items"
    ]
});

// prints "no item"
console.log(tr`${0} items`);

// prints "1 item"
console.log(tr`${1} items`);

// prints "42 items"
console.log(tr`${42} items`);

If the dynamic argument is a number, its value will be used to select the correct translation.

You are not limited to numbers, for instance you can also use boolean values:

tr.addTranslations({
    "this proposal is ${}": [
        "cette proposition est fausse",
        "cette proposition est vraie"
    ]
});

// prints "cette proposition est vraie"
console.log(tr`this proposal is ${true}`);

If your template string contains several dynamic arguments, you can use the # sign to indicate which one will be used to determine the plural form (by default, the first one is used):

tr.addTranslations({
    "${}: ${#} items": [
        "${}: no item",
        "${}: 1 item",
        "${}: ${} items"
    ]
});

// print "Ref0001: no item"
console.log(tr`${'Ref0001'}: ${0} items`);

Support for formatters

You can register formatters to be able to use them in translations.

A formatter is either:

  • an object having a method named format. This method will receive the value of the dynamic argument as parameter and will return the formatted value.
  • a function that will receive the value of the dynamic argument as parameter and will return the formatted value.

Intl.NumberFormat and Intl.DateTimeFormat are compliant because the instances have a method named format.

Use the function tr.addFormatters to add new named formatters:

tr.addFormatters({
    'euros': new Intl.NumberFormat('en', { style: 'currency', currency: 'EUR' })
});

tr.addTranslations({
    '${} euros': '${0:euros}'
})

// prints "€1,000.00"
console.log(tr`${1000} euros`);
tr.addFormatters({
    'upper': s => s.toUpperCase()
});

tr.addTranslations({
    'Important: ${}': 'Important: ${0:upper}'
})

// prints "Important: MIND THE GAP"
console.log(tr`Important: ${'mind the gap'}`);

You can reference your formatter in the translation after the position of the dynamic argument by using the separator :. If you omit the position of the dynamic parameter, you still have to specify the separator:

tr.addTranslations({
    '${} euros': '${:euros}'
})

Loading from the configuration

You can call the function tr.load to load a complete configuration at one time including translations and formatters.

tr.load waits for an object as parameter with the following properties:

  • translations: the translations
  • numberFormats: the named formatters that will be converted to Intl.NumberFormat
  • dateTimeFormats: the named formatters that will be converted to Intl.DateTimeFormat
tr.load({
    'locales': 'en',
    'numberFormats': {
        'dollars': { style: 'currency', currency: 'USD' }
    },
    'dateTimeFormats': {
        'simpleDate': { dateStyle: 'medium' }
    },
    'translations': {
        'amount ${}': '${:dollars}',
        'date ${}': '${:simpleDate}'
    }
});

A call to tr.load does not invalidate previous translations or formatters. It will add new ones or replace the ones with the same name.

To completely remove translations and formatters previously added, you must call tr.clear().

tr.clear()

Tips and guidelines

tr is a versatile library. There is no strict rule to define keys for translation. By default, if no translation is available, tr will simply returns the formatted values passed as parameters. So I recommend you to define keys in a human spoken language. This way, the messages will remain understandable even if no translation is provided.

// prints 'hello John' if no translation is available
console.log(tr`hello ${'John'}`);

But you can also use message identifier. tr does not expect the variable arguments to be part of the message identifier when you use tr as a function.

tr.addTranslations({
    'message.hello': 'hello ${}'
});

// prints 'hello John'
console.log(tr('message.hello', 'john'));

Even if you do not want to translate your messages to other languages, you can use tr as a simple formatting library:

tr.addFormatters({
    'upper': s => s.toUpperCase()
});

tr.addTranslations({
    'upper:${}': '${0:upper}'
})

// prints "A VERY IMPORTANT MESSAGE"
console.log(tr`upper:${'a very important message'}`);