i18n-js 3.8.2 → 3.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.editorconfig +1 -1
- data/.github/workflows/tests.yaml +5 -0
- data/Appraisals +4 -0
- data/CHANGELOG.md +40 -2
- data/README.md +49 -19
- data/app/assets/javascripts/i18n/shims.js +3 -3
- data/app/assets/javascripts/i18n.js +7 -7
- data/gemfiles/i18n_1_9.gemfile +7 -0
- data/i18n-js.gemspec +1 -1
- data/lib/i18n/js/dependencies.rb +6 -2
- data/lib/i18n/js/engine.rb +1 -1
- data/lib/i18n/js/formatters/js.rb +9 -2
- data/lib/i18n/js/segment.rb +2 -1
- data/lib/i18n/js/utils.rb +14 -1
- data/lib/i18n/js/version.rb +1 -1
- data/lib/i18n/js.rb +12 -2
- data/package.json +1 -1
- data/spec/fixtures/js_available_locales_custom.yml +1 -0
- data/spec/js/json_parsable.spec.js +14 -0
- data/spec/js/require.js +4 -4
- data/spec/ruby/i18n/js/segment_spec.rb +75 -8
- data/spec/ruby/i18n/js/utils_spec.rb +32 -0
- data/spec/ruby/i18n/js_spec.rb +103 -54
- data/yarn.lock +32 -25
- metadata +12 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af88256d90ed5aa70fdaf88ce224e2b3bdb378b65d3e4a826dd9073484d6d691
|
|
4
|
+
data.tar.gz: 3a6409f3e78871438978ebaeb10853e6c49b38eddb3be679a4bf5f550ebc1b17
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 93da6d4965b27b83a8064a0665b3689e8a55bf750881b4cfd00d220e3e73379c56840ff452a3fe586c66c69ff7b1f5132193160913ced2d956e2145ff4567894
|
|
7
|
+
data.tar.gz: 9ce7b91903ac75ee8e7c320058d45893330033eb5628b2ef1a3d8e29466053d21b931a6f1c87c15f7bb1f83bbce0c5c33a8b785c8be79c5acbdbb48eafb459ba
|
data/.editorconfig
CHANGED
|
@@ -4,11 +4,13 @@ on:
|
|
|
4
4
|
pull_request:
|
|
5
5
|
branches:
|
|
6
6
|
- main
|
|
7
|
+
- v3
|
|
7
8
|
paths-ignore:
|
|
8
9
|
- 'README.md'
|
|
9
10
|
push:
|
|
10
11
|
branches:
|
|
11
12
|
- main
|
|
13
|
+
- v3
|
|
12
14
|
paths-ignore:
|
|
13
15
|
- 'README.md'
|
|
14
16
|
|
|
@@ -26,6 +28,8 @@ jobs:
|
|
|
26
28
|
- 2.5
|
|
27
29
|
- 2.6
|
|
28
30
|
- 2.7
|
|
31
|
+
- '3.0'
|
|
32
|
+
- 3.1
|
|
29
33
|
gemfile:
|
|
30
34
|
- gemfiles/i18n_0_6.gemfile
|
|
31
35
|
- gemfiles/i18n_0_7.gemfile
|
|
@@ -40,6 +44,7 @@ jobs:
|
|
|
40
44
|
- gemfiles/i18n_1_6.gemfile
|
|
41
45
|
- gemfiles/i18n_1_7.gemfile
|
|
42
46
|
- gemfiles/i18n_1_8.gemfile
|
|
47
|
+
- gemfiles/i18n_1_9.gemfile
|
|
43
48
|
allow_failures:
|
|
44
49
|
- false
|
|
45
50
|
include:
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
|
-
This project adheres to [Semantic Versioning](
|
|
3
|
+
This project adheres to [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
@@ -18,6 +18,40 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
18
18
|
- Nothing
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
## [3.9.1] - 2022-02-08
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- [Ruby] Allow rails 7
|
|
26
|
+
(PR: https://github.com/fnando/i18n-js/pull/638)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## [3.9.0]
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- [Ruby] Allow to set custom locales instead of using only `I18n.available_locales`.
|
|
34
|
+
(PR: https://github.com/fnando/i18n-js/pull/617)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## [3.8.4]
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- [Ruby] Fix proc exported to JS/JSON file(s) causing issues like git merge conflicts
|
|
42
|
+
(PR: https://github.com/fnando/i18n-js/pull/591)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## [3.8.3]
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- [Ruby] Generate translations in JS as `JSON.parse` instead of object literal for performance
|
|
50
|
+
(PR: https://github.com/fnando/i18n-js/pull/605)
|
|
51
|
+
(PR: https://github.com/fnando/i18n-js/pull/606)
|
|
52
|
+
(PR: https://github.com/fnando/i18n-js/pull/607)
|
|
53
|
+
|
|
54
|
+
|
|
21
55
|
## [3.8.2] - 2021-03-18
|
|
22
56
|
|
|
23
57
|
### Fixed
|
|
@@ -491,7 +525,11 @@ And today is not April Fools' Day
|
|
|
491
525
|
|
|
492
526
|
|
|
493
527
|
|
|
494
|
-
[Unreleased]: https://github.com/fnando/i18n-js/compare/v3.
|
|
528
|
+
[Unreleased]: https://github.com/fnando/i18n-js/compare/v3.9.1...HEAD
|
|
529
|
+
[3.9.1]: https://github.com/fnando/i18n-js/compare/v3.9.0...v3.9.1
|
|
530
|
+
[3.9.0]: https://github.com/fnando/i18n-js/compare/v3.8.4...v3.9.0
|
|
531
|
+
[3.8.4]: https://github.com/fnando/i18n-js/compare/v3.8.3...v3.8.4
|
|
532
|
+
[3.8.3]: https://github.com/fnando/i18n-js/compare/v3.8.2...v3.8.3
|
|
495
533
|
[3.8.2]: https://github.com/fnando/i18n-js/compare/v3.8.1...v3.8.2
|
|
496
534
|
[3.8.1]: https://github.com/fnando/i18n-js/compare/v3.8.0...v3.8.1
|
|
497
535
|
[3.8.0]: https://github.com/fnando/i18n-js/compare/v3.7.1...v3.8.0
|
data/README.md
CHANGED
|
@@ -8,11 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
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="
|
|
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
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
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://
|
|
15
|
-
<a href="https://coveralls.io/r/fnando/i18n-js"><img src="http://img.shields.io/coveralls/fnando/i18n-js.svg" alt="Coverage Status"></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>
|
|
16
15
|
<a href="https://gitter.im/fnando/i18n-js"><img src="https://img.shields.io/badge/gitter-join%20chat-1dce73.svg" alt="Gitter"></a>
|
|
17
16
|
</p>
|
|
18
17
|
|
|
@@ -59,10 +58,10 @@ For more details, see:
|
|
|
59
58
|
- [this gist](https://gist.github.com/bazzel/ecdff4718962e57c2d5569cf01d332fe)
|
|
60
59
|
- https://github.com/fnando/i18n-js/issues/597
|
|
61
60
|
|
|
62
|
-
#### Rails app with [Asset Pipeline](
|
|
61
|
+
#### Rails app with [Asset Pipeline](https://guides.rubyonrails.org/asset_pipeline.html)
|
|
63
62
|
|
|
64
63
|
If you're using the
|
|
65
|
-
[asset pipeline](
|
|
64
|
+
[asset pipeline](https://guides.rubyonrails.org/asset_pipeline.html), then you
|
|
66
65
|
must add the following line to your `app/assets/javascripts/application.js`.
|
|
67
66
|
|
|
68
67
|
```javascript
|
|
@@ -77,7 +76,7 @@ must add the following line to your `app/assets/javascripts/application.js`.
|
|
|
77
76
|
//= require i18n/translations
|
|
78
77
|
```
|
|
79
78
|
|
|
80
|
-
#### Rails app without [Asset Pipeline](
|
|
79
|
+
#### Rails app without [Asset Pipeline](https://guides.rubyonrails.org/asset_pipeline.html)
|
|
81
80
|
|
|
82
81
|
First, put this in your `application.html` (layout file). Then get the JS files
|
|
83
82
|
following the instructions below.
|
|
@@ -271,6 +270,17 @@ You must disable this feature by setting the option to `false`.
|
|
|
271
270
|
To find more examples on how to use the configuration file please refer to the
|
|
272
271
|
tests.
|
|
273
272
|
|
|
273
|
+
#### Available locales
|
|
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
|
+
```
|
|
283
|
+
|
|
274
284
|
#### Namespace
|
|
275
285
|
|
|
276
286
|
Setting the `namespace` option will change the namespace of the output
|
|
@@ -480,6 +490,8 @@ I18n.locales.no = function (locale) {
|
|
|
480
490
|
};
|
|
481
491
|
```
|
|
482
492
|
|
|
493
|
+
### Translation Missing Behaviour Control
|
|
494
|
+
|
|
483
495
|
By default a missing translation will be displayed as
|
|
484
496
|
|
|
485
497
|
[missing "name of scope" translation]
|
|
@@ -498,8 +510,10 @@ Camel case becomes lower cased text and underscores are replaced with space
|
|
|
498
510
|
|
|
499
511
|
becomes "what is your favorite Christmas present"
|
|
500
512
|
|
|
513
|
+
#### Option `missingTranslationPrefix`
|
|
514
|
+
|
|
501
515
|
In order to still detect untranslated strings, you can set
|
|
502
|
-
`
|
|
516
|
+
`I18n.missingTranslationPrefix` to something like:
|
|
503
517
|
|
|
504
518
|
```javascript
|
|
505
519
|
I18n.missingTranslationPrefix = "EE: ";
|
|
@@ -514,14 +528,27 @@ And result will be:
|
|
|
514
528
|
|
|
515
529
|
This will help you doing automated tests against your localisation assets.
|
|
516
530
|
|
|
517
|
-
|
|
531
|
+
#### Customize return when translation entry missing
|
|
532
|
+
|
|
533
|
+
Some people prefer returning `null`/`undefined` for missing translation:
|
|
518
534
|
|
|
519
535
|
```javascript
|
|
520
|
-
I18n.missingTranslation = function () {
|
|
536
|
+
I18n.missingTranslation = function (scope, options) {
|
|
521
537
|
return undefined;
|
|
522
538
|
};
|
|
523
539
|
```
|
|
524
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
|
+
|
|
525
552
|
Pluralization is possible as well and by default provides English rules:
|
|
526
553
|
|
|
527
554
|
```javascript
|
|
@@ -959,23 +986,26 @@ more details and discussion of this issue.
|
|
|
959
986
|
### JS `I18n.toCurrency` & `I18n.toNumber` cannot handle large integers
|
|
960
987
|
|
|
961
988
|
The above methods use `toFixed` and it only supports 53 bit integers. Ref:
|
|
962
|
-
|
|
989
|
+
https://2ality.com/2012/07/large-integers.html
|
|
963
990
|
|
|
964
991
|
Feel free to find & discuss possible solution(s) at issue
|
|
965
992
|
[#511](https://github.com/fnando/i18n-js/issues/511)
|
|
966
993
|
|
|
967
|
-
###
|
|
994
|
+
### May not work with all backend implementations
|
|
968
995
|
|
|
969
|
-
|
|
970
|
-
|
|
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:
|
|
971
999
|
|
|
972
1000
|
```
|
|
973
1001
|
Undefined method 'initialized?' for <your backend class>
|
|
974
1002
|
```
|
|
975
1003
|
|
|
976
|
-
For now, i18n-js is
|
|
977
|
-
|
|
978
|
-
|
|
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
|
|
979
1009
|
separate `Simple` backend, by adding the following in an initializer:
|
|
980
1010
|
|
|
981
1011
|
```ruby
|
|
@@ -1014,18 +1044,18 @@ and discussion of this issue.
|
|
|
1014
1044
|
|
|
1015
1045
|
## Maintainer
|
|
1016
1046
|
|
|
1017
|
-
- Nando Vieira - <
|
|
1047
|
+
- Nando Vieira - <https://nandovieira.com>
|
|
1018
1048
|
|
|
1019
1049
|
## Contributing
|
|
1020
1050
|
|
|
1021
1051
|
Once you've made your great commits:
|
|
1022
1052
|
|
|
1023
|
-
1. [Fork](
|
|
1053
|
+
1. [Fork](https://help.github.com/forking/) I18n.js
|
|
1024
1054
|
2. Create a branch with a clear name
|
|
1025
1055
|
3. Make your changes (Please also add/change spec, README and CHANGELOG if
|
|
1026
1056
|
applicable)
|
|
1027
1057
|
4. Push changes to the created branch
|
|
1028
|
-
5. [Create an Pull Request](
|
|
1058
|
+
5. [Create an Pull Request](https://github.com/fnando/i18n-js/pulls)
|
|
1029
1059
|
6. That's it!
|
|
1030
1060
|
|
|
1031
1061
|
Please respect the indentation rules and code style. And use 2 spaces, not tabs.
|
|
@@ -33,7 +33,7 @@ if (!Array.prototype.indexOf) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// Production steps of ECMA-262, Edition 5, 15.4.4.18
|
|
36
|
-
// Reference:
|
|
36
|
+
// Reference: https://es5.github.com/#x15.4.4.18
|
|
37
37
|
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
|
|
38
38
|
if ( !Array.prototype.forEach ) {
|
|
39
39
|
|
|
@@ -53,7 +53,7 @@ if ( !Array.prototype.forEach ) {
|
|
|
53
53
|
var len = O.length >>> 0; // Hack to convert O.length to a UInt32
|
|
54
54
|
|
|
55
55
|
// 4. If IsCallable(callback) is false, throw a TypeError exception.
|
|
56
|
-
// See:
|
|
56
|
+
// See: https://es5.github.com/#x9.11
|
|
57
57
|
if ( {}.toString.call(callback) !== "[object Function]" ) {
|
|
58
58
|
throw new TypeError( callback + " is not a function" );
|
|
59
59
|
}
|
|
@@ -139,7 +139,7 @@ if (!Array.prototype.map) {
|
|
|
139
139
|
var len = O.length >>> 0;
|
|
140
140
|
|
|
141
141
|
// 4. If IsCallable(callback) is false, throw a TypeError exception.
|
|
142
|
-
// See:
|
|
142
|
+
// See: https://es5.github.com/#x9.11
|
|
143
143
|
if (typeof callback !== 'function') {
|
|
144
144
|
throw new TypeError(callback + ' is not a function');
|
|
145
145
|
}
|
|
@@ -269,23 +269,23 @@
|
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
// Locale code format 1:
|
|
272
|
-
// According to RFC4646 (
|
|
272
|
+
// According to RFC4646 (https://www.ietf.org/rfc/rfc4646.txt)
|
|
273
273
|
// language codes for Traditional Chinese should be `zh-Hant`
|
|
274
274
|
//
|
|
275
275
|
// But due to backward compatibility
|
|
276
276
|
// We use older version of IETF language tag
|
|
277
|
-
// @see
|
|
278
|
-
// @see
|
|
277
|
+
// @see https://www.w3.org/TR/html401/struct/dirlang.html
|
|
278
|
+
// @see https://en.wikipedia.org/wiki/IETF_language_tag
|
|
279
279
|
//
|
|
280
280
|
// Format: `language-code = primary-code ( "-" subcode )*`
|
|
281
281
|
//
|
|
282
282
|
// primary-code uses ISO639-1
|
|
283
|
-
// @see
|
|
284
|
-
// @see
|
|
283
|
+
// @see https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
|
284
|
+
// @see https://www.iso.org/iso/home/standards/language_codes.htm
|
|
285
285
|
//
|
|
286
286
|
// subcode uses ISO 3166-1 alpha-2
|
|
287
|
-
// @see
|
|
288
|
-
// @see
|
|
287
|
+
// @see https://en.wikipedia.org/wiki/ISO_3166
|
|
288
|
+
// @see https://www.iso.org/iso/country_codes.htm
|
|
289
289
|
//
|
|
290
290
|
// @note
|
|
291
291
|
// subcode can be in upper case or lower case
|
data/i18n-js.gemspec
CHANGED
|
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
|
8
8
|
s.platform = Gem::Platform::RUBY
|
|
9
9
|
s.authors = ["Nando Vieira"]
|
|
10
10
|
s.email = ["fnando.vieira@gmail.com"]
|
|
11
|
-
s.homepage = "
|
|
11
|
+
s.homepage = "https://rubygems.org/gems/i18n-js"
|
|
12
12
|
s.summary = "It's a small library to provide the Rails I18n translations on the Javascript."
|
|
13
13
|
s.description = s.summary
|
|
14
14
|
s.license = "MIT"
|
data/lib/i18n/js/dependencies.rb
CHANGED
|
@@ -18,7 +18,7 @@ module I18n
|
|
|
18
18
|
# Call this in an initializer
|
|
19
19
|
def using_asset_pipeline?
|
|
20
20
|
assets_pipeline_available =
|
|
21
|
-
(rails3? || rails4? || rails5? || rails6?) &&
|
|
21
|
+
(rails3? || rails4? || rails5? || rails6? || rails7?) &&
|
|
22
22
|
Rails.respond_to?(:application) &&
|
|
23
23
|
Rails.application.config.respond_to?(:assets)
|
|
24
24
|
rails3_assets_enabled =
|
|
@@ -26,7 +26,7 @@ module I18n
|
|
|
26
26
|
assets_pipeline_available &&
|
|
27
27
|
Rails.application.config.assets.enabled != false
|
|
28
28
|
|
|
29
|
-
assets_pipeline_available && (rails4? || rails5? || rails6? || rails3_assets_enabled)
|
|
29
|
+
assets_pipeline_available && (rails4? || rails5? || rails6? || rails7? || rails3_assets_enabled)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
private
|
|
@@ -46,6 +46,10 @@ module I18n
|
|
|
46
46
|
def rails6?
|
|
47
47
|
rails? && Rails.version.to_i == 6
|
|
48
48
|
end
|
|
49
|
+
|
|
50
|
+
def rails7?
|
|
51
|
+
rails? && Rails.version.to_i == 7
|
|
52
|
+
end
|
|
49
53
|
|
|
50
54
|
def safe_gem_check(*args)
|
|
51
55
|
if Gem::Specification.respond_to?(:find_by_name)
|
data/lib/i18n/js/engine.rb
CHANGED
|
@@ -21,7 +21,7 @@ module I18n
|
|
|
21
21
|
# https://github.com/rails/sprockets-rails/blob/master/lib/sprockets/railtie.rb
|
|
22
22
|
#
|
|
23
23
|
# Finisher hook is the place which should be used as border.
|
|
24
|
-
#
|
|
24
|
+
# https://guides.rubyonrails.org/configuring.html#initializers
|
|
25
25
|
#
|
|
26
26
|
# For detail see Pull Request:
|
|
27
27
|
# https://github.com/fnando/i18n-js/pull/371
|
|
@@ -4,6 +4,12 @@ module I18n
|
|
|
4
4
|
module JS
|
|
5
5
|
module Formatters
|
|
6
6
|
class JS < Base
|
|
7
|
+
JSON_ESCAPE_MAP = {
|
|
8
|
+
"'" => "\\'",
|
|
9
|
+
"\\" => "\\\\"
|
|
10
|
+
}.freeze
|
|
11
|
+
private_constant :JSON_ESCAPE_MAP
|
|
12
|
+
|
|
7
13
|
def format(translations)
|
|
8
14
|
contents = header
|
|
9
15
|
translations.each do |locale, translations_for_locale|
|
|
@@ -20,10 +26,11 @@ module I18n
|
|
|
20
26
|
end
|
|
21
27
|
|
|
22
28
|
def line(locale, translations)
|
|
29
|
+
json_literal = @pretty_print ? translations : %(JSON.parse('#{translations.gsub(/#{Regexp.union(JSON_ESCAPE_MAP.keys)}/){|match| JSON_ESCAPE_MAP.fetch(match) }}'))
|
|
23
30
|
if @js_extend
|
|
24
|
-
%(#{@namespace}.translations["#{locale}"] = I18n.extend((#{@namespace}.translations["#{locale}"] || {}), #{
|
|
31
|
+
%(#{@namespace}.translations["#{locale}"] = I18n.extend((#{@namespace}.translations["#{locale}"] || {}), #{json_literal});\n)
|
|
25
32
|
else
|
|
26
|
-
%(#{@namespace}.translations["#{locale}"] = #{
|
|
33
|
+
%(#{@namespace}.translations["#{locale}"] = #{json_literal};\n)
|
|
27
34
|
end
|
|
28
35
|
end
|
|
29
36
|
end
|
data/lib/i18n/js/segment.rb
CHANGED
|
@@ -33,7 +33,7 @@ module I18n
|
|
|
33
33
|
# Saves JSON file containing translations
|
|
34
34
|
def save!
|
|
35
35
|
if @file =~ LOCALE_INTERPOLATOR
|
|
36
|
-
I18n.
|
|
36
|
+
I18n::JS.js_available_locales.each do |locale|
|
|
37
37
|
write_file(file_for_locale(locale), @translations.slice(locale))
|
|
38
38
|
end
|
|
39
39
|
else
|
|
@@ -50,6 +50,7 @@ module I18n
|
|
|
50
50
|
def write_file(_file = @file, _translations = @translations)
|
|
51
51
|
FileUtils.mkdir_p File.dirname(_file)
|
|
52
52
|
_translations = Utils.deep_key_sort(_translations) if @sort_translation_keys
|
|
53
|
+
_translations = Utils.deep_remove_procs(_translations)
|
|
53
54
|
contents = formatter.format(_translations)
|
|
54
55
|
|
|
55
56
|
return if File.exist?(_file) && File.read(_file) == contents
|
data/lib/i18n/js/utils.rb
CHANGED
|
@@ -3,7 +3,7 @@ module I18n
|
|
|
3
3
|
module Utils
|
|
4
4
|
PLURAL_KEYS = %i[zero one two few many other].freeze
|
|
5
5
|
|
|
6
|
-
# Based on deep_merge by Stefan Rusterholz, see <
|
|
6
|
+
# Based on deep_merge by Stefan Rusterholz, see <https://www.ruby-forum.com/topic/142809>.
|
|
7
7
|
# This method is used to handle I18n fallbacks. Given two equivalent path nodes in two locale trees:
|
|
8
8
|
# 1. If the node in the current locale appears to be an I18n pluralization (:one, :other, etc.),
|
|
9
9
|
# use the node, but merge in any missing/non-nil keys from the fallback (default) locale.
|
|
@@ -73,6 +73,19 @@ module I18n
|
|
|
73
73
|
seed[key] = value.is_a?(Hash) ? deep_key_sort(value) : value
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
|
+
|
|
77
|
+
def self.deep_remove_procs(hash)
|
|
78
|
+
# procs exist in `i18n.plural.rule` as pluralizer
|
|
79
|
+
# But having it in translation causes the exported JS/JSON changes every time
|
|
80
|
+
# https://github.com/ruby-i18n/i18n/blob/v1.8.7/lib/i18n/backend/pluralization.rb#L51
|
|
81
|
+
hash.keys.
|
|
82
|
+
each_with_object({}) do |key, seed|
|
|
83
|
+
value = hash[key]
|
|
84
|
+
next if value.is_a?(Proc)
|
|
85
|
+
|
|
86
|
+
seed[key] = value.is_a?(Hash) ? deep_remove_procs(value) : value
|
|
87
|
+
end
|
|
88
|
+
end
|
|
76
89
|
end
|
|
77
90
|
end
|
|
78
91
|
end
|
data/lib/i18n/js/version.rb
CHANGED
data/lib/i18n/js.rb
CHANGED
|
@@ -81,7 +81,7 @@ module I18n
|
|
|
81
81
|
|
|
82
82
|
# deep_merge! given result with result for fallback locale
|
|
83
83
|
def self.merge_with_fallbacks!(result)
|
|
84
|
-
|
|
84
|
+
js_available_locales.each do |locale|
|
|
85
85
|
fallback_locales = FallbackLocales.new(fallbacks, locale)
|
|
86
86
|
fallback_locales.each do |fallback_locale|
|
|
87
87
|
# `result[fallback_locale]` could be missing
|
|
@@ -183,7 +183,7 @@ module I18n
|
|
|
183
183
|
#
|
|
184
184
|
# So the input is wrapped by our class for better `#slice`
|
|
185
185
|
Private::HashWithSymbolKeys.new(translations).
|
|
186
|
-
slice(*::I18n.
|
|
186
|
+
slice(*::I18n::JS.js_available_locales).
|
|
187
187
|
to_h
|
|
188
188
|
end
|
|
189
189
|
end
|
|
@@ -213,6 +213,16 @@ module I18n
|
|
|
213
213
|
end
|
|
214
214
|
end
|
|
215
215
|
|
|
216
|
+
# Get all available locales.
|
|
217
|
+
#
|
|
218
|
+
# @return [Array<Symbol>] the locales.
|
|
219
|
+
def self.js_available_locales
|
|
220
|
+
config.fetch(:js_available_locales) do
|
|
221
|
+
# default value
|
|
222
|
+
I18n.available_locales
|
|
223
|
+
end.map(&:to_sym)
|
|
224
|
+
end
|
|
225
|
+
|
|
216
226
|
def self.sort_translation_keys?
|
|
217
227
|
@sort_translation_keys ||= (config[:sort_translation_keys]) if config.key?(:sort_translation_keys)
|
|
218
228
|
@sort_translation_keys = true if @sort_translation_keys.nil?
|
data/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
js_available_locales: ["en", "foo"]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
describe("JSON.parse", function () {
|
|
2
|
+
it('should parse', function () {
|
|
3
|
+
expect(JSON.parse('{"a":"Test\'s"}')).toEqual({
|
|
4
|
+
a: "Test's"
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
expect(JSON.parse('{"a":"say \\"hello\\""}')).toEqual({
|
|
8
|
+
a: 'say "hello"'
|
|
9
|
+
});
|
|
10
|
+
expect(JSON.parse('{"double-backslash-in-double-quote":"\\"\\\\\\\\\\""}')).toEqual({
|
|
11
|
+
'double-backslash-in-double-quote': '"\\\\"'
|
|
12
|
+
});
|
|
13
|
+
})
|
|
14
|
+
})
|
data/spec/js/require.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** vim: et:ts=4:sw=4:sts=4
|
|
2
2
|
* @license RequireJS 2.1.16 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved.
|
|
3
3
|
* Available via the MIT or new BSD license.
|
|
4
|
-
* see:
|
|
4
|
+
* see: https://github.com/jrburke/requirejs for details
|
|
5
5
|
*/
|
|
6
6
|
//Not using strict: uneven strict support in browsers, #392, and causes
|
|
7
7
|
//problems with requirejs.exec()/transpiler plugins that may not be strict.
|
|
@@ -163,7 +163,7 @@ var requirejs, require, define;
|
|
|
163
163
|
* @returns {Error}
|
|
164
164
|
*/
|
|
165
165
|
function makeError(id, msg, err, requireModules) {
|
|
166
|
-
var e = new Error(msg + '\
|
|
166
|
+
var e = new Error(msg + '\nhttps://requirejs.org/docs/errors.html#' + id);
|
|
167
167
|
e.requireType = id;
|
|
168
168
|
e.requireModules = requireModules;
|
|
169
169
|
if (err) {
|
|
@@ -1810,7 +1810,7 @@ var requirejs, require, define;
|
|
|
1810
1810
|
head = s.head = document.getElementsByTagName('head')[0];
|
|
1811
1811
|
//If BASE tag is in play, using appendChild is a problem for IE6.
|
|
1812
1812
|
//When that browser dies, this can be removed. Details in this jQuery bug:
|
|
1813
|
-
//
|
|
1813
|
+
//https://dev.jquery.com/ticket/2709
|
|
1814
1814
|
baseElement = document.getElementsByTagName('base')[0];
|
|
1815
1815
|
if (baseElement) {
|
|
1816
1816
|
head = s.head = baseElement.parentNode;
|
|
@@ -1829,7 +1829,7 @@ var requirejs, require, define;
|
|
|
1829
1829
|
*/
|
|
1830
1830
|
req.createNode = function (config, moduleName, url) {
|
|
1831
1831
|
var node = config.xhtml ?
|
|
1832
|
-
document.createElementNS('
|
|
1832
|
+
document.createElementNS('https://www.w3.org/1999/xhtml', 'html:script') :
|
|
1833
1833
|
document.createElement('script');
|
|
1834
1834
|
node.type = config.scriptType || 'text/javascript';
|
|
1835
1835
|
node.charset = 'utf-8';
|
|
@@ -131,8 +131,8 @@ EOS
|
|
|
131
131
|
|
|
132
132
|
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
|
133
133
|
MyNamespace.translations || (MyNamespace.translations = {});
|
|
134
|
-
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"test":"Test"});
|
|
135
|
-
MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), {"test":"Test2"});
|
|
134
|
+
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"test":"Test"}'));
|
|
135
|
+
MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), JSON.parse('{"test":"Test2"}'));
|
|
136
136
|
EOF
|
|
137
137
|
end
|
|
138
138
|
end
|
|
@@ -146,12 +146,54 @@ MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] ||
|
|
|
146
146
|
|
|
147
147
|
expect(File.open(File.join(temp_path, "en.js")){|f| f.read}).to eql <<-EOF
|
|
148
148
|
MyNamespace.translations || (MyNamespace.translations = {});
|
|
149
|
-
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"test":"Test"});
|
|
149
|
+
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"test":"Test"}'));
|
|
150
150
|
EOF
|
|
151
151
|
|
|
152
152
|
expect(File.open(File.join(temp_path, "fr.js")){|f| f.read}).to eql <<-EOF
|
|
153
153
|
MyNamespace.translations || (MyNamespace.translations = {});
|
|
154
|
-
MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), {"test":"Test2"});
|
|
154
|
+
MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), JSON.parse('{"test":"Test2"}'));
|
|
155
|
+
EOF
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
context "when file includes single quote" do
|
|
160
|
+
let(:file){ "tmp/i18n-js/%{locale}.js" }
|
|
161
|
+
let(:translations){ { en: { "a" => "Test's" } } }
|
|
162
|
+
|
|
163
|
+
it "should write files" do
|
|
164
|
+
file_should_exist "en.js"
|
|
165
|
+
|
|
166
|
+
expect(File.open(File.join(temp_path, "en.js")){|f| f.read}).to eql <<-EOF
|
|
167
|
+
MyNamespace.translations || (MyNamespace.translations = {});
|
|
168
|
+
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"a":"Test\\'s"}'));
|
|
169
|
+
EOF
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
context "when file includes escaped double quote" do
|
|
174
|
+
let(:file){ "tmp/i18n-js/%{locale}.js" }
|
|
175
|
+
let(:translations){ { en: { "a" => 'say "hello"' } } }
|
|
176
|
+
|
|
177
|
+
it "should escape double quote" do
|
|
178
|
+
file_should_exist "en.js"
|
|
179
|
+
|
|
180
|
+
expect(File.open(File.join(temp_path, "en.js")){|f| f.read}).to eql <<-EOF
|
|
181
|
+
MyNamespace.translations || (MyNamespace.translations = {});
|
|
182
|
+
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"a":"say \\\\"hello\\\\""}'));
|
|
183
|
+
EOF
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
context "when file includes backslash in double quote" do
|
|
188
|
+
let(:file){ "tmp/i18n-js/%{locale}.js" }
|
|
189
|
+
let(:translations){ { en: { "double-backslash-in-double-quote" => '"\\\\"' } } }
|
|
190
|
+
|
|
191
|
+
it "should escape backslash" do
|
|
192
|
+
file_should_exist "en.js"
|
|
193
|
+
|
|
194
|
+
expect(File.open(File.join(temp_path, "en.js")){|f| f.read}).to eql <<-EOF
|
|
195
|
+
MyNamespace.translations || (MyNamespace.translations = {});
|
|
196
|
+
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"double-backslash-in-double-quote":"\\\\"\\\\\\\\\\\\\\\\\\\\""}'));
|
|
155
197
|
EOF
|
|
156
198
|
end
|
|
157
199
|
end
|
|
@@ -166,7 +208,7 @@ MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] ||
|
|
|
166
208
|
|
|
167
209
|
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
|
168
210
|
MyNamespace.translations || (MyNamespace.translations = {});
|
|
169
|
-
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"a":"Test","b":"Test"});
|
|
211
|
+
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"a":"Test","b":"Test"}'));
|
|
170
212
|
EOF
|
|
171
213
|
end
|
|
172
214
|
end
|
|
@@ -181,7 +223,7 @@ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] ||
|
|
|
181
223
|
|
|
182
224
|
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
|
183
225
|
MyNamespace.translations || (MyNamespace.translations = {});
|
|
184
|
-
MyNamespace.translations["en"] = {"a":"Test","b":"Test"};
|
|
226
|
+
MyNamespace.translations["en"] = JSON.parse('{"a":"Test","b":"Test"}');
|
|
185
227
|
EOF
|
|
186
228
|
end
|
|
187
229
|
end
|
|
@@ -196,7 +238,7 @@ MyNamespace.translations["en"] = {"a":"Test","b":"Test"};
|
|
|
196
238
|
|
|
197
239
|
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
|
198
240
|
MyNamespace.translations || (MyNamespace.translations = {});
|
|
199
|
-
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"a":"Test","b":"Test"});
|
|
241
|
+
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"a":"Test","b":"Test"}'));
|
|
200
242
|
EOF
|
|
201
243
|
end
|
|
202
244
|
end
|
|
@@ -211,7 +253,32 @@ MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] ||
|
|
|
211
253
|
|
|
212
254
|
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
|
213
255
|
MyNamespace.translations || (MyNamespace.translations = {});
|
|
214
|
-
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), {"b":"Test","a":"Test"});
|
|
256
|
+
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"b":"Test","a":"Test"}'));
|
|
257
|
+
EOF
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
context "when translation entries contain procs" do
|
|
262
|
+
let(:translations) do
|
|
263
|
+
{
|
|
264
|
+
en: {
|
|
265
|
+
"test" => "Test",
|
|
266
|
+
"i18n" => {"plural" => {"rule" => proc {} }},
|
|
267
|
+
},
|
|
268
|
+
fr: {
|
|
269
|
+
"test" => "Test2",
|
|
270
|
+
"i18n" => {"plural" => {"rule" => proc {} }},
|
|
271
|
+
},
|
|
272
|
+
}
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
it "should write files without procs or their string representations" do
|
|
276
|
+
file_should_exist "segment.js"
|
|
277
|
+
|
|
278
|
+
expect(File.open(File.join(temp_path, "segment.js")){|f| f.read}).to eql <<-EOF
|
|
279
|
+
MyNamespace.translations || (MyNamespace.translations = {});
|
|
280
|
+
MyNamespace.translations["en"] = I18n.extend((MyNamespace.translations["en"] || {}), JSON.parse('{"i18n":{"plural":{}},"test":"Test"}'));
|
|
281
|
+
MyNamespace.translations["fr"] = I18n.extend((MyNamespace.translations["fr"] || {}), JSON.parse('{"i18n":{"plural":{}},"test":"Test2"}'));
|
|
215
282
|
EOF
|
|
216
283
|
end
|
|
217
284
|
end
|
|
@@ -103,4 +103,36 @@ describe I18n::JS::Utils do
|
|
|
103
103
|
expect(described_class.scopes_match?([:a, :b, :c], [:a, '*', '*'])).to eql true
|
|
104
104
|
end
|
|
105
105
|
end
|
|
106
|
+
|
|
107
|
+
describe ".deep_remove_procs" do
|
|
108
|
+
let(:proc_obj) { proc {} }
|
|
109
|
+
let(:hash_with_proc) do
|
|
110
|
+
{
|
|
111
|
+
:a => :b,
|
|
112
|
+
:c => proc_obj,
|
|
113
|
+
:d => {
|
|
114
|
+
:e => proc_obj,
|
|
115
|
+
:f => :g,
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
end
|
|
119
|
+
subject { described_class.deep_remove_procs(hash_with_proc) }
|
|
120
|
+
|
|
121
|
+
it "performs a deep keys sort without changing the original hash" do
|
|
122
|
+
should eql({
|
|
123
|
+
:a => :b,
|
|
124
|
+
:d => {
|
|
125
|
+
:f => :g,
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
expect(hash_with_proc).to eql({
|
|
129
|
+
:a => :b,
|
|
130
|
+
:c => proc_obj,
|
|
131
|
+
:d => {
|
|
132
|
+
:e => proc_obj,
|
|
133
|
+
:f => :g,
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
end
|
|
137
|
+
end
|
|
106
138
|
end
|
data/spec/ruby/i18n/js_spec.rb
CHANGED
|
@@ -67,13 +67,13 @@ describe I18n::JS do
|
|
|
67
67
|
en_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "en.js"))
|
|
68
68
|
expect(en_output).to eq(<<EOS
|
|
69
69
|
I18n.translations || (I18n.translations = {});
|
|
70
|
-
I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), {"admin":{"edit":{"title":"Edit"},"show":{"note":"more details","title":"Show"}},"date":{"abbr_day_names":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"abbr_month_names":[null,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"day_names":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"formats":{"default":"%Y-%m-%d","long":"%B %d, %Y","short":"%b %d"},"month_names":[null,"January","February","March","April","May","June","July","August","September","October","November","December"]}});
|
|
70
|
+
I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), JSON.parse('{"admin":{"edit":{"title":"Edit"},"show":{"note":"more details","title":"Show"}},"date":{"abbr_day_names":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"abbr_month_names":[null,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"day_names":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"formats":{"default":"%Y-%m-%d","long":"%B %d, %Y","short":"%b %d"},"month_names":[null,"January","February","March","April","May","June","July","August","September","October","November","December"]}}'));
|
|
71
71
|
EOS
|
|
72
72
|
)
|
|
73
73
|
fr_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "fr.js"))
|
|
74
74
|
expect(fr_output).to eq(<<EOS
|
|
75
75
|
I18n.translations || (I18n.translations = {});
|
|
76
|
-
I18n.translations["fr"] = I18n.extend((I18n.translations["fr"] || {}), {"admin":{"edit":{"title":"Editer"},"show":{"note":"plus de détails","title":"Visualiser"}},"date":{"abbr_day_names":["dim","lun","mar","mer","jeu","ven","sam"],"abbr_month_names":[null,"jan.","fév.","mar.","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"day_names":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"formats":{"default":"%d/%m/%Y","long":"%e %B %Y","long_ordinal":"%e %B %Y","only_day":"%e","short":"%e %b"},"month_names":[null,"janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"]}});
|
|
76
|
+
I18n.translations["fr"] = I18n.extend((I18n.translations["fr"] || {}), JSON.parse('{"admin":{"edit":{"title":"Editer"},"show":{"note":"plus de détails","title":"Visualiser"}},"date":{"abbr_day_names":["dim","lun","mar","mer","jeu","ven","sam"],"abbr_month_names":[null,"jan.","fév.","mar.","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"day_names":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"formats":{"default":"%d/%m/%Y","long":"%e %B %Y","long_ordinal":"%e %B %Y","only_day":"%e","short":"%e %b"},"month_names":[null,"janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"]}}'));
|
|
77
77
|
EOS
|
|
78
78
|
)
|
|
79
79
|
end
|
|
@@ -98,13 +98,13 @@ EOS
|
|
|
98
98
|
en_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "bits.en.js"))
|
|
99
99
|
expect(en_output).to eq(<<EOS
|
|
100
100
|
I18n.translations || (I18n.translations = {});
|
|
101
|
-
I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), {"date":{"formats":{"default":"%Y-%m-%d","long":"%B %d, %Y","short":"%b %d"}},"number":{"currency":{"format":{"delimiter":",","format":"%u%n","precision":2,"separator":".","unit":"$"}}}});
|
|
101
|
+
I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), JSON.parse('{"date":{"formats":{"default":"%Y-%m-%d","long":"%B %d, %Y","short":"%b %d"}},"number":{"currency":{"format":{"delimiter":",","format":"%u%n","precision":2,"separator":".","unit":"$"}}}}'));
|
|
102
102
|
EOS
|
|
103
103
|
)
|
|
104
104
|
fr_output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "bits.fr.js"))
|
|
105
105
|
expect(fr_output).to eq(<<EOS
|
|
106
106
|
I18n.translations || (I18n.translations = {});
|
|
107
|
-
I18n.translations["fr"] = I18n.extend((I18n.translations["fr"] || {}), {"date":{"formats":{"default":"%d/%m/%Y","long":"%e %B %Y","long_ordinal":"%e %B %Y","only_day":"%e","short":"%e %b"}},"number":{"currency":{"format":{"format":"%n %u","precision":2,"unit":"€"}}}});
|
|
107
|
+
I18n.translations["fr"] = I18n.extend((I18n.translations["fr"] || {}), JSON.parse('{"date":{"formats":{"default":"%d/%m/%Y","long":"%e %B %Y","long_ordinal":"%e %B %Y","only_day":"%e","short":"%e %b"}},"number":{"currency":{"format":{"format":"%n %u","precision":2,"unit":"€"}}}}'));
|
|
108
108
|
EOS
|
|
109
109
|
)
|
|
110
110
|
end
|
|
@@ -307,21 +307,30 @@ EOS
|
|
|
307
307
|
expect(subject[:de][:null_test]).to eql(nil)
|
|
308
308
|
end
|
|
309
309
|
|
|
310
|
-
context
|
|
310
|
+
context 'when given locale is in `I18n.available_locales` but its translation is missing' do
|
|
311
311
|
subject { translations[:fr][:fallback_test] }
|
|
312
312
|
|
|
313
|
-
let(:
|
|
314
|
-
|
|
315
|
-
let!(:new_available_locales) { I18n.config.available_locales + [new_locale] }
|
|
313
|
+
let(:available_locales) { %i[fr pirate] }
|
|
314
|
+
|
|
316
315
|
before do
|
|
317
|
-
I18n.
|
|
318
|
-
set_config
|
|
316
|
+
allow(::I18n).to receive(:available_locales).and_return(available_locales)
|
|
317
|
+
set_config 'js_file_per_locale_with_fallbacks_as_locale_without_fallback_translations.yml'
|
|
319
318
|
end
|
|
320
|
-
|
|
321
|
-
|
|
319
|
+
|
|
320
|
+
it { should eql(nil) }
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
context 'when given locale is in `.js_available_locales` but its translation is missing' do
|
|
324
|
+
subject { translations[:fr][:fallback_test] }
|
|
325
|
+
|
|
326
|
+
let(:available_locales) { %i[fr pirate] }
|
|
327
|
+
|
|
328
|
+
before do
|
|
329
|
+
allow(described_class).to receive(:js_available_locales).and_return(available_locales)
|
|
330
|
+
set_config 'js_file_per_locale_with_fallbacks_as_locale_without_fallback_translations.yml'
|
|
322
331
|
end
|
|
323
332
|
|
|
324
|
-
it {should eql(nil)}
|
|
333
|
+
it { should eql(nil) }
|
|
325
334
|
end
|
|
326
335
|
|
|
327
336
|
context "with I18n::Fallbacks enabled" do
|
|
@@ -385,27 +394,67 @@ EOS
|
|
|
385
394
|
end
|
|
386
395
|
end
|
|
387
396
|
|
|
388
|
-
|
|
397
|
+
describe '.js_available_locales' do
|
|
398
|
+
subject { described_class.js_available_locales }
|
|
399
|
+
|
|
400
|
+
let(:results) { described_class.scoped_translations('*.admin.*.title') }
|
|
401
|
+
let(:result) { ->(locale) { results[locale][:admin][:show][:title] } }
|
|
389
402
|
|
|
390
|
-
context
|
|
391
|
-
it
|
|
392
|
-
result = I18n::JS.scoped_translations("*.admin.*.title")
|
|
403
|
+
context 'when I18n.available_locales is not set' do
|
|
404
|
+
it { expect(subject).to eq ::I18n.available_locales }
|
|
393
405
|
|
|
394
|
-
|
|
395
|
-
expect(result
|
|
396
|
-
expect(result
|
|
406
|
+
it 'should allow all locales' do
|
|
407
|
+
expect(result.call(:en)).to eql('Show')
|
|
408
|
+
expect(result.call(:fr)).to eql('Visualiser')
|
|
409
|
+
expect(result.call(:ja)).to eql('Ignore me')
|
|
397
410
|
end
|
|
398
411
|
end
|
|
399
412
|
|
|
400
|
-
context
|
|
401
|
-
|
|
413
|
+
context 'when I18n.available_locales is set' do
|
|
414
|
+
let(:available_locales) { %i[en fr] }
|
|
415
|
+
|
|
416
|
+
before { allow(::I18n).to receive(:available_locales).and_return(available_locales) }
|
|
417
|
+
|
|
418
|
+
it { expect(subject).to eq available_locales }
|
|
419
|
+
|
|
420
|
+
it 'should ignore non-valid locales' do
|
|
421
|
+
expect(result.call(:en)).to eql('Show')
|
|
422
|
+
expect(result.call(:fr)).to eql('Visualiser')
|
|
423
|
+
expect(results).not_to include(:ja)
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
context 'when :js_available_locales set in config' do
|
|
427
|
+
before { set_config 'js_available_locales_custom.yml' }
|
|
402
428
|
|
|
403
|
-
|
|
404
|
-
|
|
429
|
+
it { expect(subject).to eq %i[en foo] }
|
|
430
|
+
|
|
431
|
+
it 'should ignore non-valid locales' do
|
|
432
|
+
expect(result.call(:en)).to eql('Show')
|
|
433
|
+
expect(results).not_to include(:fr, :ja)
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
context 'I18n.available_locales' do
|
|
440
|
+
let(:results) { described_class.scoped_translations('*.admin.*.title') }
|
|
441
|
+
let(:result) { ->(locale) { results[locale][:admin][:show][:title] } }
|
|
442
|
+
|
|
443
|
+
context 'when I18n.available_locales is not set' do
|
|
444
|
+
it 'should allow all locales' do
|
|
445
|
+
expect(result.call(:en)).to eql('Show')
|
|
446
|
+
expect(result.call(:fr)).to eql('Visualiser')
|
|
447
|
+
expect(result.call(:ja)).to eql('Ignore me')
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
context 'when I18n.available_locales is set' do
|
|
452
|
+
before { allow(::I18n).to receive(:available_locales){ [:en, :fr] } }
|
|
405
453
|
|
|
406
|
-
|
|
407
|
-
expect(result
|
|
408
|
-
expect(result.
|
|
454
|
+
it 'should ignore non-valid locales' do
|
|
455
|
+
expect(result.call(:en)).to eql('Show')
|
|
456
|
+
expect(result.call(:fr)).to eql('Visualiser')
|
|
457
|
+
expect(results).not_to include(:ja)
|
|
409
458
|
end
|
|
410
459
|
end
|
|
411
460
|
end
|
|
@@ -599,7 +648,7 @@ EOS
|
|
|
599
648
|
it "exports with the keys sorted" do
|
|
600
649
|
expect(subject).to eq <<EOS
|
|
601
650
|
I18n.translations || (I18n.translations = {});
|
|
602
|
-
I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), {"admin":{"edit":{"title":"Edit"},"show":{"note":"more details","title":"Show"}},"date":{"abbr_day_names":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"abbr_month_names":[null,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"day_names":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"formats":{"default":"%Y-%m-%d","long":"%B %d, %Y","short":"%b %d"},"month_names":[null,"January","February","March","April","May","June","July","August","September","October","November","December"]},"fallback_test":"Success","foo":"Foo","merge_plurals":{"one":"Apple","other":"Apples"},"merge_plurals_with_no_overrides":{"one":"Apple","other":"Apples","zero":"No Apple"},"merge_plurals_with_partial_overrides":{"one":"Cat","other":"Cats"},"null_test":"fallback for null","number":{"currency":{"format":{"delimiter":",","format":"%u%n","precision":2,"separator":".","unit":"$"}},"format":{"delimiter":",","precision":3,"separator":"."},"human":{"decimal_units":{"units":{"million":"Million"}}}},"time":{"am":"am","formats":{"default":"%a, %d %b %Y %H:%M:%S %z","long":"%B %d, %Y %H:%M","short":"%d %b %H:%M"},"pm":"pm"}});
|
|
651
|
+
I18n.translations["en"] = I18n.extend((I18n.translations["en"] || {}), JSON.parse('{"admin":{"edit":{"title":"Edit"},"show":{"note":"more details","title":"Show"}},"date":{"abbr_day_names":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"abbr_month_names":[null,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"day_names":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"formats":{"default":"%Y-%m-%d","long":"%B %d, %Y","short":"%b %d"},"month_names":[null,"January","February","March","April","May","June","July","August","September","October","November","December"]},"fallback_test":"Success","foo":"Foo","merge_plurals":{"one":"Apple","other":"Apples"},"merge_plurals_with_no_overrides":{"one":"Apple","other":"Apples","zero":"No Apple"},"merge_plurals_with_partial_overrides":{"one":"Cat","other":"Cats"},"null_test":"fallback for null","number":{"currency":{"format":{"delimiter":",","format":"%u%n","precision":2,"separator":".","unit":"$"}},"format":{"delimiter":",","precision":3,"separator":"."},"human":{"decimal_units":{"units":{"million":"Million"}}}},"time":{"am":"am","formats":{"default":"%a, %d %b %Y %H:%M:%S %z","long":"%B %d, %Y %H:%M","short":"%d %b %H:%M"},"pm":"pm"}}'));
|
|
603
652
|
EOS
|
|
604
653
|
end
|
|
605
654
|
end
|
|
@@ -628,13 +677,13 @@ EOS
|
|
|
628
677
|
|
|
629
678
|
expect(subject).to eq <<EOS
|
|
630
679
|
I18n.translations || (I18n.translations = {});
|
|
631
|
-
I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
|
|
632
|
-
I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
|
|
633
|
-
I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
|
|
634
|
-
I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":{\"one\":\"millón\",\"other\":\"millones\"}}}}}});
|
|
635
|
-
I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
|
|
636
|
-
I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
|
|
637
|
-
I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), {\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}});
|
|
680
|
+
I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
|
|
681
|
+
I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
|
|
682
|
+
I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
|
|
683
|
+
I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":{\"one\":\"millón\",\"other\":\"millones\"}}}}}}'));
|
|
684
|
+
I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
|
|
685
|
+
I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
|
|
686
|
+
I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), JSON.parse('{\"number\":{\"human\":{\"decimal_units\":{\"units\":{\"million\":\"Million\"}}}}}'));
|
|
638
687
|
EOS
|
|
639
688
|
end
|
|
640
689
|
end
|
|
@@ -648,8 +697,8 @@ EOS
|
|
|
648
697
|
output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "js_extend_parent.js"))
|
|
649
698
|
expect(output).to eq(<<EOS
|
|
650
699
|
I18n.translations || (I18n.translations = {});
|
|
651
|
-
I18n.translations[\"en\"] = {\"date\":{\"formats\":{\"default\":\"%Y-%m-%d\",\"long\":\"%B %d, %Y\",\"short\":\"%b %d\"}}};
|
|
652
|
-
I18n.translations[\"fr\"] = {\"date\":{\"formats\":{\"default\":\"%d/%m/%Y\",\"long\":\"%e %B %Y\",\"long_ordinal\":\"%e %B %Y\",\"only_day\":\"%e\",\"short\":\"%e %b\"}}};
|
|
700
|
+
I18n.translations[\"en\"] = JSON.parse('{\"date\":{\"formats\":{\"default\":\"%Y-%m-%d\",\"long\":\"%B %d, %Y\",\"short\":\"%b %d\"}}}');
|
|
701
|
+
I18n.translations[\"fr\"] = JSON.parse('{\"date\":{\"formats\":{\"default\":\"%d/%m/%Y\",\"long\":\"%e %B %Y\",\"long_ordinal\":\"%e %B %Y\",\"only_day\":\"%e\",\"short\":\"%e %b\"}}}');
|
|
653
702
|
EOS
|
|
654
703
|
)
|
|
655
704
|
end
|
|
@@ -663,8 +712,8 @@ EOS
|
|
|
663
712
|
output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "js_extend_segment.js"))
|
|
664
713
|
expect(output).to eq(<<EOS
|
|
665
714
|
I18n.translations || (I18n.translations = {});
|
|
666
|
-
I18n.translations[\"en\"] = {\"date\":{\"formats\":{\"default\":\"%Y-%m-%d\",\"long\":\"%B %d, %Y\",\"short\":\"%b %d\"}}};
|
|
667
|
-
I18n.translations[\"fr\"] = {\"date\":{\"formats\":{\"default\":\"%d/%m/%Y\",\"long\":\"%e %B %Y\",\"long_ordinal\":\"%e %B %Y\",\"only_day\":\"%e\",\"short\":\"%e %b\"}}};
|
|
715
|
+
I18n.translations[\"en\"] = JSON.parse('{\"date\":{\"formats\":{\"default\":\"%Y-%m-%d\",\"long\":\"%B %d, %Y\",\"short\":\"%b %d\"}}}');
|
|
716
|
+
I18n.translations[\"fr\"] = JSON.parse('{\"date\":{\"formats\":{\"default\":\"%d/%m/%Y\",\"long\":\"%e %B %Y\",\"long_ordinal\":\"%e %B %Y\",\"only_day\":\"%e\",\"short\":\"%e %b\"}}}');
|
|
668
717
|
EOS
|
|
669
718
|
)
|
|
670
719
|
end
|
|
@@ -686,7 +735,7 @@ EOS
|
|
|
686
735
|
|
|
687
736
|
expect(subject).to eq <<EOS
|
|
688
737
|
I18n.translations || (I18n.translations = {});
|
|
689
|
-
I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), {\"merge_plurals\":{\"one\":\"Apple\",\"other\":\"Apples\"}});\nI18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), {\"merge_plurals\":{\"one\":\"Pomme\",\"other\":\"Pommes\",\"zero\":\"Pomme\"}});
|
|
738
|
+
I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), JSON.parse('{\"merge_plurals\":{\"one\":\"Apple\",\"other\":\"Apples\"}}'));\nI18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), JSON.parse('{\"merge_plurals\":{\"one\":\"Pomme\",\"other\":\"Pommes\",\"zero\":\"Pomme\"}}'));
|
|
690
739
|
EOS
|
|
691
740
|
end
|
|
692
741
|
end
|
|
@@ -707,13 +756,13 @@ EOS
|
|
|
707
756
|
|
|
708
757
|
expect(subject).to eq <<EOS
|
|
709
758
|
I18n.translations || (I18n.translations = {});
|
|
710
|
-
I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
|
|
711
|
-
I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
|
|
712
|
-
I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
|
|
713
|
-
I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
|
|
714
|
-
I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
|
|
715
|
-
I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), {\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}});
|
|
716
|
-
I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), {\"merge_plurals_with_no_overrides\":{\"few\":\"кошек\",\"many\":\"кошка\",\"one\":\"кот\",\"other\":\"кошек\"}});
|
|
759
|
+
I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
|
|
760
|
+
I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
|
|
761
|
+
I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
|
|
762
|
+
I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
|
|
763
|
+
I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
|
|
764
|
+
I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"one\":\"Apple\",\"other\":\"Apples\",\"zero\":\"No Apple\"}}'));
|
|
765
|
+
I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), JSON.parse('{\"merge_plurals_with_no_overrides\":{\"few\":\"кошек\",\"many\":\"кошка\",\"one\":\"кот\",\"other\":\"кошек\"}}'));
|
|
717
766
|
EOS
|
|
718
767
|
end
|
|
719
768
|
end
|
|
@@ -735,13 +784,13 @@ EOS
|
|
|
735
784
|
|
|
736
785
|
expect(subject).to eq <<EOS
|
|
737
786
|
I18n.translations || (I18n.translations = {});
|
|
738
|
-
I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
|
|
739
|
-
I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
|
|
740
|
-
I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"few\":null,\"many\":null,\"one\":\"Cat\",\"other\":\"Cats\"}});
|
|
741
|
-
I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
|
|
742
|
-
I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
|
|
743
|
-
I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
|
|
744
|
-
I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), {\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}});
|
|
787
|
+
I18n.translations[\"de\"] = I18n.extend((I18n.translations[\"de\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
|
|
788
|
+
I18n.translations[\"en\"] = I18n.extend((I18n.translations[\"en\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
|
|
789
|
+
I18n.translations[\"en-US\"] = I18n.extend((I18n.translations[\"en-US\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"few\":null,\"many\":null,\"one\":\"Cat\",\"other\":\"Cats\"}}'));
|
|
790
|
+
I18n.translations[\"es\"] = I18n.extend((I18n.translations[\"es\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
|
|
791
|
+
I18n.translations[\"fr\"] = I18n.extend((I18n.translations[\"fr\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
|
|
792
|
+
I18n.translations[\"ja\"] = I18n.extend((I18n.translations[\"ja\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
|
|
793
|
+
I18n.translations[\"ru\"] = I18n.extend((I18n.translations[\"ru\"] || {}), JSON.parse('{\"merge_plurals_with_partial_overrides\":{\"one\":\"Cat\",\"other\":\"Cats\"}}'));
|
|
745
794
|
EOS
|
|
746
795
|
end
|
|
747
796
|
end
|
data/yarn.lock
CHANGED
|
@@ -13,9 +13,10 @@ brace-expansion@^1.1.7:
|
|
|
13
13
|
balanced-match "^1.0.0"
|
|
14
14
|
concat-map "0.0.1"
|
|
15
15
|
|
|
16
|
-
coffeescript
|
|
17
|
-
version "
|
|
18
|
-
resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-
|
|
16
|
+
coffeescript@~1.12.7:
|
|
17
|
+
version "1.12.7"
|
|
18
|
+
resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.12.7.tgz#e57ee4c4867cf7f606bfc4a0f2d550c0981ddd27"
|
|
19
|
+
integrity sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA==
|
|
19
20
|
|
|
20
21
|
concat-map@0.0.1:
|
|
21
22
|
version "0.0.1"
|
|
@@ -50,9 +51,10 @@ globule@^1.0.0:
|
|
|
50
51
|
lodash "~4.17.10"
|
|
51
52
|
minimatch "~3.0.2"
|
|
52
53
|
|
|
53
|
-
growl@^1.10.
|
|
54
|
+
growl@^1.10.5:
|
|
54
55
|
version "1.10.5"
|
|
55
56
|
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
|
|
57
|
+
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
|
|
56
58
|
|
|
57
59
|
inflight@^1.0.4:
|
|
58
60
|
version "1.0.6"
|
|
@@ -65,24 +67,26 @@ inherits@2:
|
|
|
65
67
|
version "2.0.3"
|
|
66
68
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
|
67
69
|
|
|
68
|
-
jasmine-growl-reporter@~
|
|
69
|
-
version "
|
|
70
|
-
resolved "https://registry.yarnpkg.com/jasmine-growl-reporter/-/jasmine-growl-reporter-
|
|
70
|
+
jasmine-growl-reporter@~2.0.0:
|
|
71
|
+
version "2.0.0"
|
|
72
|
+
resolved "https://registry.yarnpkg.com/jasmine-growl-reporter/-/jasmine-growl-reporter-2.0.0.tgz#4943a2481193d66a8a68ee2f38b6c360fb037859"
|
|
73
|
+
integrity sha512-RYwVfPaGgxQQSHDOt6jQ99/KAkFQ/Fiwg/AzBS+uO9A4UhGhxb7hwXaUUSU/Zs0MxBoFNqmIRC+7P4/+5O3lXg==
|
|
71
74
|
dependencies:
|
|
72
|
-
growl "^1.10.
|
|
75
|
+
growl "^1.10.5"
|
|
73
76
|
|
|
74
|
-
jasmine-node@^
|
|
75
|
-
version "
|
|
76
|
-
resolved "https://registry.yarnpkg.com/jasmine-node/-/jasmine-node-
|
|
77
|
+
jasmine-node@^3.0.0:
|
|
78
|
+
version "3.0.0"
|
|
79
|
+
resolved "https://registry.yarnpkg.com/jasmine-node/-/jasmine-node-3.0.0.tgz#f12b6fdd24633402ec23e8ea6fef6ffbcb464f90"
|
|
80
|
+
integrity sha512-vUa5Q7bQYwHHqi6FlJYndiKqZp+d+c3MKe0QUMwwrC4JRmoRV3zkg0buxB/uQ6qLh0NO34TNstpAnvaZ6xGlAA==
|
|
77
81
|
dependencies:
|
|
78
|
-
coffeescript "
|
|
82
|
+
coffeescript "~1.12.7"
|
|
79
83
|
gaze "~1.1.2"
|
|
80
|
-
jasmine-growl-reporter "~
|
|
84
|
+
jasmine-growl-reporter "~2.0.0"
|
|
81
85
|
jasmine-reporters "~1.0.0"
|
|
82
86
|
mkdirp "~0.3.5"
|
|
83
|
-
requirejs "
|
|
84
|
-
underscore "
|
|
85
|
-
walkdir "
|
|
87
|
+
requirejs "~2.3.6"
|
|
88
|
+
underscore "~1.9.1"
|
|
89
|
+
walkdir "~0.0.12"
|
|
86
90
|
|
|
87
91
|
jasmine-reporters@~1.0.0:
|
|
88
92
|
version "1.0.2"
|
|
@@ -91,8 +95,8 @@ jasmine-reporters@~1.0.0:
|
|
|
91
95
|
mkdirp "~0.3.5"
|
|
92
96
|
|
|
93
97
|
lodash@~4.17.10:
|
|
94
|
-
version "4.17.
|
|
95
|
-
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.
|
|
98
|
+
version "4.17.21"
|
|
99
|
+
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
|
96
100
|
|
|
97
101
|
minimatch@^3.0.4, minimatch@~3.0.2:
|
|
98
102
|
version "3.0.4"
|
|
@@ -114,17 +118,20 @@ path-is-absolute@^1.0.0:
|
|
|
114
118
|
version "1.0.1"
|
|
115
119
|
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
|
116
120
|
|
|
117
|
-
requirejs
|
|
118
|
-
version "2.3.
|
|
119
|
-
resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.
|
|
121
|
+
requirejs@~2.3.6:
|
|
122
|
+
version "2.3.6"
|
|
123
|
+
resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9"
|
|
124
|
+
integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==
|
|
120
125
|
|
|
121
|
-
|
|
122
|
-
version "1.9.
|
|
123
|
-
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.
|
|
126
|
+
underscore@~1.9.1:
|
|
127
|
+
version "1.9.2"
|
|
128
|
+
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.2.tgz#0c8d6f536d6f378a5af264a72f7bec50feb7cf2f"
|
|
129
|
+
integrity sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==
|
|
124
130
|
|
|
125
|
-
|
|
131
|
+
walkdir@~0.0.12:
|
|
126
132
|
version "0.0.12"
|
|
127
133
|
resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.0.12.tgz#2f24f1ade64aab1e458591d4442c8868356e9281"
|
|
134
|
+
integrity sha512-HFhaD4mMWPzFSqhpyDG48KDdrjfn409YQuVW7ckZYhW4sE87mYtWifdB/+73RA7+p4s4K18n5Jfx1kHthE1gBw==
|
|
128
135
|
|
|
129
136
|
wrappy@1:
|
|
130
137
|
version "1.0.2"
|
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.9.1
|
|
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: 2022-02-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: i18n
|
|
@@ -128,6 +128,7 @@ files:
|
|
|
128
128
|
- gemfiles/i18n_1_6.gemfile
|
|
129
129
|
- gemfiles/i18n_1_7.gemfile
|
|
130
130
|
- gemfiles/i18n_1_8.gemfile
|
|
131
|
+
- gemfiles/i18n_1_9.gemfile
|
|
131
132
|
- i18n-js.gemspec
|
|
132
133
|
- i18njs.png
|
|
133
134
|
- lib/i18n-js.rb
|
|
@@ -152,6 +153,7 @@ files:
|
|
|
152
153
|
- spec/fixtures/default.yml
|
|
153
154
|
- spec/fixtures/erb.yml
|
|
154
155
|
- spec/fixtures/except_condition.yml
|
|
156
|
+
- spec/fixtures/js_available_locales_custom.yml
|
|
155
157
|
- spec/fixtures/js_export_dir_custom.yml
|
|
156
158
|
- spec/fixtures/js_export_dir_none.yml
|
|
157
159
|
- spec/fixtures/js_extend_parent.yml
|
|
@@ -189,6 +191,7 @@ files:
|
|
|
189
191
|
- spec/js/jasmine/jasmine.css
|
|
190
192
|
- spec/js/jasmine/jasmine.js
|
|
191
193
|
- spec/js/jasmine/jasmine_favicon.png
|
|
194
|
+
- spec/js/json_parsable.spec.js
|
|
192
195
|
- spec/js/locales.spec.js
|
|
193
196
|
- spec/js/localization.spec.js
|
|
194
197
|
- spec/js/numbers.spec.js
|
|
@@ -207,11 +210,11 @@ files:
|
|
|
207
210
|
- spec/ruby/i18n/js_spec.rb
|
|
208
211
|
- spec/spec_helper.rb
|
|
209
212
|
- yarn.lock
|
|
210
|
-
homepage:
|
|
213
|
+
homepage: https://rubygems.org/gems/i18n-js
|
|
211
214
|
licenses:
|
|
212
215
|
- MIT
|
|
213
216
|
metadata: {}
|
|
214
|
-
post_install_message:
|
|
217
|
+
post_install_message:
|
|
215
218
|
rdoc_options: []
|
|
216
219
|
require_paths:
|
|
217
220
|
- lib
|
|
@@ -226,8 +229,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
226
229
|
- !ruby/object:Gem::Version
|
|
227
230
|
version: '0'
|
|
228
231
|
requirements: []
|
|
229
|
-
rubygems_version: 3.
|
|
230
|
-
signing_key:
|
|
232
|
+
rubygems_version: 3.3.6
|
|
233
|
+
signing_key:
|
|
231
234
|
specification_version: 4
|
|
232
235
|
summary: It's a small library to provide the Rails I18n translations on the Javascript.
|
|
233
236
|
test_files:
|
|
@@ -235,6 +238,7 @@ test_files:
|
|
|
235
238
|
- spec/fixtures/default.yml
|
|
236
239
|
- spec/fixtures/erb.yml
|
|
237
240
|
- spec/fixtures/except_condition.yml
|
|
241
|
+
- spec/fixtures/js_available_locales_custom.yml
|
|
238
242
|
- spec/fixtures/js_export_dir_custom.yml
|
|
239
243
|
- spec/fixtures/js_export_dir_none.yml
|
|
240
244
|
- spec/fixtures/js_extend_parent.yml
|
|
@@ -272,6 +276,7 @@ test_files:
|
|
|
272
276
|
- spec/js/jasmine/jasmine.css
|
|
273
277
|
- spec/js/jasmine/jasmine.js
|
|
274
278
|
- spec/js/jasmine/jasmine_favicon.png
|
|
279
|
+
- spec/js/json_parsable.spec.js
|
|
275
280
|
- spec/js/locales.spec.js
|
|
276
281
|
- spec/js/localization.spec.js
|
|
277
282
|
- spec/js/numbers.spec.js
|