handlebars-i18n 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,8 +5,7 @@
5
5
  * @date: 2021-01
6
6
  *
7
7
  * usage:
8
- * $ cd examples/node-example
9
- * $ node simple-example
8
+ * $ npm run example:js
10
9
  */
11
10
 
12
11
 
@@ -0,0 +1,86 @@
1
+ import * as HandlebarsI18n from "../../dist/handlebars-i18n";
2
+ import * as i18next from "i18next";
3
+ import * as handlebars from "handlebars";
4
+ import { readFileSync } from "fs";
5
+
6
+ /**
7
+ * A simple example using handlebars-i18n
8
+ * with TypeScript.
9
+ *
10
+ * @author: Dief Bell
11
+ * @date: 2023-02
12
+ *
13
+ * usage:
14
+ * $ npm run example:ts
15
+ */
16
+
17
+
18
+ // -- The translation phrases for i18next
19
+ i18next
20
+ .init({
21
+ resources: {
22
+ "en-GB": {
23
+ translation: {
24
+ "key0": "Change Language to",
25
+ "key1": "What is good?",
26
+ "key2": "{{what}} is good.",
27
+ "key3WithCount": "{{count}} item",
28
+ "key3WithCount_plural": "{{count}} items",
29
+ "key4": "Selected Language is:"
30
+ }
31
+ },
32
+ "de-DE": {
33
+ translation: {
34
+ "key0": "Sprache wechseln zu",
35
+ "key1": "Was ist gut?",
36
+ "key2": "{{what}} ist gut.",
37
+ "key3WithCount": "{{count}} Gegenstand",
38
+ "key3WithCount_plural": "{{count}} Gegenstände",
39
+ "key4": "Die ausgewählte Sprache ist:"
40
+ }
41
+ }
42
+ },
43
+ lng: "en-GB",
44
+ compatibilityJSON: "v2"
45
+ });
46
+
47
+ // -- Handlebars" example data object
48
+ const data = {
49
+ sayWhat: "handlebars-i18n",
50
+ holdKey3: "key3WithCount",
51
+ holdKey4: "key4",
52
+ mynumber: 33.333,
53
+ myMmaxDigits: 1,
54
+ myPrice: 12.99,
55
+ myDate: "2020-03-11T03:24:00"
56
+ };
57
+
58
+ // -- Init and configure handlebars-i18n
59
+ HandlebarsI18n.init();
60
+
61
+ HandlebarsI18n.configure([
62
+ // generic configuration for all languages for number representation:
63
+ [ "all", "NumberFormat", { minimumFractionDigits: 2 } ],
64
+
65
+ // generic configurations per language for price representation:
66
+ [ "en-GB", "PriceFormat", { currency: "USD" } ],
67
+ [ "de-DE", "PriceFormat", { currency: "EUR" } ],
68
+
69
+ // generic configurations per language for date representation:
70
+ [ "en-GB", "DateTimeFormat", { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric" } ],
71
+ [ "de-DE", "DateTimeFormat", { year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", hour12: false } ],
72
+
73
+ // configurations per language with custom formats for date:
74
+ [ "en-GB", "DateTimeFormat", { year: "numeric" }, "custom-year-only" ],
75
+ [ "de-DE", "DateTimeFormat", { year: "numeric" }, "custom-year-only" ],
76
+ [ "en-GB", "DateTimeFormat", { year: "numeric", month: "numeric", day: "numeric" }, "custom-date-short" ],
77
+ [ "de-DE", "DateTimeFormat", { year: "numeric", month: "numeric", day: "numeric" }, "custom-date-short" ],
78
+ [ "en-GB", "DateTimeFormat", { hour: "numeric", minute: "numeric", second: "numeric", hour12: false }, "custom-time" ],
79
+ [ "de-DE", "DateTimeFormat", { hour: "numeric", minute: "numeric", second: "numeric", hour12: false }, "custom-time" ]
80
+ ]);
81
+
82
+ const template = readFileSync(__dirname + "/test.hbs", { encoding: "utf-8" });
83
+ const compiled = handlebars.compile(template);
84
+ i18next.changeLanguage("de-DE"); // --> Test the changes by replacing "de-DE" with "en-GB"
85
+
86
+ console.log("\x1b[36m%s\x1b[0m", compiled(data));
@@ -0,0 +1,81 @@
1
+ // Simple translation, key given as string:
2
+ {{__ "key1"}}
3
+
4
+ // Translation with variable replacement:
5
+ {{__ "key2" what=sayWhat}}
6
+
7
+ // Phrase with [singular] / plural:
8
+ {{__ "key3WithCount" count=1}}
9
+
10
+ // Phrase with singular / [plural]:
11
+ {{__ "key3WithCount" count=7}}
12
+
13
+ // Override language to use:
14
+ {{__ "key1" lng="de-DE"}}
15
+
16
+
17
+ // Output selected language
18
+ // ----------------------------------------
19
+
20
+ // Translation key given through handlebars variable and _locale output:
21
+ {{__ holdKey4}} {{_locale}}
22
+
23
+ // Check against selected language:
24
+ {{#if (localeIs "en-DE")}}English {{else}}Deutsch {{/if}}
25
+
26
+
27
+ // Number representation
28
+ // ----------------------------------------
29
+
30
+ // Number representation as configured for all languages:
31
+ {{_num 7000}}
32
+
33
+ // Number representation with specific format attribute:
34
+ {{_num 3.1415926 maximumFractionDigits=0}}
35
+
36
+ // Number and attribute given through handlebars variables:
37
+ {{_num mynumber maximumFractionDigits=myMaxDigits}}
38
+
39
+
40
+ // Price representation
41
+ // ----------------------------------------
42
+
43
+ // Price representation as configured per language:
44
+ {{_price 9999.99}}
45
+
46
+ // Price representation with specific format attributes:
47
+ {{_price 1000.99 currency="JPY" minimumFractionDigits=0}}
48
+
49
+ // Price given through handlebars variable and with with specific format attribute:
50
+ {{_price myPrice currency="DKK"}}
51
+
52
+
53
+ // date representation
54
+ // ----------------------------------------
55
+
56
+ // Todays date as configured per language:
57
+ {{_date}}
58
+
59
+ // Date given as date string:
60
+ {{_date "2020-03-11T03:24:00"}}
61
+
62
+ // Date given in milliseconds since begin of unix epoch:
63
+ {{_date 1583922952743}}
64
+
65
+ // Date given as javascript date parameter array:
66
+ {{_date "[2012, 11, 20, 3, 0, 0]"}}
67
+
68
+ // Todays date with with specific format attributes:
69
+ {{_date "today" year="2-digit" month="2-digit" day="2-digit"}}
70
+
71
+ // Date given through handlebars variable:
72
+ {{_date myDate}}
73
+
74
+ // Date formated by custom configuration (subset "custom-year-only"):
75
+ {{_date myDate format="custom-year-only"}}
76
+
77
+ // Date formated by custom configuration (subset "custom-date-short"):
78
+ {{_date myDate format="custom-date-short"}}
79
+
80
+ // Date formated by custom configuration (subset "custom-date-short"):
81
+ {{_date myDate format="custom-time"}}
@@ -0,0 +1,8 @@
1
+ {
2
+ "include": [ "./index.ts" ],
3
+ "compilerOptions": {
4
+ "target": "ES2022",
5
+ "module": "CommonJS",
6
+ "baseUrl": "../../"
7
+ }
8
+ }
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "handlebars-i18n",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "description": "handlebars-i18n adds internationlization to handlebars.js using i18next and Intl",
5
5
  "main": "dist/handlebars-i18n.js",
6
6
  "scripts": {
7
7
  "test": "nyc mocha",
8
- "coveralls": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
8
+ "coveralls": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage",
9
+ "example:js": "cd examples/node-example && node simple-example.js",
10
+ "example:ts": "cd examples/typescript && tsc && node index.js"
9
11
  },
10
12
  "directories": {
11
13
  "test": "test"
@@ -42,6 +44,8 @@
42
44
  "devDependencies": {
43
45
  "@commitlint/cli": "16.2.3",
44
46
  "@commitlint/config-conventional": "16.2.1",
47
+ "@types/intl": "^1.2.0",
48
+ "@types/node": "^18.13.0",
45
49
  "chai": "4.3.6",
46
50
  "coveralls": "3.1.1",
47
51
  "gulp": "4.0.2",
@@ -51,12 +55,13 @@
51
55
  "husky": "7.0.4",
52
56
  "istanbul": "0.4.5",
53
57
  "mocha": "9.2.2",
54
- "nyc": "15.1.0"
58
+ "nyc": "15.1.0",
59
+ "typescript": "^4.9.5"
55
60
  },
56
61
  "dependencies": {
57
- "handlebars": "4.7.7",
58
- "i18next": "21.6.14",
59
- "intl": "1.2.5"
62
+ "handlebars": "^4.7.7",
63
+ "i18next": "^21.6.14",
64
+ "intl": "^1.2.5"
60
65
  },
61
66
  "husky": {
62
67
  "hooks": {
package/readme.md CHANGED
@@ -2,13 +2,14 @@
2
2
 
3
3
  `handlebars-i18n` adds the internationalization features of [i18next](https://www.i18next.com/) to [handlebars.js](https://handlebarsjs.com/). It also provides **date**, **number**, and **currency formatting** via [Intl](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Intl). Use as node module or in the web browser.
4
4
 
5
- Handlebars-i18n is listed amongst i18next’s [framework helpers](https://www.i18next.com/overview/supported-frameworks).
5
+ Handlebars-i18n is listed amongst i18next’s [framework helpers](https://www.i18next.com/overview/supported-frameworks). Now supports Typescript thanks to [@DiefBell](DiefBell).
6
6
 
7
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
8
- [![Build Status](https://travis-ci.org/fwalzel/handlebars-i18n.svg?branch=master)](https://travis-ci.org/fwalzel/handlebars-i18n)
9
- [![Coverage Status](https://coveralls.io/repos/github/fwalzel/handlebars-i18next/badge.svg?branch=master)](https://coveralls.io/github/fwalzel/handlebars-i18next?branch=master)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
8
+ [![Build Status](https://travis-ci.org/fwalzel/handlebars-i18n.svg?branch=master)](https://travis-ci.org/fwalzel/handlebars-i18n)
9
+ [![Coverage Status](https://coveralls.io/repos/github/fwalzel/handlebars-i18next/badge.svg?branch=master)](https://coveralls.io/github/fwalzel/handlebars-i18next?branch=master)
10
10
  [![Code Quality](https://api.codiga.io/project/29087/score/svg)](https://api.codiga.io/project/29087/score/svg)
11
11
  [![Known Vulnerabilities](https://snyk.io/test/github/Aller-Couleur/handlebars-i18n/badge.svg)](https://snyk.io/test/github/Aller-Couleur/handlebars-i18n/badge.svg)
12
+ ![npm](https://img.shields.io/npm/dm/handlebars-i18n)
12
13
 
13
14
 
14
15
  ## License
@@ -47,7 +48,7 @@ Usage in web browser:
47
48
  <script src="handlebars-i18n.js"></script>
48
49
 
49
50
  <script>
50
- HandlebarsI18n.init()
51
+ HandlebarsI18n.init()
51
52
  </script>
52
53
  ```
53
54
 
@@ -56,24 +57,24 @@ Usage in web browser:
56
57
  Initialize i18next with your language strings and default settings:
57
58
 
58
59
  ```javascript
59
- const i18next = require('i18next');
60
+ const i18next = require("i18next");
60
61
 
61
62
  i18next.init({
62
- resources : {
63
- "en" : {
64
- translation : {
65
- "phrase1": "What is good?",
66
- "phrase2": "{{thing}} is good."
67
- }
68
- },
69
- "de" : {
70
- translation: {
71
- "phrase1": "Was ist gut?",
72
- "phrase2": "{{thing}} ist gut."
73
- }
74
- }
63
+ resources : {
64
+ "en" : {
65
+ translation : {
66
+ "phrase1": "What is good?",
67
+ "phrase2": "{{thing}} is good."
68
+ }
75
69
  },
76
- lng : "en"
70
+ "de" : {
71
+ translation: {
72
+ "phrase1": "Was ist gut?",
73
+ "phrase2": "{{thing}} ist gut."
74
+ }
75
+ }
76
+ },
77
+ lng : "en"
77
78
  });
78
79
  ```
79
80
 
@@ -81,7 +82,7 @@ Set your Handlebars.js data object:
81
82
 
82
83
  ```javascript
83
84
  let data = {
84
- myItem: "handlebars-i18n",
85
+ myItem: "handlebars-i18n",
85
86
  myPrice: 1200.99,
86
87
  myDate: "2020-03-11T03:24:00"
87
88
  }
@@ -130,19 +131,24 @@ Finally use in template:
130
131
  :point_right: See the *examples folder* in the repo for more use cases and details.
131
132
 
132
133
 
133
- ## Run tests
134
+ ## NEW! :star_struck: Additional CLI Helper for Handlebars-i18n
135
+
136
+ Handlebars-i18n has its own command line interface [handlebars-i18n-cli](https://www.npmjs.com/package/handlebars-i18n-cli) by now.
134
137
 
135
138
  ```bash
136
- $ npm test
139
+ $ npm i handlebars-i18n-cli --save-dev
137
140
  ```
138
141
 
142
+ Automatically extract translation strings from handlebars templates and generate i18next conform json files from it.
143
+ Handlebars-i18n-cli also helps to keep your translations up to date when changes are made in the templates over time.
144
+
139
145
 
140
146
  ## API
141
147
 
142
148
 
143
149
  ### __
144
150
 
145
- Returns the phrase associated with the given key for the selected language. __ will take all options i18next’s [t-function](https://www.i18next.com/overview/api#t) would take.
151
+ Returns the phrase associated with the given key for the selected language. __ will take all options i18next’s [t-function](https://www.i18next.com/overview/api#t) would take.
146
152
  The primary key can be passed hard encoded in the template when written in quotes:
147
153
 
148
154
  ```
@@ -164,12 +170,12 @@ Template usage:
164
170
 
165
171
  The i18next resource:
166
172
 
167
- ```
173
+ ```javascript
168
174
  "en" : {
169
- translation : {
170
- "whatIsWhat": "{{a}} is {{b}}."
171
- }
172
- },
175
+ translation : {
176
+ "whatIsWhat": "{{a}} is {{b}}."
177
+ }
178
+ }
173
179
  ```
174
180
 
175
181
  **Plurals**
@@ -179,12 +185,12 @@ The i18next resource:
179
185
  ```
180
186
 
181
187
  ```javascript
182
- 'en' : {
188
+ "en" : {
183
189
  translation : {
184
- 'keyWithCount': '{{count}} item',
185
- 'keyWithCount_plural': '{{count}} items',
190
+ "keyWithCount" : "{{count}} item",
191
+ "keyWithCount_plural" : "{{count}} items"
186
192
  }
187
- },
193
+ }, ...
188
194
  ```
189
195
 
190
196
  **Override globally selected language**
@@ -193,7 +199,7 @@ The i18next resource:
193
199
  {{__ "key1" lng="de"}}
194
200
  ```
195
201
 
196
- Will output the contents for "**de**" even though other language is selected.
202
+ Will output the contents for "**de**" even though other language is selected.
197
203
 
198
204
  ---
199
205
 
@@ -219,7 +225,7 @@ Checks a string against i18next’s currently selected language. Returns **true*
219
225
 
220
226
  ### _date
221
227
 
222
- Outputs a formated date according to the language specific conventions.
228
+ Outputs a formatted date according to the language specific conventions.
223
229
 
224
230
  ```
225
231
  {{_date}}
@@ -233,6 +239,8 @@ If called without argument the current date is returned. Any other input date ca
233
239
  {{_date "2020-03-11T03:24:00"}}
234
240
  ```
235
241
 
242
+ or
243
+
236
244
  ```
237
245
  {{_date "December 17, 1995 03:24:00"}}
238
246
  ```
@@ -260,7 +268,7 @@ You can add multiple arguments for individual formatting. See [Intl DateTimeForm
260
268
 
261
269
  ### _num
262
270
 
263
- Outputs a formated 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**".
271
+ 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**".
264
272
 
265
273
  ```
266
274
  {{_num 4100000.8314 }}
@@ -279,7 +287,7 @@ Will output **3.14** for "**en**", but **3,14** for "**de**".
279
287
 
280
288
  ### _price
281
289
 
282
- Outputs a formated currency string according to the language specific conventions of price representation, e.g. **€9,999.99** for "**en**", but **9.999,99 €** for "**de**".
290
+ 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**".
283
291
 
284
292
 
285
293
  ```
@@ -308,52 +316,49 @@ HandlebarsI18n.configure("all", "DateTimeFormat", {timeZone: "America/Los_Angele
308
316
 
309
317
  First argument is the language shortcode or "**all**" for all languages. Second is the format option you want to address (DateTimeFormat, NumberFormat, or PriceFormat). Third argument ist the options object with the specific settings.
310
318
 
311
- ### Custom language format subsets
319
+ ### Custom language format subsets
312
320
 
313
- You can define specific subsets to be used in the template, i.e. if you want the date in different formatts such as:
321
+ You can define specific subsets to be used in the template, i.e. if you want the date in different formats such as:
314
322
 
315
323
  - **2020** (year-only)
316
324
  - **11.3.2020** (standard-date)
317
325
  - **7:24:02** (time-only)
318
326
 
319
- To do this define a 4th parameter with a custom name:
320
-
327
+ To do this, define a 4th parameter with a custom name:
321
328
 
322
329
  ```javascript
323
330
  HandlebarsI18n.configure([
324
- ["en", "DateTimeFormat", {year:'numeric'}, "year-only"],
325
- ["en", "DateTimeFormat", {year:'numeric', month:'numeric', day:'numeric'}, "standard-date"],
326
- ['en', 'DateTimeFormat', { hour:'numeric', minute:'numeric', second:'numeric', hour12:false}, "time-only"]
331
+ ["en", "DateTimeFormat", {year:"numeric"}, "year-only"],
332
+ ["en", "DateTimeFormat", {year:"numeric", month:"numeric", day:"numeric"}, "standard-date"],
333
+ ['en', 'DateTimeFormat', {hour:"numeric", minute:"numeric", second:"numeric", hour12:false}, "time-only"]
327
334
  ]);
328
335
  ```
329
336
 
330
- Call a subset in template wit the parameter "format", like:
337
+ Call a subset in template with the parameter format="custom-name", like:
331
338
 
332
339
  ```
333
340
  {{_date myDate format="year-only"}}
334
341
  ```
335
342
 
336
-
337
-
338
343
  ### The lookup cascade
339
344
 
340
345
  The general lookup cascade is:
341
346
 
342
- - **1st Priority**: The argument given in the template for custom configurations by the key "format", i.e. `{{_date format="my-custom-format"}}`
343
- - **2nd Priority**: The extra argument(s) given in the template, e.g. `{{_date timeZone="America/Los_Angeles" year="2-digit"}}`
347
+ - **1st Priority**: The argument given in the template for custom configurations by the key "format", i.e. `{{_date format="my-custom-format"}}`
348
+ - **2nd Priority**: The extra argument(s) given in the template, e.g. `{{_date timeZone="America/Los_Angeles" year="2-digit"}}`
344
349
  - **3rd Priority**: The global setting configured for the current language, such as "**en**"
345
350
  - **4th Priority**: The global setting configured for **all** languages
346
351
  - **Default**: The **Intl** default setting
347
352
 
348
353
  **Example:**
349
354
 
350
- This defines that all prices for all languages are represented as Dollar:
355
+ This defines that all prices for all languages are represented in Dollar:
351
356
 
352
357
  ```javascript
353
358
  HandlebarsI18n.configure("all", "PriceFormat", {currency: "USD"});
354
359
  ```
355
360
 
356
- This defines that all prices for all languages are represented as Dollar, but that for language French the currency is Euro:
361
+ This defines that all prices for all languages are represented in Dollar, but that for the language French the currency is Euro:
357
362
 
358
363
  ```javascript
359
364
  HandlebarsI18n.configure([
@@ -372,11 +377,13 @@ HandlebarsI18n.reset();
372
377
 
373
378
  ## Using custom instances of Handlebars and/or i18next
374
379
 
375
- 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:
380
+ Sometimes you may want to use a Handlebars object you have already modified before, or you may want to use multiple
381
+ discrete instances of Handlebars. In this case you can pass you custom Handlebars instance to the init function to use
382
+ it instead of the generic Handlebars object like so:
376
383
 
377
384
  ```javascript
378
- const HandlebarsModified = require('handlebars');
379
- HandlebarsModified.registerHelper('foo', function() { return 'what you want' });
385
+ const HandlebarsModified = require("handlebars");
386
+ HandlebarsModified.registerHelper("foo", function() { return "what you want" });
380
387
  HandlebarsI18n.init(HandlebarsModified);
381
388
  ```
382
389
 
@@ -385,11 +392,20 @@ HandlebarsI18n will have your previously defined method **foo()** by now.
385
392
  The same can be done for a custom instance of i18next. Pass it as the second argument to the init function.
386
393
 
387
394
  ```javascript
388
- const i18nextCustom = require('i18next');
389
- i18nextCustom.createInstance( /*... pass some params here */ );
395
+ const i18nextCustom = require("i18next");
396
+ i18nextCustom.createInstance( /* pass some params here ... */ );
390
397
  HandlebarsI18n.init(null, i18nextCustom);
391
398
  ```
392
399
 
400
+ ## Run tests
401
+
402
+ ```bash
403
+ $ npm test
404
+ ```
405
+
406
+ ## Merci à vous
407
+
408
+ For your contribution, I would like to thank [@MickL](https://github.com/MickL), [@dargmuesli](https://github.com/dargmuesli), and [@DiefBell](DiefBell).
393
409
 
394
410
  ## Note
395
411