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 CHANGED
@@ -1,5 +1,6 @@
1
1
  *.gem
2
2
  .bundle
3
+ .jhw-cache
3
4
  Gemfile.lock
4
5
  pkg/*
5
6
  log/*
data/README.md CHANGED
@@ -1,7 +1,26 @@
1
1
  # Exvo Globalize
2
2
 
3
- This gem lets you make use of the Globalize app (http://globalize.exvo.com/)
4
- to handle the translation of your Rails app into multiple languages.
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
- => "14-09-2011"
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 (http://globalize.exvo.com/) and order some translations (Globalize should automatically detect the gem installation and should let you choose the JSON translations option).
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
- ## Running the tests
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
- Running tests via `Guard` is the recommended way:
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 tests can be run separately as well:
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
- 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
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 interpolate(str, obj) {
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 keyToArray(key) {
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 locale() {
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(locale(), key, opts.defaultValue);
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(locale(), ["number", "format"]);
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(locale(), keyToArray(scope));
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(locale(), ["date"]);
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(locale(), ["time"]);
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(locale(), ["number", "format"]),
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(locale(), ["number", "currency", "format"]),
294
- this.lookup(locale(), ["number", "format"]),
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(locale(), ["number", "percentage", "format"]),
344
- this.lookup(locale(), ["number", "format"]),
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 count == 1 ? value.one : value.other;
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: "' + locale();
517
+ var message = '[missing translation: "' + I18n.current_locale();
360
518
  for (var i in key) {
361
519
  message += "." + key[i];
362
520
  }
@@ -114,7 +114,8 @@ pl:
114
114
  units:
115
115
  byte:
116
116
  one: "bajt"
117
- other: "bajty"
117
+ few: "bajty"
118
+ other: "bajtów"
118
119
  kb: "KB"
119
120
  mb: "MB"
120
121
  gb: "GB"
@@ -1,3 +1,3 @@
1
1
  module ExvoGlobalize
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.1"
3
3
  end
@@ -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(102)).toEqual("102bajty")
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 ", 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
+ 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")).toEqual("nie, 29 lis 2009 15:07:59 +0100")
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: "bajt",
85
- other: "bajty"
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: 11
4
+ hash: 9
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 0
10
- version: 0.5.0
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-14 00:00:00 +02:00
18
+ date: 2011-09-19 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency