i18n-js 3.0.0 → 3.0.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 +24 -0
- data/.npmignore +26 -0
- data/CHANGELOG.md +13 -1
- data/README.md +2 -2
- data/app/assets/javascripts/i18n.js +132 -90
- data/lib/i18n/js/dependencies.rb +9 -29
- data/lib/i18n/js/engine.rb +28 -45
- data/lib/i18n/js/version.rb +1 -1
- data/package.json +1 -1
- data/spec/js/translate.spec.js +36 -1
- data/spec/js/translations.js +8 -0
- metadata +5 -5
- data/spec/ruby/i18n/js/dependencies_spec.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6045fc4e7caf2df9308248a08c9a5f7f74d08a5
|
4
|
+
data.tar.gz: 3ac4f6ee77a6afa9948a73758bfcb70ecf92a156
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b56080a8ec45da012f3a846d8d811ed80245f76f2c3905079cf7930b08b3775b2381757b20b2384ab91e17fcfd76586daf459c594b31f03aa04e31fc65a8fe0
|
7
|
+
data.tar.gz: 9d093f0a6c62daee153bc8d9b7702f2aab193d660a752e17e1c0fe4595637f19748819dc7c45d4e46816adaf97342d56f3db1285a687f565fd87e74ac308cf58
|
data/.editorconfig
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# EditorConfig is awesome: http://EditorConfig.org
|
2
|
+
|
3
|
+
# top-most EditorConfig file
|
4
|
+
root = true
|
5
|
+
|
6
|
+
# default configuration
|
7
|
+
[*]
|
8
|
+
indent_style = space
|
9
|
+
indent_size = 2
|
10
|
+
insert_final_newline = true
|
11
|
+
trim_trailing_whitespace = true
|
12
|
+
|
13
|
+
# Unix-style newlines with a newline ending every file
|
14
|
+
end_of_line = lf
|
15
|
+
|
16
|
+
# Set default charset
|
17
|
+
charset = utf-8
|
18
|
+
|
19
|
+
# Tab indentation (no size specified)
|
20
|
+
[Makefile]
|
21
|
+
indent_style = tab
|
22
|
+
|
23
|
+
[*.{md,markdown}]
|
24
|
+
trim_trailing_whitespace = false
|
data/.npmignore
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package
|
2
|
+
|
3
|
+
# tests
|
4
|
+
spec
|
5
|
+
coverage
|
6
|
+
|
7
|
+
# build tools
|
8
|
+
.travis.yml
|
9
|
+
|
10
|
+
# linters
|
11
|
+
.jscsrc
|
12
|
+
.jshintrc
|
13
|
+
.eslintrc*
|
14
|
+
|
15
|
+
# editor settings
|
16
|
+
.idea
|
17
|
+
.editorconfig
|
18
|
+
|
19
|
+
# Ruby code
|
20
|
+
gemfiles
|
21
|
+
lib
|
22
|
+
Gemfile*
|
23
|
+
*.gemspec
|
24
|
+
Rakefile
|
25
|
+
Appraisals
|
26
|
+
|
data/CHANGELOG.md
CHANGED
@@ -18,6 +18,17 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
18
18
|
- Nothing
|
19
19
|
|
20
20
|
|
21
|
+
## [3.0.1] - 2017-08-02
|
22
|
+
|
23
|
+
### Changed
|
24
|
+
|
25
|
+
- [Ruby] Relax Rails detection code to work with alternative installation methods
|
26
|
+
(PR: https://github.com/fnando/i18n-js/pull/467)
|
27
|
+
- [JS] Fix fallback when "3-part" locale like `zh-Hant-TW` is used
|
28
|
+
It fallbacks to `zh` only before, now it fallbacks to `zh-Hant`
|
29
|
+
(PR: https://github.com/fnando/i18n-js/pull/465)
|
30
|
+
|
31
|
+
|
21
32
|
## [3.0.0] - 2017-04-01
|
22
33
|
|
23
34
|
This is a fake official release, the *real* one will be `3.0.0.rc17`
|
@@ -240,7 +251,8 @@ And today is not April Fools' Day
|
|
240
251
|
|
241
252
|
|
242
253
|
|
243
|
-
[Unreleased]: https://github.com/fnando/i18n-js/compare/v3.0.
|
254
|
+
[Unreleased]: https://github.com/fnando/i18n-js/compare/v3.0.1...HEAD
|
255
|
+
[3.0.1]: https://github.com/fnando/i18n-js/compare/v3.0.0...v3.0.1
|
244
256
|
[3.0.0]: https://github.com/fnando/i18n-js/compare/v3.0.0.rc16...v3.0.0
|
245
257
|
[3.0.0.rc16]: https://github.com/fnando/i18n-js/compare/v3.0.0.rc15...v3.0.0.rc16
|
246
258
|
[3.0.0.rc15]: https://github.com/fnando/i18n-js/compare/v3.0.0.rc14...v3.0.0.rc15
|
data/README.md
CHANGED
@@ -257,7 +257,7 @@ translations:
|
|
257
257
|
```
|
258
258
|
|
259
259
|
|
260
|
-
####
|
260
|
+
#### Javascript Deep Merge (:js_extend option)
|
261
261
|
|
262
262
|
By default, the output file Javascript will call the `I18n.extend` method to ensure that newly loaded locale
|
263
263
|
files are deep-merged with any locale data already in memory. To disable this either globally or per-file,
|
@@ -453,7 +453,7 @@ I18n.pluralization["ru"] = function (count) {
|
|
453
453
|
};
|
454
454
|
```
|
455
455
|
|
456
|
-
You can find all rules on <http://unicode.org/
|
456
|
+
You can find all rules on <http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html>.
|
457
457
|
|
458
458
|
If you're using the same scope over and over again, you may use the `scope` option.
|
459
459
|
|
@@ -52,7 +52,17 @@
|
|
52
52
|
// Borrowed from Underscore.js
|
53
53
|
var isObject = function(obj) {
|
54
54
|
var type = typeof obj;
|
55
|
-
return type === 'function' || type === 'object'
|
55
|
+
return type === 'function' || type === 'object'
|
56
|
+
};
|
57
|
+
|
58
|
+
var isFunction = function(func) {
|
59
|
+
var type = typeof func;
|
60
|
+
return type === 'function'
|
61
|
+
};
|
62
|
+
|
63
|
+
// Check if value is different than undefined and null;
|
64
|
+
var isSet = function(value) {
|
65
|
+
return typeof(value) !== 'undefined' && value !== null;
|
56
66
|
};
|
57
67
|
|
58
68
|
// Is a given value an array?
|
@@ -95,6 +105,14 @@
|
|
95
105
|
return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
|
96
106
|
}
|
97
107
|
|
108
|
+
var lazyEvaluate = function(message, scope) {
|
109
|
+
if (isFunction(message)) {
|
110
|
+
return message(scope);
|
111
|
+
} else {
|
112
|
+
return message;
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
98
116
|
var merge = function (dest, obj) {
|
99
117
|
var key, value;
|
100
118
|
for (key in obj) if (obj.hasOwnProperty(key)) {
|
@@ -173,60 +191,21 @@
|
|
173
191
|
, missingTranslationPrefix: ''
|
174
192
|
};
|
175
193
|
|
194
|
+
// Set default locale. This locale will be used when fallback is enabled and
|
195
|
+
// the translation doesn't exist in a particular locale.
|
176
196
|
I18n.reset = function() {
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
// Set the current locale to `en`.
|
182
|
-
this.locale = DEFAULT_OPTIONS.locale;
|
183
|
-
|
184
|
-
// Set the translation key separator.
|
185
|
-
this.defaultSeparator = DEFAULT_OPTIONS.defaultSeparator;
|
186
|
-
|
187
|
-
// Set the placeholder format. Accepts `{{placeholder}}` and `%{placeholder}`.
|
188
|
-
this.placeholder = DEFAULT_OPTIONS.placeholder;
|
189
|
-
|
190
|
-
// Set if engine should fallback to the default locale when a translation
|
191
|
-
// is missing.
|
192
|
-
this.fallbacks = DEFAULT_OPTIONS.fallbacks;
|
193
|
-
|
194
|
-
// Set the default translation object.
|
195
|
-
this.translations = DEFAULT_OPTIONS.translations;
|
196
|
-
|
197
|
-
// Set the default missing behaviour
|
198
|
-
this.missingBehaviour = DEFAULT_OPTIONS.missingBehaviour;
|
199
|
-
|
200
|
-
// Set the default missing string prefix for guess behaviour
|
201
|
-
this.missingTranslationPrefix = DEFAULT_OPTIONS.missingTranslationPrefix;
|
202
|
-
|
197
|
+
var key;
|
198
|
+
for (key in DEFAULT_OPTIONS) {
|
199
|
+
this[key] = DEFAULT_OPTIONS[key];
|
200
|
+
}
|
203
201
|
};
|
204
202
|
|
205
203
|
// Much like `reset`, but only assign options if not already assigned
|
206
204
|
I18n.initializeOptions = function() {
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
this.locale = DEFAULT_OPTIONS.locale;
|
212
|
-
|
213
|
-
if (typeof(this.defaultSeparator) === "undefined" && this.defaultSeparator !== null)
|
214
|
-
this.defaultSeparator = DEFAULT_OPTIONS.defaultSeparator;
|
215
|
-
|
216
|
-
if (typeof(this.placeholder) === "undefined" && this.placeholder !== null)
|
217
|
-
this.placeholder = DEFAULT_OPTIONS.placeholder;
|
218
|
-
|
219
|
-
if (typeof(this.fallbacks) === "undefined" && this.fallbacks !== null)
|
220
|
-
this.fallbacks = DEFAULT_OPTIONS.fallbacks;
|
221
|
-
|
222
|
-
if (typeof(this.translations) === "undefined" && this.translations !== null)
|
223
|
-
this.translations = DEFAULT_OPTIONS.translations;
|
224
|
-
|
225
|
-
if (typeof(this.missingBehaviour) === "undefined" && this.missingBehaviour !== null)
|
226
|
-
this.missingBehaviour = DEFAULT_OPTIONS.missingBehaviour;
|
227
|
-
|
228
|
-
if (typeof(this.missingTranslationPrefix) === "undefined" && this.missingTranslationPrefix !== null)
|
229
|
-
this.missingTranslationPrefix = DEFAULT_OPTIONS.missingTranslationPrefix;
|
205
|
+
var key;
|
206
|
+
for (key in DEFAULT_OPTIONS) if (!isSet(this[key])) {
|
207
|
+
this[key] = DEFAULT_OPTIONS[key];
|
208
|
+
}
|
230
209
|
};
|
231
210
|
I18n.initializeOptions();
|
232
211
|
|
@@ -252,7 +231,7 @@
|
|
252
231
|
I18n.locales.get = function(locale) {
|
253
232
|
var result = this[locale] || this[I18n.locale] || this["default"];
|
254
233
|
|
255
|
-
if (
|
234
|
+
if (isFunction(result)) {
|
256
235
|
result = result(locale);
|
257
236
|
}
|
258
237
|
|
@@ -267,8 +246,6 @@
|
|
267
246
|
I18n.locales["default"] = function(locale) {
|
268
247
|
var locales = []
|
269
248
|
, list = []
|
270
|
-
, countryCode
|
271
|
-
, count
|
272
249
|
;
|
273
250
|
|
274
251
|
// Handle the inline locale option that can be provided to
|
@@ -287,19 +264,85 @@
|
|
287
264
|
locales.push(I18n.defaultLocale);
|
288
265
|
}
|
289
266
|
|
267
|
+
// Locale code format 1:
|
268
|
+
// According to RFC4646 (http://www.ietf.org/rfc/rfc4646.txt)
|
269
|
+
// language codes for Traditional Chinese should be `zh-Hant`
|
270
|
+
//
|
271
|
+
// But due to backward compatibility
|
272
|
+
// We use older version of IETF language tag
|
273
|
+
// @see http://www.w3.org/TR/html401/struct/dirlang.html
|
274
|
+
// @see http://en.wikipedia.org/wiki/IETF_language_tag
|
275
|
+
//
|
276
|
+
// Format: `language-code = primary-code ( "-" subcode )*`
|
277
|
+
//
|
278
|
+
// primary-code uses ISO639-1
|
279
|
+
// @see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
280
|
+
// @see http://www.iso.org/iso/home/standards/language_codes.htm
|
281
|
+
//
|
282
|
+
// subcode uses ISO 3166-1 alpha-2
|
283
|
+
// @see http://en.wikipedia.org/wiki/ISO_3166
|
284
|
+
// @see http://www.iso.org/iso/country_codes.htm
|
285
|
+
//
|
286
|
+
// @note
|
287
|
+
// subcode can be in upper case or lower case
|
288
|
+
// defining it in upper case is a convention only
|
289
|
+
|
290
|
+
|
291
|
+
// Locale code format 2:
|
292
|
+
// Format: `code = primary-code ( "-" region-code )*`
|
293
|
+
// primary-code uses ISO 639-1
|
294
|
+
// script-code uses ISO 15924
|
295
|
+
// region-code uses ISO 3166-1 alpha-2
|
296
|
+
// Example: zh-Hant-TW, en-HK, zh-Hant-CN
|
297
|
+
//
|
298
|
+
// It is similar to RFC4646 (or actually the same),
|
299
|
+
// but seems to be limited to language, script, region
|
300
|
+
|
290
301
|
// Compute each locale with its country code.
|
291
|
-
// So this will return an array containing
|
292
|
-
// `de-DE` and `de`
|
293
|
-
|
294
|
-
|
302
|
+
// So this will return an array containing
|
303
|
+
// `de-DE` and `de`
|
304
|
+
// or
|
305
|
+
// `zh-hans-tw`, `zh-hans`, `zh`
|
306
|
+
// locales.
|
307
|
+
locales.forEach(function(locale) {
|
308
|
+
var localeParts = locale.split("-");
|
309
|
+
var firstFallback = null;
|
310
|
+
var secondFallback = null;
|
311
|
+
if (localeParts.length === 3) {
|
312
|
+
firstFallback = localeParts[0];
|
313
|
+
secondFallback = [
|
314
|
+
localeParts[0],
|
315
|
+
localeParts[1]
|
316
|
+
].join("-");
|
317
|
+
}
|
318
|
+
else if (localeParts.length === 2) {
|
319
|
+
firstFallback = localeParts[0];
|
320
|
+
}
|
295
321
|
|
296
|
-
if (
|
322
|
+
if (list.indexOf(locale) === -1) {
|
297
323
|
list.push(locale);
|
298
324
|
}
|
299
325
|
|
300
|
-
if (I18n.fallbacks
|
301
|
-
|
326
|
+
if (! I18n.fallbacks) {
|
327
|
+
return;
|
302
328
|
}
|
329
|
+
|
330
|
+
[
|
331
|
+
firstFallback,
|
332
|
+
secondFallback
|
333
|
+
].forEach(function(nullableFallbackLocale) {
|
334
|
+
// We don't want null values
|
335
|
+
if (typeof nullableFallbackLocale === "undefined") { return; }
|
336
|
+
if (nullableFallbackLocale === null) { return; }
|
337
|
+
// We don't want duplicate values
|
338
|
+
//
|
339
|
+
// Comparing with `locale` first is faster than
|
340
|
+
// checking whether value's presence in the list
|
341
|
+
if (nullableFallbackLocale === locale) { return; }
|
342
|
+
if (list.indexOf(nullableFallbackLocale) !== -1) { return; }
|
343
|
+
|
344
|
+
list.push(nullableFallbackLocale);
|
345
|
+
});
|
303
346
|
});
|
304
347
|
|
305
348
|
// No locales set? English it is.
|
@@ -336,28 +379,27 @@
|
|
336
379
|
};
|
337
380
|
|
338
381
|
// Check if value is different than undefined and null;
|
339
|
-
I18n.isSet =
|
340
|
-
return value !== undefined && value !== null;
|
341
|
-
};
|
382
|
+
I18n.isSet = isSet;
|
342
383
|
|
343
384
|
// Find and process the translation using the provided scope and options.
|
344
385
|
// This is used internally by some functions and should not be used as an
|
345
386
|
// public API.
|
346
387
|
I18n.lookup = function(scope, options) {
|
347
|
-
options =
|
388
|
+
options = options || {}
|
348
389
|
|
349
390
|
var locales = this.locales.get(options.locale).slice()
|
350
391
|
, requestedLocale = locales[0]
|
351
392
|
, locale
|
352
393
|
, scopes
|
394
|
+
, fullScope
|
353
395
|
, translations
|
354
396
|
;
|
355
397
|
|
356
|
-
|
398
|
+
fullScope = this.getFullScope(scope, options);
|
357
399
|
|
358
400
|
while (locales.length) {
|
359
401
|
locale = locales.shift();
|
360
|
-
scopes =
|
402
|
+
scopes = fullScope.split(this.defaultSeparator);
|
361
403
|
translations = this.translations[locale];
|
362
404
|
|
363
405
|
if (!translations) {
|
@@ -376,8 +418,8 @@
|
|
376
418
|
}
|
377
419
|
}
|
378
420
|
|
379
|
-
if (
|
380
|
-
return options.defaultValue;
|
421
|
+
if (isSet(options.defaultValue)) {
|
422
|
+
return lazyEvaluate(options.defaultValue, scope);
|
381
423
|
}
|
382
424
|
};
|
383
425
|
|
@@ -391,7 +433,7 @@
|
|
391
433
|
if (isObject(translations)) {
|
392
434
|
while (pluralizerKeys.length) {
|
393
435
|
pluralizerKey = pluralizerKeys.shift();
|
394
|
-
if (
|
436
|
+
if (isSet(translations[pluralizerKey])) {
|
395
437
|
message = translations[pluralizerKey];
|
396
438
|
break;
|
397
439
|
}
|
@@ -403,7 +445,7 @@
|
|
403
445
|
|
404
446
|
// Lookup dedicated to pluralization
|
405
447
|
I18n.pluralizationLookup = function(count, scope, options) {
|
406
|
-
options =
|
448
|
+
options = options || {}
|
407
449
|
var locales = this.locales.get(options.locale).slice()
|
408
450
|
, requestedLocale = locales[0]
|
409
451
|
, locale
|
@@ -437,7 +479,7 @@
|
|
437
479
|
}
|
438
480
|
|
439
481
|
if (message == null || message == undefined) {
|
440
|
-
if (
|
482
|
+
if (isSet(options.defaultValue)) {
|
441
483
|
if (isObject(options.defaultValue)) {
|
442
484
|
message = this.pluralizationLookupWithoutFallback(count, options.locale, options.defaultValue);
|
443
485
|
} else {
|
@@ -492,7 +534,7 @@
|
|
492
534
|
continue;
|
493
535
|
}
|
494
536
|
|
495
|
-
if (
|
537
|
+
if (isSet(options[attr])) {
|
496
538
|
continue;
|
497
539
|
}
|
498
540
|
|
@@ -511,15 +553,14 @@
|
|
511
553
|
|
512
554
|
// Defaults should be an array of hashes containing either
|
513
555
|
// fallback scopes or messages
|
514
|
-
if (
|
556
|
+
if (isSet(options.defaults)) {
|
515
557
|
translationOptions = translationOptions.concat(options.defaults);
|
516
558
|
}
|
517
559
|
|
518
560
|
// Maintain support for defaultValue. Since it is always a message
|
519
561
|
// insert it in to the translation options as such.
|
520
|
-
if (
|
562
|
+
if (isSet(options.defaultValue)) {
|
521
563
|
translationOptions.push({ message: options.defaultValue });
|
522
|
-
delete options.defaultValue;
|
523
564
|
}
|
524
565
|
|
525
566
|
return translationOptions;
|
@@ -527,20 +568,23 @@
|
|
527
568
|
|
528
569
|
// Translate the given scope with the provided options.
|
529
570
|
I18n.translate = function(scope, options) {
|
530
|
-
options =
|
571
|
+
options = options || {}
|
531
572
|
|
532
|
-
var copiedOptions = this.prepareOptions(options);
|
533
573
|
var translationOptions = this.createTranslationOptions(scope, options);
|
534
574
|
|
535
575
|
var translation;
|
576
|
+
|
577
|
+
var optionsWithoutDefault = this.prepareOptions(options)
|
578
|
+
delete optionsWithoutDefault.defaultValue
|
579
|
+
|
536
580
|
// Iterate through the translation options until a translation
|
537
581
|
// or message is found.
|
538
582
|
var translationFound =
|
539
583
|
translationOptions.some(function(translationOption) {
|
540
|
-
if (
|
541
|
-
translation = this.lookup(translationOption.scope,
|
542
|
-
} else if (
|
543
|
-
translation = translationOption.message;
|
584
|
+
if (isSet(translationOption.scope)) {
|
585
|
+
translation = this.lookup(translationOption.scope, optionsWithoutDefault);
|
586
|
+
} else if (isSet(translationOption.message)) {
|
587
|
+
translation = lazyEvaluate(translationOption.message, scope);
|
544
588
|
}
|
545
589
|
|
546
590
|
if (translation !== undefined && translation !== null) {
|
@@ -554,8 +598,8 @@
|
|
554
598
|
|
555
599
|
if (typeof(translation) === "string") {
|
556
600
|
translation = this.interpolate(translation, options);
|
557
|
-
} else if (isObject(translation) &&
|
558
|
-
translation = this.pluralize(options.count, scope,
|
601
|
+
} else if (isObject(translation) && isSet(options.count)) {
|
602
|
+
translation = this.pluralize(options.count, scope, options);
|
559
603
|
}
|
560
604
|
|
561
605
|
return translation;
|
@@ -563,7 +607,7 @@
|
|
563
607
|
|
564
608
|
// This function interpolates the all variables in the given message.
|
565
609
|
I18n.interpolate = function(message, options) {
|
566
|
-
options =
|
610
|
+
options = options || {}
|
567
611
|
var matches = message.match(this.placeholder)
|
568
612
|
, placeholder
|
569
613
|
, value
|
@@ -581,7 +625,7 @@
|
|
581
625
|
placeholder = matches.shift();
|
582
626
|
name = placeholder.replace(this.placeholder, "$1");
|
583
627
|
|
584
|
-
if (
|
628
|
+
if (isSet(options[name])) {
|
585
629
|
value = options[name].toString().replace(/\$/gm, "_#$#_");
|
586
630
|
} else if (name in options) {
|
587
631
|
value = this.nullPlaceholder(placeholder, message, options);
|
@@ -600,7 +644,7 @@
|
|
600
644
|
// The pluralized translation may have other placeholders,
|
601
645
|
// which will be retrieved from `options`.
|
602
646
|
I18n.pluralize = function(count, scope, options) {
|
603
|
-
options = this.prepareOptions(options)
|
647
|
+
options = this.prepareOptions({count: String(count)}, options)
|
604
648
|
var pluralizer, message, result;
|
605
649
|
|
606
650
|
result = this.pluralizationLookup(count, scope, options);
|
@@ -608,8 +652,6 @@
|
|
608
652
|
return this.missingTranslation(scope, options);
|
609
653
|
}
|
610
654
|
|
611
|
-
options.count = String(count);
|
612
|
-
|
613
655
|
if (result.message != undefined && result.message != null) {
|
614
656
|
return this.interpolate(result.message, options);
|
615
657
|
}
|
@@ -982,10 +1024,10 @@
|
|
982
1024
|
};
|
983
1025
|
|
984
1026
|
I18n.getFullScope = function(scope, options) {
|
985
|
-
options =
|
1027
|
+
options = options || {}
|
986
1028
|
|
987
1029
|
// Deal with the scope as an array.
|
988
|
-
if (scope
|
1030
|
+
if (isArray(scope)) {
|
989
1031
|
scope = scope.join(this.defaultSeparator);
|
990
1032
|
}
|
991
1033
|
|
data/lib/i18n/js/dependencies.rb
CHANGED
@@ -4,28 +4,12 @@ module I18n
|
|
4
4
|
# we need to specify pre-release version suffix in version constraint
|
5
5
|
module Dependencies
|
6
6
|
class << self
|
7
|
-
def rails3?
|
8
|
-
safe_gem_check("rails", "~> 3.0") && running_rails3?
|
9
|
-
end
|
10
|
-
|
11
|
-
def rails4?
|
12
|
-
safe_gem_check("rails", "~> 4.0", ">= 4.0.0.beta1") && running_rails4?
|
13
|
-
end
|
14
|
-
|
15
|
-
def rails5?
|
16
|
-
safe_gem_check("rails", "~> 5.0", ">= 5.0.0.beta1") && running_rails5?
|
17
|
-
end
|
18
|
-
|
19
|
-
def sprockets_supports_register_preprocessor?
|
20
|
-
defined?(Sprockets) && Sprockets.respond_to?(:register_preprocessor)
|
21
|
-
end
|
22
|
-
|
23
7
|
def rails?
|
24
|
-
|
8
|
+
defined?(Rails) && Rails.respond_to?(:version)
|
25
9
|
end
|
26
10
|
|
27
|
-
def
|
28
|
-
safe_gem_check("rails",
|
11
|
+
def sprockets_rails_v2_plus?
|
12
|
+
safe_gem_check("sprockets-rails", ">= 2")
|
29
13
|
end
|
30
14
|
|
31
15
|
# This cannot be called at class definition time
|
@@ -47,20 +31,16 @@ module I18n
|
|
47
31
|
|
48
32
|
private
|
49
33
|
|
50
|
-
def
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
def running_rails4?
|
55
|
-
running_rails? && Rails.version.to_i == 4
|
34
|
+
def rails3?
|
35
|
+
rails? && Rails.version.to_i == 3
|
56
36
|
end
|
57
37
|
|
58
|
-
def
|
59
|
-
|
38
|
+
def rails4?
|
39
|
+
rails? && Rails.version.to_i == 4
|
60
40
|
end
|
61
41
|
|
62
|
-
def
|
63
|
-
|
42
|
+
def rails5?
|
43
|
+
rails? && Rails.version.to_i == 5
|
64
44
|
end
|
65
45
|
|
66
46
|
def safe_gem_check(*args)
|
data/lib/i18n/js/engine.rb
CHANGED
@@ -9,56 +9,39 @@ module I18n
|
|
9
9
|
end
|
10
10
|
|
11
11
|
class Engine < ::Rails::Engine
|
12
|
-
|
13
|
-
|
14
|
-
# `.sprockets_supports_register_preprocessor?` called
|
15
|
-
sprockets_version = Gem::Version.new(Sprockets::VERSION).release
|
16
|
-
v2_only = Gem::Dependency.new("", " ~> 2")
|
17
|
-
v3_plus = Gem::Dependency.new("", " >= 3")
|
12
|
+
# See https://github.com/rails/sprockets/blob/master/guides/extending_sprockets.md#supporting-all-versions-of-sprockets-in-processors
|
13
|
+
# for reference of supporting multiple versions
|
18
14
|
|
19
|
-
|
20
|
-
|
15
|
+
# `sprockets.environment` was used for 1.x of `sprockets-rails`
|
16
|
+
# https://github.com/rails/sprockets-rails/issues/227
|
17
|
+
#
|
18
|
+
# References for current values:
|
19
|
+
#
|
20
|
+
# Here is where sprockets are attached with Rails. There is no 'sprockets.environment' mentioned.
|
21
|
+
# https://github.com/rails/sprockets-rails/blob/master/lib/sprockets/railtie.rb
|
22
|
+
#
|
23
|
+
# Finisher hook is the place which should be used as border.
|
24
|
+
# http://guides.rubyonrails.org/configuring.html#initializers
|
25
|
+
#
|
26
|
+
# For detail see Pull Request:
|
27
|
+
# https://github.com/fnando/i18n-js/pull/371
|
28
|
+
initializer "i18n-js.register_preprocessor", after: :engines_blank_point, before: :finisher_hook do
|
29
|
+
# This must be called inside initializer block
|
30
|
+
# For details see comments for `using_asset_pipeline?`
|
31
|
+
next unless JS::Dependencies.using_asset_pipeline?
|
21
32
|
|
22
|
-
#
|
23
|
-
#
|
33
|
+
# From README of 2.x & 3.x of `sprockets-rails`
|
34
|
+
# It seems the `configure` block is preferred way to call `register_preprocessor`
|
35
|
+
# Not sure if this will break older versions of rails
|
24
36
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
|
28
|
-
# https://github.com/rails/sprockets-rails/blob/master/lib/sprockets/railtie.rb
|
29
|
-
#
|
30
|
-
# Finisher hook is the place which should be used as border.
|
31
|
-
# http://guides.rubyonrails.org/configuring.html#initializers
|
32
|
-
#
|
33
|
-
# For detail see Pull Request:
|
34
|
-
# https://github.com/fnando/i18n-js/pull/371
|
35
|
-
#
|
36
|
-
# Not using -> for JRuby compatibility
|
37
|
-
# See https://github.com/fnando/i18n-js/issues/419
|
38
|
-
initializer_args = case sprockets_version
|
39
|
-
when lambda {|v| v2_only.match?("", v) || v3_plus.match?("", v) }
|
40
|
-
{ after: :engines_blank_point, before: :finisher_hook }
|
41
|
-
else
|
42
|
-
raise StandardError, "Sprockets version #{sprockets_version} is not supported"
|
43
|
-
end
|
44
|
-
|
45
|
-
initializer "i18n-js.register_preprocessor", initializer_args do
|
46
|
-
# This must be called inside initializer block
|
47
|
-
# For details see comments for `using_asset_pipeline?`
|
48
|
-
next unless JS::Dependencies.using_asset_pipeline?
|
49
|
-
|
50
|
-
# From README of 2.x & 3.x of `sprockets-rails`
|
51
|
-
# It seems the `configure` block is preferred way to call `register_preprocessor`
|
52
|
-
# Not sure if this will break older versions of rails
|
53
|
-
#
|
54
|
-
# https://github.com/rails/sprockets-rails/blob/v2.3.3/README.md
|
55
|
-
# https://github.com/rails/sprockets-rails/blob/v3.0.0/README.md
|
37
|
+
# https://github.com/rails/sprockets-rails/blob/v2.3.3/README.md
|
38
|
+
# https://github.com/rails/sprockets-rails/blob/v3.0.0/README.md
|
39
|
+
if JS::Dependencies.sprockets_rails_v2_plus?
|
56
40
|
Rails.application.config.assets.configure do |config|
|
57
|
-
config.register_preprocessor(
|
58
|
-
"application/javascript",
|
59
|
-
::I18n::JS::SprocketsExtension,
|
60
|
-
)
|
41
|
+
config.register_preprocessor("application/javascript", ::I18n::JS::SprocketsExtension)
|
61
42
|
end
|
43
|
+
elsif Rails.application.assets.respond_to?(:register_preprocessor)
|
44
|
+
Rails.application.assets.register_preprocessor("application/javascript", ::I18n::JS::SprocketsExtension)
|
62
45
|
end
|
63
46
|
end
|
64
47
|
end
|
data/lib/i18n/js/version.rb
CHANGED
data/package.json
CHANGED
data/spec/js/translate.spec.js
CHANGED
@@ -65,7 +65,7 @@ describe("Translate", function(){
|
|
65
65
|
expect(I18n.t("hello", {locale: "pt-BR"})).toEqual("Olá Mundo!");
|
66
66
|
});
|
67
67
|
|
68
|
-
it("fallbacks to the default locale when I18n.
|
68
|
+
it("fallbacks to the default locale when I18n.fallbacks is enabled", function(){
|
69
69
|
I18n.locale = "pt-BR";
|
70
70
|
I18n.fallbacks = true;
|
71
71
|
expect(I18n.t("greetings.stranger")).toEqual("Hello stranger!");
|
@@ -83,6 +83,21 @@ describe("Translate", function(){
|
|
83
83
|
expect(I18n.t("hello")).toEqual("Hallo Welt!");
|
84
84
|
});
|
85
85
|
|
86
|
+
describe("when a 3-part locale is used", function(){
|
87
|
+
beforeEach(function(){
|
88
|
+
I18n.locale = "zh-Hant-TW";
|
89
|
+
I18n.fallbacks = true;
|
90
|
+
});
|
91
|
+
|
92
|
+
it("fallbacks to 2-part locale when absent", function(){
|
93
|
+
expect(I18n.t("cat")).toEqual("貓");
|
94
|
+
});
|
95
|
+
|
96
|
+
it("fallbacks to 1-part locale when 2-part missing requested translation", function(){
|
97
|
+
expect(I18n.t("dog")).toEqual("狗");
|
98
|
+
});
|
99
|
+
});
|
100
|
+
|
86
101
|
it("fallbacks using custom rules (function)", function(){
|
87
102
|
I18n.locale = "no";
|
88
103
|
I18n.fallbacks = true;
|
@@ -145,6 +160,26 @@ describe("Translate", function(){
|
|
145
160
|
actual = I18n.t("foo", options);
|
146
161
|
expect(actual).toEqual("Hello all!");
|
147
162
|
});
|
163
|
+
|
164
|
+
it("uses default scope over default value if default scope is found", function() {
|
165
|
+
var options = {
|
166
|
+
defaults: [{scope: "hello"}]
|
167
|
+
, defaultValue: "Hello all!"
|
168
|
+
};
|
169
|
+
actual = I18n.t("foo", options);
|
170
|
+
expect(actual).toEqual("Hello World!");
|
171
|
+
})
|
172
|
+
|
173
|
+
it("uses default value with lazy evaluation", function () {
|
174
|
+
var options = {
|
175
|
+
defaults: [{scope: "bar"}]
|
176
|
+
, defaultValue: function(scope) {
|
177
|
+
return scope.toUpperCase();
|
178
|
+
}
|
179
|
+
};
|
180
|
+
actual = I18n.t("foo", options);
|
181
|
+
expect(actual).toEqual("FOO");
|
182
|
+
})
|
148
183
|
});
|
149
184
|
|
150
185
|
it("uses default value for simple translation", function(){
|
data/spec/js/translations.js
CHANGED
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.0.
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nando Vieira
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -93,7 +93,9 @@ executables: []
|
|
93
93
|
extensions: []
|
94
94
|
extra_rdoc_files: []
|
95
95
|
files:
|
96
|
+
- ".editorconfig"
|
96
97
|
- ".gitignore"
|
98
|
+
- ".npmignore"
|
97
99
|
- ".travis.yml"
|
98
100
|
- Appraisals
|
99
101
|
- CHANGELOG.md
|
@@ -170,7 +172,6 @@ files:
|
|
170
172
|
- spec/js/translate.spec.js
|
171
173
|
- spec/js/translations.js
|
172
174
|
- spec/js/utility_functions.spec.js
|
173
|
-
- spec/ruby/i18n/js/dependencies_spec.rb
|
174
175
|
- spec/ruby/i18n/js/fallback_locales_spec.rb
|
175
176
|
- spec/ruby/i18n/js/segment_spec.rb
|
176
177
|
- spec/ruby/i18n/js/utils_spec.rb
|
@@ -196,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
197
|
version: '0'
|
197
198
|
requirements: []
|
198
199
|
rubyforge_project:
|
199
|
-
rubygems_version: 2.6.
|
200
|
+
rubygems_version: 2.6.12
|
200
201
|
signing_key:
|
201
202
|
specification_version: 4
|
202
203
|
summary: It's a small library to provide the Rails I18n translations on the Javascript.
|
@@ -249,7 +250,6 @@ test_files:
|
|
249
250
|
- spec/js/translate.spec.js
|
250
251
|
- spec/js/translations.js
|
251
252
|
- spec/js/utility_functions.spec.js
|
252
|
-
- spec/ruby/i18n/js/dependencies_spec.rb
|
253
253
|
- spec/ruby/i18n/js/fallback_locales_spec.rb
|
254
254
|
- spec/ruby/i18n/js/segment_spec.rb
|
255
255
|
- spec/ruby/i18n/js/utils_spec.rb
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe I18n::JS::Dependencies, ".sprockets_supports_register_preprocessor?" do
|
4
|
-
|
5
|
-
subject { described_class.sprockets_supports_register_preprocessor? }
|
6
|
-
|
7
|
-
context 'when Sprockets is available to register preprocessors' do
|
8
|
-
let!(:sprockets_double) do
|
9
|
-
class_double('Sprockets').as_stubbed_const(register_processor: true).tap do |double|
|
10
|
-
allow(double).to receive(:respond_to?).with(:register_preprocessor).and_return(true)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
it { is_expected.to be_truthy }
|
15
|
-
it 'calls respond_to? with register_preprocessor on Sprockets' do
|
16
|
-
expect(sprockets_double).to receive(:respond_to?).with(:register_preprocessor).and_return(true)
|
17
|
-
subject
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'when Sprockets is NOT available to register preprocessors' do
|
22
|
-
let!(:sprockets_double) do
|
23
|
-
class_double('Sprockets').as_stubbed_const(register_processor: true).tap do |double|
|
24
|
-
allow(double).to receive(:respond_to?).with(:register_preprocessor).and_return(false)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
it { is_expected.to be_falsy }
|
29
|
-
it 'calls respond_to? with register_preprocessor on Sprockets' do
|
30
|
-
expect(sprockets_double).to receive(:respond_to?).with(:register_preprocessor).and_return(false)
|
31
|
-
subject
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context 'when Sprockets is missing' do
|
36
|
-
before do
|
37
|
-
hide_const('Sprockets')
|
38
|
-
expect { Sprockets }.to raise_error(NameError)
|
39
|
-
end
|
40
|
-
|
41
|
-
it { is_expected.to be_falsy }
|
42
|
-
end
|
43
|
-
end
|