exvo_globalize 0.4.0 → 0.5.0
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.
- 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
|