handlebars-i18n
v1.10.4
Published
handlebars-i18n adds internationalization to handlebars.js using i18next and Intl.
Downloads
66,988
Maintainers
Readme
handlebars-i18n
What it is about: handlebars-i18n adds the translation features of i18next
to handlebars.js. It also provides date, number, and currency formatting
via Intl. Use as node module or in the web browser. handlebars-i18n is listed amongst i18next’s official framework helpers.
Key Features & Advantages
- handlebars-i18n comes lightweight, well tested, and with detailed examples
- allows granular custom presets per language
- supports Typescript
- has an optional CLI for automatic Translations via DeepL
Please Support
handlebars-i18n is free but not free of value. If you make serious use of handlebars-i18n, I’d be delighted if you
Install
npm i handlebars-i18nImport
Import with ES6 syntax:
import HandlebarsI18n from "handlebars-i18n";
HandlebarsI18n.init();As commonJS within node environment:
const HandlebarsI18n = require("handlebars-i18n");
HandlebarsI18n.init();Usage in web browser (old school):
<script src="handlebars.js"></script>
<script src="i18next.js"></script>
<script src="handlebars-i18n.js"></script>
<script>
HandlebarsI18n.init()
</script>Via CDN:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/handlebars-i18n.min.js"></script>Quick Example
Initialize i18next with your language strings and default settings:
const i18next = require("i18next");
i18next.init({
resources: {
"en": {
translation: {
"phrase1": "What is good?",
"phrase2": "{{thing}} is good."
}
},
"de": {
translation: {
"phrase1": "Was ist gut?",
"phrase2": "{{thing}} ist gut."
}
}
},
lng: "en",
compatibilityJSON: 'v2'
});Set your Handlebars.js data object:
let data = {
myItem: "handlebars-i18n",
myPrice: 1200.99,
myDate: "2020-03-11T03:24:00"
}Initialize handlebars-i18n:
HandlebarsI18n.init();Optionally configure your language specific number, currency, and date-time defaults:
HandlebarsI18n.configure([
["en", "PriceFormat", {currency: "USD"}],
["de", "PriceFormat", {currency: "EUR"}]
]);Finally use in template:
<p> {{__ "phrase1"}} </p>- output: en → What is good? | de → Was ist gut?
<p> {{__ "phrase2" thing=myItem}} </p>- output: en → handlebars-i18n is good. | de → handlebars-i18n ist gut.
<p> {{_date myDate}} </p>- output: en → March 11, 2020 at 3:24 AM | de → 11.3.2020, 03:24
<p> {{_price myPrice}} </p>- output: en → $1,200.99 | de → 1.200,99 $
Detailed Examples
:point_right: See the examples folder in the repo for more use cases and details.
- Open
examples/browser-example/index.htmlin your web browser to see an implementation with a simple UI. - Prompt
npm run example:jsfrom the root of this repo to log a very basic node example to console. - Prompt
npm run example:tsto compile and log a typescript example.
Additional CLI Helper for Handlebars-i18n available
:metal: handlebars-i18n has its own command line
interface handlebars-i18n-cli.
npm i handlebars-i18n-cli --save-dev- programmatically extract/ update translation strings from handlebars templates and generate i18next conform JSON files from it
- automatic translation of i18next JSON via DeepL’s free API
Template Functions
__
Returns the phrase associated with the given key for the selected language. __ will take all options
i18next’s t-function would take.
The key can be passed hard encoded in the template when written in quotes:
{{__ "keyToTranslationPhrase"}}… or it can be referenced via a handlebars variable:
{{__ keyFromHandlebarsData}}Variable Replacement
Template usage:
{{__ "whatIsWhat" a="Everything" b="fine"}}The i18next resource:
"en" : {
translation : {
"whatIsWhat" : "{{a}} is {{b}}."
}
}- output: en → Everything is fine.
Plurals
{{__ "keyWithCount" count=8}}"en" : {
translation : {
"keyWithCount" : "{{count}} item",
"keyWithCount_plural" : "{{count}} items"
}
}, ...Override the globally selected language
{{__ "key1" lng="de"}}Will output the contents for de even though a different language is globally set.
Looping over an array (or object) of translations
<ul>
{{#each (__ "fruits")}}
<li>{{this}}</li>
{{/each}}
</ul>In this case the key fruits would contain an array of translation strings, like:
{
en: {
translation: {
fruits: ["Apple", "Banana", "Cherry"]
}
},
returnObjects: true
}It is recommended to set returnObjects actively to true in the i18next.init object if you want to loop over
an array or objects of properties.
keyExists
Checks if a i18next translation key exists. Returns true or false.
{{#if (keyExists "myKey")}} {{__ "myKey"}} {{/if}}_locale
Returns the shortcode of i18next’s currently selected language such as en, de, ja … etc.
{{_locale}}localeIs
Checks a string against i18next’s currently selected language. Returns true or false.
{{#if (localeIs "en")}} ... {{/if}}_date
Outputs a formatted date according to the language specific conventions.
{{_date}}If called without argument the current date is returned. Any other input date can be passed as a conventional date
string, a number (timestamp in milliseconds), or a date array. _date accepts all arguments
Javascript’s new Date()
constructor would accept.
Date argument given as date string:
{{_date "2020-03-11T03:24:00"}}or
{{_date "December 17, 1995 03:24:00"}}Date argument given as number (milliseconds since begin of unix epoch):
{{_date 1583922952743}}Date argument given as javascript date array [year, monthIndex [, day [, hour [, minutes [, seconds [, milliseconds]]]]]]:
{{_date "[2012, 11, 20, 3, 0, 0]"}}Additional arguments for formatting:
You can add multiple arguments for individual formatting. See Intl DateTimeFormat for your option arguments. Alternatively check this repo’s TS types in handlebars-i18n.d.ts.
{{_date 1583922952743 year="2-digit" day="2-digit" timeZone="America/Los_Angeles"}}_dateAdd
Adds a time offset in a given unit to a date, returns the modified date.
{{_dateAdd "1996-12-17" 24 unit="hour"}}- output: en → 12/18/1996
The first argument is a date (see function _date for valid date inputs). The second argument is a time amount given
as number. The option unit specifies the time amount. Possible units
are second | minute | hour | day | week | month | quarter | year (default is hour).
Further options as for function _date can be applied.
_dateDiff
Outputs the time difference between two given dates in the requested unit.
{{_dateDiff "2000-12-17" "2001-12-17" unit="year"}}- output: en → in 1 year
The second date argument is subtracted from the first. If the difference is a positive value, a future event statement
is made. A negative value refers to a past date. (If no second argument is given, the default date is the present moment).
Allowed date input formats are similar to _date, options equal _dateRel. Default unit is hour.
_dateRel
Outputs a string with a relative date statement, formatted according to the language specific conventions.
{{_dateRel 7 unit="hour"}}- output: en → in 7 hours
{{_dateRel -7 unit="hour"}}- output: en → 7 hours ago
A positive number argument leads to a future event statement, a negative refers to a past date. Possible units
are second | minute | hour | day | week | month | quarter | year (default is hour).
For a complete set of options (such as numberingSystem or localeMatcher)
see Intl.RelativeTimeFormat Constructor.
Alternatively check this repo’s TS types in handlebars-i18n.d.ts.
_num
Outputs a formatted number according to the language specific conventions of number representation.
{{_num 3.14159}}Additional arguments for formatting:
You can add multiple arguments for individual formatting. See Intl NumberFormat for your option arguments. Alternatively check this repo’s TS types in handlebars-i18n.d.ts.
{{_num 3.14159 maximumFractionDigits=2}}- output: en → 3.14 | de → 3,14
_price
Outputs a formatted currency string according to the language specific conventions of price representation.
{{_price 9999.99}}Additional arguments for formatting:
You can add multiple arguments for individual currency formatting. See Intl NumberFormat for your option arguments. Alternatively check this repo’s TS types in handlebars-i18n.d.ts.
{{_price 1000 currency="JPY" minimumFractionDigits=2}}How to use HandlebarsI18n.configure method
Generic language format settings
Instead of defining the formatting options for each date, number or price anew, you can configure global settings for all languages or only for specific languages.
HandlebarsI18n.configure("all", "DateTimeFormat", {timeZone: "America/Los_Angeles"});First argument is the language shortcode or "all" for all languages. Second is the format option you want to
address (DateTimeFormat, RelativeTimeFormat, NumberFormat, or PriceFormat). Third argument is the options object
with the specific settings.
Examples for generic settings:
HandlebarsI18n.configure("all", "RelativeTimeFormat", {style: "long", unit: "second"});HandlebarsI18n.configure("all", "NumberFormat", {numberingSystem: "latn", maximumFractionDigits: 0});HandlebarsI18n.configure("all", "PriceFormat", {currency: "HKD", currencyDisplay: "code"});Custom language format subsets
You can also define specific subsets to be used in the template, i.e. if you want the date in different formats such as:
- 2020 (
year-only) - 11.3.2020 (
standard-date) - 7:24:02 (
time-only)
To do this, define a 4th parameter with a custom name:
HandlebarsI18n.configure([
["en", "DateTimeFormat", {year: "numeric"}, "year-only"],
["en", "DateTimeFormat", {year: "numeric", month: "numeric", day: "numeric"}, "standard-date"],
['en', 'DateTimeFormat', {hour: "numeric", minute: "numeric", second: "numeric", hour12: false}, "time-only"]
]);Call a subset in template with the parameter format="custom-name", like:
{{_date myDate format="year-only"}}Subsets must be defined per language, a subset for "all" is invalid.
The lookup cascade
The general lookup cascade is:
- 1st Priority: The argument given in the template for custom configurations by the key "format",
i.e.
{{_date format="my-custom-format"}} - 2nd Priority: The extra argument(s) given in the template,
e.g.
{{_date timeZone="America/Los_Angeles" year="2-digit"}} - 3rd Priority: The global setting configured for the current language, such as "en"
- 4th Priority: The global setting configured for all languages
- Default: The Intl default setting
Example:
This defines that all prices for all languages are represented in Dollar:
HandlebarsI18n.configure("all", "PriceFormat", {currency: "USD"});This defines that all prices for all languages are represented in Dollar, but that for the language French the currency is Euro:
HandlebarsI18n.configure([
["all", "PriceFormat", {currency: "USD"}],
["fr", "PriceFormat", {currency: "EUR"}]
]);Reset existing configuration
Dismiss all existing configurations:
HandlebarsI18n.reset();Using custom instances of Handlebars and/or i18next
Sometimes you may want to use a Handlebars object you have already modified before, or you may want to use multiple discrete instances of Handlebars. In this case you can pass you custom Handlebars instance to the init function to use it instead of the generic Handlebars object like so:
const HandlebarsModified = require("handlebars");
HandlebarsModified.registerHelper("foo", function () {
return "bar"
});
HandlebarsI18n.init(HandlebarsModified);HandlebarsI18n will have your previously defined method foo by now.
The same can be done for a custom instance of i18next. Pass it as the second argument to the init function.
const i18nextCustom = require("i18next");
i18nextCustom.createInstance( /* pass some params here ... */);
HandlebarsI18n.init(null, i18nextCustom);Run tests
npm testLicense
MIT License, Copyright (c) 2020–26 Florian Walzel
Contributing
Contributions are welcome! Please open an issue or submit a pull request on GitHub.
Merci à vous
For your contribution, I would like to thank @MickL, @dargmuesli, and @DiefBell.
Note on alternatives
There is a different package named handlebars-i18next by @jgonggrijp which might also suit your needs. Cheers!

