i18n-js 3.0.0.rc8 → 3.0.0.rc9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/Appraisals +5 -1
- data/CHANGELOG.md +13 -0
- data/README.md +104 -7
- data/app/assets/javascripts/i18n.js +85 -49
- data/app/assets/javascripts/i18n/filtered.js.erb +1 -3
- data/gemfiles/i18n_0_7.gemfile +7 -0
- data/i18n-js.gemspec +0 -1
- data/lib/i18n/js.rb +54 -44
- data/lib/i18n/js/dependencies.rb +8 -6
- data/lib/i18n/js/segment.rb +39 -0
- data/lib/i18n/js/utils.rb +10 -2
- data/lib/i18n/js/version.rb +1 -1
- data/package.json +4 -0
- data/spec/fixtures/except_condition.yml +5 -0
- data/spec/fixtures/js_export_dir_custom.yml +6 -0
- data/spec/fixtures/js_export_dir_none.yml +6 -0
- data/spec/fixtures/js_file_with_namespace_and_pretty_print.yml +5 -0
- data/spec/i18n_js_spec.rb +139 -118
- data/spec/js/currency.spec.js +3 -1
- data/spec/js/defaults.spec.js +8 -0
- data/spec/js/interpolation.spec.js +58 -4
- data/spec/js/require.js +2083 -0
- data/spec/js/specs_requirejs.html +71 -0
- data/spec/js/translate.spec.js +21 -0
- data/spec/js/translations.js +3 -1
- data/spec/segment_spec.rb +71 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/sprockets_spec.rb +42 -0
- data/spec/utils_spec.rb +69 -0
- metadata +23 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e722b7f34475d50126d5ba7556c9a517f65266f
|
4
|
+
data.tar.gz: 668e6660683a5eb93b2812f656af2439237299e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0cdc594d00611b72e9ca9327389d9f90b5b4d2990b8ecc3f144b44dfaf03aa793b01acc6a28aa57e46c492fe923eefa5b879696e654a7c689486d46258a4a84
|
7
|
+
data.tar.gz: 9ae2cea1e167dc49edf962a1ccb0d0ceb153a7d53e5207bd8c830deed4b1a58a9d19b41b9cdae209fefb385c68798412925fb85874ea02e8670b7081ae609095
|
data/.travis.yml
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 1.9.3
|
4
3
|
- 2.0
|
5
4
|
- 2.1
|
6
5
|
- 2.2
|
@@ -12,8 +11,8 @@ before_install: # Need to install npm to test js
|
|
12
11
|
- npm install jasmine-node@1.14.2
|
13
12
|
gemfile:
|
14
13
|
- gemfiles/i18n_0_6.gemfile
|
14
|
+
- gemfiles/i18n_0_7.gemfile
|
15
15
|
matrix:
|
16
16
|
fast_finish: true
|
17
17
|
allow_failures:
|
18
|
-
- rvm: 2.2
|
19
18
|
- rvm: ruby-head
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
@@ -3,8 +3,21 @@
|
|
3
3
|
|
4
4
|
### enhancements
|
5
5
|
|
6
|
+
- [JS] Force currency number sign to be at first place using `sign_first` option, default to `true`
|
7
|
+
- [Ruby] Add option `namespace` & `pretty_print` ([#300](https://github.com/fnando/i18n-js/pull/300))
|
8
|
+
- [Ruby] Add option `export_i18n_js` ([#301](https://github.com/fnando/i18n-js/pull/301))
|
9
|
+
- [Ruby] Now the gem also detects pre-release versions of `rails`
|
10
|
+
- [Ruby] Add `:except` option to exclude certain phrases or groups of phrases from the
|
11
|
+
outputted translations ([#312](https://github.com/fnando/i18n-js/pull/312))
|
12
|
+
- [JS] You can now set `I18n.missingBehavior='guess'` to have the scope string output as text instead of of the
|
13
|
+
"[missing `scope`]" message when no translation is available.
|
14
|
+
- [JS] Combined that with `I18n.missingTranslationPrefix='SOMETHING'` and you can
|
15
|
+
still identify those missing strings.
|
16
|
+
|
6
17
|
### bug fixes
|
7
18
|
|
19
|
+
- [JS] Fix missing translation message when scope is passed in options
|
20
|
+
|
8
21
|
|
9
22
|
## 3.0.0.rc8
|
10
23
|
|
data/README.md
CHANGED
@@ -23,8 +23,10 @@ Features:
|
|
23
23
|
Add the gem to your Gemfile.
|
24
24
|
|
25
25
|
source "https://rubygems.org"
|
26
|
-
gem "rails", "
|
27
|
-
|
26
|
+
gem "rails", "your_rails_version"
|
27
|
+
# You only need this RC version constraint during the development of `3.0.0`, once stable version is released you can remove `rc8` suffix
|
28
|
+
# `3.0.0.rc8` is the latest version of released RC version when this entry is changed, you might want to change it later
|
29
|
+
gem "i18n-js", ">= 3.0.0.rc8"
|
28
30
|
|
29
31
|
#### Rails app with [Asset Pipeline](http://guides.rubyonrails.org/asset_pipeline.html)
|
30
32
|
|
@@ -107,21 +109,45 @@ translations:
|
|
107
109
|
<% end %>
|
108
110
|
```
|
109
111
|
|
112
|
+
You are able to exclude certain phrases or whole groups of phrases by
|
113
|
+
specifying the YAML key(s) in the `except` configuration option. The outputted
|
114
|
+
JS translations file (exported or generated by the middleware) will omit any
|
115
|
+
keys listed in `except` configuration param:
|
116
|
+
|
117
|
+
```yaml
|
118
|
+
translations:
|
119
|
+
- except: ['active_admin', 'ransack']
|
120
|
+
```
|
121
|
+
|
122
|
+
|
110
123
|
#### Export Configuration (For other things)
|
111
|
-
|
124
|
+
|
125
|
+
- `I18n::JS.config_file_path`
|
112
126
|
Expected Type: `String`
|
113
127
|
Default: `config/i18n-js.yml`
|
114
128
|
Behaviour: Try to read the config file from that location
|
115
|
-
|
129
|
+
|
130
|
+
- `I18n::JS.export_i18n_js_dir_path`
|
116
131
|
Expected Type: `String`
|
117
132
|
Default: `public/javascripts`
|
118
133
|
Behaviour:
|
119
134
|
- 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`
|
120
|
-
- `nil`: Disable `i18n.js` exporting
|
135
|
+
- Any non-`String` (`nil`, `false`, `:none`, etc): Disable `i18n.js` exporting
|
136
|
+
|
137
|
+
- You may also set `export_i18n_js` in your config file, e.g.:
|
138
|
+
|
139
|
+
```yaml
|
140
|
+
export_i18n_js_: false
|
141
|
+
# OR
|
142
|
+
export_i18n_js: "my/path"
|
143
|
+
|
144
|
+
translations:
|
145
|
+
- ...
|
146
|
+
``
|
121
147
|
|
122
148
|
To find more examples on how to use the configuration file please refer to the tests.
|
123
149
|
|
124
|
-
|
150
|
+
#### Fallbacks
|
125
151
|
|
126
152
|
If you specify the `fallbacks` option, you will be able to fill missing translations with those inside fallback locale(s).
|
127
153
|
Default value is `true`.
|
@@ -180,11 +206,54 @@ You must disable this feature by setting the option to `false`.
|
|
180
206
|
To find more examples on how to use the configuration file please refer to the tests.
|
181
207
|
|
182
208
|
|
209
|
+
#### Namespace
|
210
|
+
|
211
|
+
Setting the `namespace` option will change the namespace of the output Javascript file to something other than `I18n`.
|
212
|
+
This can be useful in no-conflict scenarios. Example:
|
213
|
+
|
214
|
+
```yaml
|
215
|
+
translations:
|
216
|
+
- file: "public/javascripts/i18n/translations.js"
|
217
|
+
namespace: "MyNamespace"
|
218
|
+
```
|
219
|
+
|
220
|
+
will create:
|
221
|
+
|
222
|
+
```
|
223
|
+
MyNamespace.translations || (MyNamespace.translations = {});
|
224
|
+
MyNamespace.translations["en"] = { ... }
|
225
|
+
```
|
226
|
+
|
227
|
+
|
228
|
+
#### Pretty Print
|
229
|
+
|
230
|
+
Set the `pretty_print` option if you would like whitespace and indentation in your output file (default: false)
|
231
|
+
|
232
|
+
```yaml
|
233
|
+
translations:
|
234
|
+
- file: "public/javascripts/i18n/translations.js"
|
235
|
+
pretty_print: true
|
236
|
+
```
|
237
|
+
|
238
|
+
|
183
239
|
#### Vanilla JavaScript
|
184
240
|
|
185
241
|
Just add the `i18n.js` file to your page. You'll have to build the translations object
|
186
242
|
by hand or using your favorite programming language. More info below.
|
187
243
|
|
244
|
+
|
245
|
+
#### Via NPM with webpack and CommonJS
|
246
|
+
|
247
|
+
Add the following line to your package.json dependencies (where version is the version you want - n.b. npm install requires it to be the gzipped tarball, see [npm install](https://www.npmjs.org/doc/cli/npm-install.html))
|
248
|
+
```javascript
|
249
|
+
"i18n-js": "http://github.com/fnando/i18n-js/archive/v3.0.0.rc8.tar.gz"
|
250
|
+
```
|
251
|
+
Run npm install then use via
|
252
|
+
```javascript
|
253
|
+
var i18n = require("i18n-js");
|
254
|
+
```
|
255
|
+
|
256
|
+
|
188
257
|
### Setting up
|
189
258
|
|
190
259
|
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.
|
@@ -240,7 +309,7 @@ You can also provide a list of default fallbacks for missing scopes:
|
|
240
309
|
I18n.t("some.missing.scope", {defaults: [{scope: "some.existing.scope"}]});
|
241
310
|
|
242
311
|
// As a simple translation
|
243
|
-
I18n.t("some.missing.scope", {defaults: [{message: "
|
312
|
+
I18n.t("some.missing.scope", {defaults: [{message: "Some message"}]});
|
244
313
|
|
245
314
|
Default values must be provided as an array of hashs where the key is the
|
246
315
|
type of translation desired, a `scope` or a `message`. The translation returned
|
@@ -271,6 +340,33 @@ are three different ways of doing it so:
|
|
271
340
|
I18n.locales.no = "nb";
|
272
341
|
I18n.locales.no = function(locale){ return ["nb"]; };
|
273
342
|
|
343
|
+
By default a missing translation will be displayed as
|
344
|
+
|
345
|
+
[missing "name of scope" translation]
|
346
|
+
|
347
|
+
While you are developing or if you do not want to provide a translation
|
348
|
+
in the default language you can set
|
349
|
+
|
350
|
+
I18n.missingBehaviour='guess';
|
351
|
+
|
352
|
+
this will take the last section of your scope and guess the intended value.
|
353
|
+
Camel case becomes lower cased text and underscores are replaced with space
|
354
|
+
|
355
|
+
questionnaire.whatIsYourFavorite_ChristmasPresent
|
356
|
+
|
357
|
+
becomes "what is your favorite Christmas present"
|
358
|
+
|
359
|
+
In order to still detect untranslated strings, you can
|
360
|
+
i18n.missingTranslationPrefix to something like:
|
361
|
+
|
362
|
+
I18n.missingTranslationPrefix = 'EE: '
|
363
|
+
|
364
|
+
And result will be:
|
365
|
+
|
366
|
+
"EE: what is your favorite Christmas present"
|
367
|
+
|
368
|
+
This will help you doing automated tests against your localisation assets.
|
369
|
+
|
274
370
|
Pluralization is possible as well and by default provides English rules:
|
275
371
|
|
276
372
|
I18n.t("inbox.counting", {count: 10}); // You have 10 messages
|
@@ -350,6 +446,7 @@ The `toCurrency` function accepts the following options:
|
|
350
446
|
- `format`: sets the format of the output string
|
351
447
|
- `unit`: sets the denomination of the currency
|
352
448
|
- `strip_insignificant_zeros`: defaults to `false`
|
449
|
+
- `sign_first`: defaults to `true`
|
353
450
|
|
354
451
|
You can provide only the options you want to override:
|
355
452
|
|
@@ -16,11 +16,9 @@
|
|
16
16
|
if (typeof module !== 'undefined' && module.exports) {
|
17
17
|
// Node/CommonJS
|
18
18
|
module.exports = factory(this);
|
19
|
-
|
20
19
|
} else if (typeof define === 'function' && define.amd) {
|
21
20
|
// AMD
|
22
|
-
define((function(global){ return function(){ factory(global); }})(this));
|
23
|
-
|
21
|
+
define('i18n', (function(global){ return function(){ return factory(global); }})(this));
|
24
22
|
} else {
|
25
23
|
// Browser globals
|
26
24
|
this.I18n = factory(this);
|
@@ -61,13 +59,16 @@
|
|
61
59
|
unit: "$"
|
62
60
|
, precision: 2
|
63
61
|
, format: "%u%n"
|
62
|
+
, sign_first: true
|
64
63
|
, delimiter: ","
|
65
64
|
, separator: "."
|
66
65
|
};
|
67
66
|
|
68
67
|
// Set default percentage format.
|
69
68
|
var PERCENTAGE_FORMAT = {
|
70
|
-
|
69
|
+
unit: "%"
|
70
|
+
, precision: 3
|
71
|
+
, format: "%n%u"
|
71
72
|
, separator: "."
|
72
73
|
, delimiter: ""
|
73
74
|
};
|
@@ -77,12 +78,27 @@
|
|
77
78
|
|
78
79
|
// Other default options
|
79
80
|
var DEFAULT_OPTIONS = {
|
80
|
-
|
81
|
-
locale
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
81
|
+
// Set default locale. This locale will be used when fallback is enabled and
|
82
|
+
// the translation doesn't exist in a particular locale.
|
83
|
+
defaultLocale: "en"
|
84
|
+
// Set the current locale to `en`.
|
85
|
+
, locale: "en"
|
86
|
+
// Set the translation key separator.
|
87
|
+
, defaultSeparator: "."
|
88
|
+
// Set the placeholder format. Accepts `{placeholder}}` and `%{placeholder}`.}
|
89
|
+
, placeholder: /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm
|
90
|
+
// Set if engine should fallback to the default locale when a translation
|
91
|
+
// is missing.
|
92
|
+
, fallbacks: false
|
93
|
+
// Set the default translation object.
|
94
|
+
, translations: {}
|
95
|
+
// Set missing translation behavior. 'message' will display a message
|
96
|
+
// that the translation is missing, 'guess' will try to guess the string
|
97
|
+
, missingBehaviour: 'message'
|
98
|
+
// if you use missingBehaviour with 'message', but want to know that the
|
99
|
+
// string is actually missing for testing purposes, you can prefix the
|
100
|
+
// guessed string by setting the value here. By default, no prefix!
|
101
|
+
, missingTranslationPrefix: ''
|
86
102
|
};
|
87
103
|
|
88
104
|
I18n.reset = function() {
|
@@ -105,6 +121,13 @@
|
|
105
121
|
|
106
122
|
// Set the default translation object.
|
107
123
|
this.translations = DEFAULT_OPTIONS.translations;
|
124
|
+
|
125
|
+
// Set the default missing behaviour
|
126
|
+
this.missingBehaviour = DEFAULT_OPTIONS.missingBehaviour;
|
127
|
+
|
128
|
+
// Set the default missing string prefix for guess behaviour
|
129
|
+
this.missingTranslationPrefix = DEFAULT_OPTIONS.missingTranslationPrefix;
|
130
|
+
|
108
131
|
};
|
109
132
|
|
110
133
|
// Much like `reset`, but only assign options if not already assigned
|
@@ -252,18 +275,7 @@
|
|
252
275
|
, translations
|
253
276
|
;
|
254
277
|
|
255
|
-
|
256
|
-
if (scope.constructor === Array) {
|
257
|
-
scope = scope.join(this.defaultSeparator);
|
258
|
-
}
|
259
|
-
|
260
|
-
// Deal with the scope option provided through the second argument.
|
261
|
-
//
|
262
|
-
// I18n.t('hello', {scope: 'greetings'});
|
263
|
-
//
|
264
|
-
if (options.scope) {
|
265
|
-
scope = [options.scope, scope].join(this.defaultSeparator);
|
266
|
-
}
|
278
|
+
scope = this.getFullScope(scope, options);
|
267
279
|
|
268
280
|
while (locales.length) {
|
269
281
|
locale = locales.shift();
|
@@ -390,7 +402,7 @@
|
|
390
402
|
}, this);
|
391
403
|
|
392
404
|
if (!translationFound) {
|
393
|
-
return this.missingTranslation(scope);
|
405
|
+
return this.missingTranslation(scope, options);
|
394
406
|
}
|
395
407
|
|
396
408
|
if (typeof(translation) === "string") {
|
@@ -451,7 +463,7 @@
|
|
451
463
|
}
|
452
464
|
|
453
465
|
if (!translations) {
|
454
|
-
return this.missingTranslation(scope);
|
466
|
+
return this.missingTranslation(scope, options);
|
455
467
|
}
|
456
468
|
|
457
469
|
pluralizer = this.pluralization.get(options.locale);
|
@@ -471,14 +483,21 @@
|
|
471
483
|
};
|
472
484
|
|
473
485
|
// Return a missing translation message for the given parameters.
|
474
|
-
I18n.missingTranslation = function(scope) {
|
475
|
-
|
486
|
+
I18n.missingTranslation = function(scope, options) {
|
487
|
+
//guess intended string
|
488
|
+
if(this.missingBehaviour == 'guess'){
|
489
|
+
//get only the last portion of the scope
|
490
|
+
var s = scope.split('.').slice(-1)[0];
|
491
|
+
//replace underscore with space && camelcase with space and lowercase letter
|
492
|
+
return (this.missingTranslationPrefix.length > 0 ? this.missingTranslationPrefix : '') +
|
493
|
+
s.replace('_',' ').replace(/([a-z])([A-Z])/g,
|
494
|
+
function(match, p1, p2) {return p1 + ' ' + p2.toLowerCase()} );
|
495
|
+
}
|
476
496
|
|
477
|
-
|
478
|
-
|
479
|
-
message += '" translation]';
|
497
|
+
var fullScope = this.getFullScope(scope, options);
|
498
|
+
var fullScopeWithLocale = [this.currentLocale(), fullScope].join(this.defaultSeparator);
|
480
499
|
|
481
|
-
return
|
500
|
+
return '[missing "' + fullScopeWithLocale + '" translation]';
|
482
501
|
};
|
483
502
|
|
484
503
|
// Return a missing placeholder message for given parameters
|
@@ -514,6 +533,8 @@
|
|
514
533
|
, precision
|
515
534
|
, buffer = []
|
516
535
|
, formattedNumber
|
536
|
+
, format = options.format || "%n"
|
537
|
+
, sign = negative ? "-" : ""
|
517
538
|
;
|
518
539
|
|
519
540
|
number = parts[0];
|
@@ -534,9 +555,18 @@
|
|
534
555
|
formattedNumber += options.separator + precision;
|
535
556
|
}
|
536
557
|
|
537
|
-
if (
|
538
|
-
|
558
|
+
if (options.sign_first) {
|
559
|
+
format = "%s" + format;
|
539
560
|
}
|
561
|
+
else {
|
562
|
+
format = format.replace("%n", "%s%n");
|
563
|
+
}
|
564
|
+
|
565
|
+
formattedNumber = format
|
566
|
+
.replace("%u", options.unit)
|
567
|
+
.replace("%n", formattedNumber)
|
568
|
+
.replace("%s", sign)
|
569
|
+
;
|
540
570
|
|
541
571
|
return formattedNumber;
|
542
572
|
};
|
@@ -564,13 +594,7 @@
|
|
564
594
|
, CURRENCY_FORMAT
|
565
595
|
);
|
566
596
|
|
567
|
-
|
568
|
-
number = options.format
|
569
|
-
.replace("%u", options.unit)
|
570
|
-
.replace("%n", number)
|
571
|
-
;
|
572
|
-
|
573
|
-
return number;
|
597
|
+
return this.toNumber(number, options);
|
574
598
|
};
|
575
599
|
|
576
600
|
// Localize several values.
|
@@ -782,8 +806,7 @@
|
|
782
806
|
, PERCENTAGE_FORMAT
|
783
807
|
);
|
784
808
|
|
785
|
-
|
786
|
-
return number + "%";
|
809
|
+
return this.toNumber(number, options);
|
787
810
|
};
|
788
811
|
|
789
812
|
// Convert a number into a readable size representation.
|
@@ -810,18 +833,31 @@
|
|
810
833
|
|
811
834
|
options = this.prepareOptions(
|
812
835
|
options
|
813
|
-
, {precision: precision, format: "%n%u", delimiter: ""}
|
836
|
+
, {unit: unit, precision: precision, format: "%n%u", delimiter: ""}
|
814
837
|
);
|
815
838
|
|
816
|
-
|
817
|
-
number = options.format
|
818
|
-
.replace("%u", unit)
|
819
|
-
.replace("%n", number)
|
820
|
-
;
|
821
|
-
|
822
|
-
return number;
|
839
|
+
return this.toNumber(size, options);
|
823
840
|
};
|
824
841
|
|
842
|
+
I18n.getFullScope = function(scope, options) {
|
843
|
+
options = this.prepareOptions(options);
|
844
|
+
|
845
|
+
// Deal with the scope as an array.
|
846
|
+
if (scope.constructor === Array) {
|
847
|
+
scope = scope.join(this.defaultSeparator);
|
848
|
+
}
|
849
|
+
|
850
|
+
// Deal with the scope option provided through the second argument.
|
851
|
+
//
|
852
|
+
// I18n.t('hello', {scope: 'greetings'});
|
853
|
+
//
|
854
|
+
if (options.scope) {
|
855
|
+
scope = [options.scope, scope].join(this.defaultSeparator);
|
856
|
+
}
|
857
|
+
|
858
|
+
return scope;
|
859
|
+
}
|
860
|
+
|
825
861
|
// Set aliases, so we can save some typing.
|
826
862
|
I18n.t = I18n.translate;
|
827
863
|
I18n.l = I18n.localize;
|