handlebars-i18n
v1.8.1
Published
handlebars-i18n adds internationalization to handlebars.js using i18next and Intl.
Downloads
7,213
Maintainers
Readme
handlebars-i18n
handlebars-i18n
adds the internationalization 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. Supports Typescript.
Handlebars-i18n is listed amongst i18next’s framework helpers.
License
Copyright (c) 2020–24 Florian Walzel,
MIT License
If you use handlebars-i18n in a professional context, you could
Install
npm i handlebars-i18n
Import
Import as commonJS within node environment:
const HandlebarsI18n = require("handlebars-i18n");
HandlebarsI18n.init();
With ES6 import syntax:
import * as HandlebarsI18n from "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 jsDelivr 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"
});
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>
- returns for "en" → What is good?
<p> {{__ "phrase2" thing=myItem}} </p>
- returns for "en" → handlebars-i18n is good.
<p> {{_date myDate}} </p>
- returns for "en" → March 11, 2020, 4:24 AM
<p> {{_price myPrice}} </p>
- returns for "en" → $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.html
in your Web browser to see an implementation with a simple UI. - Run
npm run example:js
in the console to get a very basic node example logged. - Run
npm run example:ts
to 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
Automatically extract translation strings from handlebars templates and generate i18next conform json files from it. Handlebars-i18n-cli also helps to keep your translations up to date when changes are made in the templates over time.
API
__
Returns the phrase associated with the given key for the selected language. __ will take all options i18next’s t-function would take. The primary 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}}."
}
}
Plurals
{{__ "keyWithCount" count=8}}
"en" : {
translation : {
"keyWithCount" : "{{count}} item",
"keyWithCount_plural" : "{{count}} items"
}
},
Override globally selected language
{{__ "key1" lng="de"}}
Will output the contents for "de" even though other language is selected.
_locale
Returns the shortcode of i18next’s currently selected language such as "en", "de", "fi", "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 :tada: new in 1.8
Adds a time offset in a given unit to a date, returns the modified date.
{{_dateAdd "1996-12-17" 24 unit="hour"}}
Will output for "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 relative time difference between two given dates.
{{_dateDiff "1996-12-17T00:00:00" "1995-12-17T00:00:00" unit="year"}}
Will output for "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"}}
Will output for "en" → in 7 hours
{{_dateRel -7 unit="hour"}}
Will output for "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, e.g. 4,100,000.8314 for "en", but 4.100.000,8314 for "de".
{{_num 4100000.8314 }}
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}}
Will output 3.14 for "en", but 3,14 for "de".
_price
Outputs a formatted currency string according to the language specific conventions of price representation, e.g. €9,999.99 for "en", but 9.999,99 € for "de".
{{_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 "what you want"
});
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 test
Merci à vous
For your contribution, I would like to thank @MickL, @dargmuesli, and @DiefBell.
Note
There is a different package named handlebars-i18next by @jgonggrijp which might also suit your needs. Cheers!