{"id":15771797,"url":"https://github.com/aller-couleur/handlebars-i18n","last_synced_at":"2025-04-30T15:22:42.894Z","repository":{"id":42574861,"uuid":"268824824","full_name":"Aller-Couleur/handlebars-i18n","owner":"Aller-Couleur","description":"handlebars-i18next.js adds the internationalization features of i18next and Intl to handlebars.js","archived":false,"fork":false,"pushed_at":"2023-09-05T21:20:44.000Z","size":1377,"stargazers_count":16,"open_issues_count":6,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-10-05T22:00:52.578Z","etag":null,"topics":["currency-formatting","globalization-and-localization","handlebars","handlebars-js","i18n","i18next","internationalization","intl","intl-numberformat","language-specific-conventions","localization","node-module"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Aller-Couleur.png","metadata":{"files":{"readme":"readme.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-06-02T14:34:05.000Z","updated_at":"2023-10-20T11:37:24.221Z","dependencies_parsed_at":"2023-02-08T09:16:48.931Z","dependency_job_id":"ce2d7fc4-93bd-4150-bdd1-04fe7b88d254","html_url":"https://github.com/Aller-Couleur/handlebars-i18n","commit_stats":{"total_commits":184,"total_committers":8,"mean_commits":23.0,"dds":"0.27717391304347827","last_synced_commit":"613a872f155876eb32ed937931887cbfc2e7d38e"},"previous_names":[],"tags_count":10,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aller-Couleur%2Fhandlebars-i18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aller-Couleur%2Fhandlebars-i18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aller-Couleur%2Fhandlebars-i18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aller-Couleur%2Fhandlebars-i18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Aller-Couleur","download_url":"https://codeload.github.com/Aller-Couleur/handlebars-i18n/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246351336,"owners_count":20763285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["currency-formatting","globalization-and-localization","handlebars","handlebars-js","i18n","i18next","internationalization","intl","intl-numberformat","language-specific-conventions","localization","node-module"],"created_at":"2024-10-04T15:05:14.527Z","updated_at":"2025-03-31T15:30:56.434Z","avatar_url":"https://github.com/Aller-Couleur.png","language":"JavaScript","funding_links":["https://www.buymeacoffee.com/fwalzel"],"categories":[],"sub_categories":[],"readme":"# handlebars-i18n\n\n`handlebars-i18n` adds the internationalization features of [i18next](https://www.i18next.com/)\nto [handlebars.js](https://handlebarsjs.com/). It also provides **date**, **number**, and **currency formatting**\nvia [Intl](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Intl). Use as node module or in\nthe web browser. Supports Typescript.\n\nHandlebars-i18n is listed amongst i18next’s [framework helpers](https://www.i18next.com/overview/supported-frameworks).\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n![Node.js version](https://img.shields.io/badge/node-%3E%3D14-brightgreen)\n[![Build](https://github.com/fwalzel/handlebars-i18n/actions/workflows/node.js.yml/badge.svg)](https://github.com/fwalzel/handlebars-i18n/actions/workflows/node.js.yml/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/Aller-Couleur/handlebars-i18n/badge.svg?branch=master)](https://coveralls.io/github/Aller-Couleur/handlebars-i18n?branch=master)\n[![Code Climate](https://codeclimate.com/github/Aller-Couleur/handlebars-i18n/badges/gpa.svg)](https://codeclimate.com/github/Aller-Couleur/handlebars-i18n)\n[![Known Vulnerabilities](https://snyk.io/test/github/Aller-Couleur/handlebars-i18n/badge.svg)](https://snyk.io/test/github/Aller-Couleur/handlebars-i18n/badge.svg)\n![npm](https://img.shields.io/npm/dt/handlebars-i18n)\n![npm](https://img.shields.io/npm/dm/handlebars-i18n)\n![GitHub stars](https://img.shields.io/github/stars/fwalzel/handlebars-i18n?style=social)\n\n## License\n\nCopyright (c) 2020–24 Florian Walzel,\n\nMIT License\n\nIf you use handlebars-i18n in a professional context, you could\n\n[![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge\u0026logo=buy-me-a-coffee\u0026logoColor=black)](https://www.buymeacoffee.com/fwalzel)\n\n## Install\n\n```sh\nnpm i handlebars-i18n\n```\n\n## Import\n\nImport as commonJS within node environment:\n\n```javascript\nconst HandlebarsI18n = require(\"handlebars-i18n\");\nHandlebarsI18n.init();\n```\n\nWith ES6 import syntax:\n\n```typescript\nimport * as HandlebarsI18n from \"handlebars-i18n\";\nHandlebarsI18n.init();\n```\n\nUsage in web browser (old school):\n\n```javascript\n\u003cscript src=\"handlebars.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"i18next.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"handlebars-i18n.js\"\u003e\u003c/script\u003e\n\n\u003cscript\u003e\n  HandlebarsI18n.init()\n\u003c/script\u003e\n```\n\nVia jsDelivr CDN:\n```javascript\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/handlebars-i18n@1.8.0/dist/handlebars-i18n.min.js\"\u003e\u003c/script\u003e\n```\n\n## Quick example\n\nInitialize i18next with your language strings and default settings:\n\n```javascript\nconst i18next = require(\"i18next\");\n\ni18next.init({\n  resources: {\n    \"en\": {\n      translation: {\n        \"phrase1\": \"What is good?\",\n        \"phrase2\": \"{{thing}} is good.\"\n      }\n    },\n    \"de\": {\n      translation: {\n        \"phrase1\": \"Was ist gut?\",\n        \"phrase2\": \"{{thing}} ist gut.\"\n      }\n    }\n  },\n  lng: \"en\"\n});\n```\n\nSet your Handlebars.js data object:\n\n```javascript\nlet data = {\n  myItem: \"handlebars-i18n\",\n  myPrice: 1200.99,\n  myDate: \"2020-03-11T03:24:00\"\n}\n\n```\n\nInitialize handlebars-i18n:\n\n```javascript\nHandlebarsI18n.init();\n```\n\nOptionally configure your language specific number, currency, and date-time defaults:\n\n```javascript\nHandlebarsI18n.configure([\n  [\"en\", \"PriceFormat\", {currency: \"USD\"}],\n  [\"de\", \"PriceFormat\", {currency: \"EUR\"}]\n]);\n```\n\nFinally use in template:\n\n```\n\u003cp\u003e {{__ \"phrase1\"}} \u003c/p\u003e\n```\n\n* returns for \"en\" \u0026#x2192; **What is good?**\n\n```\n\u003cp\u003e {{__ \"phrase2\" thing=myItem}} \u003c/p\u003e\n```\n\n* returns for \"en\" \u0026#x2192; **handlebars-i18n is good.**\n\n```\n\u003cp\u003e {{_date myDate}} \u003c/p\u003e\n```\n\n* returns for \"en\" \u0026#x2192; **March 11, 2020, 4:24 AM**\n\n```\n\u003cp\u003e {{_price myPrice}} \u003c/p\u003e\n```\n\n* returns for \"en\" \u0026#x2192; **$1,200.99**\n\n## Detailed examples\n\n:point_right: See the *examples folder* in the repo for more use cases and details.\n\n- Open `examples/browser-example/index.html` in your Web browser to see an implementation with a simple UI.\n- Run `npm run example:js` in the console to get a very basic node example logged.\n- Run `npm run example:ts` to compile and log a typescript example.\n\n## Additional CLI Helper for Handlebars-i18n available :metal:\n\nHandlebars-i18n has its own command line\ninterface [handlebars-i18n-cli](https://www.npmjs.com/package/handlebars-i18n-cli).\n\n```sh\nnpm i handlebars-i18n-cli --save-dev\n```\n\nAutomatically extract translation strings from handlebars templates and generate i18next conform json files from it.\nHandlebars-i18n-cli also helps to keep[](https://) your translations up to date when changes are made in the templates\nover time.\n\n## API\n\n### __\n\nReturns the phrase associated with the given key for the selected language. __ will take all options\ni18next’s [t-function](https://www.i18next.com/overview/api#t) would take.\nThe primary key can be passed hard encoded in the template when written in quotes:\n\n```\n{{__ \"keyToTranslationPhrase\"}}\n```\n\n… or it can be referenced via a handlebars variable:\n\n```\n{{__ keyFromHandlebarsData}}\n```\n\n**Variable Replacement**\n\nTemplate usage:\n\n```\n{{__ \"whatIsWhat\" a=\"Everything\" b=\"fine\"}}\n```\n\nThe i18next resource:\n\n```javascript\n\"en\" : {\n  translation : {\n    \"whatIsWhat\" : \"{{a}} is {{b}}.\"\n  }\n}\n```\n\n**Plurals**\n\n```\n{{__ \"keyWithCount\" count=8}}\n```\n\n```javascript\n\"en\" : {\n  translation : {\n    \"keyWithCount\" : \"{{count}} item\", \n    \"keyWithCount_plural\" : \"{{count}} items\"\n  }\n}, \n```\n\n**Override globally selected language**\n\n```\n{{__ \"key1\" lng=\"de\"}}\n```\n\nWill output the contents for \"**de**\" even though other language is selected.\n\n---\n\n### _locale\n\nReturns the shortcode of i18next’s currently selected language such as \"**en**\", \"**de**\", \"**fi**\", \"**ja**\" … etc.\n\n```\n{{_locale}}\n```\n\n---\n\n### localeIs\n\nChecks a string against i18next’s currently selected language. Returns **true** or **false**.\n\n```\n{{#if (localeIs \"en\")}} ... {{/if}}\n```\n\n---\n\n### _date\n\nOutputs a formatted date according to the language specific conventions.\n\n```\n{{_date}}\n```\n\nIf called without argument the current date is returned. Any other input date can be passed as a conventional date\nstring, a number (timestamp in milliseconds), or a date array. _date accepts all arguments\nJavascript’s [new Date()](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Date)\nconstructor would accept.\n\n**Date argument given as date string:**\n\n```\n{{_date \"2020-03-11T03:24:00\"}}\n```\n\nor\n\n```\n{{_date \"December 17, 1995 03:24:00\"}}\n```\n\n**Date argument given as number (milliseconds since begin of unix epoch):**\n\n```\n{{_date 1583922952743}}\n```\n\n**Date argument given as javascript date array** [year, monthIndex [, day [, hour [, minutes [,\nseconds [, milliseconds]]]]]]:\n\n```\n{{_date \"[2012, 11, 20, 3, 0, 0]\"}}\n```\n\n**Additional arguments for formatting**\n\nYou can add multiple arguments for individual formatting.\nSee [Intl DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat)\nfor your option arguments. Alternatively check this repo’s TS types\nin [handlebars-i18n.d.ts](./dist/handlebars-i18n.d.ts).\n\n```\n{{_date 1583922952743 year=\"2-digit\" day=\"2-digit\" timeZone=\"America/Los_Angeles\"}}\n```\n\n---\n\n### _dateAdd :tada: new in 1.8\n\nAdds a time offset in a given unit to a date, returns the modified date.\n\n```\n{{_dateAdd \"1996-12-17\" 24 unit=\"hour\"}}\n```\n\nWill output for \"en\" \u0026#x2192; **12/18/1996**\n\nThe first argument is a date (see function **_date** for valid date inputs). The second argument is a time amount given \nas number. The option **unit** specifies the time amount. Possible units\nare `\"second\"` | `\"minute\"` | `\"hour\"` | `\"day\"` | `\"week\"` | `\"month\"` | `\"quarter\"` |`\"year\"` (default is `\"hour\"`).\nFurther options as for function **_date** can be applied.\n\n---\n\n### _dateDiff\n\nOutputs the relative time difference between two given dates.\n\n```\n{{_dateDiff \"1996-12-17T00:00:00\" \"1995-12-17T00:00:00\" unit=\"year\"}}\n```\n\nWill output for \"en\" \u0026#x2192; **in 1 year**\n\nThe second date argument is subtracted from the first. If the difference is a positive value, a future event statement\nis made. A negative value refers to a past date. (If no second argument is given, the default date is the present moment). \nAllowed date input formats are similar to **_date**, options equal **_dateRel**. Default unit is `\"hour\"`.\n\n---\n\n### _dateRel \n\nOutputs a string with a relative date statement, formatted according to the language specific conventions.\n\n```\n{{_dateRel 7 unit=\"hour\"}}\n```\n\nWill output for \"en\" \u0026#x2192; **in 7 hours**\n\n```\n{{_dateRel -7 unit=\"hour\"}}\n```\n\nWill output for \"en\" \u0026#x2192; **7 hours ago**\n\nA positive number argument leads to a future event statement, a negative refers to a past date. Possible units\nare `\"second\"` | `\"minute\"` | `\"hour\"` | `\"day\"` | `\"week\"` | `\"month\"` | `\"quarter\"` |`\"year\"` (default is `\"hour\"`). \nFor a complete set of options (such as `numberingSystem` or `localeMatcher`)\nsee [Intl.RelativeTimeFormat Constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat).\nAlternatively check this repo’s TS types in [handlebars-i18n.d.ts](./dist/handlebars-i18n.d.ts).\n\n---\n\n### _num\n\nOutputs a formatted number according to the language specific conventions of number representation, e.g. \n**4,100,000.8314** for \"**en**\", but **4.100.000,8314** for \"**de**\".\n\n```\n{{_num 4100000.8314 }}\n```\n\n**Additional arguments for formatting**\n\nYou can add multiple arguments for individual formatting.\nSee [Intl NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat)\nfor your option arguments. Alternatively check this repo’s TS types\nin [handlebars-i18n.d.ts](./dist/handlebars-i18n.d.ts).\n\n```\n{{_num 3.14159 maximumFractionDigits=2}}\n```\n\nWill output **3.14** for \"**en**\", but **3,14** for \"**de**\".\n\n---\n\n### _price\n\nOutputs a formatted currency string according to the language specific conventions of price representation, e.g. \n**€9,999.99** for \"**en**\", but **9.999,99 €** for \"**de**\".\n\n```\n{{_price 9999.99}}\n```\n\n**Additional arguments for formatting**\n\nYou can add multiple arguments for individual currency formatting.\nSee [Intl NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat)\nfor your option arguments. Alternatively check this repo’s TS types\nin [handlebars-i18n.d.ts](./dist/handlebars-i18n.d.ts).\n\n```\n{{_price 1000 currency=\"JPY\" minimumFractionDigits=2}}\n```\n\n---\n\n## How to use HandlebarsI18n.configure method\n\n### Generic language format settings\n\nInstead of defining the formatting options for each date, number or price anew, you can configure global settings for\nall languages or only for specific languages.\n\n```javascript\nHandlebarsI18n.configure(\"all\", \"DateTimeFormat\", {timeZone: \"America/Los_Angeles\"});\n```\n\nFirst argument is the language shortcode or \"**all**\" for all languages. Second is the format option you want to\naddress (`DateTimeFormat`, `RelativeTimeFormat`, `NumberFormat`, or `PriceFormat`). Third argument is the options object\nwith the specific settings.\n\nExamples for generic settings:\n\n```javascript\nHandlebarsI18n.configure(\"all\", \"RelativeTimeFormat\", {style: \"long\", unit: \"second\"});\n```\n\n```javascript\nHandlebarsI18n.configure(\"all\", \"NumberFormat\", {numberingSystem: \"latn\", maximumFractionDigits: 0});\n```\n\n```javascript\nHandlebarsI18n.configure(\"all\", \"PriceFormat\", {currency: \"HKD\", currencyDisplay: \"code\"});\n```\n\n### Custom language format subsets\n\nYou can also define specific subsets to be used in the template, i.e. if you want the date in different formats such as:\n\n- **2020** (year-only)\n- **11.3.2020** (standard-date)\n- **7:24:02** (time-only)\n\nTo do this, define a 4th parameter with a custom name:\n\n```javascript\nHandlebarsI18n.configure([\n  [\"en\", \"DateTimeFormat\", {year: \"numeric\"}, \"year-only\"],\n  [\"en\", \"DateTimeFormat\", {year: \"numeric\", month: \"numeric\", day: \"numeric\"}, \"standard-date\"],\n  ['en', 'DateTimeFormat', {hour: \"numeric\", minute: \"numeric\", second: \"numeric\", hour12: false}, \"time-only\"]\n]);\n```\n\nCall a subset in template with the parameter format=\"custom-name\", like:\n\n```\n{{_date myDate format=\"year-only\"}}\n```\n\nSubsets must be defined per language, a subset for \"all\" is invalid.\n\n### The lookup cascade\n\nThe general lookup cascade is:\n\n- **1st Priority**: The argument given in the template for custom configurations by the key \"format\",\n  i.e. `{{_date format=\"my-custom-format\"}}`\n- **2nd Priority**: The extra argument(s) given in the template,\n  e.g. `{{_date timeZone=\"America/Los_Angeles\" year=\"2-digit\"}}`\n- **3rd Priority**: The global setting configured for the current language, such as \"**en**\"\n- **4th Priority**: The global setting configured for **all** languages\n- **Default**: The **Intl** default setting\n\n**Example:**\n\nThis defines that all prices for all languages are represented in Dollar:\n\n```javascript\nHandlebarsI18n.configure(\"all\", \"PriceFormat\", {currency: \"USD\"});\n```\n\nThis defines that all prices for all languages are represented in Dollar, but that for the language French the currency\nis Euro:\n\n```javascript\nHandlebarsI18n.configure([\n  [\"all\", \"PriceFormat\", {currency: \"USD\"}],\n  [\"fr\", \"PriceFormat\", {currency: \"EUR\"}]\n]);\n```\n\n### Reset existing configuration\n\nDismiss all existing configurations:\n\n```javascript\nHandlebarsI18n.reset();\n```\n\n## Using custom instances of Handlebars and/or i18next\n\nSometimes you may want to use a Handlebars object you have already modified before, or you may want to use multiple\ndiscrete instances of Handlebars. In this case you can pass you custom Handlebars instance to the init function to use\nit instead of the generic Handlebars object like so:\n\n```javascript\nconst HandlebarsModified = require(\"handlebars\");\nHandlebarsModified.registerHelper(\"foo\", function () {\n  return \"what you want\"\n});\nHandlebarsI18n.init(HandlebarsModified);\n```\n\nHandlebarsI18n will have your previously defined method **foo()** by now.\n\nThe same can be done for a custom instance of i18next. Pass it as the second argument to the init function.\n\n```javascript\nconst i18nextCustom = require(\"i18next\");\ni18nextCustom.createInstance( /* pass some params here ... */);\nHandlebarsI18n.init(null, i18nextCustom);\n```\n\n## Run tests\n\n```sh\nnpm test\n```\n\n## Merci à vous\n\nFor your contribution, I would like to\nthank [@MickL](https://github.com/MickL), [@dargmuesli](https://github.com/dargmuesli), and [@DiefBell](DiefBell).\n\n## Note\n\nThere is a *different* package named [handlebars-i18next](https://www.npmjs.com/package/handlebars-i18next)\nby [@jgonggrijp](https://github.com/jgonggrijp) which might also suit your needs. Cheers!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faller-couleur%2Fhandlebars-i18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faller-couleur%2Fhandlebars-i18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faller-couleur%2Fhandlebars-i18n/lists"}