i18n-js 3.5.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/Appraisals +4 -0
- data/CHANGELOG.md +46 -1
- data/README.md +28 -10
- data/app/assets/javascripts/i18n.js +27 -24
- data/app/assets/javascripts/i18n/shims.js +32 -0
- data/gemfiles/i18n_1_8.gemfile +7 -0
- data/i18n-js.gemspec +1 -1
- data/lib/i18n/js/formatters/base.rb +2 -1
- data/lib/i18n/js/formatters/js.rb +1 -1
- data/lib/i18n/js/segment.rb +5 -2
- data/lib/i18n/js/version.rb +1 -1
- data/package.json +1 -1
- data/spec/fixtures/js_file_with_namespace_prefix_and_pretty_print.yml +1 -0
- data/spec/js/localization.spec.js +38 -14
- data/spec/js/numbers.spec.js +4 -0
- data/spec/js/pluralization.spec.js +10 -2
- data/spec/js/translate.spec.js +68 -48
- data/spec/js/translations.js +27 -2
- data/spec/ruby/i18n/js_spec.rb +2 -1
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b219edefbe002f4d278f6677a3d1b25a313392e9bcef34f5a6c6ac3ac4a2dd90
|
4
|
+
data.tar.gz: 8aa014849035847f081f9ef53f1824d1405feedb5d2eb61a979885bf3d8b4d06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e75a5ebff4ca0a1572376a816185c42e21ee343b4a44c8b3a4a2c7831241bc5af77a79522b1ce541e86773bce39ae3088365c67fdd8dfe245af522c808ecebaa
|
7
|
+
data.tar.gz: dceaa789df1e2712849300687afcabbbc73a3f4557d2cb3f08bafda30f357ea9b9d794cf914240398cec8798a102f54d9839bdc92d53327e3124715eddcf1c8f
|
data/.travis.yml
CHANGED
@@ -12,6 +12,7 @@ rvm:
|
|
12
12
|
- 2.4
|
13
13
|
- 2.5
|
14
14
|
- 2.6
|
15
|
+
- 2.7
|
15
16
|
- ruby-head
|
16
17
|
before_install:
|
17
18
|
# Needed to test JS
|
@@ -29,6 +30,7 @@ gemfile:
|
|
29
30
|
- gemfiles/i18n_1_5.gemfile
|
30
31
|
- gemfiles/i18n_1_6.gemfile
|
31
32
|
- gemfiles/i18n_1_7.gemfile
|
33
|
+
- gemfiles/i18n_1_8.gemfile
|
32
34
|
matrix:
|
33
35
|
fast_finish: true
|
34
36
|
allow_failures:
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
@@ -18,6 +18,46 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
18
18
|
- Nothing
|
19
19
|
|
20
20
|
|
21
|
+
## [3.8.0] - 2020-10-15
|
22
|
+
|
23
|
+
### Added
|
24
|
+
|
25
|
+
- [JS] Add option `scope` for `toHumanSize()`
|
26
|
+
(PR: https://github.com/fnando/i18n-js/pull/583)
|
27
|
+
|
28
|
+
|
29
|
+
## [3.7.1] - 2020-06-30
|
30
|
+
|
31
|
+
### Fixed
|
32
|
+
|
33
|
+
- [JS] For translation missing behaviour `guess`, replace all underscores to spaces properly
|
34
|
+
(PR: https://github.com/fnando/i18n-js/pull/574)
|
35
|
+
|
36
|
+
|
37
|
+
## [3.7.0] - 2020-05-29
|
38
|
+
|
39
|
+
### Added
|
40
|
+
|
41
|
+
- [JS] Allow options to be passed in when calling `I18n.localize`/`I18n.l`
|
42
|
+
(PR: https://github.com/fnando/i18n-js/pull/570)
|
43
|
+
|
44
|
+
|
45
|
+
## [3.6.0] - 2020-02-14
|
46
|
+
|
47
|
+
### Added
|
48
|
+
|
49
|
+
- [Ruby] Allow `suffix` to be added to generated translations files
|
50
|
+
(PR: https://github.com/fnando/i18n-js/pull/561)
|
51
|
+
|
52
|
+
|
53
|
+
## [3.5.1] - 2019-12-21
|
54
|
+
|
55
|
+
### Changed
|
56
|
+
|
57
|
+
- [JS] Bound shortcut functions
|
58
|
+
(PR: https://github.com/fnando/i18n-js/pull/560)
|
59
|
+
|
60
|
+
|
21
61
|
## [3.5.0] - 2019-11-12
|
22
62
|
|
23
63
|
### Added
|
@@ -433,7 +473,12 @@ And today is not April Fools' Day
|
|
433
473
|
|
434
474
|
|
435
475
|
|
436
|
-
[Unreleased]: https://github.com/fnando/i18n-js/compare/v3.
|
476
|
+
[Unreleased]: https://github.com/fnando/i18n-js/compare/v3.8.0...HEAD
|
477
|
+
[3.8.0]: https://github.com/fnando/i18n-js/compare/v3.7.1...v3.8.0
|
478
|
+
[3.7.1]: https://github.com/fnando/i18n-js/compare/v3.7.0...v3.7.1
|
479
|
+
[3.7.0]: https://github.com/fnando/i18n-js/compare/v3.6.0...v3.7.0
|
480
|
+
[3.6.0]: https://github.com/fnando/i18n-js/compare/v3.5.1...v3.6.0
|
481
|
+
[3.5.1]: https://github.com/fnando/i18n-js/compare/v3.5.0...v3.5.1
|
437
482
|
[3.5.0]: https://github.com/fnando/i18n-js/compare/v3.4.2...v3.5.0
|
438
483
|
[3.4.2]: https://github.com/fnando/i18n-js/compare/v3.4.1...v3.4.2
|
439
484
|
[3.4.1]: https://github.com/fnando/i18n-js/compare/v3.4.0...v3.4.1
|
data/README.md
CHANGED
@@ -37,6 +37,18 @@ Add the gem to your Gemfile.
|
|
37
37
|
gem "i18n-js"
|
38
38
|
```
|
39
39
|
|
40
|
+
#### Rails with [webpacker](https://github.com/rails/webpacker)
|
41
|
+
|
42
|
+
If you're using `webpacker`, you may need to add the dependencies to your client with:
|
43
|
+
|
44
|
+
```
|
45
|
+
yarn add i18n-js
|
46
|
+
# or, if you're using npm,
|
47
|
+
npm install i18n-js
|
48
|
+
```
|
49
|
+
|
50
|
+
For more details, see [this gist](https://gist.github.com/bazzel/ecdff4718962e57c2d5569cf01d332fe).
|
51
|
+
|
40
52
|
#### Rails app with [Asset Pipeline](http://guides.rubyonrails.org/asset_pipeline.html)
|
41
53
|
|
42
54
|
If you're using the [asset pipeline](http://guides.rubyonrails.org/asset_pipeline.html),
|
@@ -248,9 +260,9 @@ MyNamespace.translations["en"] = { ... }
|
|
248
260
|
```
|
249
261
|
|
250
262
|
|
251
|
-
### Adding
|
263
|
+
### Adding prefix & suffix to the translations file(s)
|
252
264
|
|
253
|
-
Setting the `prefix: "import I18n from 'i18n-js';\n"` option will add the line at the
|
265
|
+
Setting the `prefix: "import I18n from 'i18n-js';\n"` option will add the line at the beginning of the resultant translation file.
|
254
266
|
This can be useful to use this gem with the [i18n-js](https://www.npmjs.com/package/i18n-js) npm package, which is quite useful to use it with webpack.
|
255
267
|
The user should provide the semi-colon and the newline character if needed.
|
256
268
|
|
@@ -267,6 +279,11 @@ will create:
|
|
267
279
|
```
|
268
280
|
import I18n from 'i18n-js';
|
269
281
|
I18n.translations || (I18n.translations = {});
|
282
|
+
```
|
283
|
+
|
284
|
+
|
285
|
+
`suffix` option is added in https://github.com/fnando/i18n-js/pull/561.
|
286
|
+
It's similar to `prefix` so won't explain it in details.
|
270
287
|
|
271
288
|
|
272
289
|
#### Pretty Print
|
@@ -320,7 +337,7 @@ var i18n = require("i18n-js");
|
|
320
337
|
|
321
338
|
### Setting up
|
322
339
|
|
323
|
-
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
|
340
|
+
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 contexts, you can follow the rest of this setting up section.
|
324
341
|
|
325
342
|
Set your locale is easy as
|
326
343
|
```javascript
|
@@ -388,7 +405,7 @@ I18n.t("some.missing.scope", {defaults: [{scope: "some.existing.scope"}]});
|
|
388
405
|
I18n.t("some.missing.scope", {defaults: [{message: "Some message"}]});
|
389
406
|
```
|
390
407
|
|
391
|
-
Default values must be provided as an array of
|
408
|
+
Default values must be provided as an array of hashes where the key is the
|
392
409
|
type of translation desired, a `scope` or a `message`. The translation returned
|
393
410
|
will be either the first scope recognized, or the first message defined.
|
394
411
|
|
@@ -487,7 +504,7 @@ I18n.pluralization["ru"] = function (count) {
|
|
487
504
|
};
|
488
505
|
```
|
489
506
|
|
490
|
-
You can find all rules on <
|
507
|
+
You can find all rules on <https://unicode-org.github.io/cldr-staging/charts/37/supplemental/language_plural_rules.html>.
|
491
508
|
|
492
509
|
If you're using the same scope over and over again, you may use the `scope` option.
|
493
510
|
|
@@ -569,6 +586,7 @@ The `toHumanSize` function accepts the following options:
|
|
569
586
|
- `delimiter`: defaults to `""`
|
570
587
|
- `strip_insignificant_zeros`: defaults to `false`
|
571
588
|
- `format`: defaults to `%n%u`
|
589
|
+
- `scope`: defaults to `""`
|
572
590
|
|
573
591
|
<!---->
|
574
592
|
|
@@ -723,7 +741,7 @@ This method is useful for very large apps where a single contained translations.
|
|
723
741
|
|
724
742
|
To use this with require.js we are only going to change a few things from above.
|
725
743
|
|
726
|
-
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.
|
744
|
+
1. In your `config/i18n-js.yml` we need to add a better location for the i18n to be exported to. You want to use this location so that it can be properly precompiled by r.js.
|
727
745
|
|
728
746
|
```yaml
|
729
747
|
export_i18n_js: "app/assets/javascript/nls"
|
@@ -767,7 +785,7 @@ To use this with require.js we are only going to change a few things from above.
|
|
767
785
|
// ...
|
768
786
|
});
|
769
787
|
```
|
770
|
-
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
|
788
|
+
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.
|
771
789
|
|
772
790
|
```rake
|
773
791
|
# lib/tasks/i18n.rake
|
@@ -828,7 +846,7 @@ These commands will remove *all* fingerprinted assets, and you will have to reco
|
|
828
846
|
$ rake assets:precompile
|
829
847
|
```
|
830
848
|
|
831
|
-
or similar commands.
|
849
|
+
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.
|
832
850
|
|
833
851
|
2. You can change something in a different locale file.
|
834
852
|
|
@@ -839,9 +857,9 @@ or similar commands. If you are precompiling assets on the target machine(s), c
|
|
839
857
|
### Translations in JS are not updated when Sprockets not loaded before this gem
|
840
858
|
|
841
859
|
The "rails engine" declaration will try to detect existence of "sprockets" before adding the initailizer
|
842
|
-
If sprockets is loaded after this gem, the preprocessor for
|
860
|
+
If sprockets is loaded after this gem, the preprocessor for
|
843
861
|
making JS translations file cache to depend on content of locale files will not be hooked.
|
844
|
-
So ensure sprockets is loaded before this gem
|
862
|
+
So ensure sprockets is loaded before this gem by moving the entry of sprockets in the Gemfile or adding "require" statements for sprockets somewhere.
|
845
863
|
|
846
864
|
**Note:** See issue [#404](https://github.com/fnando/i18n-js/issues/404) for more details and discussion of this issue.
|
847
865
|
|
@@ -402,7 +402,7 @@
|
|
402
402
|
|
403
403
|
while (locales.length) {
|
404
404
|
locale = locales.shift();
|
405
|
-
scopes = fullScope.split(this.defaultSeparator);
|
405
|
+
scopes = fullScope.split(options.separator || this.defaultSeparator);
|
406
406
|
translations = this.translations[locale];
|
407
407
|
|
408
408
|
if (!translations) {
|
@@ -459,7 +459,7 @@
|
|
459
459
|
|
460
460
|
while (locales.length) {
|
461
461
|
locale = locales.shift();
|
462
|
-
scopes = scope.split(this.defaultSeparator);
|
462
|
+
scopes = scope.split(options.separator || this.defaultSeparator);
|
463
463
|
translations = this.translations[locale];
|
464
464
|
|
465
465
|
if (!translations) {
|
@@ -679,13 +679,13 @@
|
|
679
679
|
var s = scope.split('.').slice(-1)[0];
|
680
680
|
//replace underscore with space && camelcase with space and lowercase letter
|
681
681
|
return (this.missingTranslationPrefix.length > 0 ? this.missingTranslationPrefix : '') +
|
682
|
-
s.replace(
|
682
|
+
s.replace(/_/g,' ').replace(/([a-z])([A-Z])/g,
|
683
683
|
function(match, p1, p2) {return p1 + ' ' + p2.toLowerCase()} );
|
684
684
|
}
|
685
685
|
|
686
686
|
var localeForTranslation = (options != null && options.locale != null) ? options.locale : this.currentLocale();
|
687
687
|
var fullScope = this.getFullScope(scope, options);
|
688
|
-
var fullScopeWithLocale = [localeForTranslation, fullScope].join(this.defaultSeparator);
|
688
|
+
var fullScopeWithLocale = [localeForTranslation, fullScope].join(options.separator || this.defaultSeparator);
|
689
689
|
|
690
690
|
return '[missing "' + fullScopeWithLocale + '" translation]';
|
691
691
|
};
|
@@ -779,8 +779,8 @@
|
|
779
779
|
I18n.toCurrency = function(number, options) {
|
780
780
|
options = this.prepareOptions(
|
781
781
|
options
|
782
|
-
, this.lookup("number.currency.format")
|
783
|
-
, this.lookup("number.format")
|
782
|
+
, this.lookup("number.currency.format", options)
|
783
|
+
, this.lookup("number.format", options)
|
784
784
|
, CURRENCY_FORMAT
|
785
785
|
);
|
786
786
|
|
@@ -799,17 +799,17 @@
|
|
799
799
|
|
800
800
|
switch (scope) {
|
801
801
|
case "currency":
|
802
|
-
return this.toCurrency(value);
|
802
|
+
return this.toCurrency(value, options);
|
803
803
|
case "number":
|
804
|
-
scope = this.lookup("number.format");
|
804
|
+
scope = this.lookup("number.format", options);
|
805
805
|
return this.toNumber(value, scope);
|
806
806
|
case "percentage":
|
807
|
-
return this.toPercentage(value);
|
807
|
+
return this.toPercentage(value, options);
|
808
808
|
default:
|
809
809
|
var localizedValue;
|
810
810
|
|
811
811
|
if (scope.match(/^(date|time)/)) {
|
812
|
-
localizedValue = this.toTime(scope, value);
|
812
|
+
localizedValue = this.toTime(scope, value, options);
|
813
813
|
} else {
|
814
814
|
localizedValue = value.toString();
|
815
815
|
}
|
@@ -914,8 +914,8 @@
|
|
914
914
|
// %Y - Year with century
|
915
915
|
// %z/%Z - Timezone offset (+0545)
|
916
916
|
//
|
917
|
-
I18n.strftime = function(date, format) {
|
918
|
-
var options = this.lookup("date")
|
917
|
+
I18n.strftime = function(date, format, options) {
|
918
|
+
var options = this.lookup("date", options)
|
919
919
|
, meridianOptions = I18n.meridian()
|
920
920
|
;
|
921
921
|
|
@@ -984,9 +984,9 @@
|
|
984
984
|
};
|
985
985
|
|
986
986
|
// Convert the given dateString into a formatted date.
|
987
|
-
I18n.toTime = function(scope, dateString) {
|
987
|
+
I18n.toTime = function(scope, dateString, options) {
|
988
988
|
var date = this.parseDate(dateString)
|
989
|
-
, format = this.lookup(scope)
|
989
|
+
, format = this.lookup(scope, options)
|
990
990
|
;
|
991
991
|
|
992
992
|
// A date input of `null` or `undefined` will be returned as-is
|
@@ -1003,15 +1003,15 @@
|
|
1003
1003
|
return date_string;
|
1004
1004
|
}
|
1005
1005
|
|
1006
|
-
return this.strftime(date, format);
|
1006
|
+
return this.strftime(date, format, options);
|
1007
1007
|
};
|
1008
1008
|
|
1009
1009
|
// Convert a number into a formatted percentage value.
|
1010
1010
|
I18n.toPercentage = function(number, options) {
|
1011
1011
|
options = this.prepareOptions(
|
1012
1012
|
options
|
1013
|
-
, this.lookup("number.percentage.format")
|
1014
|
-
, this.lookup("number.format")
|
1013
|
+
, this.lookup("number.percentage.format", options)
|
1014
|
+
, this.lookup("number.format", options)
|
1015
1015
|
, PERCENTAGE_FORMAT
|
1016
1016
|
);
|
1017
1017
|
|
@@ -1025,6 +1025,7 @@
|
|
1025
1025
|
, iterations = 0
|
1026
1026
|
, unit
|
1027
1027
|
, precision
|
1028
|
+
, fullScope
|
1028
1029
|
;
|
1029
1030
|
|
1030
1031
|
while (size >= kb && iterations < 4) {
|
@@ -1033,10 +1034,12 @@
|
|
1033
1034
|
}
|
1034
1035
|
|
1035
1036
|
if (iterations === 0) {
|
1036
|
-
|
1037
|
+
fullScope = this.getFullScope("number.human.storage_units.units.byte", options);
|
1038
|
+
unit = this.t(fullScope, {count: size});
|
1037
1039
|
precision = 0;
|
1038
1040
|
} else {
|
1039
|
-
|
1041
|
+
fullScope = this.getFullScope("number.human.storage_units.units." + SIZE_UNITS[iterations], options);
|
1042
|
+
unit = this.t(fullScope);
|
1040
1043
|
precision = (size - Math.floor(size) === 0) ? 0 : 1;
|
1041
1044
|
}
|
1042
1045
|
|
@@ -1053,7 +1056,7 @@
|
|
1053
1056
|
|
1054
1057
|
// Deal with the scope as an array.
|
1055
1058
|
if (isArray(scope)) {
|
1056
|
-
scope = scope.join(this.defaultSeparator);
|
1059
|
+
scope = scope.join(options.separator || this.defaultSeparator);
|
1057
1060
|
}
|
1058
1061
|
|
1059
1062
|
// Deal with the scope option provided through the second argument.
|
@@ -1061,7 +1064,7 @@
|
|
1061
1064
|
// I18n.t('hello', {scope: 'greetings'});
|
1062
1065
|
//
|
1063
1066
|
if (options.scope) {
|
1064
|
-
scope = [options.scope, scope].join(this.defaultSeparator);
|
1067
|
+
scope = [options.scope, scope].join(options.separator || this.defaultSeparator);
|
1065
1068
|
}
|
1066
1069
|
|
1067
1070
|
return scope;
|
@@ -1084,9 +1087,9 @@
|
|
1084
1087
|
};
|
1085
1088
|
|
1086
1089
|
// Set aliases, so we can save some typing.
|
1087
|
-
I18n.t = I18n.translate;
|
1088
|
-
I18n.l = I18n.localize;
|
1089
|
-
I18n.p = I18n.pluralize;
|
1090
|
+
I18n.t = I18n.translate.bind(I18n);
|
1091
|
+
I18n.l = I18n.localize.bind(I18n);
|
1092
|
+
I18n.p = I18n.pluralize.bind(I18n);
|
1090
1093
|
|
1091
1094
|
return I18n;
|
1092
1095
|
}));
|
@@ -206,3 +206,35 @@ if (!Array.prototype.map) {
|
|
206
206
|
return A;
|
207
207
|
};
|
208
208
|
}
|
209
|
+
|
210
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
|
211
|
+
if (!Function.prototype.bind) (function(){
|
212
|
+
var ArrayPrototypeSlice = Array.prototype.slice;
|
213
|
+
Function.prototype.bind = function(otherThis) {
|
214
|
+
if (typeof this !== 'function') {
|
215
|
+
// closest thing possible to the ECMAScript 5
|
216
|
+
// internal IsCallable function
|
217
|
+
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
|
218
|
+
}
|
219
|
+
|
220
|
+
var baseArgs= ArrayPrototypeSlice .call(arguments, 1),
|
221
|
+
baseArgsLength = baseArgs.length,
|
222
|
+
fToBind = this,
|
223
|
+
fNOP = function() {},
|
224
|
+
fBound = function() {
|
225
|
+
baseArgs.length = baseArgsLength; // reset to default base arguments
|
226
|
+
baseArgs.push.apply(baseArgs, arguments);
|
227
|
+
return fToBind.apply(
|
228
|
+
fNOP.prototype.isPrototypeOf(this) ? this : otherThis, baseArgs
|
229
|
+
);
|
230
|
+
};
|
231
|
+
|
232
|
+
if (this.prototype) {
|
233
|
+
// Function.prototype doesn't have a prototype property
|
234
|
+
fNOP.prototype = this.prototype;
|
235
|
+
}
|
236
|
+
fBound.prototype = new fNOP();
|
237
|
+
|
238
|
+
return fBound;
|
239
|
+
};
|
240
|
+
})();
|
data/i18n-js.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
s.add_dependency "i18n", ">= 0.6.6"
|
22
22
|
|
23
|
-
s.add_development_dependency "appraisal", "~> 2.
|
23
|
+
s.add_development_dependency "appraisal", "~> 2.3"
|
24
24
|
s.add_development_dependency "rspec", "~> 3.0"
|
25
25
|
s.add_development_dependency "rake", "~> 12.0"
|
26
26
|
s.add_development_dependency "gem-release", ">= 0.7"
|
@@ -2,11 +2,12 @@ module I18n
|
|
2
2
|
module JS
|
3
3
|
module Formatters
|
4
4
|
class Base
|
5
|
-
def initialize(js_extend: false, namespace: nil, pretty_print: false, prefix: nil)
|
5
|
+
def initialize(js_extend: false, namespace: nil, pretty_print: false, prefix: nil, suffix: nil)
|
6
6
|
@js_extend = js_extend
|
7
7
|
@namespace = namespace
|
8
8
|
@pretty_print = pretty_print
|
9
9
|
@prefix = prefix
|
10
|
+
@suffix = suffix
|
10
11
|
end
|
11
12
|
|
12
13
|
protected
|
data/lib/i18n/js/segment.rb
CHANGED
@@ -7,7 +7,7 @@ module I18n
|
|
7
7
|
|
8
8
|
# Class which enscapulates a translations hash and outputs a single JSON translation file
|
9
9
|
class Segment
|
10
|
-
OPTIONS = [:namespace, :pretty_print, :js_extend, :prefix, :sort_translation_keys, :json_only].freeze
|
10
|
+
OPTIONS = [:namespace, :pretty_print, :js_extend, :prefix, :suffix, :sort_translation_keys, :json_only].freeze
|
11
11
|
LOCALE_INTERPOLATOR = /%\{locale\}/
|
12
12
|
|
13
13
|
attr_reader *([:file, :translations] | OPTIONS)
|
@@ -25,6 +25,7 @@ module I18n
|
|
25
25
|
@pretty_print = !!options[:pretty_print]
|
26
26
|
@js_extend = options.key?(:js_extend) ? !!options[:js_extend] : true
|
27
27
|
@prefix = options.key?(:prefix) ? options[:prefix] : nil
|
28
|
+
@suffix = options.key?(:suffix) ? options[:suffix] : nil
|
28
29
|
@sort_translation_keys = options.key?(:sort_translation_keys) ? !!options[:sort_translation_keys] : true
|
29
30
|
@json_only = options.key?(:json_only) ? !!options[:json_only] : false
|
30
31
|
end
|
@@ -70,7 +71,9 @@ module I18n
|
|
70
71
|
{ js_extend: @js_extend,
|
71
72
|
namespace: @namespace,
|
72
73
|
pretty_print: @pretty_print,
|
73
|
-
prefix: @prefix
|
74
|
+
prefix: @prefix,
|
75
|
+
suffix: @suffix
|
76
|
+
}
|
74
77
|
end
|
75
78
|
end
|
76
79
|
end
|
data/lib/i18n/js/version.rb
CHANGED
data/package.json
CHANGED
@@ -10,45 +10,69 @@ describe("Localization", function(){
|
|
10
10
|
I18n.translations = Translations();
|
11
11
|
});
|
12
12
|
|
13
|
+
it("sets bound alias", function() {
|
14
|
+
expect(I18n.l).toEqual(jasmine.any(Function));
|
15
|
+
expect(I18n.l).not.toBe(I18n.localize);
|
16
|
+
});
|
17
|
+
|
13
18
|
it("localizes number", function(){
|
14
|
-
expect(I18n.
|
19
|
+
expect(I18n.localize("number", 1234567)).toEqual("1,234,567.000");
|
20
|
+
});
|
21
|
+
|
22
|
+
it("localizes number with 'l' shortcut", function(){
|
23
|
+
var l = I18n.l;
|
24
|
+
expect(l("number", 1234567)).toEqual("1,234,567.000");
|
15
25
|
});
|
16
26
|
|
17
27
|
it("localizes currency", function(){
|
18
|
-
expect(I18n.
|
28
|
+
expect(I18n.localize("currency", 1234567)).toEqual("$1,234,567.00");
|
19
29
|
});
|
20
30
|
|
21
31
|
it("localizes date strings", function(){
|
22
32
|
I18n.locale = "pt-BR";
|
23
33
|
|
24
|
-
expect(I18n.
|
25
|
-
expect(I18n.
|
26
|
-
expect(I18n.
|
34
|
+
expect(I18n.localize("date.formats.default", "2009-11-29")).toEqual("29/11/2009");
|
35
|
+
expect(I18n.localize("date.formats.short", "2009-01-07")).toEqual("07 de Janeiro");
|
36
|
+
expect(I18n.localize("date.formats.long", "2009-01-07")).toEqual("07 de Janeiro de 2009");
|
37
|
+
});
|
38
|
+
|
39
|
+
it("localizes strings with locale from options", function(){
|
40
|
+
I18n.locale = "en";
|
41
|
+
|
42
|
+
expect(I18n.localize("date.formats.default", "2009-11-29", { locale: "pt-BR" })).toEqual("29/11/2009");
|
43
|
+
expect(I18n.localize("date.formats.short", "2009-01-07", { locale: "pt-BR" })).toEqual("07 de Janeiro");
|
44
|
+
expect(I18n.localize("date.formats.long", "2009-01-07", { locale: "pt-BR" })).toEqual("07 de Janeiro de 2009");
|
45
|
+
expect(I18n.localize("time.formats.default", "2009-11-29 15:07:59", { locale: "pt-BR" })).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
|
46
|
+
expect(I18n.localize("time.formats.short", "2009-01-07 09:12:35", { locale: "pt-BR" })).toEqual("07/01, 09:12 h");
|
47
|
+
expect(I18n.localize("time.formats.long", "2009-11-29 15:07:59", { locale: "pt-BR" })).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
|
48
|
+
expect(I18n.localize("number", 1234567, { locale: "pt-BR" })).toEqual("1,234,567.000");
|
49
|
+
expect(I18n.localize("currency", 1234567, { locale: "pt-BR" })).toEqual("R$ 1.234.567,00");
|
50
|
+
expect(I18n.localize("percentage", 123.45, { locale: "pt-BR" })).toEqual("123,45%");
|
27
51
|
});
|
28
52
|
|
29
53
|
it("localizes time strings", function(){
|
30
54
|
I18n.locale = "pt-BR";
|
31
55
|
|
32
|
-
expect(I18n.
|
33
|
-
expect(I18n.
|
34
|
-
expect(I18n.
|
56
|
+
expect(I18n.localize("time.formats.default", "2009-11-29 15:07:59")).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
|
57
|
+
expect(I18n.localize("time.formats.short", "2009-01-07 09:12:35")).toEqual("07/01, 09:12 h");
|
58
|
+
expect(I18n.localize("time.formats.long", "2009-11-29 15:07:59")).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
|
35
59
|
});
|
36
60
|
|
37
61
|
it("return 'Invalid Date' or original value for invalid input", function(){
|
38
|
-
expect(I18n.
|
39
|
-
expect(I18n.
|
40
|
-
expect(I18n.
|
62
|
+
expect(I18n.localize("time.formats.default", "")).toEqual("Invalid Date");
|
63
|
+
expect(I18n.localize("time.formats.default", null)).toEqual(null);
|
64
|
+
expect(I18n.localize("time.formats.default", undefined)).toEqual(undefined);
|
41
65
|
});
|
42
66
|
|
43
67
|
it("localizes date/time strings with placeholders", function(){
|
44
68
|
I18n.locale = "pt-BR";
|
45
69
|
|
46
|
-
expect(I18n.
|
47
|
-
expect(I18n.
|
70
|
+
expect(I18n.localize("date.formats.short_with_placeholders", "2009-01-07", { p1: "!", p2: "?" })).toEqual("07 de Janeiro ! ?");
|
71
|
+
expect(I18n.localize("time.formats.short_with_placeholders", "2009-01-07 09:12:35", { p1: "!" })).toEqual("07/01, 09:12 h !");
|
48
72
|
});
|
49
73
|
|
50
74
|
it("localizes percentage", function(){
|
51
75
|
I18n.locale = "pt-BR";
|
52
|
-
expect(I18n.
|
76
|
+
expect(I18n.localize("percentage", 123.45)).toEqual("123,45%");
|
53
77
|
});
|
54
78
|
});
|
data/spec/js/numbers.spec.js
CHANGED
@@ -150,6 +150,10 @@ describe("Numbers", function(){
|
|
150
150
|
expect(I18n.toHumanSize(1024 * 1.6, {precision: 0})).toEqual("2KB");
|
151
151
|
});
|
152
152
|
|
153
|
+
it("returns number as human size using custom scope", function(){
|
154
|
+
expect(I18n.toHumanSize(1024 * 1024, {scope: "extended"})).toEqual("1Megabyte");
|
155
|
+
});
|
156
|
+
|
153
157
|
it("formats numbers with strip insignificant zero", function() {
|
154
158
|
options = {separator: ".", delimiter: ",", strip_insignificant_zeros: true};
|
155
159
|
|
@@ -10,8 +10,9 @@ describe("Pluralization", function(){
|
|
10
10
|
I18n.translations = Translations();
|
11
11
|
});
|
12
12
|
|
13
|
-
it("sets alias", function() {
|
14
|
-
expect(I18n.p).toEqual(
|
13
|
+
it("sets bound alias", function() {
|
14
|
+
expect(I18n.p).toEqual(jasmine.any(Function));
|
15
|
+
expect(I18n.p).not.toBe(I18n.pluralize);
|
15
16
|
});
|
16
17
|
|
17
18
|
it("pluralizes scope", function(){
|
@@ -20,6 +21,13 @@ describe("Pluralization", function(){
|
|
20
21
|
expect(I18n.p(5, "inbox")).toEqual("You have 5 messages");
|
21
22
|
});
|
22
23
|
|
24
|
+
it("pluralizes scope with 'p' shortcut", function(){
|
25
|
+
var p = I18n.p;
|
26
|
+
expect(p(0, "inbox")).toEqual("You have no messages");
|
27
|
+
expect(p(1, "inbox")).toEqual("You have 1 message");
|
28
|
+
expect(p(5, "inbox")).toEqual("You have 5 messages");
|
29
|
+
});
|
30
|
+
|
23
31
|
it("pluralizes using the 'other' scope", function(){
|
24
32
|
I18n.translations["en"]["inbox"]["zero"] = null;
|
25
33
|
expect(I18n.p(0, "inbox")).toEqual("You have 0 messages");
|
data/spec/js/translate.spec.js
CHANGED
@@ -10,83 +10,98 @@ describe("Translate", function(){
|
|
10
10
|
I18n.translations = Translations();
|
11
11
|
});
|
12
12
|
|
13
|
+
it("sets bound alias", function() {
|
14
|
+
expect(I18n.t).toEqual(jasmine.any(Function));
|
15
|
+
expect(I18n.t).not.toBe(I18n.translate);
|
16
|
+
});
|
17
|
+
|
13
18
|
it("returns translation for single scope", function(){
|
14
|
-
expect(I18n.
|
19
|
+
expect(I18n.translate("hello")).toEqual("Hello World!");
|
20
|
+
});
|
21
|
+
|
22
|
+
it("returns translation with 't' shortcut", function(){
|
23
|
+
var t = I18n.t;
|
24
|
+
expect(t("hello")).toEqual("Hello World!");
|
15
25
|
});
|
16
26
|
|
17
27
|
it("returns translation as object", function(){
|
18
|
-
expect(I18n.
|
28
|
+
expect(I18n.translate("greetings")).toEqual(I18n.translations.en.greetings);
|
19
29
|
});
|
20
30
|
|
21
31
|
it("returns missing message translation for valid scope with null", function(){
|
22
|
-
actual = I18n.
|
32
|
+
actual = I18n.translate("null_key");
|
23
33
|
expected = '[missing "en.null_key" translation]';
|
24
34
|
expect(actual).toEqual(expected);
|
25
35
|
});
|
26
36
|
|
27
37
|
it("returns missing message translation for invalid scope", function(){
|
28
|
-
actual = I18n.
|
38
|
+
actual = I18n.translate("invalid.scope");
|
29
39
|
expected = '[missing "en.invalid.scope" translation]';
|
30
40
|
expect(actual).toEqual(expected);
|
31
41
|
});
|
32
42
|
|
33
43
|
it("returns missing message translation with provided locale for invalid scope", function(){
|
34
|
-
actual = I18n.
|
44
|
+
actual = I18n.translate("invalid.scope", { locale: "ja" });
|
35
45
|
expected = '[missing "ja.invalid.scope" translation]';
|
36
46
|
expect(actual).toEqual(expected);
|
37
47
|
});
|
38
48
|
|
39
49
|
it("returns guessed translation if missingBehaviour is set to guess", function(){
|
40
50
|
I18n.missingBehaviour = 'guess'
|
41
|
-
|
42
|
-
|
43
|
-
|
51
|
+
|
52
|
+
var actual_1 = I18n.translate("invalid.thisIsAutomaticallyGeneratedTranslation");
|
53
|
+
var expected_1 = 'this is automatically generated translation';
|
54
|
+
expect(actual_1).toEqual(expected_1);
|
55
|
+
|
56
|
+
var actual_2 = I18n.translate("invalid.this_is_automatically_generated_translation");
|
57
|
+
var expected_2 = 'this is automatically generated translation';
|
58
|
+
expect(actual_2).toEqual(expected_2);
|
44
59
|
});
|
45
60
|
|
46
61
|
it("returns guessed translation with prefix if missingBehaviour is set to guess and prefix is also provided", function(){
|
47
62
|
I18n.missingBehaviour = 'guess'
|
48
63
|
I18n.missingTranslationPrefix = 'EE: '
|
49
|
-
actual = I18n.
|
64
|
+
actual = I18n.translate("invalid.thisIsAutomaticallyGeneratedTranslation");
|
50
65
|
expected = 'EE: this is automatically generated translation';
|
51
66
|
expect(actual).toEqual(expected);
|
52
67
|
});
|
53
68
|
|
54
69
|
it("returns missing message translation for valid scope with scope", function(){
|
55
|
-
actual = I18n.
|
70
|
+
actual = I18n.translate("monster", {scope: "greetings"});
|
56
71
|
expected = '[missing "en.greetings.monster" translation]';
|
57
72
|
expect(actual).toEqual(expected);
|
58
73
|
});
|
59
74
|
|
60
75
|
it("returns translation for single scope on a custom locale", function(){
|
61
76
|
I18n.locale = "pt-BR";
|
62
|
-
expect(I18n.
|
77
|
+
expect(I18n.translate("hello")).toEqual("Olá Mundo!");
|
63
78
|
});
|
64
79
|
|
65
80
|
it("returns translation for multiple scopes", function(){
|
66
|
-
expect(I18n.
|
81
|
+
expect(I18n.translate("greetings.stranger")).toEqual("Hello stranger!");
|
67
82
|
});
|
68
83
|
|
69
84
|
it("returns translation with default locale option", function(){
|
70
|
-
expect(I18n.
|
71
|
-
expect(I18n.
|
85
|
+
expect(I18n.translate("hello", {locale: "en"})).toEqual("Hello World!");
|
86
|
+
expect(I18n.translate("hello", {locale: "pt-BR"})).toEqual("Olá Mundo!");
|
72
87
|
});
|
73
88
|
|
74
89
|
it("fallbacks to the default locale when I18n.fallbacks is enabled", function(){
|
75
90
|
I18n.locale = "pt-BR";
|
76
91
|
I18n.fallbacks = true;
|
77
|
-
expect(I18n.
|
92
|
+
expect(I18n.translate("greetings.stranger")).toEqual("Hello stranger!");
|
78
93
|
});
|
79
94
|
|
80
95
|
it("fallbacks to default locale when providing an unknown locale", function(){
|
81
96
|
I18n.locale = "fr";
|
82
97
|
I18n.fallbacks = true;
|
83
|
-
expect(I18n.
|
98
|
+
expect(I18n.translate("greetings.stranger")).toEqual("Hello stranger!");
|
84
99
|
});
|
85
100
|
|
86
101
|
it("fallbacks to less specific locale", function(){
|
87
102
|
I18n.locale = "de-DE";
|
88
103
|
I18n.fallbacks = true;
|
89
|
-
expect(I18n.
|
104
|
+
expect(I18n.translate("hello")).toEqual("Hallo Welt!");
|
90
105
|
});
|
91
106
|
|
92
107
|
describe("when a 3-part locale is used", function(){
|
@@ -96,15 +111,15 @@ describe("Translate", function(){
|
|
96
111
|
});
|
97
112
|
|
98
113
|
it("fallbacks to 2-part locale when absent", function(){
|
99
|
-
expect(I18n.
|
114
|
+
expect(I18n.translate("cat")).toEqual("貓");
|
100
115
|
});
|
101
116
|
|
102
117
|
it("fallbacks to 1-part locale when 2-part missing requested translation", function(){
|
103
|
-
expect(I18n.
|
118
|
+
expect(I18n.translate("dog")).toEqual("狗");
|
104
119
|
});
|
105
120
|
|
106
121
|
it("fallbacks to 2-part for the first time", function(){
|
107
|
-
expect(I18n.
|
122
|
+
expect(I18n.translate("dragon")).toEqual("龍");
|
108
123
|
});
|
109
124
|
});
|
110
125
|
|
@@ -115,7 +130,7 @@ describe("Translate", function(){
|
|
115
130
|
return ["nb"];
|
116
131
|
};
|
117
132
|
|
118
|
-
expect(I18n.
|
133
|
+
expect(I18n.translate("hello")).toEqual("Hei Verden!");
|
119
134
|
});
|
120
135
|
|
121
136
|
it("fallbacks using custom rules (array)", function() {
|
@@ -123,7 +138,7 @@ describe("Translate", function(){
|
|
123
138
|
I18n.fallbacks = true;
|
124
139
|
I18n.locales["no"] = ["no", "nb"];
|
125
140
|
|
126
|
-
expect(I18n.
|
141
|
+
expect(I18n.translate("hello")).toEqual("Hei Verden!");
|
127
142
|
});
|
128
143
|
|
129
144
|
it("fallbacks using custom rules (string)", function() {
|
@@ -131,25 +146,25 @@ describe("Translate", function(){
|
|
131
146
|
I18n.fallbacks = true;
|
132
147
|
I18n.locales["no"] = "nb";
|
133
148
|
|
134
|
-
expect(I18n.
|
149
|
+
expect(I18n.translate("hello")).toEqual("Hei Verden!");
|
135
150
|
});
|
136
151
|
|
137
152
|
describe("when provided default values", function() {
|
138
153
|
it("uses scope provided in defaults if scope doesn't exist", function() {
|
139
|
-
actual = I18n.
|
154
|
+
actual = I18n.translate("Hello!", {defaults: [{scope: "greetings.stranger"}]});
|
140
155
|
expect(actual).toEqual("Hello stranger!");
|
141
156
|
});
|
142
157
|
|
143
158
|
it("continues to fallback until a scope is found", function() {
|
144
159
|
var defaults = [{scope: "foo"}, {scope: "hello"}];
|
145
160
|
|
146
|
-
actual = I18n.
|
161
|
+
actual = I18n.translate("foo", {defaults: defaults});
|
147
162
|
expect(actual).toEqual("Hello World!");
|
148
163
|
});
|
149
164
|
|
150
165
|
it("uses message if specified as a default", function() {
|
151
166
|
var defaults = [{message: "Hello all!"}];
|
152
|
-
actual = I18n.
|
167
|
+
actual = I18n.translate("foo", {defaults: defaults});
|
153
168
|
expect(actual).toEqual("Hello all!");
|
154
169
|
});
|
155
170
|
|
@@ -158,7 +173,7 @@ describe("Translate", function(){
|
|
158
173
|
{scope: "bar"}
|
159
174
|
, {message: "Hello all!"}
|
160
175
|
, {scope: "hello"}];
|
161
|
-
actual = I18n.
|
176
|
+
actual = I18n.translate("foo", {defaults: defaults});
|
162
177
|
expect(actual).toEqual("Hello all!");
|
163
178
|
});
|
164
179
|
|
@@ -167,7 +182,7 @@ describe("Translate", function(){
|
|
167
182
|
defaults: [{scope: "bar"}]
|
168
183
|
, defaultValue: "Hello all!"
|
169
184
|
};
|
170
|
-
actual = I18n.
|
185
|
+
actual = I18n.translate("foo", options);
|
171
186
|
expect(actual).toEqual("Hello all!");
|
172
187
|
});
|
173
188
|
|
@@ -176,7 +191,7 @@ describe("Translate", function(){
|
|
176
191
|
defaults: [{scope: "hello"}]
|
177
192
|
, defaultValue: "Hello all!"
|
178
193
|
};
|
179
|
-
actual = I18n.
|
194
|
+
actual = I18n.translate("foo", options);
|
180
195
|
expect(actual).toEqual("Hello World!");
|
181
196
|
})
|
182
197
|
|
@@ -187,36 +202,36 @@ describe("Translate", function(){
|
|
187
202
|
return scope.toUpperCase();
|
188
203
|
}
|
189
204
|
};
|
190
|
-
actual = I18n.
|
205
|
+
actual = I18n.translate("foo", options);
|
191
206
|
expect(actual).toEqual("FOO");
|
192
207
|
})
|
193
208
|
|
194
209
|
it("pluralizes using the correct scope if translation is found within default scope", function() {
|
195
210
|
expect(I18n.translations["en"]["mailbox"]).toEqual(undefined);
|
196
|
-
actual = I18n.
|
197
|
-
expected = I18n.
|
211
|
+
actual = I18n.translate("mailbox.inbox", {count: 1, defaults: [{scope: "inbox"}]});
|
212
|
+
expected = I18n.translate("inbox", {count: 1})
|
198
213
|
expect(actual).toEqual(expected)
|
199
214
|
})
|
200
215
|
});
|
201
216
|
|
202
217
|
it("uses default value for simple translation", function(){
|
203
|
-
actual = I18n.
|
218
|
+
actual = I18n.translate("warning", {defaultValue: "Warning!"});
|
204
219
|
expect(actual).toEqual("Warning!");
|
205
220
|
});
|
206
221
|
|
207
222
|
it("uses default value for plural translation", function(){
|
208
|
-
actual = I18n.
|
223
|
+
actual = I18n.translate("message", {defaultValue: { one: '%{count} message', other: '%{count} messages'}, count: 1});
|
209
224
|
expect(actual).toEqual("1 message");
|
210
225
|
});
|
211
226
|
|
212
227
|
it("uses default value for unknown locale", function(){
|
213
228
|
I18n.locale = "fr";
|
214
|
-
actual = I18n.
|
229
|
+
actual = I18n.translate("warning", {defaultValue: "Warning!"});
|
215
230
|
expect(actual).toEqual("Warning!");
|
216
231
|
});
|
217
232
|
|
218
233
|
it("uses default value with interpolation", function(){
|
219
|
-
actual = I18n.
|
234
|
+
actual = I18n.translate(
|
220
235
|
"alert",
|
221
236
|
{defaultValue: "Attention! {{message}}", message: "You're out of quota!"}
|
222
237
|
);
|
@@ -225,33 +240,33 @@ describe("Translate", function(){
|
|
225
240
|
});
|
226
241
|
|
227
242
|
it("ignores default value when scope exists", function(){
|
228
|
-
actual = I18n.
|
243
|
+
actual = I18n.translate("hello", {defaultValue: "What's up?"});
|
229
244
|
expect(actual).toEqual("Hello World!");
|
230
245
|
});
|
231
246
|
|
232
247
|
it("returns translation for custom scope separator", function(){
|
233
248
|
I18n.defaultSeparator = "•";
|
234
|
-
actual = I18n.
|
249
|
+
actual = I18n.translate("greetings•stranger");
|
235
250
|
expect(actual).toEqual("Hello stranger!");
|
236
251
|
});
|
237
252
|
|
238
253
|
it("returns boolean values", function() {
|
239
|
-
expect(I18n.
|
240
|
-
expect(I18n.
|
254
|
+
expect(I18n.translate("booleans.yes")).toEqual(true);
|
255
|
+
expect(I18n.translate("booleans.no")).toEqual(false);
|
241
256
|
});
|
242
257
|
|
243
258
|
it("escapes $ when doing substitution (IE)", function(){
|
244
259
|
I18n.locale = "en";
|
245
260
|
|
246
|
-
expect(I18n.
|
247
|
-
expect(I18n.
|
248
|
-
expect(I18n.
|
261
|
+
expect(I18n.translate("paid", {price: "$0"})).toEqual("You were paid $0");
|
262
|
+
expect(I18n.translate("paid", {price: "$0.12"})).toEqual("You were paid $0.12");
|
263
|
+
expect(I18n.translate("paid", {price: "$1.35"})).toEqual("You were paid $1.35");
|
249
264
|
});
|
250
265
|
|
251
266
|
it("replaces all occurrences of escaped $", function(){
|
252
267
|
I18n.locale = "en";
|
253
268
|
|
254
|
-
expect(I18n.
|
269
|
+
expect(I18n.translate("paid_with_vat", {
|
255
270
|
price: "$0.12",
|
256
271
|
vat: "$0.02"}
|
257
272
|
)).toEqual("You were paid $0.12 (incl. VAT $0.02)");
|
@@ -259,20 +274,20 @@ describe("Translate", function(){
|
|
259
274
|
|
260
275
|
it("sets default scope", function(){
|
261
276
|
var options = {scope: "greetings"};
|
262
|
-
expect(I18n.
|
277
|
+
expect(I18n.translate("stranger", options)).toEqual("Hello stranger!");
|
263
278
|
});
|
264
279
|
|
265
280
|
it("accepts the scope as an array", function(){
|
266
|
-
expect(I18n.
|
281
|
+
expect(I18n.translate(["greetings", "stranger"])).toEqual("Hello stranger!");
|
267
282
|
});
|
268
283
|
|
269
284
|
it("accepts the scope as an array using a base scope", function(){
|
270
|
-
expect(I18n.
|
285
|
+
expect(I18n.translate(["stranger"], {scope: "greetings"})).toEqual("Hello stranger!");
|
271
286
|
});
|
272
287
|
|
273
288
|
it("returns an array with values interpolated", function(){
|
274
289
|
var options = {value: 314};
|
275
|
-
expect(I18n.
|
290
|
+
expect(I18n.translate("arrayWithParams", options)).toEqual([
|
276
291
|
null,
|
277
292
|
"An item with a param of " + options.value,
|
278
293
|
"Another item with a param of " + options.value,
|
@@ -281,4 +296,9 @@ describe("Translate", function(){
|
|
281
296
|
{foo: "bar"}
|
282
297
|
]);
|
283
298
|
});
|
299
|
+
|
300
|
+
|
301
|
+
it("returns value with key containing dot but different separator specified", function() {
|
302
|
+
expect(I18n.t(["A implies B means something."], {scope: "sentences_with_dots", separator: "|"})).toEqual("A implies B means that when A is true, B must be true.");
|
303
|
+
});
|
284
304
|
});
|
data/spec/js/translations.js
CHANGED
@@ -58,6 +58,18 @@
|
|
58
58
|
}
|
59
59
|
}
|
60
60
|
|
61
|
+
, extended: {
|
62
|
+
number: {
|
63
|
+
human: {
|
64
|
+
storage_units: {
|
65
|
+
units: {
|
66
|
+
"mb": "Megabyte"
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
61
73
|
, arrayWithParams: [
|
62
74
|
null,
|
63
75
|
"An item with a param of {{value}}",
|
@@ -67,7 +79,11 @@
|
|
67
79
|
{foo: "bar"}
|
68
80
|
]
|
69
81
|
|
70
|
-
, null_key: null
|
82
|
+
, null_key: null,
|
83
|
+
|
84
|
+
sentences_with_dots: {
|
85
|
+
"A implies B means something.": "A implies B means that when A is true, B must be true."
|
86
|
+
}
|
71
87
|
};
|
72
88
|
|
73
89
|
Translations["en-US"] = {
|
@@ -90,7 +106,16 @@
|
|
90
106
|
hello: "Olá Mundo!"
|
91
107
|
|
92
108
|
, number: {
|
93
|
-
|
109
|
+
currency: {
|
110
|
+
format: {
|
111
|
+
delimiter: ".",
|
112
|
+
format: "%u %n",
|
113
|
+
precision: 2,
|
114
|
+
separator: ",",
|
115
|
+
unit: "R$"
|
116
|
+
}
|
117
|
+
}
|
118
|
+
, percentage: {
|
94
119
|
format: {
|
95
120
|
delimiter: ""
|
96
121
|
, separator: ","
|
data/spec/ruby/i18n/js_spec.rb
CHANGED
@@ -351,7 +351,7 @@ EOS
|
|
351
351
|
end
|
352
352
|
end
|
353
353
|
|
354
|
-
context "namespace, prefix and pretty_print options" do
|
354
|
+
context "namespace, prefix, suffix, and pretty_print options" do
|
355
355
|
|
356
356
|
before do
|
357
357
|
stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
|
@@ -379,6 +379,7 @@ EOS
|
|
379
379
|
"foo": "Foo",
|
380
380
|
"fallback_test": "Success"
|
381
381
|
};
|
382
|
+
//test
|
382
383
|
EOS
|
383
384
|
}$/)
|
384
385
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n-js
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nando Vieira
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '2.
|
33
|
+
version: '2.3'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '2.
|
40
|
+
version: '2.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,6 +126,7 @@ files:
|
|
126
126
|
- gemfiles/i18n_1_5.gemfile
|
127
127
|
- gemfiles/i18n_1_6.gemfile
|
128
128
|
- gemfiles/i18n_1_7.gemfile
|
129
|
+
- gemfiles/i18n_1_8.gemfile
|
129
130
|
- i18n-js.gemspec
|
130
131
|
- lib/i18n-js.rb
|
131
132
|
- lib/i18n/js.rb
|
@@ -207,7 +208,7 @@ homepage: http://rubygems.org/gems/i18n-js
|
|
207
208
|
licenses:
|
208
209
|
- MIT
|
209
210
|
metadata: {}
|
210
|
-
post_install_message:
|
211
|
+
post_install_message:
|
211
212
|
rdoc_options: []
|
212
213
|
require_paths:
|
213
214
|
- lib
|
@@ -222,8 +223,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
222
223
|
- !ruby/object:Gem::Version
|
223
224
|
version: '0'
|
224
225
|
requirements: []
|
225
|
-
rubygems_version: 3.
|
226
|
-
signing_key:
|
226
|
+
rubygems_version: 3.1.4
|
227
|
+
signing_key:
|
227
228
|
specification_version: 4
|
228
229
|
summary: It's a small library to provide the Rails I18n translations on the Javascript.
|
229
230
|
test_files:
|