i18n-js 3.3.0 → 3.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +1 -1
  3. data/.github/FUNDING.yml +3 -0
  4. data/.github/workflows/tests.yaml +106 -0
  5. data/Appraisals +16 -0
  6. data/CHANGELOG.md +153 -4
  7. data/README.md +505 -333
  8. data/app/assets/javascripts/i18n/shims.js +35 -3
  9. data/app/assets/javascripts/i18n.js +37 -33
  10. data/gemfiles/i18n_1_10.gemfile +7 -0
  11. data/gemfiles/i18n_1_7.gemfile +7 -0
  12. data/gemfiles/i18n_1_8.gemfile +7 -0
  13. data/gemfiles/i18n_1_9.gemfile +7 -0
  14. data/i18n-js.gemspec +2 -2
  15. data/i18njs.png +0 -0
  16. data/lib/i18n/js/dependencies.rb +6 -2
  17. data/lib/i18n/js/engine.rb +1 -1
  18. data/lib/i18n/js/formatters/base.rb +3 -1
  19. data/lib/i18n/js/formatters/js.rb +12 -4
  20. data/lib/i18n/js/middleware.rb +1 -1
  21. data/lib/i18n/js/private/config_store.rb +31 -0
  22. data/lib/i18n/js/segment.rb +9 -3
  23. data/lib/i18n/js/utils.rb +34 -8
  24. data/lib/i18n/js/version.rb +1 -1
  25. data/lib/i18n/js.rb +25 -10
  26. data/package.json +2 -2
  27. data/spec/fixtures/js_available_locales_custom.yml +1 -0
  28. data/spec/fixtures/{js_file_with_namespace_and_pretty_print.yml → js_file_with_namespace_prefix_and_pretty_print.yml} +2 -0
  29. data/spec/fixtures/locales.yml +38 -0
  30. data/spec/fixtures/merge_plurals_with_no_overrides.yml +4 -0
  31. data/spec/fixtures/merge_plurals_with_partial_overrides.yml +4 -0
  32. data/spec/fixtures/millions.yml +4 -0
  33. data/spec/js/dates.spec.js +1 -0
  34. data/spec/js/json_parsable.spec.js +14 -0
  35. data/spec/js/localization.spec.js +38 -14
  36. data/spec/js/numbers.spec.js +4 -0
  37. data/spec/js/pluralization.spec.js +19 -2
  38. data/spec/js/require.js +4 -4
  39. data/spec/js/translate.spec.js +68 -48
  40. data/spec/js/translations.js +27 -2
  41. data/spec/ruby/i18n/js/segment_spec.rb +75 -8
  42. data/spec/ruby/i18n/js/utils_spec.rb +32 -0
  43. data/spec/ruby/i18n/js_spec.rb +169 -35
  44. data/spec/spec_helper.rb +1 -0
  45. data/yarn.lock +32 -25
  46. metadata +26 -9
  47. data/.travis.yml +0 -37
data/README.md CHANGED
@@ -1,14 +1,21 @@
1
- # I18n.js
1
+ <p align="center">
2
+ <img width="250" height="58" src="https://github.com/fnando/i18n-js/raw/main/i18njs.png" alt="i18n.js">
3
+ </p>
2
4
 
3
- [![Gem Version](http://img.shields.io/gem/v/i18n-js.svg?style=flat-square)](http://badge.fury.io/rb/i18n-js)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
5
+ <p align="center">
6
+ It's a small library to provide the Rails I18n translations on the JavaScript.
7
+ </p>
5
8
 
6
- [![Build Status](http://img.shields.io/travis/fnando/i18n-js.svg?style=flat-square)](https://travis-ci.org/fnando/i18n-js)
7
- [![Coverage Status](http://img.shields.io/coveralls/fnando/i18n-js.svg?style=flat-square)](https://coveralls.io/r/fnando/i18n-js)
9
+ <p align="center">
10
+ <a href="https://github.com/fnando/i18n-js/actions?query=workflow%3ATests"><img src="https://github.com/fnando/i18n-js/workflows/Tests/badge.svg" alt="Tests"></a>
11
+ <a href="https://badge.fury.io/rb/i18n-js"><img src="https://img.shields.io/gem/v/i18n-js.svg" alt="Gem Version"></a>
12
+ <a href="https://www.npmjs.com/package/i18n-js"><img src="https://img.shields.io/npm/v/i18n-js.svg" alt="npm"></a>
13
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
14
+ <a href="https://coveralls.io/r/fnando/i18n-js"><img src="https://img.shields.io/coveralls/fnando/i18n-js.svg" alt="Coverage Status"></a>
15
+ <a href="https://gitter.im/fnando/i18n-js"><img src="https://img.shields.io/badge/gitter-join%20chat-1dce73.svg" alt="Gitter"></a>
16
+ </p>
8
17
 
9
- [![Gitter](https://img.shields.io/badge/gitter-join%20chat-1dce73.svg?style=flat-square)](https://gitter.im/fnando/i18n-js)
10
-
11
- It's a small library to provide the Rails I18n translations on the JavaScript.
18
+ ---
12
19
 
13
20
  Features:
14
21
 
@@ -20,8 +27,9 @@ Features:
20
27
  - Lots more! :)
21
28
 
22
29
  ## Version Notice
23
- The `master` branch (including this README) is for latest `3.0.0` instead of `2.x`.
24
30
 
31
+ The `main` branch (including this README) is for latest `3.0.0` instead of
32
+ `2.x`.
25
33
 
26
34
  ## Usage
27
35
 
@@ -30,14 +38,31 @@ The `master` branch (including this README) is for latest `3.0.0` instead of `2.
30
38
  #### Rails app
31
39
 
32
40
  Add the gem to your Gemfile.
41
+
33
42
  ```ruby
34
43
  gem "i18n-js"
35
44
  ```
36
45
 
37
- #### Rails app with [Asset Pipeline](http://guides.rubyonrails.org/asset_pipeline.html)
46
+ #### Rails with [webpacker](https://github.com/rails/webpacker)
47
+
48
+ If you're using `webpacker`, you may need to add the dependencies to your client
49
+ with:
50
+
51
+ ```
52
+ yarn add i18n-js
53
+ # or, if you're using npm,
54
+ npm install i18n-js
55
+ ```
56
+
57
+ For more details, see:
58
+ - [this gist](https://gist.github.com/bazzel/ecdff4718962e57c2d5569cf01d332fe)
59
+ - https://github.com/fnando/i18n-js/issues/597
60
+
61
+ #### Rails app with [Asset Pipeline](https://guides.rubyonrails.org/asset_pipeline.html)
38
62
 
39
- If you're using the [asset pipeline](http://guides.rubyonrails.org/asset_pipeline.html),
40
- then you must add the following line to your `app/assets/javascripts/application.js`.
63
+ If you're using the
64
+ [asset pipeline](https://guides.rubyonrails.org/asset_pipeline.html), then you
65
+ must add the following line to your `app/assets/javascripts/application.js`.
41
66
 
42
67
  ```javascript
43
68
  //
@@ -51,11 +76,11 @@ then you must add the following line to your `app/assets/javascripts/application
51
76
  //= require i18n/translations
52
77
  ```
53
78
 
54
- #### Rails app without [Asset Pipeline](http://guides.rubyonrails.org/asset_pipeline.html)
79
+ #### Rails app without [Asset Pipeline](https://guides.rubyonrails.org/asset_pipeline.html)
55
80
 
81
+ First, put this in your `application.html` (layout file). Then get the JS files
82
+ following the instructions below.
56
83
 
57
- First, put this in your `application.html` (layout file).
58
- Then get the JS files following the instructions below.
59
84
  ```erb
60
85
  <%# This is just an example, you can put `i18n.js` and `translations.js` anywhere you like %>
61
86
  <%# Unlike the Asset Pipeline example, you need to require both **in order** %>
@@ -63,55 +88,66 @@ Then get the JS files following the instructions below.
63
88
  <%= javascript_include_tag "translations", skip_pipeline: true %>
64
89
  ```
65
90
 
66
- **There are two ways to get `translations.js` (For Rails app without Asset Pipeline).**
67
-
68
- 1. This `translations.js` file can be automatically generated by the `I18n::JS::Middleware`.
69
- Just add `config.middleware.use I18n::JS::Middleware` to your `config/application.rb` file.
70
- 2. If you can't or prefer not to generate this file,
71
- you can move the middleware line to your `config/environments/development.rb` file
72
- and run `rake i18n:js:export` before deploying.
73
- This will export all translation files, including the custom scopes
74
- you may have defined on `config/i18n-js.yml`.
75
- If `I18n.available_locales` is set (e.g. in your Rails `config/application.rb` file)
76
- then only the specified locales will be exported.
77
- Current version of `i18n.js` will also be exported to avoid version mismatching by downloading.
91
+ **There are two ways to get `translations.js` (For Rails app without Asset
92
+ Pipeline).**
93
+
94
+ 1. This `translations.js` file can be automatically generated by the
95
+ `I18n::JS::Middleware`. Just add `config.middleware.use I18n::JS::Middleware`
96
+ to your `config/application.rb` file.
97
+ 2. If you can't or prefer not to generate this file, you can move the middleware
98
+ line to your `config/environments/development.rb` file and run
99
+ `rake i18n:js:export` before deploying. This will export all translation
100
+ files, including the custom scopes you may have defined on
101
+ `config/i18n-js.yml`. If `I18n.available_locales` is set (e.g. in your Rails
102
+ `config/application.rb` file) then only the specified locales will be
103
+ exported. Current version of `i18n.js` will also be exported to avoid version
104
+ mismatching by downloading.
78
105
 
79
106
  #### Export Configuration (For translations)
80
107
 
81
- Exported translation files generated by `I18n::JS::Middleware` or `rake i18n:js:export` can be customized with config file `config/i18n-js.yml`
82
- (use `rails generate i18n:js:config` to create it).
83
- You can even get more files generated to different folders and with different translations to best suit your needs.
84
- The config file also affects developers using Asset Pipeline to require translations.
85
- Except the option `file`, since all translations are required by adding `//= require i18n/translations`.
108
+ Exported translation files generated by `I18n::JS::Middleware` or
109
+ `rake i18n:js:export` can be customized with config file `config/i18n-js.yml`
110
+ (use `rails generate i18n:js:config` to create it). You can even get more files
111
+ generated to different folders and with different translations to best suit your
112
+ needs. The config file also affects developers using Asset Pipeline to require
113
+ translations. Except the option `file`, since all translations are required by
114
+ adding `//= require i18n/translations`.
86
115
 
87
116
  Examples:
117
+
88
118
  ```yaml
89
119
  translations:
90
- - file: 'public/javascripts/path-to-your-messages-file.js'
91
- only: '*.date.formats'
92
- - file: 'public/javascripts/path-to-your-second-file.js'
93
- only: ['*.activerecord', '*.admin.*.title']
120
+ - file: "public/javascripts/path-to-your-messages-file.js"
121
+ only: "*.date.formats"
122
+ - file: "public/javascripts/path-to-your-second-file.js"
123
+ only: ["*.activerecord", "*.admin.*.title"]
94
124
  ```
95
125
 
96
- If `only` is omitted all the translations will be saved. Also, make sure you add that initial `*`; it specifies that all languages will be exported. If you want to export only one language, you can do something like this:
126
+ If `only` is omitted all the translations will be saved. Also, make sure you add
127
+ that initial `*`; it specifies that all languages will be exported. If you want
128
+ to export only one language, you can do something like this:
129
+
97
130
  ```yaml
98
131
  translations:
99
- - file: 'public/javascripts/en.js'
100
- only: 'en.*'
101
- - file: 'public/javascripts/pt-BR.js'
102
- only: 'pt-BR.*'
132
+ - file: "public/javascripts/en.js"
133
+ only: "en.*"
134
+ - file: "public/javascripts/pt-BR.js"
135
+ only: "pt-BR.*"
103
136
  ```
104
137
 
105
- Optionally, you can auto generate a translation file per available locale if you specify the `%{locale}` placeholder.
138
+ Optionally, you can auto generate a translation file per available locale if you
139
+ specify the `%{locale}` placeholder.
140
+
106
141
  ```yaml
107
142
  translations:
108
- - file: "public/javascripts/i18n/%{locale}.js"
109
- only: '*'
110
- - file: "public/javascripts/frontend/i18n/%{locale}.js"
111
- only: ['*.frontend', '*.users.*']
143
+ - file: "public/javascripts/i18n/%{locale}.js"
144
+ only: "*"
145
+ - file: "public/javascripts/frontend/i18n/%{locale}.js"
146
+ only: ["*.frontend", "*.users.*"]
112
147
  ```
113
148
 
114
149
  You can also include ERB in your config file.
150
+
115
151
  ```yaml
116
152
  translations:
117
153
  <% Widgets.each do |widget| %>
@@ -120,39 +156,37 @@ translations:
120
156
  <% end %>
121
157
  ```
122
158
 
123
- You are able to exclude certain phrases or whole groups of phrases by
124
- specifying the YAML key(s) in the `except` configuration option. The outputted
125
- JS translations file (exported or generated by the middleware) will omit any
126
- keys listed in `except` configuration param:
159
+ You are able to exclude certain phrases or whole groups of phrases by specifying
160
+ the YAML key(s) in the `except` configuration option. The outputted JS
161
+ translations file (exported or generated by the middleware) will omit any keys
162
+ listed in `except` configuration param:
127
163
 
128
164
  ```yaml
129
165
  translations:
130
- - except: ['*.active_admin', '*.ransack', '*.activerecord.errors']
166
+ - except: ["*.active_admin", "*.ransack", "*.activerecord.errors"]
131
167
  ```
132
168
 
133
-
134
169
  #### Export Configuration (For other things)
135
170
 
136
- - `I18n::JS.config_file_path`
137
- Expected Type: `String`
138
- Default: `config/i18n-js.yml`
139
- Behaviour: Try to read the config file from that location
171
+ - `I18n::JS.config_file_path` Expected Type: `String` Default:
172
+ `config/i18n-js.yml` Behaviour: Try to read the config file from that location
140
173
 
141
- - `I18n::JS.export_i18n_js_dir_path`
142
- Expected Type: `String`
143
- Default: `public/javascripts`
144
- Behaviour:
145
- - Any `String`: considered as a relative path for a folder to `Rails.root` and export `i18n.js` to that folder for `rake i18n:js:export`
174
+ - `I18n::JS.export_i18n_js_dir_path` Expected Type: `String` Default:
175
+ `public/javascripts` Behaviour:
176
+
177
+ - Any `String`: considered as a relative path for a folder to `Rails.root` and
178
+ export `i18n.js` to that folder for `rake i18n:js:export`
146
179
  - Any non-`String` (`nil`, `false`, `:none`, etc): Disable `i18n.js` exporting
147
180
 
148
- - `I18n::JS.sort_translation_keys`
149
- Expected Type: `Boolean`
150
- Default: `true`
181
+ - `I18n::JS.sort_translation_keys` Expected Type: `Boolean` Default: `true`
151
182
  Behaviour:
152
- - Sets whether or not to deep sort all translation keys in order to generate identical output for the same translations
183
+
184
+ - Sets whether or not to deep sort all translation keys in order to generate
185
+ identical output for the same translations
153
186
  - Set to true to ensure identical asset fingerprints for the asset pipeline
154
187
 
155
- - You may also set `export_i18n_js` and `sort_translation_keys` in your config file, e.g.:
188
+ - You may also set `export_i18n_js` and `sort_translation_keys` in your config
189
+ file, e.g.:
156
190
 
157
191
  ```yaml
158
192
  export_i18n_js: false
@@ -165,21 +199,24 @@ translations:
165
199
  - ...
166
200
  ```
167
201
 
168
- To find more examples on how to use the configuration file please refer to the tests.
202
+ To find more examples on how to use the configuration file please refer to the
203
+ tests.
169
204
 
170
205
  #### Fallbacks
171
206
 
172
- If you specify the `fallbacks` option, you will be able to fill missing translations with those inside fallback locale(s).
173
- Default value is `true`.
207
+ If you specify the `fallbacks` option, you will be able to fill missing
208
+ translations with those inside fallback locale(s). Default value is `true`.
174
209
 
175
210
  Examples:
211
+
176
212
  ```yaml
177
213
  fallbacks: true
178
214
 
179
215
  translations:
180
- - file: "public/javascripts/i18n/%{locale}.js"
181
- only: '*'
216
+ - file: "public/javascripts/i18n/%{locale}.js"
217
+ only: "*"
182
218
  ```
219
+
183
220
  This will enable merging fallbacks into each file. (set to `false` to disable).
184
221
  If you use `I18n` with fallbacks, the fallbacks defined there will be used.
185
222
  Otherwise `I18n.default_locale` will be used.
@@ -188,9 +225,10 @@ Otherwise `I18n.default_locale` will be used.
188
225
  fallbacks: :de
189
226
 
190
227
  translations:
191
- - file: "public/javascripts/i18n/%{locale}.js"
192
- only: '*'
228
+ - file: "public/javascripts/i18n/%{locale}.js"
229
+ only: "*"
193
230
  ```
231
+
194
232
  Here, the specified locale `:de` will be used as fallback for all locales.
195
233
 
196
234
  ```yaml
@@ -199,42 +237,60 @@ fallbacks:
199
237
  de: "en"
200
238
 
201
239
  translations:
202
- - file: "public/javascripts/i18n/%{locale}.js"
203
- only: '*'
240
+ - file: "public/javascripts/i18n/%{locale}.js"
241
+ only: "*"
204
242
  ```
205
- Fallbacks defined will be used, if not defined (e.g. `:pl`) `I18n.fallbacks` or `I18n.default_locale` will be used.
243
+
244
+ Fallbacks defined will be used, if not defined (e.g. `:pl`) `I18n.fallbacks` or
245
+ `I18n.default_locale` will be used.
206
246
 
207
247
  ```yaml
208
248
  fallbacks: :default_locale
209
249
 
210
250
  translations:
211
- - file: "public/javascripts/i18n/%{locale}.js"
212
- only: '*'
251
+ - file: "public/javascripts/i18n/%{locale}.js"
252
+ only: "*"
213
253
  ```
214
- Setting the option to `:default_locale` will enforce the fallback to use the `I18n.default_locale`, ignoring `I18n.fallbacks`.
254
+
255
+ Setting the option to `:default_locale` will enforce the fallback to use the
256
+ `I18n.default_locale`, ignoring `I18n.fallbacks`.
215
257
 
216
258
  Examples:
259
+
217
260
  ```yaml
218
261
  fallbacks: false
219
262
 
220
263
  translations:
221
- - file: "public/javascripts/i18n/%{locale}.js"
222
- only: '*'
264
+ - file: "public/javascripts/i18n/%{locale}.js"
265
+ only: "*"
223
266
  ```
267
+
224
268
  You must disable this feature by setting the option to `false`.
225
269
 
226
- To find more examples on how to use the configuration file please refer to the tests.
270
+ To find more examples on how to use the configuration file please refer to the
271
+ tests.
272
+
273
+ #### Available locales
227
274
 
275
+ By specifying option `js_available_locales` with a list of locales, this list
276
+ would be used instead of default `I18n.available_locales` to generate translations.
277
+
278
+ Example:
279
+
280
+ ```yaml
281
+ js_available_locales: ["de", "en"]
282
+ ```
228
283
 
229
284
  #### Namespace
230
285
 
231
- Setting the `namespace` option will change the namespace of the output Javascript file to something other than `I18n`.
232
- This can be useful in no-conflict scenarios. Example:
286
+ Setting the `namespace` option will change the namespace of the output
287
+ Javascript file to something other than `I18n`. This can be useful in
288
+ no-conflict scenarios. Example:
233
289
 
234
290
  ```yaml
235
291
  translations:
236
- - file: "public/javascripts/i18n/translations.js"
237
- namespace: "MyNamespace"
292
+ - file: "public/javascripts/i18n/translations.js"
293
+ namespace: "MyNamespace"
238
294
  ```
239
295
 
240
296
  will create:
@@ -244,43 +300,67 @@ MyNamespace.translations || (MyNamespace.translations = {});
244
300
  MyNamespace.translations["en"] = { ... }
245
301
  ```
246
302
 
303
+ ### Adding prefix & suffix to the translations file(s)
247
304
 
248
- #### Pretty Print
305
+ Setting the `prefix: "import I18n from 'i18n-js';\n"` option will add the line
306
+ at the beginning of the resultant translation file. This can be useful to use
307
+ this gem with the [i18n-js](https://www.npmjs.com/package/i18n-js) npm package,
308
+ which is quite useful to use it with webpack. The user should provide the
309
+ semi-colon and the newline character if needed.
249
310
 
250
- Set the `pretty_print` option if you would like whitespace and indentation in your output file (default: false)
311
+ For example:
251
312
 
252
313
  ```yaml
253
314
  translations:
254
- - file: "public/javascripts/i18n/translations.js"
255
- pretty_print: true
315
+ - file: "public/javascripts/i18n/translations.js"
316
+ prefix: "import I18n from 'i18n-js';\n"
256
317
  ```
257
318
 
319
+ will create:
258
320
 
259
- #### Javascript Deep Merge (:js_extend option)
321
+ ```
322
+ import I18n from 'i18n-js';
323
+ I18n.translations || (I18n.translations = {});
324
+ ```
260
325
 
261
- By default, the output file Javascript will call the `I18n.extend` method to ensure that newly loaded locale
262
- files are deep-merged with any locale data already in memory. To disable this either globally or per-file,
263
- set the `js_extend` option to false
326
+ `suffix` option is added in https://github.com/fnando/i18n-js/pull/561.
327
+ It's similar to `prefix` so won't explain it in details.
328
+
329
+ #### Pretty Print
330
+
331
+ Set the `pretty_print` option if you would like whitespace and indentation in
332
+ your output file (default: false)
264
333
 
265
334
  ```yaml
266
- js_extend: false # this will disable Javascript I18n.extend globally
267
335
  translations:
268
- - file: "public/javascripts/i18n/translations.js"
269
- js_extend: false # this will disable Javascript I18n.extend for this file
336
+ - file: "public/javascripts/i18n/translations.js"
337
+ pretty_print: true
270
338
  ```
271
339
 
340
+ #### Javascript Deep Merge (:js_extend option)
272
341
 
273
- #### Vanilla JavaScript
342
+ By default, the output file Javascript will call the `I18n.extend` method to
343
+ ensure that newly loaded locale files are deep-merged with any locale data
344
+ already in memory. To disable this either globally or per-file, set the
345
+ `js_extend` option to false
274
346
 
275
- Just add the `i18n.js` file to your page. You'll have to build the translations object
276
- by hand or using your favorite programming language. More info below.
347
+ ```yaml
348
+ js_extend: false # this will disable Javascript I18n.extend globally
349
+ translations:
350
+ - file: "public/javascripts/i18n/translations.js"
351
+ js_extend: false # this will disable Javascript I18n.extend for this file
352
+ ```
277
353
 
354
+ #### Vanilla JavaScript
355
+
356
+ Just add the `i18n.js` file to your page. You'll have to build the translations
357
+ object by hand or using your favorite programming language. More info below.
278
358
 
279
359
  #### Via NPM with webpack and CommonJS
280
360
 
361
+ Add the following line to your package.json dependencies where version is the
362
+ version you want:
281
363
 
282
- Add the following line to your package.json dependencies
283
- where version is the version you want
284
364
  ```javascript
285
365
  "i18n-js": "{version_constraint}"
286
366
 
@@ -288,17 +368,21 @@ where version is the version you want
288
368
  // npm install requires it to be the gzipped tarball, see [npm install](https://www.npmjs.org/doc/cli/npm-install.html)
289
369
  "i18n-js": "https://github.com/fnando/i18n-js/archive/{tag_name_or_branch_name_or_commit_sha}.tar.gz"
290
370
  ```
371
+
291
372
  Run npm install then use via
373
+
292
374
  ```javascript
293
375
  var i18n = require("i18n-js");
294
376
  ```
295
377
 
296
-
297
378
  ### Setting up
298
379
 
299
- You **don't** need to set up a thing. The default settings will work just okay. But if you want to split translations into several files or specify specific contexts, you can follow the rest of this setting up section.
380
+ You **don't** need to set up a thing. The default settings will work just okay.
381
+ But if you want to split translations into several files or specify contexts,
382
+ you can follow the rest of this setting up section.
300
383
 
301
384
  Set your locale is easy as
385
+
302
386
  ```javascript
303
387
  I18n.defaultLocale = "pt-BR";
304
388
  I18n.locale = "pt-BR";
@@ -306,9 +390,11 @@ I18n.currentLocale();
306
390
  // pt-BR
307
391
  ```
308
392
 
309
- **NOTE:** You can now apply your configuration **before I18n** is loaded like this:
393
+ **NOTE:** You can now apply your configuration **before I18n** is loaded like
394
+ this:
395
+
310
396
  ```javascript
311
- I18n = {} // You must define this object in top namespace, which should be `window`
397
+ I18n = {}; // You must define this object in top namespace, which should be `window`
312
398
  I18n.defaultLocale = "pt-BR";
313
399
  I18n.locale = "pt-BR";
314
400
 
@@ -318,7 +404,8 @@ I18n.currentLocale();
318
404
  // pt-BR
319
405
  ```
320
406
 
321
- In practice, you'll have something like the following in your `application.html.erb`:
407
+ In practice, you'll have something like the following in your
408
+ `application.html.erb`:
322
409
 
323
410
  ```erb
324
411
  <script type="text/javascript">
@@ -332,7 +419,7 @@ You can use translate your messages:
332
419
  ```javascript
333
420
  I18n.t("some.scoped.translation");
334
421
  // or translate with explicit setting of locale
335
- I18n.t("some.scoped.translation", {locale: "fr"});
422
+ I18n.t("some.scoped.translation", { locale: "fr" });
336
423
  ```
337
424
 
338
425
  You can also interpolate values:
@@ -340,36 +427,38 @@ You can also interpolate values:
340
427
  ```javascript
341
428
  // You need the `translations` object setup first
342
429
  I18n.translations["en"] = {
343
- greeting: "Hello %{name}"
344
- }
430
+ greeting: "Hello %{name}",
431
+ };
345
432
 
346
- I18n.t("greeting", {name: "John Doe"});
433
+ I18n.t("greeting", { name: "John Doe" });
347
434
  ```
435
+
348
436
  You can set default values for missing scopes:
437
+
349
438
  ```javascript
350
439
  // simple translation
351
- I18n.t("some.missing.scope", {defaultValue: "A default message"});
440
+ I18n.t("some.missing.scope", { defaultValue: "A default message" });
352
441
 
353
442
  // with interpolation
354
- I18n.t("noun", {defaultValue: "I'm a {{noun}}", noun: "Mac"});
443
+ I18n.t("noun", { defaultValue: "I'm a {{noun}}", noun: "Mac" });
355
444
  ```
356
445
 
357
446
  You can also provide a list of default fallbacks for missing scopes:
358
447
 
359
448
  ```javascript
360
449
  // As a scope
361
- I18n.t("some.missing.scope", {defaults: [{scope: "some.existing.scope"}]});
450
+ I18n.t("some.missing.scope", { defaults: [{ scope: "some.existing.scope" }] });
362
451
 
363
452
  // As a simple translation
364
- I18n.t("some.missing.scope", {defaults: [{message: "Some message"}]});
453
+ I18n.t("some.missing.scope", { defaults: [{ message: "Some message" }] });
365
454
  ```
366
455
 
367
- Default values must be provided as an array of hashs where the key is the
368
- type of translation desired, a `scope` or a `message`. The translation returned
369
- will be either the first scope recognized, or the first message defined.
456
+ Default values must be provided as an array of hashes where the key is the type
457
+ of translation desired, a `scope` or a `message`. The translation returned will
458
+ be either the first scope recognized, or the first message defined.
370
459
 
371
- The translation will fallback to the `defaultValue` translation if no scope
372
- in `defaults` matches and if no default of type `message` is found.
460
+ The translation will fallback to the `defaultValue` translation if no scope in
461
+ `defaults` matches and if no default of type `message` is found.
373
462
 
374
463
  Translation fallback can be enabled by enabling the `I18n.fallbacks` option:
375
464
 
@@ -379,9 +468,9 @@ Translation fallback can be enabled by enabling the `I18n.fallbacks` option:
379
468
  </script>
380
469
  ```
381
470
 
382
- By default missing translations will first be looked for in less
383
- specific versions of the requested locale and if that fails by taking
384
- them from your `I18n.defaultLocale`.
471
+ By default missing translations will first be looked for in less specific
472
+ versions of the requested locale and if that fails by taking them from your
473
+ `I18n.defaultLocale`.
385
474
 
386
475
  ```javascript
387
476
  // if I18n.defaultLocale = "en" and translation doesn't exist
@@ -390,24 +479,28 @@ them from your `I18n.defaultLocale`.
390
479
  I18n.t("some.missing.scope");
391
480
  ```
392
481
 
393
- Custom fallback rules can also be specified for a particular language. There
394
- are three different ways of doing it so:
482
+ Custom fallback rules can also be specified for a particular language. There are
483
+ three different ways of doing it so:
395
484
 
396
485
  ```javascript
397
486
  I18n.locales.no = ["nb", "en"];
398
487
  I18n.locales.no = "nb";
399
- I18n.locales.no = function(locale){ return ["nb"]; };
488
+ I18n.locales.no = function (locale) {
489
+ return ["nb"];
490
+ };
400
491
  ```
401
492
 
493
+ ### Translation Missing Behaviour Control
494
+
402
495
  By default a missing translation will be displayed as
403
496
 
404
497
  [missing "name of scope" translation]
405
498
 
406
- While you are developing or if you do not want to provide a translation
407
- in the default language you can set
499
+ While you are developing or if you do not want to provide a translation in the
500
+ default language you can set
408
501
 
409
502
  ```javascript
410
- I18n.missingBehaviour='guess';
503
+ I18n.missingBehaviour = "guess";
411
504
  ```
412
505
 
413
506
  this will take the last section of your scope and guess the intended value.
@@ -417,28 +510,49 @@ Camel case becomes lower cased text and underscores are replaced with space
417
510
 
418
511
  becomes "what is your favorite Christmas present"
419
512
 
420
- In order to still detect untranslated strings, you can
421
- i18n.missingTranslationPrefix to something like:
513
+ #### Option `missingTranslationPrefix`
514
+
515
+ In order to still detect untranslated strings, you can set
516
+ `I18n.missingTranslationPrefix` to something like:
517
+
422
518
  ```javascript
423
- I18n.missingTranslationPrefix = 'EE: ';
519
+ I18n.missingTranslationPrefix = "EE: ";
424
520
  ```
425
521
 
426
522
  And result will be:
523
+
427
524
  ```javascript
428
- "EE: what is your favorite Christmas present"
525
+ "EE: what is your favorite Christmas present";
526
+
429
527
  ```
430
528
 
431
529
  This will help you doing automated tests against your localisation assets.
432
530
 
433
- Some people prefer returning `null` for missing translation:
531
+ #### Customize return when translation entry missing
532
+
533
+ Some people prefer returning `null`/`undefined` for missing translation:
534
+
434
535
  ```javascript
435
- I18n.missingTranslation = function () { return undefined; };
536
+ I18n.missingTranslation = function (scope, options) {
537
+ return undefined;
538
+ };
436
539
  ```
437
540
 
541
+ ### Option `defaultSeparator` (global) / `separator` (local)
542
+
543
+ Default separator of translation key is `.` (dot)
544
+ Meaning `I18n.t("scope.entry")` would search for translation entry `I18n.translations[locale].scope.entry`
545
+ Using a different separator can be done either globally or locally.
546
+
547
+ Globally: `I18n.defaultSeparator = newSeparator`
548
+ Locally: `I18n.t("full_sentences|Server Busy. Please retry later", {separator: '|'})`
549
+
550
+ ### Pluralization
551
+
438
552
  Pluralization is possible as well and by default provides English rules:
439
553
 
440
554
  ```javascript
441
- I18n.t("inbox.counting", {count: 10}); // You have 10 messages
555
+ I18n.t("inbox.counting", { count: 10 }); // You have 10 messages
442
556
  ```
443
557
 
444
558
  The sample above expects the following translation:
@@ -454,21 +568,34 @@ en:
454
568
 
455
569
  **NOTE:** Rails I18n recognizes the `zero` option.
456
570
 
457
- If you need special rules just define them for your language, for example Russian, just add a new pluralizer:
571
+ If you need special rules just define them for your language, for example
572
+ Russian, just add a new pluralizer:
458
573
 
459
574
  ```javascript
460
575
  I18n.pluralization["ru"] = function (count) {
461
- var key = count % 10 == 1 && count % 100 != 11 ? "one" : [2, 3, 4].indexOf(count % 10) >= 0 && [12, 13, 14].indexOf(count % 100) < 0 ? "few" : count % 10 == 0 || [5, 6, 7, 8, 9].indexOf(count % 10) >= 0 || [11, 12, 13, 14].indexOf(count % 100) >= 0 ? "many" : "other";
576
+ var key =
577
+ count % 10 == 1 && count % 100 != 11
578
+ ? "one"
579
+ : [2, 3, 4].indexOf(count % 10) >= 0 &&
580
+ [12, 13, 14].indexOf(count % 100) < 0
581
+ ? "few"
582
+ : count % 10 == 0 ||
583
+ [5, 6, 7, 8, 9].indexOf(count % 10) >= 0 ||
584
+ [11, 12, 13, 14].indexOf(count % 100) >= 0
585
+ ? "many"
586
+ : "other";
462
587
  return [key];
463
588
  };
464
589
  ```
465
590
 
466
- You can find all rules on <http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html>.
591
+ You can find all rules on
592
+ <https://unicode-org.github.io/cldr-staging/charts/37/supplemental/language_plural_rules.html>.
467
593
 
468
- If you're using the same scope over and over again, you may use the `scope` option.
594
+ If you're using the same scope over and over again, you may use the `scope`
595
+ option.
469
596
 
470
597
  ```javascript
471
- var options = {scope: "activerecord.attributes.user"};
598
+ var options = { scope: "activerecord.attributes.user" };
472
599
 
473
600
  I18n.t("name", options);
474
601
  I18n.t("email", options);
@@ -497,14 +624,13 @@ I18n.l("percentage", 123.45);
497
624
  // 123.450%
498
625
  ```
499
626
 
500
- To have more control over number formatting, you can use the
501
- `I18n.toNumber`, `I18n.toPercentage`, `I18n.toCurrency` and `I18n.toHumanSize`
502
- functions.
627
+ To have more control over number formatting, you can use the `I18n.toNumber`,
628
+ `I18n.toPercentage`, `I18n.toCurrency` and `I18n.toHumanSize` functions.
503
629
 
504
630
  ```javascript
505
- I18n.toNumber(1000); // 1,000.000
506
- I18n.toCurrency(1000); // $1,000.00
507
- I18n.toPercentage(100); // 100.000%
631
+ I18n.toNumber(1000); // 1,000.000
632
+ I18n.toCurrency(1000); // $1,000.00
633
+ I18n.toPercentage(100); // 100.000%
508
634
  ```
509
635
 
510
636
  The `toNumber` and `toPercentage` functions accept the following options:
@@ -517,9 +643,9 @@ The `toNumber` and `toPercentage` functions accept the following options:
517
643
  See some number formatting examples:
518
644
 
519
645
  ```javascript
520
- I18n.toNumber(1000, {precision: 0}); // 1,000
521
- I18n.toNumber(1000, {delimiter: ".", separator: ","}); // 1.000,000
522
- I18n.toNumber(1000, {delimiter: ".", precision: 0}); // 1.000
646
+ I18n.toNumber(1000, { precision: 0 }); // 1,000
647
+ I18n.toNumber(1000, { delimiter: ".", separator: "," }); // 1.000,000
648
+ I18n.toNumber(1000, { delimiter: ".", precision: 0 }); // 1.000
523
649
  ```
524
650
 
525
651
  The `toCurrency` function accepts the following options:
@@ -535,7 +661,7 @@ The `toCurrency` function accepts the following options:
535
661
  You can provide only the options you want to override:
536
662
 
537
663
  ```javascript
538
- I18n.toCurrency(1000, {precision: 0}); // $1,000
664
+ I18n.toCurrency(1000, { precision: 0 }); // $1,000
539
665
  ```
540
666
 
541
667
  The `toHumanSize` function accepts the following options:
@@ -545,6 +671,7 @@ The `toHumanSize` function accepts the following options:
545
671
  - `delimiter`: defaults to `""`
546
672
  - `strip_insignificant_zeros`: defaults to `false`
547
673
  - `format`: defaults to `%n%u`
674
+ - `scope`: defaults to `""`
548
675
 
549
676
  <!---->
550
677
 
@@ -553,18 +680,17 @@ I18n.toHumanSize(1234); // 1KB
553
680
  I18n.toHumanSize(1234 * 1024); // 1MB
554
681
  ```
555
682
 
556
-
557
683
  #### Date formatting
558
684
 
559
685
  ```javascript
560
686
  // accepted formats
561
- I18n.l("date.formats.short", "2009-09-18"); // yyyy-mm-dd
562
- I18n.l("time.formats.short", "2009-09-18 23:12:43"); // yyyy-mm-dd hh:mm:ss
563
- I18n.l("time.formats.short", "2009-11-09T18:10:34"); // JSON format with local Timezone (part of ISO-8601)
687
+ I18n.l("date.formats.short", "2009-09-18"); // yyyy-mm-dd
688
+ I18n.l("time.formats.short", "2009-09-18 23:12:43"); // yyyy-mm-dd hh:mm:ss
689
+ I18n.l("time.formats.short", "2009-11-09T18:10:34"); // JSON format with local Timezone (part of ISO-8601)
564
690
  I18n.l("time.formats.short", "2009-11-09T18:10:34Z"); // JSON format in UTC (part of ISO-8601)
565
- I18n.l("date.formats.short", 1251862029000); // Epoch time
566
- I18n.l("date.formats.short", "09/18/2009"); // mm/dd/yyyy
567
- I18n.l("date.formats.short", (new Date())); // Date object
691
+ I18n.l("date.formats.short", 1251862029000); // Epoch time
692
+ I18n.l("date.formats.short", "09/18/2009"); // mm/dd/yyyy
693
+ I18n.l("date.formats.short", new Date()); // Date object
568
694
  ```
569
695
 
570
696
  You can also add placeholders to the date format:
@@ -573,14 +699,16 @@ You can also add placeholders to the date format:
573
699
  I18n.translations["en"] = {
574
700
  date: {
575
701
  formats: {
576
- ordinal_day: "%B %{day}"
577
- }
578
- }
579
- }
580
- I18n.l("date.formats.ordinal_day", "2009-09-18", { day: '18th' }); // Sep 18th
702
+ ordinal_day: "%B %{day}",
703
+ },
704
+ },
705
+ };
706
+
707
+ I18n.l("date.formats.ordinal_day", "2009-09-18", { day: "18th" }); // Sep 18th
581
708
  ```
582
709
 
583
- If you prefer, you can use the `I18n.toTime` and `I18n.strftime` functions to format dates.
710
+ If you prefer, you can use the `I18n.toTime` and `I18n.strftime` functions to
711
+ format dates.
584
712
 
585
713
  ```javascript
586
714
  var date = new Date();
@@ -599,7 +727,7 @@ The accepted formats for `I18n.strftime` are:
599
727
  %d - Day of the month (01..31)
600
728
  %-d - Day of the month (1..31)
601
729
  %H - Hour of the day, 24-hour clock (00..23)
602
- %-H - Hour of the day, 24-hour clock (0..23)
730
+ %-H/%k - Hour of the day, 24-hour clock (0..23)
603
731
  %I - Hour of the day, 12-hour clock (01..12)
604
732
  %-I/%l - Hour of the day, 12-hour clock (1..12)
605
733
  %m - Month of the year (01..12)
@@ -619,8 +747,10 @@ The accepted formats for `I18n.strftime` are:
619
747
  Check out `spec/*.spec.js` files for more examples!
620
748
 
621
749
  #### Using pluralization and number formatting together
622
- Sometimes you might want to display translation with formatted number, like adding thousand delimiters to displayed number
623
- You can do this:
750
+
751
+ Sometimes you might want to display translation with formatted number, like
752
+ adding thousand delimiters to displayed number You can do this:
753
+
624
754
  ```json
625
755
  {
626
756
  "en": {
@@ -632,153 +762,176 @@ You can do this:
632
762
  }
633
763
  }
634
764
  ```
765
+
635
766
  ```js
636
767
  var point_in_number = 1000;
637
- I18n.t('point', { count: point_in_number, formatted_number: I18n.toNumber(point_in_number) });
768
+ I18n.t("point", {
769
+ count: point_in_number,
770
+ formatted_number: I18n.toNumber(point_in_number),
771
+ });
638
772
  ```
639
- Output should be `1,000 points`
640
773
 
774
+ Output should be `1,000 points`
641
775
 
642
776
  ## Using multiple exported translation files on a page.
643
- This method is useful for very large apps where a single contained translations.js file is not desirable. Examples would be a global translations file and a more specific route translation file.
777
+
778
+ This method is useful for very large apps where a single contained
779
+ translations.js file is not desirable. Examples would be a global translations
780
+ file and a more specific route translation file.
644
781
 
645
782
  ### Rails without asset pipeline
646
- 1. Setup your `config/i18n-js.yml` to have multiple files and try to minimize any overlap.
647
-
648
- ```yaml
649
- sort_translation_keys: true
650
- fallbacks: false
651
-
652
- translations:
653
- + file: "app/assets/javascript/nls/welcome.js"
654
- only:
655
- + '*.welcome.*'
656
-
657
- + file: "app/assets/javascript/nls/albums.js"
658
- only:
659
- + '*.albums.*'
660
-
661
- + file: "app/assets/javascript/nls/global.js"
662
- only:
663
- + '*'
664
- # Exempt any routes specific translations from being
665
- # included in the global translation file
666
- except:
667
- + '*.welcome.*'
668
- + '*.albums.*'
669
- ```
670
- When `rake i18n:js:export` is executed it will create 3 translations files that can be loaded via the `javascript_include_tag`
671
-
672
- 2. Add the `javascript_include_tag` to your layout and to any route specific files that will require it.
673
- ```ruby
674
- # views/layouts/application.html.erb
675
- <%= javascript_include_tag(
676
- "i18n"
677
- "nls/global"
678
- ) %>
679
- ```
680
- and in the route specific
681
-
682
- ```ruby
683
- # views/welcome/index.html.erb
684
- <%= javascript_include_tag(
685
- "nls/welcome"
686
- ) %>
687
- ```
783
+
784
+ 1. Setup your `config/i18n-js.yml` to have multiple files and try to minimize
785
+ any overlap.
786
+
787
+ ```yaml
788
+ sort_translation_keys: true
789
+ fallbacks: false
790
+
791
+ translations:
792
+ + file: "app/assets/javascript/nls/welcome.js"
793
+ only:
794
+ + '*.welcome.*'
795
+
796
+ + file: "app/assets/javascript/nls/albums.js"
797
+ only:
798
+ + '*.albums.*'
799
+
800
+ + file: "app/assets/javascript/nls/global.js"
801
+ only:
802
+ + '*'
803
+ # Exempt any routes specific translations from being
804
+ # included in the global translation file
805
+ except:
806
+ + '*.welcome.*'
807
+ + '*.albums.*'
808
+ ```
809
+
810
+ When `rake i18n:js:export` is executed it will create 3 translations files that
811
+ can be loaded via the `javascript_include_tag`
812
+
813
+ 2. Add the `javascript_include_tag` to your layout and to any route specific
814
+ files that will require it.
815
+
816
+ ```ruby
817
+ # views/layouts/application.html.erb
818
+ <%= javascript_include_tag(
819
+ "i18n"
820
+ "nls/global"
821
+ ) %>
822
+ ```
823
+
824
+ and in the route specific
825
+
826
+ ```ruby
827
+ # views/welcome/index.html.erb
828
+ <%= javascript_include_tag(
829
+ "nls/welcome"
830
+ ) %>
831
+ ```
688
832
 
689
833
  3. Make sure that you add these files to your `config/application.rb`
690
834
 
691
- ```ruby
692
- config.assets.precompile += %w(
693
- i18n
694
- nls/*
695
- )
696
- ```
835
+ ```ruby
836
+ config.assets.precompile += %w(
837
+ i18n
838
+ nls/*
839
+ )
840
+ ```
697
841
 
698
842
  ### Using require.js / r.js
699
843
 
700
844
  To use this with require.js we are only going to change a few things from above.
701
845
 
702
- 1. In your `config/i18n-js.yml` we need to add a better location for the i18n to be exported. You want to use this location so that it can be properly precompiled by r.js.
703
-
704
- ```yaml
705
- export_i18n_js: "app/assets/javascript/nls"
706
- ```
707
-
708
- 2. In your `config/require.yml` we need to add a map, shim all the translations, and include them into the appropriate modules
709
-
710
- ```yaml
711
- # In your maps add (if you do not have this you will need to add it)
712
- map:
713
- '*':
714
- i18n: 'nls/i18n'
715
-
716
- # In your shims
717
- shims:
718
- nls/welcome:
719
- deps:
720
- + i18n
721
-
722
- nls/global:
723
- deps:
724
- + i18n
725
-
726
- # Finally in your modules
727
- modules:
728
- + name: 'application'
729
- include:
730
- + i18n
731
- + 'nls/global'
732
-
733
- + name: 'welcome'
734
- exclude:
735
- + application
736
- include:
737
- + 'nls/welcome'
738
- ```
739
- 3. When `rake assets:precompile` is executed it will optimize the translations into the correct modules so they are loaded with their assigned module, and loading them with requirejs is as simple as requiring any other shim.
740
-
741
- ```javascript
742
- define(['welcome/other_asset','nls/welcome'], function (otherAsset){
743
- // ...
744
- });
745
- ```
746
- 4. (optional) As an additional configuration we can make a task to be run before the requirejs optimizer. This will allow any automated scripts that run the requirejs optimizer to export the strings before we run r.js
747
-
748
- ```rake
749
- # lib/tasks/i18n.rake
750
- Rake::Task[:'i18n:js:export'].prerequisites.clear
751
- task :'i18n:js:export' => :'i18n:js:before_export'
752
- task :'requirejs:precompile:external' => :'i18n:js:export'
753
-
754
- namespace :i18n do
755
- namespace :js do
756
- task :before_export => :'assets:environment' do
757
- I18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{yml,rb}')]
758
- I18n.backend.load_translations
759
- end
846
+ 1. In your `config/i18n-js.yml` we need to add a better location for the i18n to
847
+ be exported to. You want to use this location so that it can be properly
848
+ precompiled by r.js.
849
+
850
+ ```yaml
851
+ export_i18n_js: "app/assets/javascript/nls"
852
+ ```
853
+
854
+ 2. In your `config/require.yml` we need to add a map, shim all the translations,
855
+ and include them into the appropriate modules
856
+
857
+ ```yaml
858
+ # In your maps add (if you do not have this you will need to add it)
859
+ map:
860
+ '*':
861
+ i18n: 'nls/i18n'
862
+
863
+ # In your shims
864
+ shims:
865
+ nls/welcome:
866
+ deps:
867
+ + i18n
868
+
869
+ nls/global:
870
+ deps:
871
+ + i18n
872
+
873
+ # Finally in your modules
874
+ modules:
875
+ + name: 'application'
876
+ include:
877
+ + i18n
878
+ + 'nls/global'
879
+
880
+ + name: 'welcome'
881
+ exclude:
882
+ + application
883
+ include:
884
+ + 'nls/welcome'
885
+ ```
886
+
887
+ 3. When `rake assets:precompile` is executed it will optimize the translations
888
+ into the correct modules so they are loaded with their assigned module, and
889
+ loading them with requirejs is as simple as requiring any other shim.
890
+
891
+ ```javascript
892
+ define(["welcome/other_asset", "nls/welcome"], function (otherAsset) {
893
+ // ...
894
+ });
895
+ ```
896
+
897
+ 4. (optional) As an additional configuration we can make a task to be run before
898
+ the requirejs optimizer. This will allow any automated scripts that run the
899
+ requirejs optimizer to export the strings before we run r.js.
900
+
901
+ ```rake
902
+ # lib/tasks/i18n.rake
903
+ Rake::Task[:'i18n:js:export'].prerequisites.clear
904
+ task :'i18n:js:export' => :'i18n:js:before_export'
905
+ task :'requirejs:precompile:external' => :'i18n:js:export'
906
+
907
+ namespace :i18n do
908
+ namespace :js do
909
+ task :before_export => :'assets:environment' do
910
+ I18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{yml,rb}')]
911
+ I18n.backend.load_translations
760
912
  end
761
913
  end
762
- ```
914
+ end
915
+ ```
763
916
 
764
917
  ## Using I18n.js with other languages (Python, PHP, ...)
765
918
 
766
- The JavaScript library is language agnostic; so you can use it with PHP, Python, [your favorite language here].
767
- The only requirement is that you need to set the `translations` attribute like following:
919
+ The JavaScript library is language agnostic; so you can use it with PHP, Python,
920
+ [your favorite language here]. The only requirement is that you need to set the
921
+ `translations` attribute like following:
768
922
 
769
923
  ```javascript
770
924
  I18n.translations = {};
771
925
 
772
926
  I18n.translations["en"] = {
773
- message: "Some special message for you"
774
- }
927
+ message: "Some special message for you",
928
+ };
775
929
 
776
930
  I18n.translations["pt-BR"] = {
777
- message: "Uma mensagem especial para você"
778
- }
931
+ message: "Uma mensagem especial para você",
932
+ };
779
933
  ```
780
934
 
781
-
782
935
  ## Known Issues
783
936
 
784
937
  ### Missing translations in precompiled file(s) after adding any new locale file
@@ -786,66 +939,83 @@ I18n.translations["pt-BR"] = {
786
939
  Due to the design of `sprockets`:
787
940
 
788
941
  - `depend_on` only takes file paths, not directory paths
789
- - registered `preprocessors` are only run when the fingerprint of any asset file, including `.erb` files, is changed
942
+ - registered `preprocessors` are only run when the fingerprint of any asset
943
+ file, including `.erb` files, is changed
944
+
945
+ This means that new locale files will not be detected, and so they will not
946
+ trigger a i18n-js refresh. There are a few approaches to work around this:
790
947
 
791
- This means that new locale files will not be detected, and so they will not trigger a i18n-js refresh. There are a few approaches to work around this:
948
+ 1. You can force i18n-js to update its translations by completely clearing the
949
+ assets cache. Use one of the following:
792
950
 
793
- 1. You can force i18n-js to update its translations by completely clearing the assets cache. Use one of the following:
794
-
795
951
  ```bash
796
952
  $ rake assets:clobber
797
953
  # Or, with older versions of Rails:
798
954
  $ rake tmp:cache:clear
799
955
  ```
800
956
 
801
- These commands will remove *all* fingerprinted assets, and you will have to recompile them with
957
+ These commands will remove _all_ fingerprinted assets, and you will have to
958
+ recompile them with
802
959
 
803
960
  ```bash
804
961
  $ rake assets:precompile
805
962
  ```
806
963
 
807
- or similar commands. If you are precompiling assets on the target machine(s), cached pages may be broken by this, so they will need to be refreshed.
964
+ or similar commands. If you are precompiling assets on the target machine(s),
965
+ cached pages may be broken by this, so they will need to be refreshed.
808
966
 
809
967
  2. You can change something in a different locale file.
810
968
 
811
969
  3. Finally, you can change `config.assets.version`.
812
970
 
813
- **Note:** See issue [#213](https://github.com/fnando/i18n-js/issues/213) for more details and discussion of this issue.
971
+ **Note:** See issue [#213](https://github.com/fnando/i18n-js/issues/213) for
972
+ more details and discussion of this issue.
814
973
 
815
974
  ### Translations in JS are not updated when Sprockets not loaded before this gem
816
975
 
817
- The "rails engine" declaration will try to detect existence of "sprockets" before adding the initailizer
818
- If sprockets is loaded after this gem, the preprocessor for
819
- making JS translations file cache to depend on content of locale files will not be hooked.
820
- So ensure sprockets is loaded before this gem like moving entry of sprockets in Gemfile or adding "require" statements for sprockets somewhere.
976
+ The "rails engine" declaration will try to detect existence of "sprockets"
977
+ before adding the initailizer If sprockets is loaded after this gem, the
978
+ preprocessor for making JS translations file cache to depend on content of
979
+ locale files will not be hooked. So ensure sprockets is loaded before this gem
980
+ by moving the entry of sprockets in the Gemfile or adding "require" statements
981
+ for sprockets somewhere.
821
982
 
822
- **Note:** See issue [#404](https://github.com/fnando/i18n-js/issues/404) for more details and discussion of this issue.
983
+ **Note:** See issue [#404](https://github.com/fnando/i18n-js/issues/404) for
984
+ more details and discussion of this issue.
823
985
 
824
986
  ### JS `I18n.toCurrency` & `I18n.toNumber` cannot handle large integers
825
987
 
826
- The above methods use `toFixed` and it only supports 53 bit integers.
827
- Ref: http://2ality.com/2012/07/large-integers.html
988
+ The above methods use `toFixed` and it only supports 53 bit integers. Ref:
989
+ https://2ality.com/2012/07/large-integers.html
828
990
 
829
- Feel free to find & discuss possible solution(s) at issue [#511](https://github.com/fnando/i18n-js/issues/511)
991
+ Feel free to find & discuss possible solution(s) at issue
992
+ [#511](https://github.com/fnando/i18n-js/issues/511)
830
993
 
831
- ### Only works with `Simple` backend
994
+ ### May not work with all backend implementations
832
995
 
833
- If you set `I18n.backend` to something other than the default `Simple` backend, you will likely get an exception like this:
996
+ I18n backend implementations have to conform to a specific interface to work
997
+ with i18n-js. For backends that do not conform to the interface, you will likely
998
+ get an exception like this:
834
999
 
835
1000
  ```
836
1001
  Undefined method 'initialized?' for <your backend class>
837
1002
  ```
838
1003
 
839
- For now, i18n-js is only compatible with the `Simple` backend.
840
- If you need a more sophisticated backend for your rails application, like `I18n::Backend::ActiveRecord`, you can setup i18n-js to get translations from a separate `Simple` backend, by adding the following in an initializer:
1004
+ For now, i18n-js is compatible with the `Simple` backend and with
1005
+ `I18n::Backend::ActiveRecord` (>= 0.4.0).
1006
+
1007
+ If you need a more sophisticated backend for your rails application that doesn't
1008
+ implement the required methods, you can setup i18n-js to get translations from a
1009
+ separate `Simple` backend, by adding the following in an initializer:
841
1010
 
842
1011
  ```ruby
843
1012
  I18n::JS.backend = I18n.backend
844
1013
  I18n.backend = I18n::Backend::Chain.new(<your other backend(s)>, I18n.backend)
845
1014
  ```
846
1015
 
847
- This will use your backend with the default `Simple` backend as fallback, while i18n-js only sees and uses the simple backend.
848
- This means however, that only translations from your static locale files will be present in JavaScript.
1016
+ This will use your backend with the default `Simple` backend as fallback, while
1017
+ i18n-js only sees and uses the simple backend. This means however, that only
1018
+ translations from your static locale files will be present in JavaScript.
849
1019
 
850
1020
  If you do cannot use a `Chain`-Backend for some reason, you can also set
851
1021
 
@@ -854,9 +1024,11 @@ I18n::JS.backend = I18n::Backend::Simple.new
854
1024
  I18n.backend = <something different>
855
1025
  ```
856
1026
 
857
- However, the automatic reloading of translations in developement will not work in this case.
858
- This is because Rails calls `I18n.reload!` for each request in development, but `reload!` will not be called on `I18n::JS.backend`, since it is a different object.
859
- One option would be to patch `I18n.reload!` in an initializer:
1027
+ However, the automatic reloading of translations in developement will not work
1028
+ in this case. This is because Rails calls `I18n.reload!` for each request in
1029
+ development, but `reload!` will not be called on `I18n::JS.backend`, since it is
1030
+ a different object. One option would be to patch `I18n.reload!` in an
1031
+ initializer:
860
1032
 
861
1033
  ```ruby
862
1034
  module I18n
@@ -867,25 +1039,27 @@ module I18n
867
1039
  end
868
1040
  ```
869
1041
 
870
- See issue [#428](https://github.com/fnando/i18n-js/issues/428) for more details and discussion of this issue.
1042
+ See issue [#428](https://github.com/fnando/i18n-js/issues/428) for more details
1043
+ and discussion of this issue.
871
1044
 
872
1045
  ## Maintainer
873
1046
 
874
- - Nando Vieira - <http://nandovieira.com.br>
1047
+ - Nando Vieira - <https://nandovieira.com>
875
1048
 
876
1049
  ## Contributing
877
1050
 
878
1051
  Once you've made your great commits:
879
1052
 
880
- 1. [Fork](http://help.github.com/forking/) I18n.js
1053
+ 1. [Fork](https://help.github.com/forking/) I18n.js
881
1054
  2. Create a branch with a clear name
882
- 3. Make your changes (Please also add/change spec, README and CHANGELOG if applicable)
1055
+ 3. Make your changes (Please also add/change spec, README and CHANGELOG if
1056
+ applicable)
883
1057
  4. Push changes to the created branch
884
- 5. [Create an Pull Request](http://github.com/fnando/i18n-js/pulls)
1058
+ 5. [Create an Pull Request](https://github.com/fnando/i18n-js/pulls)
885
1059
  6. That's it!
886
1060
 
887
- Please respect the indentation rules and code style.
888
- And use 2 spaces, not tabs. And don't touch the versioning thing.
1061
+ Please respect the indentation rules and code style. And use 2 spaces, not tabs.
1062
+ And don't touch the versioning thing.
889
1063
 
890
1064
  ## Running tests
891
1065
 
@@ -907,21 +1081,19 @@ You can run both Ruby and JavaScript specs with `rake spec`.
907
1081
 
908
1082
  (The MIT License)
909
1083
 
910
- Permission is hereby granted, free of charge, to any person obtaining
911
- a copy of this software and associated documentation files (the
912
- 'Software'), to deal in the Software without restriction, including
913
- without limitation the rights to use, copy, modify, merge, publish,
914
- distribute, sublicense, and/or sell copies of the Software, and to
915
- permit persons to whom the Software is furnished to do so, subject to
916
- the following conditions:
917
-
918
- The above copyright notice and this permission notice shall be
919
- included in all copies or substantial portions of the Software.
920
-
921
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
922
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
923
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
924
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
925
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
926
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
927
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1084
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
1085
+ this software and associated documentation files (the 'Software'), to deal in
1086
+ the Software without restriction, including without limitation the rights to
1087
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
1088
+ the Software, and to permit persons to whom the Software is furnished to do so,
1089
+ subject to the following conditions:
1090
+
1091
+ The above copyright notice and this permission notice shall be included in all
1092
+ copies or substantial portions of the Software.
1093
+
1094
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1095
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
1096
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
1097
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
1098
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1099
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.