exvo_globalize 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/README.md +48 -14
- data/app/assets/javascripts/exvo_globalize_i18n.js +176 -18
- data/config/locales/pl.yml +2 -1
- data/lib/exvo_globalize/version.rb +1 -1
- data/spec/javascripts/exvo_globalize_i18n_spec.js +44 -5
- data/spec/javascripts/fixtures/translations.js +29 -3
- metadata +4 -4
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,26 @@
|
|
1
1
|
# Exvo Globalize
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
Rails gem providing universal I18n support for your application. Supports I18n of both your normal Ruby/Rails app (based on the i18n gem) as well as javascript using a custom i18n library.
|
4
|
+
|
5
|
+
Ruby/Rails features:
|
6
|
+
|
7
|
+
* additional database backed I18n backend to store the translations
|
8
|
+
* in-memory caching of database backed translations
|
9
|
+
* pluralization rules for 108 languages (`config/locales/plurals.rb`)
|
10
|
+
* localization rules for 51 languages (`config/locales/*.(yml|rb)`)
|
11
|
+
* locale fallback support (will search for translation using `I18n.default_locale` when not found using requested locale)
|
12
|
+
* web UI to view your application’s translations (`/globalize/translations`)
|
13
|
+
|
14
|
+
Javascript features:
|
15
|
+
|
16
|
+
* all translations defined in `config/locales/*` are available in javascript
|
17
|
+
* localization support for dates, times, numbers, currencies (localization rules are read from `config/locales/*.(yml|rb)`)
|
18
|
+
* locale fallback support (will search for translation using `I18n.default_locale` when not found using requested locale)
|
19
|
+
* global t() and l() helpers to translate and localize phrases, respectively
|
20
|
+
* does not depend on any other external javascript library
|
21
|
+
|
22
|
+
|
23
|
+
This gem also integrates your application with [Globalize](http://store.exvo.com/apps/shops/globalize/items/globalize-125). Globalize is a service for website owners, who want to translate their websites into multiple languages by using human (as opposed to machine/automatic) translators.
|
5
24
|
|
6
25
|
|
7
26
|
|
@@ -137,7 +156,7 @@ I18n.strftime(I18n.parseDate("<%= Time.now %>"), "%Y/%m/%d %H:%M")
|
|
137
156
|
|
138
157
|
// uses formats from `config/locale/en.yml` file
|
139
158
|
I18n.l("date.formats.default", "Wed Sep 14 12:03:11 +0200 2011")
|
140
|
-
=> "
|
159
|
+
=> "2011-09-14"
|
141
160
|
|
142
161
|
I18n.l("date.formats.long", "2011-09-14")
|
143
162
|
=> "September 14, 2011"
|
@@ -165,7 +184,7 @@ $ bundle exec rake globalize:translations:dump:ruby
|
|
165
184
|
|
166
185
|
## Globalize integration
|
167
186
|
|
168
|
-
In order to fully integrate this gem with Globalize, after installing it you need to register your application
|
187
|
+
In order to fully integrate this gem with Globalize, after installing it you need to [register your application](http://store.exvo.com/apps/shops/globalize/items/globalize-125) and order some translations (Globalize should automatically detect the gem installation and should let you choose the JSON translations option).
|
169
188
|
|
170
189
|
By default a link between your application and Globalize is established by using `request.host` by the gem. If your application’s main DNS record is a CNAME (as is the common case when using Heroku), you can set your application’s domain in the `config/initializers/exvo_globalize.rb` file:
|
171
190
|
|
@@ -185,16 +204,31 @@ http://yourawesomewebapp.com/globalize/translations
|
|
185
204
|
And pressing `Update translations`.
|
186
205
|
|
187
206
|
|
207
|
+
### Caveats
|
188
208
|
|
189
|
-
|
209
|
+
* Adding or changing any existing translations requires application restart for those new updated translations to be visible (it is because of the caching mechanism, which does not currently support cache-invalidation).
|
210
|
+
* Heroku considerations: updating translations from Globalize, when there are many translations in many different languages is a time consuming process. Unfortunately Heroku has a habit of silently killing web processes running longer than a specified period of time (typically 30s). When that happenes your translations will be only partially updated. Best way to deal with that is to update them from `heroku console` using this script:
|
211
|
+
|
212
|
+
```ruby
|
213
|
+
ENV["GLOBALIZE_USE_PRODUCTION_SERVER"] = "true"
|
190
214
|
|
191
|
-
|
215
|
+
@globalize_app = GlobalizeApp.new("your-applications-host-registered-at-globalize")
|
216
|
+
|
217
|
+
translations = @globalize_app.fetch_translations
|
218
|
+
I18n.backend.store_nested_translations(translations)
|
219
|
+
```
|
220
|
+
|
221
|
+
|
222
|
+
|
223
|
+
## Running the specs
|
224
|
+
|
225
|
+
Running specs via `Guard` is the recommended way:
|
192
226
|
|
193
227
|
```bash
|
194
228
|
$ bundle exec guard
|
195
229
|
```
|
196
230
|
|
197
|
-
But
|
231
|
+
But specs can be run separately as well:
|
198
232
|
|
199
233
|
```bash
|
200
234
|
$ bundle exec rspec spec
|
@@ -206,18 +240,18 @@ and
|
|
206
240
|
$ jasmine-headless-webkit -c
|
207
241
|
```
|
208
242
|
|
209
|
-
There is a great guide for setting up `jasmine-headless-webkit` in your OS if you have problems with it
|
210
|
-
http://johnbintz.github.com/jasmine-headless-webkit/
|
243
|
+
There is a [great guide](http://johnbintz.github.com/jasmine-headless-webkit/) for setting up `jasmine-headless-webkit` in your OS if you have problems with it.
|
211
244
|
|
212
245
|
|
213
246
|
|
214
247
|
## Copyrights
|
215
248
|
|
216
|
-
exvo_globalize is based on the following projects:
|
217
|
-
|
218
|
-
https://github.com/svenfuchs/
|
219
|
-
https://github.com/
|
220
|
-
https://github.com/
|
249
|
+
[exvo_globalize](https://github.com/Exvo/exvo_globalize/) is based on the following projects:
|
250
|
+
|
251
|
+
* [i18n](https://github.com/svenfuchs/i18n)
|
252
|
+
* [rails-i18n](https://github.com/svenfuchs/rails-i18n/)
|
253
|
+
* [babilu](https://github.com/toretore/babilu)
|
254
|
+
* [i18n-js](https://github.com/spider-network/i18n-js)
|
221
255
|
|
222
256
|
|
223
257
|
Copyright © 2011 Exvo.com Development BV, released under the MIT license
|
@@ -1,24 +1,39 @@
|
|
1
|
+
//
|
2
|
+
// exvo_globalize_i18n.js
|
3
|
+
// Version: 0.5.1
|
4
|
+
//
|
1
5
|
(function() {
|
2
6
|
|
3
7
|
I18n = {};
|
4
8
|
|
9
|
+
// Check if an Array contains an object
|
10
|
+
function isInArray(a, obj) {
|
11
|
+
var i = a.length;
|
12
|
+
while (i--) {
|
13
|
+
if (a[i] === obj) {
|
14
|
+
return true;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
return false;
|
18
|
+
};
|
19
|
+
|
5
20
|
var interpolatePattern = /%\{([^}]+)\}/g;
|
6
21
|
|
7
22
|
// Replace %{foo} with obj.foo
|
8
|
-
function
|
23
|
+
I18n.interpolate = function(str, obj) {
|
9
24
|
return str.replace(interpolatePattern, function() {
|
10
25
|
return typeof obj[arguments[1]] == 'undefined' ? arguments[0] : obj[arguments[1]];
|
11
26
|
});
|
12
27
|
};
|
13
28
|
|
14
29
|
// Split "foo.bar" to ["foo", "bar"] if key is a string
|
15
|
-
function
|
30
|
+
I18n.keyToArray = function(key) {
|
16
31
|
if (!key) return [];
|
17
32
|
if (typeof key != "string") return key;
|
18
33
|
return key.split('.');
|
19
34
|
};
|
20
35
|
|
21
|
-
function
|
36
|
+
I18n.current_locale = function() {
|
22
37
|
return I18n.locale || I18n.defaultLocale;
|
23
38
|
};
|
24
39
|
|
@@ -70,14 +85,14 @@
|
|
70
85
|
} else {
|
71
86
|
opts = opts || {};
|
72
87
|
opts.defaultValue = opts.defaultValue || null;
|
73
|
-
key = keyToArray(opts.scope).concat(keyToArray(key));
|
74
|
-
var value = this.lookup(
|
88
|
+
key = I18n.keyToArray(opts.scope).concat(I18n.keyToArray(key));
|
89
|
+
var value = this.lookup(I18n.current_locale(), key, opts.defaultValue);
|
75
90
|
|
76
91
|
// fall back to I18n.default_locale for missing translations
|
77
92
|
if (value == null && I18n.locale != I18n.default_locale) value = this.lookup(I18n.default_locale, key, opts.defaultLocale);
|
78
93
|
|
79
94
|
if (typeof value != "string" && value) value = this.pluralize(value, opts.count);
|
80
|
-
if (typeof value == "string") value = interpolate(value, opts);
|
95
|
+
if (typeof value == "string") value = I18n.interpolate(value, opts);
|
81
96
|
if (value == null) value = this.missingTranslation(key)
|
82
97
|
return value;
|
83
98
|
}
|
@@ -104,7 +119,7 @@
|
|
104
119
|
if (defaults.length == 0) {
|
105
120
|
return null;
|
106
121
|
} 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));
|
122
|
+
return this.lookup(locale, keys.slice(0, keys.length - 1).concat(I18n.keyToArray(defaults[0].substr(1))), defaults.slice(1));
|
108
123
|
} else {
|
109
124
|
return defaults[0];
|
110
125
|
}
|
@@ -116,7 +131,7 @@
|
|
116
131
|
case "currency":
|
117
132
|
return this.toCurrency(value);
|
118
133
|
case "number":
|
119
|
-
scope = this.lookup(
|
134
|
+
scope = this.lookup(I18n.current_locale(), ["number", "format"]);
|
120
135
|
return this.toNumber(value, scope);
|
121
136
|
case "percentage":
|
122
137
|
return this.toPercentage(value);
|
@@ -164,7 +179,7 @@
|
|
164
179
|
|
165
180
|
I18n.toTime = function(scope, d) {
|
166
181
|
var date = this.parseDate(d);
|
167
|
-
var format = this.lookup(
|
182
|
+
var format = this.lookup(I18n.current_locale(), I18n.keyToArray(scope));
|
168
183
|
|
169
184
|
if (date.toString().match(/invalid/i)) {
|
170
185
|
return date.toString();
|
@@ -178,14 +193,14 @@
|
|
178
193
|
};
|
179
194
|
|
180
195
|
I18n.strftime = function(date, format) {
|
181
|
-
var options = this.lookup(
|
196
|
+
var options = this.lookup(I18n.current_locale(), ["date"]);
|
182
197
|
|
183
198
|
if (!options) {
|
184
199
|
return date.toString();
|
185
200
|
}
|
186
201
|
|
187
202
|
// get meridian from ":time" i18n key
|
188
|
-
options.time = this.lookup(
|
203
|
+
options.time = this.lookup(I18n.current_locale(), ["time"]);
|
189
204
|
if (!options.time || !options.time.am || !options.time.pm) {
|
190
205
|
options.time = { am: "AM", pm: "PM" };
|
191
206
|
}
|
@@ -245,7 +260,7 @@
|
|
245
260
|
I18n.toNumber = function(number, options) {
|
246
261
|
options = this.prepareOptions(
|
247
262
|
options,
|
248
|
-
this.lookup(
|
263
|
+
this.lookup(I18n.current_locale(), ["number", "format"]),
|
249
264
|
{precision: 3, separator: ".", delimiter: ",", strip_insignificant_zeros: false}
|
250
265
|
);
|
251
266
|
|
@@ -290,8 +305,8 @@
|
|
290
305
|
I18n.toCurrency = function(number, options) {
|
291
306
|
options = this.prepareOptions(
|
292
307
|
options,
|
293
|
-
this.lookup(
|
294
|
-
this.lookup(
|
308
|
+
this.lookup(I18n.current_locale(), ["number", "currency", "format"]),
|
309
|
+
this.lookup(I18n.current_locale(), ["number", "format"]),
|
295
310
|
{unit: "$", precision: 2, format: "%u%n", delimiter: ",", separator: "."}
|
296
311
|
);
|
297
312
|
|
@@ -340,8 +355,8 @@
|
|
340
355
|
I18n.toPercentage = function(number, options) {
|
341
356
|
options = this.prepareOptions(
|
342
357
|
options,
|
343
|
-
this.lookup(
|
344
|
-
this.lookup(
|
358
|
+
this.lookup(I18n.current_locale(), ["number", "percentage", "format"]),
|
359
|
+
this.lookup(I18n.current_locale(), ["number", "format"]),
|
345
360
|
{precision: 3, separator: ".", delimiter: ""}
|
346
361
|
);
|
347
362
|
|
@@ -349,14 +364,157 @@
|
|
349
364
|
return number + "%";
|
350
365
|
};
|
351
366
|
|
367
|
+
// Pluralization function
|
352
368
|
I18n.pluralize = function(value, count) {
|
353
369
|
if (typeof count != 'number') return value;
|
354
|
-
return
|
370
|
+
return I18n.plurals[I18n.current_locale()](value, count);
|
355
371
|
};
|
356
372
|
|
373
|
+
// Default pluralization rules
|
374
|
+
I18n.default_pluralization_rule = function(value, count) {
|
375
|
+
return count == 1 ? value.one : value.other;
|
376
|
+
}
|
377
|
+
I18n.other_default_pluralization_rule = function(value, count) {
|
378
|
+
return count == 1 || count == 0 ? value.one : value.other;
|
379
|
+
}
|
380
|
+
|
381
|
+
// Pluralization Rules for each language
|
382
|
+
I18n.plurals = {
|
383
|
+
"af": I18n.default_pluralization_rule,
|
384
|
+
"am": I18n.other_default_pluralization_rule,
|
385
|
+
"ar": function(value, count) {
|
386
|
+
if (typeof count != 'number') return value;
|
387
|
+
return count == 0 ? value.zero : count == 1 ? value.one : count == 2 ? value.two : isInArray([3, 4, 5, 6, 7, 8, 9, 10], count % 100) ? value.few : isInArray([3, 4, 5, 6, 7, 8, 9, 10], count % 100) ? value.few : isInArray([11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99], count % 100) ? value.many : value.other;
|
388
|
+
},
|
389
|
+
"az": function(value, count) { return value.other; },
|
390
|
+
"be": function(value, count) {
|
391
|
+
return count % 10 == 1 && count % 100 != 11 ? value.one : isInArray([2,3,4], count % 10) && !isInArray([12,13,14], count % 100) ? value.few : count % 10 == 0 || isInArray([5,6,7,8,9], count % 10) || isInArray([11,12,13,14], count % 100) ? value.many : valye.other;
|
392
|
+
},
|
393
|
+
"bg": I18n.default_pluralization_rule,
|
394
|
+
"bh": I18n.default_pluralization_rule,
|
395
|
+
"bn": I18n.default_pluralization_rule,
|
396
|
+
"bo": function(value, count) { return value.other; },
|
397
|
+
"bs": function(value, count) {
|
398
|
+
return count % 10 == 1 && count % 100 != 11 ? value.one : isInArray([2,3,4], count % 10) && !isInArray([12,13,14], count % 100) ? value.few : count % 10 == 0 || isInArray([5,6,7,8,9], count % 10) || isInArray([11,12,13,14], count % 100) ? value.many : value.other;
|
399
|
+
},
|
400
|
+
"ca": I18n.default_pluralization_rule,
|
401
|
+
"cs": function(value, count) { return count == 1 ? value.one : isInArray([2,3,4], count) ? value.few : value.other; },
|
402
|
+
"cy": function(value, count) { return count == 1 ? value.one : count == 2 ? value.two : count == 8 || count == 11 ? value.many : value.other; },
|
403
|
+
"da": I18n.default_pluralization_rule,
|
404
|
+
"de": I18n.default_pluralization_rule,
|
405
|
+
"dz": function(value, count) { return value.other; },
|
406
|
+
"el": I18n.default_pluralization_rule,
|
407
|
+
"en": I18n.default_pluralization_rule,
|
408
|
+
"eo": I18n.default_pluralization_rule,
|
409
|
+
"es": I18n.default_pluralization_rule,
|
410
|
+
"et": I18n.default_pluralization_rule,
|
411
|
+
"eu": I18n.default_pluralization_rule,
|
412
|
+
"fa": function(value, count) { return value.other; },
|
413
|
+
"fi": I18n.default_pluralization_rule,
|
414
|
+
"fil": I18n.other_default_pluralization_rule,
|
415
|
+
"fo": I18n.default_pluralization_rule,
|
416
|
+
"fr": function(value, count) { return isInArray([0,1], count) ? value.one : value.other; },
|
417
|
+
"fur": I18n.default_pluralization_rule,
|
418
|
+
"fy": I18n.default_pluralization_rule,
|
419
|
+
"ga": function(value, count) { return count == 1 ? value.one : count == 2 ? value.two : value.other; },
|
420
|
+
"gl": I18n.default_pluralization_rule,
|
421
|
+
"gu": I18n.default_pluralization_rule,
|
422
|
+
"guw": I18n.other_default_pluralization_rule,
|
423
|
+
"ha": I18n.default_pluralization_rule,
|
424
|
+
"he": I18n.default_pluralization_rule,
|
425
|
+
"hi": I18n.other_default_pluralization_rule,
|
426
|
+
"hr": function(value, count) {
|
427
|
+
return count % 10 == 1 && count % 100 != 11 ? value.one : isInArray([2,3,4], count % 10) && !isInArray([12,13,14], count % 100) ? value.few : count % 10 == 0 || isInArray([5,6,7,8,9], count % 10) || isInArray([11,12,13,14], count % 100) ? value.many : value.other;
|
428
|
+
},
|
429
|
+
"hu": function(value, count) { return value.other; },
|
430
|
+
"id": function(value, count) { return value.other; },
|
431
|
+
"is": I18n.default_pluralization_rule,
|
432
|
+
"it": I18n.default_pluralization_rule,
|
433
|
+
"iw": I18n.default_pluralization_rule,
|
434
|
+
"ja": function(value, count) { return value.other; },
|
435
|
+
"jv": function(value, count) { return value.other; },
|
436
|
+
"ka": function(value, count) { return value.other; },
|
437
|
+
"km": function(value, count) { return value.other; },
|
438
|
+
"kn": function(value, count) { return value.other; },
|
439
|
+
"ko": function(value, count) { return value.other; },
|
440
|
+
"ku": I18n.default_pluralization_rule,
|
441
|
+
"lb": I18n.default_pluralization_rule,
|
442
|
+
"ln": I18n.other_default_pluralization_rule,
|
443
|
+
"lt": function(value, count) {
|
444
|
+
return count % 10 == 1 && ! isInArray([11, 12, 13, 14, 15, 16, 17, 18, 19], count % 100) ? value.one : isInArray([2, 3, 4, 5, 6, 7, 8, 9], count % 10) && ! isInArray([11, 12, 13, 14, 15, 16, 17, 18, 19], count % 100) ? value.few : value.other;
|
445
|
+
},
|
446
|
+
"lv": function(value, count) { return count == 0 ? value.zero : count % 10 == 1 && count % 100 != 11 ? value.one : value.other; },
|
447
|
+
"mg": I18n.default_pluralization_rule,
|
448
|
+
"mk": function(value, count) { return count % 10 == 1 ? value.one : value.other; },
|
449
|
+
"ml": I18n.default_pluralization_rule,
|
450
|
+
"mn": I18n.default_pluralization_rule,
|
451
|
+
"mo": function(value, count) { return count ==1 ? value.one : count == 0 ? value.few : value.other; },
|
452
|
+
"mr": I18n.default_pluralization_rule,
|
453
|
+
"ms": function(value, count) { return value.other; },
|
454
|
+
"mt": function(value, count) {
|
455
|
+
return count == 1 ? value.one : count == 0 || isInArray([2,3,4,5,6,7,8,9,10], count % 100) ? value.few : isInArray([11,12,13,14,15,16,17,18,19], count % 100) ? value.many : value.other;
|
456
|
+
},
|
457
|
+
"my": function(value, count) { return value.other; },
|
458
|
+
"nah": I18n.default_pluralization_rule,
|
459
|
+
"nb": I18n.default_pluralization_rule,
|
460
|
+
"ne": I18n.default_pluralization_rule,
|
461
|
+
"nl": I18n.default_pluralization_rule,
|
462
|
+
"nn": I18n.default_pluralization_rule,
|
463
|
+
"no": I18n.default_pluralization_rule,
|
464
|
+
"nso": I18n.other_default_pluralization_rule,
|
465
|
+
"or": I18n.default_pluralization_rule,
|
466
|
+
"pa": I18n.default_pluralization_rule,
|
467
|
+
"pap": I18n.default_pluralization_rule,
|
468
|
+
"pl": function(value, count) {
|
469
|
+
return count == 1 ? value.one : isInArray([2,3,4], count % 10) && !isInArray([12,13,14], count % 100) ? value.few : value.other;
|
470
|
+
},
|
471
|
+
"ps": I18n.default_pluralization_rule,
|
472
|
+
"pt": I18n.other_default_pluralization_rule,
|
473
|
+
"pt-PT": I18n.default_pluralization_rule,
|
474
|
+
"ro": function(value, count) { return count == 1 ? value.one : count == 0 ? value.few : value.other; },
|
475
|
+
"ru": function(value, count) {
|
476
|
+
return count % 10 == 1 && count % 100 != 11 ? value.one : isInArray([2,3,4], count % 10) && !isInArray([12,13,14], count % 100) ? value.few : count % 10 == 0 || isInArray([5,6,7,8,9], count % 10) || isInArray([11,12,13,14], count % 100) ? value.many : value.other;
|
477
|
+
},
|
478
|
+
"se": function(value, count) { return count == 1 ? value.one : count == 2 ? value.two : value.other; },
|
479
|
+
"sh": function(value, count) {
|
480
|
+
return count % 10 == 1 && count % 100 != 11 ? value.one : isInArray([2,3,4], count % 10) && !isInArray([12,13,14], count % 100) ? value.few : count % 10 == 0 || isInArray([5,6,7,8,9], count % 10) || isInArray([11,12,13,14], count % 100) ? value.many : value.other;
|
481
|
+
},
|
482
|
+
"sk": function(value, count) { return count == 1 ? value.one : isInArray([2,3,4], count) ? valuer.few : value.other; },
|
483
|
+
"sl": function(value, count) { return count % 100 == 1 ? value.one : count % 100 == 2 ? value.two : isInArray([3,4], count % 100) ? value.few : value.other; },
|
484
|
+
"sma": function(value, count) { return count == 1 ? value.one : count == 2 ? value.two : value.other; },
|
485
|
+
"smi": function(value, count) { return count == 1 ? value.one : count == 2 ? value.two : value.other; },
|
486
|
+
"smj": function(value, count) { return count == 1 ? value.one : count == 2 ? value.two : value.other; },
|
487
|
+
"smn": function(value, count) { return count == 1 ? value.one : count == 2 ? value.two : value.other; },
|
488
|
+
"sms": function(value, count) { return count == 1 ? value.one : count == 2 ? value.two : value.other; },
|
489
|
+
"so": I18n.default_pluralization_rule,
|
490
|
+
"sq": I18n.default_pluralization_rule,
|
491
|
+
"sr": function(value, count) {
|
492
|
+
return count % 10 == 1 && count % 100 != 11 ? value.one : isInArray([2,3,4], count % 10) && ! isInArray([12,13,14], count % 100) ? value.few : count % 10 == 0 || isInArray([5,6,7,8,9], count % 10) || isInArray([11,12,13,14], count % 100) ? value.many : value.other;
|
493
|
+
},
|
494
|
+
"sv": I18n.default_pluralization_rule,
|
495
|
+
"sw": I18n.default_pluralization_rule,
|
496
|
+
"ta": I18n.default_pluralization_rule,
|
497
|
+
"te": I18n.default_pluralization_rule,
|
498
|
+
"th": function(value, count) { return value.other; },
|
499
|
+
"ti": I18n.other_default_pluralization_rule,
|
500
|
+
"tk": I18n.default_pluralization_rule,
|
501
|
+
"tl": I18n.other_default_pluralization_rule,
|
502
|
+
"to": function(value, count) { return value.other; },
|
503
|
+
"tr": function(value, count) { return value.other; },
|
504
|
+
"uk": function(value, count) {
|
505
|
+
return count % 10 == 1 && count % 100 != 11 ? value.one : isInArray([2,3,4], count % 10) && !isInArray([12,13,14], count % 100) ? value.few : count % 10 == 0 || isInArray([5,6,7,8,9], count % 10) || isInArray([11,12,13,14], count % 100) ? value.many : value.other;
|
506
|
+
},
|
507
|
+
"ur": I18n.default_pluralization_rule,
|
508
|
+
"vi": function(value, count) { return value.other; },
|
509
|
+
"wa": I18n.other_default_pluralization_rule,
|
510
|
+
"yo": function(value, count) { return value.other; },
|
511
|
+
"zh": function(value, count) { return value.other; },
|
512
|
+
"zu": I18n.default_pluralization_rule
|
513
|
+
}
|
514
|
+
|
357
515
|
// Returns '[missing translation: "en.missing"]' when translation is not found
|
358
516
|
I18n.missingTranslation = function(key) {
|
359
|
-
var message = '[missing translation: "' +
|
517
|
+
var message = '[missing translation: "' + I18n.current_locale();
|
360
518
|
for (var i in key) {
|
361
519
|
message += "." + key[i];
|
362
520
|
}
|
data/config/locales/pl.yml
CHANGED
@@ -164,11 +164,13 @@ describe("Localization of human sizes", function() {
|
|
164
164
|
I18n.locale = "pl"
|
165
165
|
})
|
166
166
|
|
167
|
-
it("localizes numbers in human sizes", function() {
|
167
|
+
it("localizes numbers in human sizes using pluralization rules", function() {
|
168
168
|
kb = 1024
|
169
169
|
|
170
170
|
expect(I18n.toHumanSize(1)).toEqual("1bajt")
|
171
|
-
expect(I18n.toHumanSize(
|
171
|
+
expect(I18n.toHumanSize(5)).toEqual("5bajtów")
|
172
|
+
expect(I18n.toHumanSize(12)).toEqual("12bajtów")
|
173
|
+
expect(I18n.toHumanSize(22)).toEqual("22bajty")
|
172
174
|
|
173
175
|
expect(I18n.toHumanSize(kb)).toEqual("1KB")
|
174
176
|
expect(I18n.toHumanSize(kb * 1.5)).toEqual("1,5KB")
|
@@ -365,8 +367,9 @@ describe("Date parsing", function() {
|
|
365
367
|
expect(I18n.strftime(date, "%I")).toEqual("12")
|
366
368
|
})
|
367
369
|
|
368
|
-
it("parses and formats a Ruby Time.now.to_s string
|
369
|
-
|
370
|
+
it("parses and formats a Ruby Time.now.to_s string", function() {
|
371
|
+
// the `Time.now` string below is devoid of timezone information; this way this test can pass in different timezones
|
372
|
+
expect(I18n.strftime(I18n.parseDate("Wed Sep 14 12:03:11 2011"), "%Y/%m/%d %H:%M")).toEqual("2011/09/14 12:03")
|
370
373
|
})
|
371
374
|
|
372
375
|
it("localizes date strings", function() {
|
@@ -376,9 +379,45 @@ describe("Date parsing", function() {
|
|
376
379
|
})
|
377
380
|
|
378
381
|
it("localizes time strings", function() {
|
379
|
-
expect(I18n.l("time.formats.default", "2009-11-29 15:07:59")).
|
382
|
+
expect(I18n.l("time.formats.default", "2009-11-29 15:07:59")).toMatch("nie, 29 lis 2009 15:07:59")
|
380
383
|
expect(I18n.l("time.formats.short", "2009-01-07 09:12:35")).toEqual("07 sty 09:12")
|
381
384
|
expect(I18n.l("time.formats.long", "2009-11-29 15:07:59")).toEqual("listopad 29, 2009 15:07")
|
382
385
|
})
|
383
386
|
|
384
387
|
})
|
388
|
+
|
389
|
+
describe("Pluralizations", function() {
|
390
|
+
|
391
|
+
it("correctly pluralizes the English phrase", function() {
|
392
|
+
I18n.locale = "en"
|
393
|
+
expect(I18n.t("contact", {count: 1})).toEqual("1 Contact")
|
394
|
+
expect(I18n.t("contact", {count: 2})).toEqual("2 Contacts")
|
395
|
+
expect(I18n.t("contact", {count: 22})).toEqual("22 Contacts")
|
396
|
+
})
|
397
|
+
|
398
|
+
it("correctly pluralizes the French phrase", function() {
|
399
|
+
I18n.locale = "fr"
|
400
|
+
expect(I18n.t("contact", {count: 0})).toEqual("0 contact")
|
401
|
+
expect(I18n.t("contact", {count: 1})).toEqual("1 contact")
|
402
|
+
expect(I18n.t("contact", {count: 2})).toEqual("2 contacts")
|
403
|
+
expect(I18n.t("contact", {count: 5})).toEqual("5 contacts")
|
404
|
+
})
|
405
|
+
|
406
|
+
it("correctly pluralizes the Polish phrase", function() {
|
407
|
+
I18n.locale = "pl"
|
408
|
+
expect(I18n.t("contact", {count: 1})).toEqual("1 Kontakt")
|
409
|
+
expect(I18n.t("contact", {count: 2})).toEqual("2 Kontakty")
|
410
|
+
expect(I18n.t("contact", {count: 5})).toEqual("5 Kontaktów")
|
411
|
+
expect(I18n.t("contact", {count: 12})).toEqual("12 Kontaktów")
|
412
|
+
expect(I18n.t("contact", {count: 22})).toEqual("22 Kontakty")
|
413
|
+
})
|
414
|
+
|
415
|
+
it("correctly pluralizes the Portuguese phrase", function() {
|
416
|
+
I18n.locale = "pt"
|
417
|
+
expect(I18n.t("contact", {count: 0})).toEqual("0 Contato")
|
418
|
+
expect(I18n.t("contact", {count: 1})).toEqual("1 Contato")
|
419
|
+
expect(I18n.t("contact", {count: 2})).toEqual("2 Contatos")
|
420
|
+
expect(I18n.t("contact", {count: 22})).toEqual("22 Contatos")
|
421
|
+
})
|
422
|
+
|
423
|
+
})
|
@@ -7,6 +7,11 @@ I18n.translations = {
|
|
7
7
|
hello: "Hello %{name}!",
|
8
8
|
world: "World",
|
9
9
|
|
10
|
+
contact: {
|
11
|
+
one: "1 Contact",
|
12
|
+
other: "%{count} Contacts"
|
13
|
+
},
|
14
|
+
|
10
15
|
page: {
|
11
16
|
footer: "Footer",
|
12
17
|
title: "Title",
|
@@ -17,6 +22,13 @@ I18n.translations = {
|
|
17
22
|
}
|
18
23
|
},
|
19
24
|
|
25
|
+
fr: {
|
26
|
+
contact: {
|
27
|
+
one: "%{count} contact",
|
28
|
+
other: "%{count} contacts"
|
29
|
+
}
|
30
|
+
},
|
31
|
+
|
20
32
|
pl: {
|
21
33
|
date: {
|
22
34
|
formats: {
|
@@ -81,8 +93,9 @@ I18n.translations = {
|
|
81
93
|
format: "%n %u",
|
82
94
|
units: {
|
83
95
|
byte: {
|
84
|
-
one:
|
85
|
-
|
96
|
+
one: "bajt",
|
97
|
+
few: "bajty",
|
98
|
+
other: "bajtów"
|
86
99
|
},
|
87
100
|
kb: "KB",
|
88
101
|
mb: "MB",
|
@@ -93,6 +106,19 @@ I18n.translations = {
|
|
93
106
|
}
|
94
107
|
},
|
95
108
|
|
96
|
-
world: "Świat"
|
109
|
+
world: "Świat",
|
110
|
+
|
111
|
+
contact: {
|
112
|
+
one: "1 Kontakt",
|
113
|
+
few: "%{count} Kontakty",
|
114
|
+
other: "%{count} Kontaktów"
|
115
|
+
}
|
116
|
+
},
|
117
|
+
|
118
|
+
pt: {
|
119
|
+
contact: {
|
120
|
+
one: "%{count} Contato",
|
121
|
+
other: "%{count} Contatos"
|
122
|
+
}
|
97
123
|
}
|
98
124
|
}
|
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: 9
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 5
|
9
|
-
-
|
10
|
-
version: 0.5.
|
9
|
+
- 1
|
10
|
+
version: 0.5.1
|
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-19 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|