exvo_globalize 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +84 -3
- data/Rakefile +1 -1
- data/app/assets/javascripts/exvo_globalize_i18n.js +359 -75
- data/app/controllers/globalize_translations_controller.rb +3 -4
- data/lib/exvo_globalize/backend/chain.rb +13 -2
- data/lib/exvo_globalize/version.rb +1 -1
- data/spec/controllers/globalize_translations_controller_spec.rb +1 -1
- data/spec/exvo_globalize/globalize_store_spec.rb +6 -0
- data/spec/javascripts/exvo_globalize_i18n_spec.js +380 -3
- data/spec/javascripts/fixtures/translations.js +97 -1
- metadata +4 -5
- data/lib/tasks/jasmine.rake +0 -8
data/README.md
CHANGED
@@ -67,11 +67,83 @@ Basic support for I18n in the javascript is included. In order for it to work yo
|
|
67
67
|
Now you can use translations inside your javascript:
|
68
68
|
|
69
69
|
```js
|
70
|
-
t("
|
71
|
-
=> "
|
70
|
+
t("hello")
|
71
|
+
=> "Hello world!"
|
72
72
|
```
|
73
73
|
|
74
|
-
The above, of course, expects you to have the `:
|
74
|
+
The above, of course, expects you to have the `:hello` key for the current `I18n.locale` in one of your `config/locales/*.yml` files.
|
75
|
+
|
76
|
+
|
77
|
+
The following I18n features are supported in javascript:
|
78
|
+
|
79
|
+
|
80
|
+
### Locale fallback
|
81
|
+
|
82
|
+
If there is no translation in the desired `locale`, there will be another check performed to see if there is a translation available in the `default_locale`. If there is, display it.
|
83
|
+
|
84
|
+
By default, when including two javascript tags in your application (see installation notes), you will have translations in the desired locale merged with translations for the default_locale available in the javascript.
|
85
|
+
|
86
|
+
|
87
|
+
### Localization
|
88
|
+
|
89
|
+
All standard I18n keys (see `config/locales/*` in this gem’s directory) are used for various localization rules. Examples follows (for `:en` locale).
|
90
|
+
|
91
|
+
|
92
|
+
#### Numbers
|
93
|
+
|
94
|
+
```js
|
95
|
+
I18n.toNumber(1234)
|
96
|
+
=> "1,234.000"
|
97
|
+
|
98
|
+
l("number", 1234)
|
99
|
+
=> "1,234.000"
|
100
|
+
```
|
101
|
+
|
102
|
+
#### Percentages
|
103
|
+
|
104
|
+
```js
|
105
|
+
I18n.toPercentage(1234)
|
106
|
+
=> "1234.000%"
|
107
|
+
|
108
|
+
l("percentage", 1234)
|
109
|
+
=> "1234.000%"
|
110
|
+
```
|
111
|
+
|
112
|
+
#### Currencies
|
113
|
+
|
114
|
+
```js
|
115
|
+
I18n.toCurrency(12)
|
116
|
+
=> "12,00 USD"
|
117
|
+
|
118
|
+
l("currency", 12)
|
119
|
+
=> "12,00 USD"
|
120
|
+
```
|
121
|
+
|
122
|
+
|
123
|
+
#### Numbers in human sizes
|
124
|
+
|
125
|
+
```js
|
126
|
+
I18n.toHumanSize(1024)
|
127
|
+
=> "1KB"
|
128
|
+
```
|
129
|
+
|
130
|
+
|
131
|
+
#### Dates and times
|
132
|
+
|
133
|
+
```js
|
134
|
+
// uses ERB Ruby interpolation
|
135
|
+
I18n.strftime(I18n.parseDate("<%= Time.now %>"), "%Y/%m/%d %H:%M")
|
136
|
+
=> "2011/09/14 12:03"
|
137
|
+
|
138
|
+
// uses formats from `config/locale/en.yml` file
|
139
|
+
I18n.l("date.formats.default", "Wed Sep 14 12:03:11 +0200 2011")
|
140
|
+
=> "14-09-2011"
|
141
|
+
|
142
|
+
I18n.l("date.formats.long", "2011-09-14")
|
143
|
+
=> "September 14, 2011"
|
144
|
+
```
|
145
|
+
|
146
|
+
See `spec/javascripts/exvo_globalize_i18n_spec.js` for all available localization forms.
|
75
147
|
|
76
148
|
|
77
149
|
|
@@ -139,4 +211,13 @@ http://johnbintz.github.com/jasmine-headless-webkit/
|
|
139
211
|
|
140
212
|
|
141
213
|
|
214
|
+
## Copyrights
|
215
|
+
|
216
|
+
exvo_globalize is based on the following projects:
|
217
|
+
https://github.com/svenfuchs/i18n
|
218
|
+
https://github.com/svenfuchs/rails-i18n/
|
219
|
+
https://github.com/toretore/babilu
|
220
|
+
https://github.com/spider-network/i18n-js
|
221
|
+
|
222
|
+
|
142
223
|
Copyright © 2011 Exvo.com Development BV, released under the MIT license
|
data/Rakefile
CHANGED
@@ -1,90 +1,374 @@
|
|
1
|
-
|
2
|
-
// Replace {{foo}} with obj.foo
|
3
|
-
function interpolate(string, object) {
|
4
|
-
return string.replace(/\{\{([^}]+)\}\}/g, function() {
|
5
|
-
return object[arguments[1]] || arguments[0];
|
6
|
-
});
|
7
|
-
};
|
1
|
+
(function() {
|
8
2
|
|
9
|
-
|
10
|
-
function keyToArray(key) {
|
11
|
-
if(!key) {
|
12
|
-
return [];
|
13
|
-
}
|
14
|
-
if(typeof key != "string") {
|
15
|
-
return key;
|
16
|
-
}
|
17
|
-
return key.split('.');
|
18
|
-
};
|
3
|
+
I18n = {};
|
19
4
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
5
|
+
var interpolatePattern = /%\{([^}]+)\}/g;
|
6
|
+
|
7
|
+
// Replace %{foo} with obj.foo
|
8
|
+
function interpolate(str, obj) {
|
9
|
+
return str.replace(interpolatePattern, function() {
|
10
|
+
return typeof obj[arguments[1]] == 'undefined' ? arguments[0] : obj[arguments[1]];
|
11
|
+
});
|
12
|
+
};
|
13
|
+
|
14
|
+
// Split "foo.bar" to ["foo", "bar"] if key is a string
|
15
|
+
function keyToArray(key) {
|
16
|
+
if (!key) return [];
|
17
|
+
if (typeof key != "string") return key;
|
18
|
+
return key.split('.');
|
19
|
+
};
|
20
|
+
|
21
|
+
function locale() {
|
22
|
+
return I18n.locale || I18n.defaultLocale;
|
23
|
+
};
|
24
|
+
|
25
|
+
I18n.isValidNode = function(obj, node) {
|
26
|
+
// local undefined variable in case another library corrupts window.undefined
|
27
|
+
var undef;
|
28
|
+
return obj[node] !== null && obj[node] !== undef;
|
29
|
+
};
|
30
|
+
|
31
|
+
// Merge serveral hash options, checking if value is set before
|
32
|
+
// overwriting any value. The precedence is from left to right.
|
33
|
+
//
|
34
|
+
// I18n.prepareOptions({name: "John Doe"}, {name: "Mary Doe", role: "user"});
|
35
|
+
// #=> {name: "John Doe", role: "user"}
|
36
|
+
I18n.prepareOptions = function() {
|
37
|
+
var options = {};
|
38
|
+
var opts;
|
39
|
+
var count = arguments.length;
|
40
|
+
|
41
|
+
for (var i = 0; i < count; i++) {
|
42
|
+
opts = arguments[i];
|
43
|
+
|
44
|
+
if (!opts) {
|
45
|
+
continue;
|
46
|
+
}
|
47
|
+
|
48
|
+
for (var key in opts) {
|
49
|
+
if (!this.isValidNode(options, key)) {
|
50
|
+
options[key] = opts[key];
|
44
51
|
}
|
45
|
-
|
52
|
+
}
|
53
|
+
}
|
46
54
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
55
|
+
return options;
|
56
|
+
};
|
57
|
+
|
58
|
+
// Works mostly the same as the Ruby equivalent, except there are
|
59
|
+
// no symbols in JavaScript, so keys are always strings. The only time
|
60
|
+
// this makes a difference is when differentiating between keys and values
|
61
|
+
// in the defaultValue option. Strings starting with ":" will be considered
|
62
|
+
// to be keys and used for lookup, while other strings are returned as-is.
|
63
|
+
I18n.translate = function(key, opts) {
|
64
|
+
if (typeof key != "string") { // Bulk lookup
|
65
|
+
var a = [], i;
|
66
|
+
for (i=0; i<key.length; i++) {
|
67
|
+
a.push(this.translate(key[i], opts));
|
68
|
+
}
|
69
|
+
return a;
|
70
|
+
} else {
|
71
|
+
opts = opts || {};
|
72
|
+
opts.defaultValue = opts.defaultValue || null;
|
73
|
+
key = keyToArray(opts.scope).concat(keyToArray(key));
|
74
|
+
var value = this.lookup(locale(), key, opts.defaultValue);
|
75
|
+
|
76
|
+
// fall back to I18n.default_locale for missing translations
|
77
|
+
if (value == null && I18n.locale != I18n.default_locale) value = this.lookup(I18n.default_locale, key, opts.defaultLocale);
|
78
|
+
|
79
|
+
if (typeof value != "string" && value) value = this.pluralize(value, opts.count);
|
80
|
+
if (typeof value == "string") value = interpolate(value, opts);
|
81
|
+
if (value == null) value = this.missingTranslation(key)
|
82
|
+
return value;
|
83
|
+
}
|
84
|
+
};
|
52
85
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
86
|
+
I18n.t = I18n.translate;
|
87
|
+
|
88
|
+
// Looks up a translation using an array of strings where the last
|
89
|
+
// is the key and any string before that define the scope. The current
|
90
|
+
// locale is always prepended and does not need to be provided. The second
|
91
|
+
// parameter is an array of strings used as defaults if the key can not be
|
92
|
+
// found. If a key starts with ":" it is used as a key for lookup.
|
93
|
+
// This method does not perform pluralization or interpolation.
|
94
|
+
I18n.lookup = function(locale, keys, defaults) {
|
95
|
+
var i = 0, value = this.translations[locale];
|
96
|
+
defaults = typeof defaults == "string" ? [defaults] : (defaults || []);
|
97
|
+
while (keys[i]) {
|
98
|
+
value = value && value[keys[i]];
|
99
|
+
i++;
|
100
|
+
}
|
101
|
+
if (value) {
|
102
|
+
return value;
|
103
|
+
} else {
|
104
|
+
if (defaults.length == 0) {
|
105
|
+
return null;
|
106
|
+
} else if (defaults[0].substr(0,1) == ':') {
|
107
|
+
return this.lookup(locale, keys.slice(0, keys.length - 1).concat(keyToArray(defaults[0].substr(1))), defaults.slice(1));
|
108
|
+
} else {
|
109
|
+
return defaults[0];
|
110
|
+
}
|
111
|
+
}
|
112
|
+
};
|
113
|
+
|
114
|
+
I18n.localize = function(scope, value) {
|
115
|
+
switch (scope) {
|
116
|
+
case "currency":
|
117
|
+
return this.toCurrency(value);
|
118
|
+
case "number":
|
119
|
+
scope = this.lookup(locale(), ["number", "format"]);
|
120
|
+
return this.toNumber(value, scope);
|
121
|
+
case "percentage":
|
122
|
+
return this.toPercentage(value);
|
123
|
+
default:
|
124
|
+
if (scope.match(/^(date|time)/)) {
|
125
|
+
return this.toTime(scope, value);
|
67
126
|
} else {
|
68
|
-
|
69
|
-
options.defaultValue = options.defaultValue || null;
|
70
|
-
key = keyToArray(options.scope).concat(keyToArray(key));
|
71
|
-
var value = lookup(key, options.defaultValue);
|
72
|
-
if(typeof value !== "string" && value) {
|
73
|
-
value = pluralize(value, options.count);
|
74
|
-
}
|
75
|
-
if(typeof value === "string") {
|
76
|
-
value = interpolate(value, options);
|
77
|
-
}
|
78
|
-
return value;
|
127
|
+
return value.toString();
|
79
128
|
}
|
80
129
|
}
|
130
|
+
};
|
131
|
+
|
132
|
+
I18n.l = I18n.localize;
|
133
|
+
|
134
|
+
I18n.parseDate = function(d) {
|
135
|
+
var matches, date;
|
136
|
+
matches = d.toString().match(/(\d{4})-(\d{2})-(\d{2})(?:[ |T](\d{2}):(\d{2}):(\d{2}))?(Z)?/);
|
137
|
+
|
138
|
+
if (matches) {
|
139
|
+
// date/time strings: yyyy-mm-dd hh:mm:ss or yyyy-mm-dd or yyyy-mm-ddThh:mm:ssZ
|
140
|
+
for (var i = 1; i <= 6; i++) {
|
141
|
+
matches[i] = parseInt(matches[i], 10) || 0;
|
142
|
+
}
|
143
|
+
|
144
|
+
// month starts on 0
|
145
|
+
matches[2] -= 1;
|
146
|
+
|
147
|
+
if (matches[7]) {
|
148
|
+
date = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]));
|
149
|
+
} else {
|
150
|
+
date = new Date(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]);
|
151
|
+
}
|
152
|
+
} else if (typeof(d) == "number") {
|
153
|
+
// UNIX timestamp
|
154
|
+
date = new Date();
|
155
|
+
date.setTime(d);
|
156
|
+
} else {
|
157
|
+
// an arbitrary javascript string
|
158
|
+
date = new Date();
|
159
|
+
date.setTime(Date.parse(d));
|
160
|
+
}
|
161
|
+
|
162
|
+
return date;
|
163
|
+
};
|
164
|
+
|
165
|
+
I18n.toTime = function(scope, d) {
|
166
|
+
var date = this.parseDate(d);
|
167
|
+
var format = this.lookup(locale(), keyToArray(scope));
|
168
|
+
|
169
|
+
if (date.toString().match(/invalid/i)) {
|
170
|
+
return date.toString();
|
171
|
+
}
|
172
|
+
|
173
|
+
if (!format) {
|
174
|
+
return date.toString();
|
175
|
+
}
|
176
|
+
|
177
|
+
return this.strftime(date, format);
|
178
|
+
};
|
179
|
+
|
180
|
+
I18n.strftime = function(date, format) {
|
181
|
+
var options = this.lookup(locale(), ["date"]);
|
182
|
+
|
183
|
+
if (!options) {
|
184
|
+
return date.toString();
|
185
|
+
}
|
81
186
|
|
82
|
-
|
83
|
-
|
84
|
-
|
187
|
+
// get meridian from ":time" i18n key
|
188
|
+
options.time = this.lookup(locale(), ["time"]);
|
189
|
+
if (!options.time || !options.time.am || !options.time.pm) {
|
190
|
+
options.time = { am: "AM", pm: "PM" };
|
191
|
+
}
|
192
|
+
|
193
|
+
var weekDay = date.getDay();
|
194
|
+
var day = date.getDate();
|
195
|
+
var year = date.getFullYear();
|
196
|
+
var month = date.getMonth() + 1;
|
197
|
+
var hour = date.getHours();
|
198
|
+
var hour12 = hour;
|
199
|
+
var meridian = hour > 11 ? "pm" : "am";
|
200
|
+
var secs = date.getSeconds();
|
201
|
+
var mins = date.getMinutes();
|
202
|
+
var offset = date.getTimezoneOffset();
|
203
|
+
var absOffsetHours = Math.floor(Math.abs(offset / 60));
|
204
|
+
var absOffsetMinutes = Math.abs(offset) - (absOffsetHours * 60);
|
205
|
+
var timezoneoffset = (offset > 0 ? "-" : "+") + (absOffsetHours.toString().length < 2 ? "0" + absOffsetHours : absOffsetHours) + (absOffsetMinutes.toString().length < 2 ? "0" + absOffsetMinutes : absOffsetMinutes);
|
206
|
+
|
207
|
+
if (hour12 > 12) {
|
208
|
+
hour12 = hour12 - 12;
|
209
|
+
} else if (hour12 === 0) {
|
210
|
+
hour12 = 12;
|
211
|
+
}
|
212
|
+
|
213
|
+
var padding = function(n) {
|
214
|
+
var s = "0" + n.toString();
|
215
|
+
return s.substr(s.length - 2);
|
85
216
|
};
|
217
|
+
|
218
|
+
var f = format;
|
219
|
+
f = f.replace("%a", options.abbr_day_names[weekDay]);
|
220
|
+
f = f.replace("%A", options.day_names[weekDay]);
|
221
|
+
f = f.replace("%b", options.abbr_month_names[month]);
|
222
|
+
f = f.replace("%B", options.month_names[month]);
|
223
|
+
f = f.replace("%d", padding(day));
|
224
|
+
f = f.replace("%-d", day);
|
225
|
+
f = f.replace("%H", padding(hour));
|
226
|
+
f = f.replace("%-H", hour);
|
227
|
+
f = f.replace("%I", padding(hour12));
|
228
|
+
f = f.replace("%-I", hour12);
|
229
|
+
f = f.replace("%m", padding(month));
|
230
|
+
f = f.replace("%-m", month);
|
231
|
+
f = f.replace("%M", padding(mins));
|
232
|
+
f = f.replace("%-M", mins);
|
233
|
+
f = f.replace("%p", options.time[meridian]);
|
234
|
+
f = f.replace("%S", padding(secs));
|
235
|
+
f = f.replace("%-S", secs);
|
236
|
+
f = f.replace("%w", weekDay);
|
237
|
+
f = f.replace("%y", padding(year));
|
238
|
+
f = f.replace("%-y", padding(year).replace(/^0+/, ""));
|
239
|
+
f = f.replace("%Y", year);
|
240
|
+
f = f.replace("%z", timezoneoffset);
|
241
|
+
|
242
|
+
return f;
|
243
|
+
};
|
244
|
+
|
245
|
+
I18n.toNumber = function(number, options) {
|
246
|
+
options = this.prepareOptions(
|
247
|
+
options,
|
248
|
+
this.lookup(locale(), ["number", "format"]),
|
249
|
+
{precision: 3, separator: ".", delimiter: ",", strip_insignificant_zeros: false}
|
250
|
+
);
|
251
|
+
|
252
|
+
var negative = number < 0;
|
253
|
+
var string = Math.abs(number).toFixed(options.precision).toString();
|
254
|
+
var parts = string.split(".");
|
255
|
+
|
256
|
+
number = parts[0];
|
257
|
+
var precision = parts[1];
|
258
|
+
|
259
|
+
var n = [];
|
260
|
+
|
261
|
+
while (number.length > 0) {
|
262
|
+
n.unshift(number.substr(Math.max(0, number.length - 3), 3));
|
263
|
+
number = number.substr(0, number.length -3);
|
264
|
+
}
|
265
|
+
|
266
|
+
var formattedNumber = n.join(options.delimiter);
|
267
|
+
|
268
|
+
if (options.precision > 0) {
|
269
|
+
formattedNumber += options.separator + parts[1];
|
270
|
+
}
|
271
|
+
|
272
|
+
if (negative) {
|
273
|
+
formattedNumber = "-" + formattedNumber;
|
274
|
+
}
|
275
|
+
|
276
|
+
if (options.strip_insignificant_zeros) {
|
277
|
+
var regex = {
|
278
|
+
separator: new RegExp(options.separator.replace(/\./, "\\.") + "$")
|
279
|
+
, zeros: /0+$/
|
280
|
+
};
|
281
|
+
|
282
|
+
formattedNumber = formattedNumber
|
283
|
+
.replace(regex.zeros, "")
|
284
|
+
.replace(regex.separator, "");
|
285
|
+
}
|
286
|
+
|
287
|
+
return formattedNumber;
|
288
|
+
};
|
289
|
+
|
290
|
+
I18n.toCurrency = function(number, options) {
|
291
|
+
options = this.prepareOptions(
|
292
|
+
options,
|
293
|
+
this.lookup(locale(), ["number", "currency", "format"]),
|
294
|
+
this.lookup(locale(), ["number", "format"]),
|
295
|
+
{unit: "$", precision: 2, format: "%u%n", delimiter: ",", separator: "."}
|
296
|
+
);
|
297
|
+
|
298
|
+
number = this.toNumber(number, options);
|
299
|
+
number = options.format
|
300
|
+
.replace("%u", options.unit)
|
301
|
+
.replace("%n", number);
|
302
|
+
|
303
|
+
return number;
|
304
|
+
};
|
305
|
+
|
306
|
+
I18n.toHumanSize = function(number, options) {
|
307
|
+
var kb = 1024
|
308
|
+
, size = number
|
309
|
+
, iterations = 0
|
310
|
+
, unit
|
311
|
+
, precision
|
312
|
+
;
|
313
|
+
|
314
|
+
while (size >= kb && iterations < 4) {
|
315
|
+
size = size / kb;
|
316
|
+
iterations += 1;
|
317
|
+
}
|
318
|
+
|
319
|
+
if (iterations === 0) {
|
320
|
+
unit = this.t("number.human.storage_units.units.byte", {count: size});
|
321
|
+
precision = 0;
|
322
|
+
} else {
|
323
|
+
unit = this.t("number.human.storage_units.units." + [null, "kb", "mb", "gb", "tb"][iterations]);
|
324
|
+
precision = (size - Math.floor(size) === 0) ? 0 : 1;
|
325
|
+
}
|
326
|
+
|
327
|
+
options = this.prepareOptions(
|
328
|
+
options,
|
329
|
+
{precision: precision, format: "%n%u", delimiter: ""}
|
330
|
+
);
|
331
|
+
|
332
|
+
number = this.toNumber(size, options);
|
333
|
+
number = options.format
|
334
|
+
.replace("%u", unit)
|
335
|
+
.replace("%n", number);
|
336
|
+
|
337
|
+
return number;
|
338
|
+
};
|
339
|
+
|
340
|
+
I18n.toPercentage = function(number, options) {
|
341
|
+
options = this.prepareOptions(
|
342
|
+
options,
|
343
|
+
this.lookup(locale(), ["number", "percentage", "format"]),
|
344
|
+
this.lookup(locale(), ["number", "format"]),
|
345
|
+
{precision: 3, separator: ".", delimiter: ""}
|
346
|
+
);
|
347
|
+
|
348
|
+
number = this.toNumber(number, options);
|
349
|
+
return number + "%";
|
350
|
+
};
|
351
|
+
|
352
|
+
I18n.pluralize = function(value, count) {
|
353
|
+
if (typeof count != 'number') return value;
|
354
|
+
return count == 1 ? value.one : value.other;
|
355
|
+
};
|
356
|
+
|
357
|
+
// Returns '[missing translation: "en.missing"]' when translation is not found
|
358
|
+
I18n.missingTranslation = function(key) {
|
359
|
+
var message = '[missing translation: "' + locale();
|
360
|
+
for (var i in key) {
|
361
|
+
message += "." + key[i];
|
362
|
+
}
|
363
|
+
return message += '"]';
|
364
|
+
};
|
365
|
+
|
86
366
|
})();
|
87
367
|
|
88
368
|
var t = (function(key, options) {
|
89
369
|
return I18n.t(key, options);
|
90
370
|
});
|
371
|
+
|
372
|
+
var l = (function(scope, value) {
|
373
|
+
return I18n.l(scope, value);
|
374
|
+
});
|
@@ -6,11 +6,10 @@ class GlobalizeTranslationsController < ApplicationController
|
|
6
6
|
layout 'exvo_globalize'
|
7
7
|
|
8
8
|
respond_to :html, :json, :js
|
9
|
-
|
9
|
+
|
10
10
|
def show
|
11
11
|
@translations = if params[:id].present?
|
12
|
-
|
13
|
-
hash.has_key?(params[:id].to_sym) ? hash[params[:id].to_sym] : {}
|
12
|
+
I18n.backend.available_translations_scoped_by_locale_with_default(params[:id].to_sym)
|
14
13
|
else
|
15
14
|
I18n.backend.available_app_translations.merge({ :default_locale => I18n.default_locale })
|
16
15
|
end
|
@@ -52,7 +51,7 @@ class GlobalizeTranslationsController < ApplicationController
|
|
52
51
|
end
|
53
52
|
|
54
53
|
private
|
55
|
-
|
54
|
+
|
56
55
|
def globalize_translations_authenticator
|
57
56
|
# get :show as JSON or JS does not require authentication
|
58
57
|
return if params[:action].to_s == 'show' and (request.format.json? or request.format.js?)
|
@@ -4,13 +4,24 @@ module I18n
|
|
4
4
|
module Implementation
|
5
5
|
|
6
6
|
# Extend the Chain backend with a custom `available_translations` method
|
7
|
-
# returning a combined
|
7
|
+
# returning a combined Hash with translations from all chained backends
|
8
8
|
def available_translations
|
9
9
|
# reverse, so that the translations from the first backend (GlobalizeStore) overwrite/overshadow others
|
10
10
|
@available_translations ||= backends.map { |backend| backend.available_translations }.reverse.inject(&:deep_merge)
|
11
11
|
end
|
12
12
|
|
13
|
-
#
|
13
|
+
# Returns a Hash of translations for the specified locale merged with translations for the default_locale
|
14
|
+
def available_translations_scoped_by_locale_with_default(locale)
|
15
|
+
default_locale_translations = { I18n.default_locale => available_translations.fetch(I18n.default_locale) { {} } }
|
16
|
+
|
17
|
+
if locale != I18n.default_locale
|
18
|
+
default_locale_translations.deep_merge({ locale => available_translations.fetch(locale) { {} } })
|
19
|
+
else
|
20
|
+
default_locale_translations
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Return a Hash only with Application translations
|
14
25
|
def available_app_translations
|
15
26
|
# save original load_path
|
16
27
|
load_path = I18n.load_path
|
@@ -81,4 +81,10 @@ describe ExvoGlobalize do
|
|
81
81
|
I18n.backend.available_translations[:en].has_key?(:title).should be_true
|
82
82
|
end
|
83
83
|
|
84
|
+
it "lists all translations for a given locale including translations for the default locale" do
|
85
|
+
translations = I18n.backend.available_translations_scoped_by_locale_with_default(:pl)
|
86
|
+
translations[:en].has_key?(:title).should be_true
|
87
|
+
translations[:pl].has_key?(:mail).should be_true
|
88
|
+
end
|
89
|
+
|
84
90
|
end
|
@@ -1,7 +1,384 @@
|
|
1
|
-
|
1
|
+
beforeEach(function() {
|
2
|
+
I18n.locale = "en"
|
3
|
+
})
|
4
|
+
|
5
|
+
describe("Basic translation functionality", function() {
|
6
|
+
|
7
|
+
it("translates the phrase", function() {
|
8
|
+
expect(I18n.translate("world")).toEqual("World")
|
9
|
+
})
|
10
|
+
|
11
|
+
it("translates the phrase for the 'pl' locale", function() {
|
12
|
+
I18n.locale = "pl"
|
13
|
+
expect(I18n.translate("world")).toEqual("Świat")
|
14
|
+
})
|
15
|
+
|
16
|
+
it("translates the phrase using I18n.t()", function() {
|
17
|
+
expect(I18n.t("world")).toEqual("World")
|
18
|
+
})
|
19
|
+
|
20
|
+
it("returns missing translation message when translation is not found", function() {
|
21
|
+
expect(I18n.t("missing")).toMatch(/missing translation/)
|
22
|
+
})
|
23
|
+
|
24
|
+
it("translates the phrase using scoped key with dots as separators", function() {
|
25
|
+
expect(I18n.t("page.intro.heading")).toEqual("Heading")
|
26
|
+
})
|
27
|
+
|
28
|
+
it("translates the phrase using dotted string scope param", function() {
|
29
|
+
expect(I18n.t("heading", {scope: "page.intro"})).toEqual("Heading")
|
30
|
+
})
|
31
|
+
|
32
|
+
it("translates the phrase using Array scope param", function() {
|
33
|
+
expect(I18n.t("heading", {scope: ["page", "intro"]})).toEqual("Heading")
|
34
|
+
})
|
35
|
+
|
36
|
+
it("supports interpolation during translation", function() {
|
37
|
+
expect(I18n.t("hello", {name: "John"})).toEqual("Hello John!")
|
38
|
+
})
|
39
|
+
|
40
|
+
})
|
41
|
+
|
42
|
+
describe("Global short functions", function() {
|
43
|
+
|
44
|
+
it("translates the phrase using t() global function", function() {
|
45
|
+
expect(t("world")).toEqual("World")
|
46
|
+
})
|
47
|
+
|
48
|
+
it("localizes the number using l() global function", function() {
|
49
|
+
expect(l("number", 1)).toEqual("1.000")
|
50
|
+
})
|
51
|
+
|
52
|
+
})
|
53
|
+
|
54
|
+
describe("Default value fallback", function() {
|
55
|
+
|
56
|
+
it("ignores defaultValue if translation is found", function() {
|
57
|
+
expect(I18n.t("world", {defaultValue: "New World"})).toEqual("World")
|
58
|
+
})
|
59
|
+
|
60
|
+
it("returns defaultValue if translation is not found", function() {
|
61
|
+
expect(I18n.t("non-existing-key", {defaultValue: "New World"})).toEqual("New World")
|
62
|
+
})
|
63
|
+
|
64
|
+
it("uses defaultValue to do another lookup if it starts with ':'", function() {
|
65
|
+
expect(I18n.t("non-existing-key", {defaultValue: ":world"})).toEqual("World")
|
66
|
+
})
|
67
|
+
|
68
|
+
it("allows an Array as defaultValue and keeps checking each of its keys for translation", function() {
|
69
|
+
expect(I18n.t("non-existing-key", {defaultValue: [":missing", ":world"]})).toEqual("World")
|
70
|
+
})
|
71
|
+
|
72
|
+
it("applies the same scope to the defaultValue as it does to the key", function() {
|
73
|
+
expect(I18n.t("non-existing-key", {scope: "page", defaultValue: [":title"]})).toEqual("Title")
|
74
|
+
})
|
75
|
+
|
76
|
+
})
|
77
|
+
|
78
|
+
describe("Locale fallback", function() {
|
79
|
+
|
80
|
+
it("falls back to I18n.default_locale when there is no translation available for the requested locale", function() {
|
81
|
+
I18n.locale = "pl"
|
82
|
+
expect(I18n.t("title", {scope: "page"})).toEqual("Title")
|
83
|
+
})
|
84
|
+
|
85
|
+
})
|
86
|
+
|
87
|
+
describe("Localization of numbers", function() {
|
88
|
+
|
89
|
+
beforeEach(function() {
|
90
|
+
I18n.locale = "pl"
|
91
|
+
})
|
92
|
+
|
93
|
+
it("localizes numbers with default settings", function() {
|
94
|
+
expect(I18n.toNumber(1)).toEqual("1,000")
|
95
|
+
expect(I18n.toNumber(1234567)).toEqual("1 234 567,000")
|
96
|
+
expect(I18n.toNumber(-1)).toEqual("-1,000")
|
97
|
+
expect(I18n.toNumber(-1234567)).toEqual("-1 234 567,000")
|
98
|
+
})
|
99
|
+
|
100
|
+
it("localizes numbers with custom options", function() {
|
101
|
+
expect(I18n.toNumber(1234.19, {precision: 0})).toEqual("1 234")
|
102
|
+
expect(I18n.toNumber(1234, {separator: '-'})).toEqual("1 234-000")
|
103
|
+
expect(I18n.toNumber(1234, {delimiter: '-'})).toEqual("1-234,000")
|
104
|
+
expect(I18n.toNumber(65, {precision: 4, strip_insignificant_zeros: true})).toEqual("65")
|
105
|
+
expect(I18n.toNumber(1.2, {precision: 4, strip_insignificant_zeros: true})).toEqual("1,2")
|
106
|
+
})
|
107
|
+
|
108
|
+
it("localizes numbers using localize() function", function() {
|
109
|
+
expect(I18n.l("number", 1)).toEqual("1,000")
|
110
|
+
expect(I18n.l("number", 1234567)).toEqual("1 234 567,000")
|
111
|
+
expect(I18n.l("number", -1)).toEqual("-1,000")
|
112
|
+
expect(I18n.l("number", -1234567)).toEqual("-1 234 567,000")
|
113
|
+
})
|
114
|
+
})
|
115
|
+
|
116
|
+
describe("Localization of percentages", function() {
|
117
|
+
|
118
|
+
beforeEach(function() {
|
119
|
+
I18n.locale = "pl"
|
120
|
+
})
|
121
|
+
|
122
|
+
it("localizes percentages with default settings", function() {
|
123
|
+
expect(I18n.toPercentage(1234)).toEqual("1234,00%")
|
124
|
+
})
|
125
|
+
|
126
|
+
it("localizes percentages with custom options", function() {
|
127
|
+
expect(I18n.toPercentage(1234.19, {delimiter: "_", precision: 0})).toEqual("1_234%")
|
128
|
+
})
|
129
|
+
|
130
|
+
it("localizes percentages using localize() function", function() {
|
131
|
+
expect(I18n.l("percentage", 12)).toEqual("12,00%")
|
132
|
+
})
|
133
|
+
|
134
|
+
})
|
135
|
+
|
136
|
+
describe("Localization of currencies", function() {
|
137
|
+
|
138
|
+
beforeEach(function() {
|
139
|
+
I18n.locale = "pl"
|
140
|
+
})
|
141
|
+
|
142
|
+
it("localizes currencies with default settings", function() {
|
143
|
+
expect(I18n.toCurrency(100.99)).toEqual("PLN 100,99")
|
144
|
+
expect(I18n.toCurrency(1000.99)).toEqual("PLN 1 000,99")
|
145
|
+
})
|
146
|
+
|
147
|
+
it("localizes currencies with custom options", function() {
|
148
|
+
expect(I18n.toCurrency(1234.19, {precision: 0})).toEqual("PLN 1 234")
|
149
|
+
expect(I18n.toCurrency(1234, {unit: "zł"})).toEqual("zł 1 234")
|
150
|
+
expect(I18n.toCurrency(1234, {separator: "-", strip_insignificant_zeros: false})).toEqual("PLN 1 234-00")
|
151
|
+
expect(I18n.toCurrency(1234, {delimiter: ""})).toEqual("PLN 1234")
|
152
|
+
expect(I18n.toCurrency(1234, {format: "%n %u"})).toEqual("1 234 PLN")
|
153
|
+
})
|
154
|
+
|
155
|
+
it("localizes currencies using localize() function", function() {
|
156
|
+
expect(I18n.l("currency", 12)).toEqual("PLN 12")
|
157
|
+
})
|
158
|
+
|
159
|
+
})
|
160
|
+
|
161
|
+
describe("Localization of human sizes", function() {
|
162
|
+
|
163
|
+
beforeEach(function() {
|
164
|
+
I18n.locale = "pl"
|
165
|
+
})
|
166
|
+
|
167
|
+
it("localizes numbers in human sizes", function() {
|
168
|
+
kb = 1024
|
169
|
+
|
170
|
+
expect(I18n.toHumanSize(1)).toEqual("1bajt")
|
171
|
+
expect(I18n.toHumanSize(102)).toEqual("102bajty")
|
172
|
+
|
173
|
+
expect(I18n.toHumanSize(kb)).toEqual("1KB")
|
174
|
+
expect(I18n.toHumanSize(kb * 1.5)).toEqual("1,5KB")
|
175
|
+
|
176
|
+
expect(I18n.toHumanSize(kb * kb)).toEqual("1MB")
|
177
|
+
expect(I18n.toHumanSize(kb * kb * 1.5)).toEqual("1,5MB")
|
178
|
+
|
179
|
+
expect(I18n.toHumanSize(kb * kb * kb)).toEqual("1GB")
|
180
|
+
expect(I18n.toHumanSize(kb * kb * kb * 1.5)).toEqual("1,5GB")
|
181
|
+
|
182
|
+
expect(I18n.toHumanSize(kb * kb * kb * kb)).toEqual("1TB")
|
183
|
+
expect(I18n.toHumanSize(kb * kb * kb * kb * 1.5)).toEqual("1,5TB")
|
184
|
+
|
185
|
+
expect(I18n.toHumanSize(kb * kb * kb * kb * kb)).toEqual("1024TB")
|
186
|
+
})
|
187
|
+
|
188
|
+
it("localizes numbers in human sizes using custom options", function() {
|
189
|
+
expect(I18n.toHumanSize(1024 * 1.6, {precision: 0})).toEqual("2KB")
|
190
|
+
})
|
191
|
+
|
192
|
+
})
|
193
|
+
|
194
|
+
describe("Date parsing", function() {
|
195
|
+
|
196
|
+
beforeEach(function() {
|
197
|
+
I18n.locale = "pl"
|
198
|
+
})
|
199
|
+
|
200
|
+
it("parses dates", function() {
|
201
|
+
expected = new Date(2009, 0, 24, 0, 0, 0)
|
202
|
+
actual = I18n.parseDate("2009-01-24")
|
203
|
+
expect(actual.toString()).toEqual(expected.toString())
|
204
|
+
|
205
|
+
expected = new Date(2009, 0, 24, 0, 15, 0)
|
206
|
+
actual = I18n.parseDate("2009-01-24 00:15:00")
|
207
|
+
expect(actual.toString()).toEqual(expected.toString())
|
208
|
+
|
209
|
+
expected = new Date(2009, 0, 24, 0, 0, 15)
|
210
|
+
actual = I18n.parseDate("2009-01-24 00:00:15")
|
211
|
+
expect(actual.toString()).toEqual(expected.toString())
|
212
|
+
|
213
|
+
expected = new Date(2009, 0, 24, 15, 33, 44)
|
214
|
+
actual = I18n.parseDate("2009-01-24 15:33:44")
|
215
|
+
expect(actual.toString()).toEqual(expected.toString())
|
216
|
+
|
217
|
+
expected = new Date(2009, 0, 24, 0, 0, 0)
|
218
|
+
actual = I18n.parseDate(expected.getTime())
|
219
|
+
expect(actual.toString()).toEqual(expected.toString())
|
220
|
+
|
221
|
+
expected = new Date(2009, 0, 24, 0, 0, 0)
|
222
|
+
actual = I18n.parseDate("01/24/2009")
|
223
|
+
expect(actual.toString()).toEqual(expected.toString())
|
224
|
+
|
225
|
+
expected = new Date(2009, 0, 24, 14, 33, 55)
|
226
|
+
actual = I18n.parseDate(expected).toString()
|
227
|
+
expect(actual).toEqual(expected.toString())
|
228
|
+
|
229
|
+
expected = new Date(2009, 0, 24, 15, 33, 44)
|
230
|
+
actual = I18n.parseDate("2009-01-24T15:33:44")
|
231
|
+
expect(actual.toString()).toEqual(expected.toString())
|
232
|
+
|
233
|
+
expected = new Date(Date.UTC(2009, 0, 24, 15, 33, 44))
|
234
|
+
actual = I18n.parseDate("2009-01-24T15:33:44Z")
|
235
|
+
expect(actual.toString()).toEqual(expected.toString())
|
236
|
+
})
|
237
|
+
|
238
|
+
it("formats dates", function() {
|
239
|
+
// 2009-04-26 19:35:44 (Sunday)
|
240
|
+
var date = new Date(2009, 3, 26, 19, 35, 44)
|
241
|
+
|
242
|
+
// short week day
|
243
|
+
expect(I18n.strftime(date, "%a")).toEqual("nie")
|
244
|
+
|
245
|
+
// full week day
|
246
|
+
expect(I18n.strftime(date, "%A")).toEqual("niedziela")
|
247
|
+
|
248
|
+
// short month
|
249
|
+
expect(I18n.strftime(date, "%b")).toEqual("kwi")
|
250
|
+
|
251
|
+
// full month
|
252
|
+
expect(I18n.strftime(date, "%B")).toEqual("kwiecień")
|
253
|
+
|
254
|
+
// day
|
255
|
+
expect(I18n.strftime(date, "%d")).toEqual("26")
|
256
|
+
|
257
|
+
// 24-hour
|
258
|
+
expect(I18n.strftime(date, "%H")).toEqual("19")
|
259
|
+
|
260
|
+
// 12-hour
|
261
|
+
expect(I18n.strftime(date, "%I")).toEqual("07")
|
262
|
+
|
263
|
+
// month
|
264
|
+
expect(I18n.strftime(date, "%m")).toEqual("04")
|
265
|
+
|
266
|
+
// minutes
|
267
|
+
expect(I18n.strftime(date, "%M")).toEqual("35")
|
268
|
+
|
269
|
+
// meridian
|
270
|
+
expect(I18n.strftime(date, "%p")).toEqual("po południu")
|
271
|
+
|
272
|
+
// seconds
|
273
|
+
expect(I18n.strftime(date, "%S")).toEqual("44")
|
274
|
+
|
275
|
+
// week day
|
276
|
+
expect(I18n.strftime(date, "%w")).toEqual("0")
|
277
|
+
|
278
|
+
// short year
|
279
|
+
expect(I18n.strftime(date, "%y")).toEqual("09")
|
280
|
+
|
281
|
+
// full year
|
282
|
+
expect(I18n.strftime(date, "%Y")).toEqual("2009")
|
283
|
+
|
284
|
+
// full date
|
285
|
+
expect(I18n.strftime(date, "%d. %B %Y, godzina %H:%M")).toEqual("26. kwiecień 2009, godzina 19:35")
|
286
|
+
})
|
287
|
+
|
288
|
+
it("formats dates without padding", function() {
|
289
|
+
// 2009-04-26 19:35:44 (Sunday)
|
290
|
+
var date = new Date(2009, 3, 9, 7, 8, 9)
|
291
|
+
|
292
|
+
// 24-hour without padding
|
293
|
+
expect(I18n.strftime(date, "%-H")).toEqual("7")
|
294
|
+
|
295
|
+
// 12-hour without padding
|
296
|
+
expect(I18n.strftime(date, "%-I")).toEqual("7")
|
297
|
+
|
298
|
+
// minutes without padding
|
299
|
+
expect(I18n.strftime(date, "%-M")).toEqual("8")
|
300
|
+
|
301
|
+
// seconds without padding
|
302
|
+
expect(I18n.strftime(date, "%-S")).toEqual("9")
|
303
|
+
|
304
|
+
// short year without padding
|
305
|
+
expect(I18n.strftime(date, "%-y")).toEqual("9")
|
306
|
+
|
307
|
+
// month without padding
|
308
|
+
expect(I18n.strftime(date, "%-m")).toEqual("4")
|
309
|
+
|
310
|
+
// day without padding
|
311
|
+
expect(I18n.strftime(date, "%-d")).toEqual("9")
|
312
|
+
})
|
313
|
+
|
314
|
+
it("formats dates with padding", function() {
|
315
|
+
// 2009-04-26 19:35:44 (Sunday)
|
316
|
+
var date = new Date(2009, 3, 9, 7, 8, 9)
|
317
|
+
|
318
|
+
// 24-hour
|
319
|
+
expect(I18n.strftime(date, "%H")).toEqual("07")
|
320
|
+
|
321
|
+
// 12-hour
|
322
|
+
expect(I18n.strftime(date, "%I")).toEqual("07")
|
323
|
+
|
324
|
+
// minutes
|
325
|
+
expect(I18n.strftime(date, "%M")).toEqual("08")
|
326
|
+
|
327
|
+
// seconds
|
328
|
+
expect(I18n.strftime(date, "%S")).toEqual("09")
|
329
|
+
|
330
|
+
// short year
|
331
|
+
expect(I18n.strftime(date, "%y")).toEqual("09")
|
332
|
+
|
333
|
+
// month
|
334
|
+
expect(I18n.strftime(date, "%m")).toEqual("04")
|
335
|
+
|
336
|
+
// day
|
337
|
+
expect(I18n.strftime(date, "%d")).toEqual("09")
|
338
|
+
})
|
339
|
+
|
340
|
+
it("formats dates with negative time zone", function() {
|
341
|
+
var date = new Date(2009, 3, 26, 19, 35, 44)
|
342
|
+
spyOn(date, "getTimezoneOffset").andReturn(345)
|
343
|
+
|
344
|
+
expect(I18n.strftime(date, "%z")).toMatch(/^(\+|-)[\d]{4}$/)
|
345
|
+
expect(I18n.strftime(date, "%z")).toEqual("-0545")
|
346
|
+
})
|
347
|
+
|
348
|
+
it("formats dates with positive time zone", function() {
|
349
|
+
var date = new Date(2009, 3, 26, 19, 35, 44)
|
350
|
+
spyOn(date, "getTimezoneOffset").andReturn(-345)
|
351
|
+
|
352
|
+
expect(I18n.strftime(date, "%z")).toMatch(/^(\+|-)[\d]{4}$/)
|
353
|
+
expect(I18n.strftime(date, "%z")).toEqual("+0545")
|
354
|
+
})
|
355
|
+
|
356
|
+
|
357
|
+
it("formats dates using hour12 values", function() {
|
358
|
+
var date = new Date(2009, 3, 26, 19, 35, 44)
|
359
|
+
expect(I18n.strftime(date, "%I")).toEqual("07")
|
360
|
+
|
361
|
+
date = new Date(2009, 3, 26, 12, 35, 44)
|
362
|
+
expect(I18n.strftime(date, "%I")).toEqual("12")
|
363
|
+
|
364
|
+
date = new Date(2009, 3, 26, 0, 35, 44)
|
365
|
+
expect(I18n.strftime(date, "%I")).toEqual("12")
|
366
|
+
})
|
367
|
+
|
368
|
+
it("parses and formats a Ruby Time.now.to_s string ", function() {
|
369
|
+
expect(I18n.strftime(I18n.parseDate("Wed Sep 14 12:03:11 +0200 2011"), "%Y/%m/%d %H:%M")).toEqual("2011/09/14 12:03")
|
370
|
+
})
|
371
|
+
|
372
|
+
it("localizes date strings", function() {
|
373
|
+
expect(I18n.l("date.formats.default", "2009-11-29")).toEqual("29-11-2009")
|
374
|
+
expect(I18n.l("date.formats.short", "2009-01-07")).toEqual("07 sty")
|
375
|
+
expect(I18n.l("date.formats.long", "2009-01-07")).toEqual("styczeń 07, 2009")
|
376
|
+
})
|
2
377
|
|
3
|
-
it("
|
4
|
-
expect(
|
378
|
+
it("localizes time strings", function() {
|
379
|
+
expect(I18n.l("time.formats.default", "2009-11-29 15:07:59")).toEqual("nie, 29 lis 2009 15:07:59 +0100")
|
380
|
+
expect(I18n.l("time.formats.short", "2009-01-07 09:12:35")).toEqual("07 sty 09:12")
|
381
|
+
expect(I18n.l("time.formats.long", "2009-11-29 15:07:59")).toEqual("listopad 29, 2009 15:07")
|
5
382
|
})
|
6
383
|
|
7
384
|
})
|
@@ -1,2 +1,98 @@
|
|
1
1
|
I18n.locale = 'en'
|
2
|
-
I18n.
|
2
|
+
I18n.default_locale = 'en'
|
3
|
+
|
4
|
+
I18n.translations = {
|
5
|
+
en: {
|
6
|
+
|
7
|
+
hello: "Hello %{name}!",
|
8
|
+
world: "World",
|
9
|
+
|
10
|
+
page: {
|
11
|
+
footer: "Footer",
|
12
|
+
title: "Title",
|
13
|
+
|
14
|
+
intro: {
|
15
|
+
heading: "Heading"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
},
|
19
|
+
|
20
|
+
pl: {
|
21
|
+
date: {
|
22
|
+
formats: {
|
23
|
+
"default": "%d-%m-%Y",
|
24
|
+
"short": "%d %b",
|
25
|
+
"long": "%B %d, %Y"
|
26
|
+
},
|
27
|
+
day_names: ["niedziela", "poniedziałek", "wtorek", "środa", "czwartek", "piątek", "sobota"],
|
28
|
+
abbr_day_names: ["nie", "pon", "wto", "śro", "czw", "pia", "sob"],
|
29
|
+
month_names: [null, "styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień"],
|
30
|
+
abbr_month_names: [null, "sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "paź", "lis", "gru"],
|
31
|
+
order: ["day", "month", "year"]
|
32
|
+
},
|
33
|
+
time: {
|
34
|
+
formats: {
|
35
|
+
"default": "%a, %d %b %Y %H:%M:%S %z",
|
36
|
+
"short": "%d %b %H:%M",
|
37
|
+
"long": "%B %d, %Y %H:%M"
|
38
|
+
},
|
39
|
+
am: "przed południem",
|
40
|
+
pm: "po południu"
|
41
|
+
},
|
42
|
+
number: {
|
43
|
+
format: {
|
44
|
+
separator: ",",
|
45
|
+
delimiter: " ",
|
46
|
+
precision: 3,
|
47
|
+
significant: false,
|
48
|
+
strip_insignificant_zeros: false
|
49
|
+
},
|
50
|
+
currency: {
|
51
|
+
format: {
|
52
|
+
format: "%u %n",
|
53
|
+
unit: "PLN",
|
54
|
+
separator: ",",
|
55
|
+
delimiter: " ",
|
56
|
+
precision: 2,
|
57
|
+
significant: false,
|
58
|
+
strip_insignificant_zeros: true
|
59
|
+
}
|
60
|
+
},
|
61
|
+
percentage: {
|
62
|
+
format: {
|
63
|
+
delimiter: "",
|
64
|
+
separator: ",",
|
65
|
+
precision: 2
|
66
|
+
}
|
67
|
+
},
|
68
|
+
precision: {
|
69
|
+
format: {
|
70
|
+
delimiter: ""
|
71
|
+
}
|
72
|
+
},
|
73
|
+
human: {
|
74
|
+
format: {
|
75
|
+
delimiter: "",
|
76
|
+
precision: 3,
|
77
|
+
significant: true,
|
78
|
+
strip_insignificant_zeros: true
|
79
|
+
},
|
80
|
+
storage_units: {
|
81
|
+
format: "%n %u",
|
82
|
+
units: {
|
83
|
+
byte: {
|
84
|
+
one: "bajt",
|
85
|
+
other: "bajty"
|
86
|
+
},
|
87
|
+
kb: "KB",
|
88
|
+
mb: "MB",
|
89
|
+
gb: "GB",
|
90
|
+
tb: "TB"
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
},
|
95
|
+
|
96
|
+
world: "Świat"
|
97
|
+
}
|
98
|
+
}
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exvo_globalize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 5
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Pawe\xC5\x82 Go\xC5\x9Bcicki"
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-09-
|
18
|
+
date: 2011-09-14 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -389,7 +389,6 @@ files:
|
|
389
389
|
- lib/generators/exvo_globalize/install_generator.rb
|
390
390
|
- lib/generators/exvo_globalize/templates/migration.rb
|
391
391
|
- lib/tasks/dump.rake
|
392
|
-
- lib/tasks/jasmine.rake
|
393
392
|
- spec/app.rb
|
394
393
|
- spec/controllers/globalize_translations_controller_spec.rb
|
395
394
|
- spec/exvo_globalize/caching_spec.rb
|