handlebars-i18n 1.5.1 → 1.6.1

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,90 @@
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
+ const myI18nInstance = i18next.createInstance();
20
+ myI18nInstance
21
+ .init({
22
+ resources: {
23
+ "en-GB": {
24
+ translation: {
25
+ "key0": "Change Language to",
26
+ "key1": "What is good?",
27
+ "key2": "{{what}} is good.",
28
+ "key3WithCount": "{{count}} item",
29
+ "key3WithCount_plural": "{{count}} items",
30
+ "key4": "Selected Language is:"
31
+ }
32
+ },
33
+ "de-DE": {
34
+ translation: {
35
+ "key0": "Sprache wechseln zu",
36
+ "key1": "Was ist gut?",
37
+ "key2": "{{what}} ist gut.",
38
+ "key3WithCount": "{{count}} Gegenstand",
39
+ "key3WithCount_plural": "{{count}} Gegenstände",
40
+ "key4": "Die ausgewählte Sprache ist:"
41
+ }
42
+ }
43
+ },
44
+ lng: "en-GB",
45
+ compatibilityJSON: "v2"
46
+ });
47
+
48
+ // -- Handlebars" example data object
49
+ const data = {
50
+ sayWhat: "handlebars-i18n",
51
+ holdKey3: "key3WithCount",
52
+ holdKey4: "key4",
53
+ mynumber: 33.333,
54
+ myMmaxDigits: 1,
55
+ myPrice: 12.99,
56
+ myDate: "2020-03-11T03:24:00"
57
+ };
58
+
59
+
60
+ const myHandlebarsInstance = handlebars.create();
61
+
62
+ // -- Init and configure handlebars-i18n
63
+ HandlebarsI18n.init(myHandlebarsInstance, myI18nInstance);
64
+
65
+ HandlebarsI18n.configure([
66
+ // generic configuration for all languages for number representation:
67
+ [ "all", "NumberFormat", { minimumFractionDigits: 2 } ],
68
+
69
+ // generic configurations per language for price representation:
70
+ [ "en-GB", "PriceFormat", { currency: "USD" } ],
71
+ [ "de-DE", "PriceFormat", { currency: "EUR" } ],
72
+
73
+ // generic configurations per language for date representation:
74
+ [ "en-GB", "DateTimeFormat", { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric" } ],
75
+ [ "de-DE", "DateTimeFormat", { year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", hour12: false } ],
76
+
77
+ // configurations per language with custom formats for date:
78
+ [ "en-GB", "DateTimeFormat", { year: "numeric" }, "custom-year-only" ],
79
+ [ "de-DE", "DateTimeFormat", { year: "numeric" }, "custom-year-only" ],
80
+ [ "en-GB", "DateTimeFormat", { year: "numeric", month: "numeric", day: "numeric" }, "custom-date-short" ],
81
+ [ "de-DE", "DateTimeFormat", { year: "numeric", month: "numeric", day: "numeric" }, "custom-date-short" ],
82
+ [ "en-GB", "DateTimeFormat", { hour: "numeric", minute: "numeric", second: "numeric", hour12: false }, "custom-time" ],
83
+ [ "de-DE", "DateTimeFormat", { hour: "numeric", minute: "numeric", second: "numeric", hour12: false }, "custom-time" ]
84
+ ]);
85
+
86
+ const template = readFileSync(__dirname + "/test.hbs", { encoding: "utf-8" });
87
+ const compiled = myHandlebarsInstance.compile(template);
88
+ myI18nInstance.changeLanguage("de-DE"); // --> Test the changes by replacing "de-DE" with "en-GB"
89
+
90
+ 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,18 +1,20 @@
1
1
  {
2
2
  "name": "handlebars-i18n",
3
- "version": "1.5.1",
3
+ "version": "1.6.1",
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"
12
14
  },
13
15
  "repository": {
14
16
  "type": "git",
15
- "url": "git+https://github.com/fwalzel/handlebars-i18n.git"
17
+ "url": "https://github.com/aller-couleur/handlebars-i18n.git"
16
18
  },
17
19
  "keywords": [
18
20
  "handlebars-i18n",
@@ -33,7 +35,7 @@
33
35
  ],
34
36
  "author": "Florian Walzel",
35
37
  "license": "MIT",
36
- "homepage": "https://github.com/fwalzel/handlebars-i18n.git#readme",
38
+ "homepage": "https://github.com/aller-couleur/handlebars-i18n.git#readme",
37
39
  "peerDependencies": {
38
40
  "handlebars": "^4.7.7",
39
41
  "i18next": "^21.6.14",
@@ -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](https://github.com/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,33 +48,40 @@ 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
 
55
+ With ES6 import syntax:
56
+
57
+ ```typescript
58
+ import * as HandlebarsI18n from "handlebars-i18n";
59
+ HandlebarsI18n.init();
60
+ ```
61
+
54
62
  ## Quick example
55
63
 
56
64
  Initialize i18next with your language strings and default settings:
57
65
 
58
66
  ```javascript
59
- const i18next = require('i18next');
67
+ const i18next = require("i18next");
60
68
 
61
69
  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
- }
70
+ resources : {
71
+ "en" : {
72
+ translation : {
73
+ "phrase1": "What is good?",
74
+ "phrase2": "{{thing}} is good."
75
+ }
75
76
  },
76
- lng : "en"
77
+ "de" : {
78
+ translation: {
79
+ "phrase1": "Was ist gut?",
80
+ "phrase2": "{{thing}} ist gut."
81
+ }
82
+ }
83
+ },
84
+ lng : "en"
77
85
  });
78
86
  ```
79
87
 
@@ -81,7 +89,7 @@ Set your Handlebars.js data object:
81
89
 
82
90
  ```javascript
83
91
  let data = {
84
- myItem: "handlebars-i18n",
92
+ myItem: "handlebars-i18n",
85
93
  myPrice: 1200.99,
86
94
  myDate: "2020-03-11T03:24:00"
87
95
  }
@@ -130,19 +138,24 @@ Finally use in template:
130
138
  :point_right: See the *examples folder* in the repo for more use cases and details.
131
139
 
132
140
 
133
- ## Run tests
141
+ ## NEW! :star_struck: Additional CLI Helper for Handlebars-i18n
142
+
143
+ Handlebars-i18n has its own command line interface [handlebars-i18n-cli](https://www.npmjs.com/package/handlebars-i18n-cli) by now.
134
144
 
135
145
  ```bash
136
- $ npm test
146
+ $ npm i handlebars-i18n-cli --save-dev
137
147
  ```
138
148
 
149
+ Automatically extract translation strings from handlebars templates and generate i18next conform json files from it.
150
+ Handlebars-i18n-cli also helps to keep your translations up to date when changes are made in the templates over time.
151
+
139
152
 
140
153
  ## API
141
154
 
142
155
 
143
156
  ### __
144
157
 
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.
158
+ 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
159
  The primary key can be passed hard encoded in the template when written in quotes:
147
160
 
148
161
  ```
@@ -164,12 +177,12 @@ Template usage:
164
177
 
165
178
  The i18next resource:
166
179
 
167
- ```
180
+ ```javascript
168
181
  "en" : {
169
- translation : {
170
- "whatIsWhat": "{{a}} is {{b}}."
171
- }
172
- },
182
+ translation : {
183
+ "whatIsWhat": "{{a}} is {{b}}."
184
+ }
185
+ }
173
186
  ```
174
187
 
175
188
  **Plurals**
@@ -179,12 +192,12 @@ The i18next resource:
179
192
  ```
180
193
 
181
194
  ```javascript
182
- 'en' : {
195
+ "en" : {
183
196
  translation : {
184
- 'keyWithCount': '{{count}} item',
185
- 'keyWithCount_plural': '{{count}} items',
197
+ "keyWithCount" : "{{count}} item",
198
+ "keyWithCount_plural" : "{{count}} items"
186
199
  }
187
- },
200
+ }, ...
188
201
  ```
189
202
 
190
203
  **Override globally selected language**
@@ -193,7 +206,7 @@ The i18next resource:
193
206
  {{__ "key1" lng="de"}}
194
207
  ```
195
208
 
196
- Will output the contents for "**de**" even though other language is selected.
209
+ Will output the contents for "**de**" even though other language is selected.
197
210
 
198
211
  ---
199
212
 
@@ -219,7 +232,7 @@ Checks a string against i18next’s currently selected language. Returns **true*
219
232
 
220
233
  ### _date
221
234
 
222
- Outputs a formated date according to the language specific conventions.
235
+ Outputs a formatted date according to the language specific conventions.
223
236
 
224
237
  ```
225
238
  {{_date}}
@@ -233,6 +246,8 @@ If called without argument the current date is returned. Any other input date ca
233
246
  {{_date "2020-03-11T03:24:00"}}
234
247
  ```
235
248
 
249
+ or
250
+
236
251
  ```
237
252
  {{_date "December 17, 1995 03:24:00"}}
238
253
  ```
@@ -260,7 +275,7 @@ You can add multiple arguments for individual formatting. See [Intl DateTimeForm
260
275
 
261
276
  ### _num
262
277
 
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**".
278
+ 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
279
 
265
280
  ```
266
281
  {{_num 4100000.8314 }}
@@ -279,7 +294,7 @@ Will output **3.14** for "**en**", but **3,14** for "**de**".
279
294
 
280
295
  ### _price
281
296
 
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**".
297
+ 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
298
 
284
299
 
285
300
  ```
@@ -308,52 +323,49 @@ HandlebarsI18n.configure("all", "DateTimeFormat", {timeZone: "America/Los_Angele
308
323
 
309
324
  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
325
 
311
- ### Custom language format subsets
326
+ ### Custom language format subsets
312
327
 
313
- You can define specific subsets to be used in the template, i.e. if you want the date in different formatts such as:
328
+ You can define specific subsets to be used in the template, i.e. if you want the date in different formats such as:
314
329
 
315
330
  - **2020** (year-only)
316
331
  - **11.3.2020** (standard-date)
317
332
  - **7:24:02** (time-only)
318
333
 
319
- To do this define a 4th parameter with a custom name:
320
-
334
+ To do this, define a 4th parameter with a custom name:
321
335
 
322
336
  ```javascript
323
337
  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"]
338
+ ["en", "DateTimeFormat", {year:"numeric"}, "year-only"],
339
+ ["en", "DateTimeFormat", {year:"numeric", month:"numeric", day:"numeric"}, "standard-date"],
340
+ ['en', 'DateTimeFormat', {hour:"numeric", minute:"numeric", second:"numeric", hour12:false}, "time-only"]
327
341
  ]);
328
342
  ```
329
343
 
330
- Call a subset in template wit the parameter "format", like:
344
+ Call a subset in template with the parameter format="custom-name", like:
331
345
 
332
346
  ```
333
347
  {{_date myDate format="year-only"}}
334
348
  ```
335
349
 
336
-
337
-
338
350
  ### The lookup cascade
339
351
 
340
352
  The general lookup cascade is:
341
353
 
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"}}`
354
+ - **1st Priority**: The argument given in the template for custom configurations by the key "format", i.e. `{{_date format="my-custom-format"}}`
355
+ - **2nd Priority**: The extra argument(s) given in the template, e.g. `{{_date timeZone="America/Los_Angeles" year="2-digit"}}`
344
356
  - **3rd Priority**: The global setting configured for the current language, such as "**en**"
345
357
  - **4th Priority**: The global setting configured for **all** languages
346
358
  - **Default**: The **Intl** default setting
347
359
 
348
360
  **Example:**
349
361
 
350
- This defines that all prices for all languages are represented as Dollar:
362
+ This defines that all prices for all languages are represented in Dollar:
351
363
 
352
364
  ```javascript
353
365
  HandlebarsI18n.configure("all", "PriceFormat", {currency: "USD"});
354
366
  ```
355
367
 
356
- This defines that all prices for all languages are represented as Dollar, but that for language French the currency is Euro:
368
+ This defines that all prices for all languages are represented in Dollar, but that for the language French the currency is Euro:
357
369
 
358
370
  ```javascript
359
371
  HandlebarsI18n.configure([
@@ -372,11 +384,13 @@ HandlebarsI18n.reset();
372
384
 
373
385
  ## Using custom instances of Handlebars and/or i18next
374
386
 
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:
387
+ Sometimes you may want to use a Handlebars object you have already modified before, or you may want to use multiple
388
+ discrete instances of Handlebars. In this case you can pass you custom Handlebars instance to the init function to use
389
+ it instead of the generic Handlebars object like so:
376
390
 
377
391
  ```javascript
378
- const HandlebarsModified = require('handlebars');
379
- HandlebarsModified.registerHelper('foo', function() { return 'what you want' });
392
+ const HandlebarsModified = require("handlebars");
393
+ HandlebarsModified.registerHelper("foo", function() { return "what you want" });
380
394
  HandlebarsI18n.init(HandlebarsModified);
381
395
  ```
382
396
 
@@ -385,11 +399,20 @@ HandlebarsI18n will have your previously defined method **foo()** by now.
385
399
  The same can be done for a custom instance of i18next. Pass it as the second argument to the init function.
386
400
 
387
401
  ```javascript
388
- const i18nextCustom = require('i18next');
389
- i18nextCustom.createInstance( /*... pass some params here */ );
402
+ const i18nextCustom = require("i18next");
403
+ i18nextCustom.createInstance( /* pass some params here ... */ );
390
404
  HandlebarsI18n.init(null, i18nextCustom);
391
405
  ```
392
406
 
407
+ ## Run tests
408
+
409
+ ```bash
410
+ $ npm test
411
+ ```
412
+
413
+ ## Merci à vous
414
+
415
+ For your contribution, I would like to thank [@MickL](https://github.com/MickL), [@dargmuesli](https://github.com/dargmuesli), and [@DiefBell](DiefBell).
393
416
 
394
417
  ## Note
395
418