i18n-js 3.8.3 → 4.0.0.alpha1
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/.github/CODEOWNERS +4 -0
- data/.github/FUNDING.yml +1 -1
- data/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +38 -0
- data/.github/dependabot.yml +15 -0
- data/.github/workflows/ruby-tests.yml +61 -0
- data/.gitignore +11 -7
- data/.rubocop.yml +12 -0
- data/CHANGELOG.md +12 -535
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +79 -0
- data/Gemfile +3 -0
- data/LICENSE.md +20 -0
- data/README.md +86 -1030
- data/Rakefile +10 -20
- data/exe/i18n +5 -0
- data/i18n-js.gemspec +47 -29
- data/lib/guard/i18n-js.rb +78 -0
- data/lib/guard/i18n-js/templates/Guardfile +10 -0
- data/lib/guard/i18n-js/version.rb +13 -0
- data/lib/i18n-js.rb +66 -1
- data/lib/i18n-js/cli.rb +47 -0
- data/lib/i18n-js/cli/command.rb +43 -0
- data/lib/i18n-js/cli/export_command.rb +108 -0
- data/lib/i18n-js/cli/init_command.rb +50 -0
- data/lib/i18n-js/cli/ui.rb +30 -0
- data/lib/i18n-js/cli/version_command.rb +18 -0
- data/lib/i18n-js/listen.rb +80 -0
- data/lib/i18n-js/schema.rb +92 -0
- data/lib/i18n-js/version.rb +5 -0
- metadata +122 -194
- data/.editorconfig +0 -24
- data/.github/workflows/tests.yaml +0 -100
- data/.npmignore +0 -27
- data/Appraisals +0 -44
- data/app/assets/javascripts/i18n.js +0 -1095
- data/app/assets/javascripts/i18n/filtered.js.erb +0 -23
- data/app/assets/javascripts/i18n/shims.js +0 -240
- data/app/assets/javascripts/i18n/translations.js +0 -3
- data/gemfiles/i18n_0_6.gemfile +0 -7
- data/gemfiles/i18n_0_7.gemfile +0 -7
- data/gemfiles/i18n_0_8.gemfile +0 -7
- data/gemfiles/i18n_0_9.gemfile +0 -7
- data/gemfiles/i18n_1_0.gemfile +0 -7
- data/gemfiles/i18n_1_1.gemfile +0 -7
- data/gemfiles/i18n_1_2.gemfile +0 -7
- data/gemfiles/i18n_1_3.gemfile +0 -7
- data/gemfiles/i18n_1_4.gemfile +0 -7
- data/gemfiles/i18n_1_5.gemfile +0 -7
- data/gemfiles/i18n_1_6.gemfile +0 -7
- data/gemfiles/i18n_1_7.gemfile +0 -7
- data/gemfiles/i18n_1_8.gemfile +0 -7
- data/i18njs.png +0 -0
- data/lib/i18n/js.rb +0 -264
- data/lib/i18n/js/dependencies.rb +0 -63
- data/lib/i18n/js/engine.rb +0 -87
- data/lib/i18n/js/fallback_locales.rb +0 -70
- data/lib/i18n/js/formatters/base.rb +0 -25
- data/lib/i18n/js/formatters/js.rb +0 -39
- data/lib/i18n/js/formatters/json.rb +0 -13
- data/lib/i18n/js/middleware.rb +0 -82
- data/lib/i18n/js/private/config_store.rb +0 -31
- data/lib/i18n/js/private/hash_with_symbol_keys.rb +0 -36
- data/lib/i18n/js/segment.rb +0 -80
- data/lib/i18n/js/utils.rb +0 -78
- data/lib/i18n/js/version.rb +0 -7
- data/lib/rails/generators/i18n/js/config/config_generator.rb +0 -19
- data/lib/rails/generators/i18n/js/config/templates/i18n-js.yml +0 -27
- data/lib/tasks/export.rake +0 -8
- data/package.json +0 -25
- data/spec/fixtures/custom_path.yml +0 -5
- data/spec/fixtures/default.yml +0 -5
- data/spec/fixtures/erb.yml +0 -5
- data/spec/fixtures/except_condition.yml +0 -7
- data/spec/fixtures/js_export_dir_custom.yml +0 -7
- data/spec/fixtures/js_export_dir_none.yml +0 -6
- data/spec/fixtures/js_extend_parent.yml +0 -6
- data/spec/fixtures/js_extend_segment.yml +0 -6
- data/spec/fixtures/js_file_per_locale.yml +0 -7
- data/spec/fixtures/js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml +0 -4
- data/spec/fixtures/js_file_per_locale_with_fallbacks_as_hash.yml +0 -6
- data/spec/fixtures/js_file_per_locale_with_fallbacks_as_locale.yml +0 -4
- data/spec/fixtures/js_file_per_locale_with_fallbacks_as_locale_without_fallback_translations.yml +0 -4
- data/spec/fixtures/js_file_per_locale_with_fallbacks_enabled.yml +0 -4
- data/spec/fixtures/js_file_per_locale_without_fallbacks.yml +0 -4
- data/spec/fixtures/js_file_with_namespace_prefix_and_pretty_print.yml +0 -9
- data/spec/fixtures/js_sort_translation_keys_false.yml +0 -6
- data/spec/fixtures/js_sort_translation_keys_true.yml +0 -6
- data/spec/fixtures/json_only.yml +0 -18
- data/spec/fixtures/locales.yml +0 -133
- data/spec/fixtures/merge_plurals.yml +0 -6
- data/spec/fixtures/merge_plurals_with_no_overrides.yml +0 -4
- data/spec/fixtures/merge_plurals_with_partial_overrides.yml +0 -4
- data/spec/fixtures/millions.yml +0 -4
- data/spec/fixtures/multiple_conditions.yml +0 -7
- data/spec/fixtures/multiple_conditions_per_locale.yml +0 -7
- data/spec/fixtures/multiple_files.yml +0 -7
- data/spec/fixtures/no_config.yml +0 -2
- data/spec/fixtures/no_scope.yml +0 -4
- data/spec/fixtures/simple_scope.yml +0 -5
- data/spec/js/currency.spec.js +0 -62
- data/spec/js/current_locale.spec.js +0 -19
- data/spec/js/dates.spec.js +0 -276
- data/spec/js/defaults.spec.js +0 -31
- data/spec/js/extend.spec.js +0 -110
- data/spec/js/interpolation.spec.js +0 -124
- data/spec/js/jasmine/MIT.LICENSE +0 -20
- data/spec/js/jasmine/jasmine-html.js +0 -190
- data/spec/js/jasmine/jasmine.css +0 -166
- data/spec/js/jasmine/jasmine.js +0 -2476
- data/spec/js/jasmine/jasmine_favicon.png +0 -0
- data/spec/js/json_parsable.spec.js +0 -14
- data/spec/js/locales.spec.js +0 -31
- data/spec/js/localization.spec.js +0 -78
- data/spec/js/numbers.spec.js +0 -174
- data/spec/js/placeholder.spec.js +0 -24
- data/spec/js/pluralization.spec.js +0 -219
- data/spec/js/prepare_options.spec.js +0 -41
- data/spec/js/require.js +0 -2083
- data/spec/js/specs.html +0 -49
- data/spec/js/specs_requirejs.html +0 -72
- data/spec/js/translate.spec.js +0 -304
- data/spec/js/translations.js +0 -188
- data/spec/js/utility_functions.spec.js +0 -20
- data/spec/ruby/i18n/js/fallback_locales_spec.rb +0 -84
- data/spec/ruby/i18n/js/segment_spec.rb +0 -261
- data/spec/ruby/i18n/js/utils_spec.rb +0 -106
- data/spec/ruby/i18n/js_spec.rb +0 -748
- data/spec/spec_helper.rb +0 -80
- data/yarn.lock +0 -131
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<%# encoding: utf-8 %>
|
|
2
|
-
|
|
3
|
-
// Using UMD pattern from
|
|
4
|
-
// https://github.com/umdjs/umd#regular-module
|
|
5
|
-
// `returnExports.js` version
|
|
6
|
-
;(function (root, factory) {
|
|
7
|
-
if (typeof define === 'function' && define.amd) {
|
|
8
|
-
// AMD. Register as an anonymous module.
|
|
9
|
-
define(["i18n"], factory);
|
|
10
|
-
} else if (typeof module === 'object' && module.exports) {
|
|
11
|
-
// Node. Does not work with strict CommonJS, but
|
|
12
|
-
// only CommonJS-like environments that support module.exports,
|
|
13
|
-
// like Node.
|
|
14
|
-
factory(require("i18n"));
|
|
15
|
-
} else {
|
|
16
|
-
// Browser globals (root is window)
|
|
17
|
-
factory(root.I18n);
|
|
18
|
-
}
|
|
19
|
-
}(this, function(I18n) {
|
|
20
|
-
"use strict";
|
|
21
|
-
|
|
22
|
-
I18n.translations = <%= I18n::JS.filtered_translations.to_json %>;
|
|
23
|
-
}));
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
|
|
2
|
-
if (!Array.prototype.indexOf) {
|
|
3
|
-
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
|
|
4
|
-
"use strict";
|
|
5
|
-
if (this == null) {
|
|
6
|
-
throw new TypeError();
|
|
7
|
-
}
|
|
8
|
-
var t = Object(this);
|
|
9
|
-
var len = t.length >>> 0;
|
|
10
|
-
if (len === 0) {
|
|
11
|
-
return -1;
|
|
12
|
-
}
|
|
13
|
-
var n = 0;
|
|
14
|
-
if (arguments.length > 1) {
|
|
15
|
-
n = Number(arguments[1]);
|
|
16
|
-
if (n != n) { // shortcut for verifying if it's NaN
|
|
17
|
-
n = 0;
|
|
18
|
-
} else if (n != 0 && n != Infinity && n != -Infinity) {
|
|
19
|
-
n = (n > 0 || -1) * Math.floor(Math.abs(n));
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
if (n >= len) {
|
|
23
|
-
return -1;
|
|
24
|
-
}
|
|
25
|
-
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
|
|
26
|
-
for (; k < len; k++) {
|
|
27
|
-
if (k in t && t[k] === searchElement) {
|
|
28
|
-
return k;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return -1;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Production steps of ECMA-262, Edition 5, 15.4.4.18
|
|
36
|
-
// Reference: http://es5.github.com/#x15.4.4.18
|
|
37
|
-
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
|
|
38
|
-
if ( !Array.prototype.forEach ) {
|
|
39
|
-
|
|
40
|
-
Array.prototype.forEach = function forEach( callback, thisArg ) {
|
|
41
|
-
|
|
42
|
-
var T, k;
|
|
43
|
-
|
|
44
|
-
if ( this == null ) {
|
|
45
|
-
throw new TypeError( "this is null or not defined" );
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
|
|
49
|
-
var O = Object(this);
|
|
50
|
-
|
|
51
|
-
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
|
|
52
|
-
// 3. Let len be ToUint32(lenValue).
|
|
53
|
-
var len = O.length >>> 0; // Hack to convert O.length to a UInt32
|
|
54
|
-
|
|
55
|
-
// 4. If IsCallable(callback) is false, throw a TypeError exception.
|
|
56
|
-
// See: http://es5.github.com/#x9.11
|
|
57
|
-
if ( {}.toString.call(callback) !== "[object Function]" ) {
|
|
58
|
-
throw new TypeError( callback + " is not a function" );
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
|
62
|
-
if ( thisArg ) {
|
|
63
|
-
T = thisArg;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// 6. Let k be 0
|
|
67
|
-
k = 0;
|
|
68
|
-
|
|
69
|
-
// 7. Repeat, while k < len
|
|
70
|
-
while( k < len ) {
|
|
71
|
-
|
|
72
|
-
var kValue;
|
|
73
|
-
|
|
74
|
-
// a. Let Pk be ToString(k).
|
|
75
|
-
// This is implicit for LHS operands of the in operator
|
|
76
|
-
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
|
|
77
|
-
// This step can be combined with c
|
|
78
|
-
// c. If kPresent is true, then
|
|
79
|
-
if ( Object.prototype.hasOwnProperty.call(O, k) ) {
|
|
80
|
-
|
|
81
|
-
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
|
|
82
|
-
kValue = O[ k ];
|
|
83
|
-
|
|
84
|
-
// ii. Call the Call internal method of callback with T as the this value and
|
|
85
|
-
// argument list containing kValue, k, and O.
|
|
86
|
-
callback.call( T, kValue, k, O );
|
|
87
|
-
}
|
|
88
|
-
// d. Increase k by 1.
|
|
89
|
-
k++;
|
|
90
|
-
}
|
|
91
|
-
// 8. return undefined
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
|
|
96
|
-
if (!Array.prototype.some)
|
|
97
|
-
{
|
|
98
|
-
Array.prototype.some = function(fun /*, thisArg */)
|
|
99
|
-
{
|
|
100
|
-
'use strict';
|
|
101
|
-
|
|
102
|
-
if (this === void 0 || this === null)
|
|
103
|
-
throw new TypeError();
|
|
104
|
-
|
|
105
|
-
var t = Object(this);
|
|
106
|
-
var len = t.length >>> 0;
|
|
107
|
-
if (typeof fun !== 'function')
|
|
108
|
-
throw new TypeError();
|
|
109
|
-
|
|
110
|
-
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
|
|
111
|
-
for (var i = 0; i < len; i++)
|
|
112
|
-
{
|
|
113
|
-
if (i in t && fun.call(thisArg, t[i], i, t))
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return false;
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
|
|
122
|
-
if (!Array.prototype.map) {
|
|
123
|
-
|
|
124
|
-
Array.prototype.map = function(callback/*, thisArg*/) {
|
|
125
|
-
|
|
126
|
-
var T, A, k;
|
|
127
|
-
|
|
128
|
-
if (this == null) {
|
|
129
|
-
throw new TypeError('this is null or not defined');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// 1. Let O be the result of calling ToObject passing the |this|
|
|
133
|
-
// value as the argument.
|
|
134
|
-
var O = Object(this);
|
|
135
|
-
|
|
136
|
-
// 2. Let lenValue be the result of calling the Get internal
|
|
137
|
-
// method of O with the argument "length".
|
|
138
|
-
// 3. Let len be ToUint32(lenValue).
|
|
139
|
-
var len = O.length >>> 0;
|
|
140
|
-
|
|
141
|
-
// 4. If IsCallable(callback) is false, throw a TypeError exception.
|
|
142
|
-
// See: http://es5.github.com/#x9.11
|
|
143
|
-
if (typeof callback !== 'function') {
|
|
144
|
-
throw new TypeError(callback + ' is not a function');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
|
148
|
-
if (arguments.length > 1) {
|
|
149
|
-
T = arguments[1];
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// 6. Let A be a new array created as if by the expression new Array(len)
|
|
153
|
-
// where Array is the standard built-in constructor with that name and
|
|
154
|
-
// len is the value of len.
|
|
155
|
-
A = new Array(len);
|
|
156
|
-
|
|
157
|
-
// 7. Let k be 0
|
|
158
|
-
k = 0;
|
|
159
|
-
|
|
160
|
-
// 8. Repeat, while k < len
|
|
161
|
-
while (k < len) {
|
|
162
|
-
|
|
163
|
-
var kValue, mappedValue;
|
|
164
|
-
|
|
165
|
-
// a. Let Pk be ToString(k).
|
|
166
|
-
// This is implicit for LHS operands of the in operator
|
|
167
|
-
// b. Let kPresent be the result of calling the HasProperty internal
|
|
168
|
-
// method of O with argument Pk.
|
|
169
|
-
// This step can be combined with c
|
|
170
|
-
// c. If kPresent is true, then
|
|
171
|
-
if (k in O) {
|
|
172
|
-
|
|
173
|
-
// i. Let kValue be the result of calling the Get internal
|
|
174
|
-
// method of O with argument Pk.
|
|
175
|
-
kValue = O[k];
|
|
176
|
-
|
|
177
|
-
// ii. Let mappedValue be the result of calling the Call internal
|
|
178
|
-
// method of callback with T as the this value and argument
|
|
179
|
-
// list containing kValue, k, and O.
|
|
180
|
-
mappedValue = callback.call(T, kValue, k, O);
|
|
181
|
-
|
|
182
|
-
// iii. Call the DefineOwnProperty internal method of A with arguments
|
|
183
|
-
// Pk, Property Descriptor
|
|
184
|
-
// { Value: mappedValue,
|
|
185
|
-
// Writable: true,
|
|
186
|
-
// Enumerable: true,
|
|
187
|
-
// Configurable: true },
|
|
188
|
-
// and false.
|
|
189
|
-
|
|
190
|
-
// In browsers that support Object.defineProperty, use the following:
|
|
191
|
-
// Object.defineProperty(A, k, {
|
|
192
|
-
// value: mappedValue,
|
|
193
|
-
// writable: true,
|
|
194
|
-
// enumerable: true,
|
|
195
|
-
// configurable: true
|
|
196
|
-
// });
|
|
197
|
-
|
|
198
|
-
// For best browser support, use the following:
|
|
199
|
-
A[k] = mappedValue;
|
|
200
|
-
}
|
|
201
|
-
// d. Increase k by 1.
|
|
202
|
-
k++;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// 9. return A
|
|
206
|
-
return A;
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
|
|
211
|
-
if (!Function.prototype.bind) (function(){
|
|
212
|
-
var ArrayPrototypeSlice = Array.prototype.slice;
|
|
213
|
-
Function.prototype.bind = function(otherThis) {
|
|
214
|
-
if (typeof this !== 'function') {
|
|
215
|
-
// closest thing possible to the ECMAScript 5
|
|
216
|
-
// internal IsCallable function
|
|
217
|
-
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
var baseArgs= ArrayPrototypeSlice .call(arguments, 1),
|
|
221
|
-
baseArgsLength = baseArgs.length,
|
|
222
|
-
fToBind = this,
|
|
223
|
-
fNOP = function() {},
|
|
224
|
-
fBound = function() {
|
|
225
|
-
baseArgs.length = baseArgsLength; // reset to default base arguments
|
|
226
|
-
baseArgs.push.apply(baseArgs, arguments);
|
|
227
|
-
return fToBind.apply(
|
|
228
|
-
fNOP.prototype.isPrototypeOf(this) ? this : otherThis, baseArgs
|
|
229
|
-
);
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
if (this.prototype) {
|
|
233
|
-
// Function.prototype doesn't have a prototype property
|
|
234
|
-
fNOP.prototype = this.prototype;
|
|
235
|
-
}
|
|
236
|
-
fBound.prototype = new fNOP();
|
|
237
|
-
|
|
238
|
-
return fBound;
|
|
239
|
-
};
|
|
240
|
-
})();
|
data/gemfiles/i18n_0_6.gemfile
DELETED
data/gemfiles/i18n_0_7.gemfile
DELETED
data/gemfiles/i18n_0_8.gemfile
DELETED
data/gemfiles/i18n_0_9.gemfile
DELETED
data/gemfiles/i18n_1_0.gemfile
DELETED
data/gemfiles/i18n_1_1.gemfile
DELETED
data/gemfiles/i18n_1_2.gemfile
DELETED
data/gemfiles/i18n_1_3.gemfile
DELETED
data/gemfiles/i18n_1_4.gemfile
DELETED
data/gemfiles/i18n_1_5.gemfile
DELETED
data/gemfiles/i18n_1_6.gemfile
DELETED
data/gemfiles/i18n_1_7.gemfile
DELETED
data/gemfiles/i18n_1_8.gemfile
DELETED
data/i18njs.png
DELETED
|
Binary file
|
data/lib/i18n/js.rb
DELETED
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
require "yaml"
|
|
2
|
-
require "fileutils"
|
|
3
|
-
require "i18n"
|
|
4
|
-
|
|
5
|
-
require "i18n/js/utils"
|
|
6
|
-
require "i18n/js/private/hash_with_symbol_keys"
|
|
7
|
-
require "i18n/js/private/config_store"
|
|
8
|
-
|
|
9
|
-
module I18n
|
|
10
|
-
module JS
|
|
11
|
-
require "i18n/js/dependencies"
|
|
12
|
-
require "i18n/js/fallback_locales"
|
|
13
|
-
require "i18n/js/segment"
|
|
14
|
-
if JS::Dependencies.rails?
|
|
15
|
-
require "i18n/js/middleware"
|
|
16
|
-
require "i18n/js/engine"
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
DEFAULT_CONFIG_PATH = "config/i18n-js.yml"
|
|
20
|
-
DEFAULT_EXPORT_DIR_PATH = "public/javascripts"
|
|
21
|
-
|
|
22
|
-
# The configuration file. This defaults to the `config/i18n-js.yml` file.
|
|
23
|
-
#
|
|
24
|
-
def self.config_file_path
|
|
25
|
-
@config_file_path ||= DEFAULT_CONFIG_PATH
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def self.config_file_path=(new_path)
|
|
29
|
-
@config_file_path = new_path
|
|
30
|
-
# new config file path = need to re-read config from new file
|
|
31
|
-
Private::ConfigStore.instance.flush_cache
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Allow using a different backend than the one globally configured
|
|
35
|
-
def self.backend
|
|
36
|
-
@backend ||= I18n.backend
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def self.backend=(alternative_backend)
|
|
40
|
-
@backend = alternative_backend
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Export translations to JavaScript, considering settings
|
|
44
|
-
# from configuration file
|
|
45
|
-
def self.export
|
|
46
|
-
export_i18n_js
|
|
47
|
-
|
|
48
|
-
translation_segments.each(&:save!)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def self.segment_for_scope(scope, exceptions)
|
|
52
|
-
if scope == "*"
|
|
53
|
-
exclude(translations, exceptions)
|
|
54
|
-
else
|
|
55
|
-
scoped_translations(scope, exceptions)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def self.configured_segments
|
|
60
|
-
config[:translations].inject([]) do |segments, options_hash|
|
|
61
|
-
options_hash_with_symbol_keys = Private::HashWithSymbolKeys.new(options_hash)
|
|
62
|
-
file = options_hash_with_symbol_keys[:file]
|
|
63
|
-
only = options_hash_with_symbol_keys[:only] || '*'
|
|
64
|
-
exceptions = [options_hash_with_symbol_keys[:except] || []].flatten
|
|
65
|
-
|
|
66
|
-
result = segment_for_scope(only, exceptions)
|
|
67
|
-
|
|
68
|
-
merge_with_fallbacks!(result) if fallbacks
|
|
69
|
-
|
|
70
|
-
unless result.empty?
|
|
71
|
-
segments << Segment.new(
|
|
72
|
-
file,
|
|
73
|
-
result,
|
|
74
|
-
extract_segment_options(options_hash_with_symbol_keys),
|
|
75
|
-
)
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
segments
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# deep_merge! given result with result for fallback locale
|
|
83
|
-
def self.merge_with_fallbacks!(result)
|
|
84
|
-
I18n.available_locales.each do |locale|
|
|
85
|
-
fallback_locales = FallbackLocales.new(fallbacks, locale)
|
|
86
|
-
fallback_locales.each do |fallback_locale|
|
|
87
|
-
# `result[fallback_locale]` could be missing
|
|
88
|
-
result[locale] = Utils.deep_merge(result[fallback_locale] || {}, result[locale] || {})
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def self.filtered_translations
|
|
94
|
-
translations = {}.tap do |result|
|
|
95
|
-
translation_segments.each do |segment|
|
|
96
|
-
Utils.deep_merge!(result, segment.translations)
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
return Utils.deep_key_sort(translations) if I18n::JS.sort_translation_keys?
|
|
100
|
-
translations
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def self.translation_segments
|
|
104
|
-
if config_file_exists? && config[:translations]
|
|
105
|
-
configured_segments
|
|
106
|
-
else
|
|
107
|
-
[Segment.new("#{DEFAULT_EXPORT_DIR_PATH}/translations.js", translations)]
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
# Load configuration file for partial exporting and
|
|
112
|
-
# custom output directory
|
|
113
|
-
def self.config
|
|
114
|
-
Private::ConfigStore.instance.fetch do
|
|
115
|
-
if config_file_exists?
|
|
116
|
-
erb_result_from_yaml_file = ERB.new(File.read(config_file_path)).result
|
|
117
|
-
Private::HashWithSymbolKeys.new(
|
|
118
|
-
(::YAML.load(erb_result_from_yaml_file) || {})
|
|
119
|
-
)
|
|
120
|
-
else
|
|
121
|
-
Private::HashWithSymbolKeys.new({})
|
|
122
|
-
end.freeze
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# @api private
|
|
127
|
-
# Check if configuration file exist
|
|
128
|
-
def self.config_file_exists?
|
|
129
|
-
File.file? config_file_path
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def self.scoped_translations(scopes, exceptions = []) # :nodoc:
|
|
133
|
-
result = {}
|
|
134
|
-
|
|
135
|
-
[scopes].flatten.each do |scope|
|
|
136
|
-
translations_without_exceptions = exclude(translations, exceptions)
|
|
137
|
-
filtered_translations = filter(translations_without_exceptions, scope) || {}
|
|
138
|
-
|
|
139
|
-
Utils.deep_merge!(result, filtered_translations)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
result
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
# Exclude keys from translations listed in the `except:` section in the config file
|
|
146
|
-
def self.exclude(translations, exceptions)
|
|
147
|
-
return translations if exceptions.empty?
|
|
148
|
-
|
|
149
|
-
exceptions.inject(translations) do |memo, exception|
|
|
150
|
-
exception_scopes = exception.to_s.split(".")
|
|
151
|
-
Utils.deep_reject(memo) do |key, value, scopes|
|
|
152
|
-
Utils.scopes_match?(scopes, exception_scopes)
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# Filter translations according to the specified scope.
|
|
158
|
-
def self.filter(translations, scopes)
|
|
159
|
-
scopes = scopes.split(".") if scopes.is_a?(String)
|
|
160
|
-
scopes = scopes.clone
|
|
161
|
-
scope = scopes.shift
|
|
162
|
-
|
|
163
|
-
if scope == "*"
|
|
164
|
-
results = {}
|
|
165
|
-
translations.each do |scope, translations|
|
|
166
|
-
tmp = scopes.empty? ? translations : filter(translations, scopes)
|
|
167
|
-
results[scope.to_sym] = tmp unless tmp.nil?
|
|
168
|
-
end
|
|
169
|
-
return results
|
|
170
|
-
elsif translations.respond_to?(:key?) && translations.key?(scope.to_sym)
|
|
171
|
-
return {scope.to_sym => scopes.empty? ? translations[scope.to_sym] : filter(translations[scope.to_sym], scopes)}
|
|
172
|
-
end
|
|
173
|
-
nil
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
# Initialize and return translations
|
|
177
|
-
def self.translations
|
|
178
|
-
self.backend.instance_eval do
|
|
179
|
-
init_translations unless initialized?
|
|
180
|
-
# When activesupport is absent,
|
|
181
|
-
# the core extension (`#slice`) from `i18n` gem will be used instead
|
|
182
|
-
# And it's causing errors (at least in test)
|
|
183
|
-
#
|
|
184
|
-
# So the input is wrapped by our class for better `#slice`
|
|
185
|
-
Private::HashWithSymbolKeys.new(translations).
|
|
186
|
-
slice(*::I18n.available_locales).
|
|
187
|
-
to_h
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
def self.use_fallbacks?
|
|
192
|
-
fallbacks != false
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
def self.json_only
|
|
196
|
-
config.fetch(:json_only) do
|
|
197
|
-
# default value
|
|
198
|
-
false
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def self.fallbacks
|
|
203
|
-
config.fetch(:fallbacks) do
|
|
204
|
-
# default value
|
|
205
|
-
true
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
def self.js_extend
|
|
210
|
-
config.fetch(:js_extend) do
|
|
211
|
-
# default value
|
|
212
|
-
true
|
|
213
|
-
end
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
def self.sort_translation_keys?
|
|
217
|
-
@sort_translation_keys ||= (config[:sort_translation_keys]) if config.key?(:sort_translation_keys)
|
|
218
|
-
@sort_translation_keys = true if @sort_translation_keys.nil?
|
|
219
|
-
@sort_translation_keys
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
def self.sort_translation_keys=(value)
|
|
223
|
-
@sort_translation_keys = !!value
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
def self.extract_segment_options(options)
|
|
227
|
-
segment_options = Private::HashWithSymbolKeys.new({
|
|
228
|
-
js_extend: js_extend,
|
|
229
|
-
sort_translation_keys: sort_translation_keys?,
|
|
230
|
-
json_only: json_only
|
|
231
|
-
}).freeze
|
|
232
|
-
segment_options.merge(options.slice(*Segment::OPTIONS))
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
### Export i18n.js
|
|
236
|
-
begin
|
|
237
|
-
|
|
238
|
-
# Copy i18n.js
|
|
239
|
-
def self.export_i18n_js
|
|
240
|
-
return unless export_i18n_js_dir_path.is_a? String
|
|
241
|
-
|
|
242
|
-
FileUtils.mkdir_p(export_i18n_js_dir_path)
|
|
243
|
-
|
|
244
|
-
i18n_js_path = File.expand_path('../../../app/assets/javascripts/i18n.js', __FILE__)
|
|
245
|
-
destination_path = File.expand_path("i18n.js", export_i18n_js_dir_path)
|
|
246
|
-
return if File.exist?(destination_path) && FileUtils.identical?(i18n_js_path, destination_path)
|
|
247
|
-
|
|
248
|
-
FileUtils.cp(i18n_js_path, export_i18n_js_dir_path)
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
def self.export_i18n_js_dir_path
|
|
252
|
-
@export_i18n_js_dir_path ||= (config[:export_i18n_js] || :none) if config.key?(:export_i18n_js)
|
|
253
|
-
@export_i18n_js_dir_path ||= DEFAULT_EXPORT_DIR_PATH
|
|
254
|
-
@export_i18n_js_dir_path
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
# Setting this to nil would disable i18n.js exporting
|
|
258
|
-
def self.export_i18n_js_dir_path=(new_path)
|
|
259
|
-
new_path = :none unless new_path.is_a? String
|
|
260
|
-
@export_i18n_js_dir_path = new_path
|
|
261
|
-
end
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
end
|