i18n-js 3.0.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|