Skip to content
This repository
Browse code

Merge pull request #5 from karalis/master

we can have meta translations in the translation bar
  • Loading branch information...
commit 83d18caca9f27e55c1f966b72dd0e25f68b51a38 2 parents 10971f6 + 1dd88f2
Ignazio Mostallino authored July 18, 2011
1  Gemfile
@@ -19,6 +19,7 @@ gem 'uglifier'
19 19
 gem 'execjs'
20 20
 gem 'jquery-rails'
21 21
 gem 'sass-rails'
  22
+gem "i18n-js", :git => "https://github.com/fnando/i18n-js.git"
22 23
 
23 24
 if RUBY_VERSION < '1.9'
24 25
   gem "ruby-debug", ">= 0.10.3"
8  Gemfile.lock
... ...
@@ -1,3 +1,10 @@
  1
+GIT
  2
+  remote: https://github.com/fnando/i18n-js.git
  3
+  revision: c560abc4b52d28fe4839cc95421430ebfc4c0a69
  4
+  specs:
  5
+    i18n-js (1.0.2)
  6
+      i18n
  7
+
1 8
 GEM
2 9
   remote: http://rubygems.org/
3 10
   specs:
@@ -167,6 +174,7 @@ DEPENDENCIES
167 174
   database_cleaner
168 175
   execjs
169 176
   factory_girl_rails (~> 1.1.beta1)
  177
+  i18n-js!
170 178
   jquery-rails
171 179
   launchy
172 180
   rails (= 3.1.0.rc4)
14  app/assets/javascripts/lost-i18n-translation.js
... ...
@@ -1,17 +1,23 @@
1 1
 $(document).ready(function() {
  2
+  //FIXME: find a way to set these dynamically 
  3
+  I18n.defaultLocale = "en";
  4
+  I18n.locale = "en";
  5
+
2 6
   var $translation_missing_count = $('.translation_missing').length;
3 7
   var $translation_present_count = $('.translation_present').length;
4 8
 
5 9
   var $newdiv = $('<div id="lost-i18n-translation-div"/>');
  10
+  var sep = " | "
  11
+  $newdiv.append("Current locale : " + I18n.currentLocale() + sep);
6 12
 
7 13
   var $tr_missing = $('<span id="lost-i18n-translation-tr-missing-count" />');
8  
-  $tr_missing.append( $translation_missing_count );
9  
-  $newdiv.append("Missing translations: " , $tr_missing );
10  
-
  14
+  $tr_missing.append( $translation_missing_count + sep);
  15
+  $newdiv.append(I18n.t("lost_i18n_translation.missing_label") + ": " , $tr_missing);
  16
+  
11 17
 
12 18
   var $tr_present = $('<span id="lost-i18n-translation-tr-present-count" />');
13 19
   $tr_present.append( $translation_present_count );
14  
-  $newdiv.append("Present translations: ", $tr_present  );
  20
+  $newdiv.append(I18n.t("lost_i18n_translation.present_label") + ": ", $tr_present);
15 21
 
16 22
   $('body').append($newdiv);
17 23
 });
4  config/i18n-js.yml
... ...
@@ -0,0 +1,4 @@
  1
+# Find more details about this configuration file at http://github.com/fnando/i18n-js
  2
+translations:
  3
+  - file: "public/javascripts/translations.js"
  4
+    only: "*"
4  config/locales/lost_i18n_translation.en.yml
... ...
@@ -0,0 +1,4 @@
  1
+en:
  2
+  lost_i18n_translation:
  3
+    missing_label: "Missing translations"
  4
+    present_label: "Present translations"
2  spec/dummy/app/assets/javascripts/application.js
@@ -8,3 +8,5 @@
8 8
 //= require jquery_ujs
9 9
 //= require_tree .
10 10
 //= require lost-i18n-translation
  11
+//= require i18n
  12
+//= require translations
6  spec/dummy/app/controllers/application_controller.rb
... ...
@@ -1,3 +1,9 @@
1 1
 class ApplicationController < ActionController::Base
2 2
   protect_from_forgery
  3
+  before_filter :export_i18n_messages
  4
+
  5
+  private
  6
+  def export_i18n_messages
  7
+    SimplesIdeias::I18n.export! if Rails.env.development?
  8
+  end
3 9
 end
2  spec/dummy/public/javascripts/translations.js
... ...
@@ -0,0 +1,2 @@
  1
+var I18n = I18n || {};
  2
+I18n.translations = {"en":{"date":{"formats":{"default":"%Y-%m-%d","short":"%b %d","long":"%B %d, %Y"},"day_names":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"abbr_day_names":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"month_names":[null,"January","February","March","April","May","June","July","August","September","October","November","December"],"abbr_month_names":[null,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"order":["year","month","day"]},"time":{"formats":{"default":"%a, %d %b %Y %H:%M:%S %z","short":"%d %b %H:%M","long":"%B %d, %Y %H:%M"},"am":"am","pm":"pm"},"support":{"array":{"words_connector":", ","two_words_connector":" and ","last_word_connector":", and "}},"errors":{"format":"%{attribute} %{message}","messages":{"inclusion":"is not included in the list","exclusion":"is reserved","invalid":"is invalid","confirmation":"doesn't match confirmation","accepted":"must be accepted","empty":"can't be empty","blank":"can't be blank","too_long":"is too long (maximum is %{count} characters)","too_short":"is too short (minimum is %{count} characters)","wrong_length":"is the wrong length (should be %{count} characters)","not_a_number":"is not a number","not_an_integer":"must be an integer","greater_than":"must be greater than %{count}","greater_than_or_equal_to":"must be greater than or equal to %{count}","equal_to":"must be equal to %{count}","less_than":"must be less than %{count}","less_than_or_equal_to":"must be less than or equal to %{count}","odd":"must be odd","even":"must be even"}},"activerecord":{"errors":{"messages":{"taken":"has already been taken","record_invalid":"Validation failed: %{errors}"}}},"number":{"format":{"separator":".","delimiter":",","precision":3,"significant":false,"strip_insignificant_zeros":false},"currency":{"format":{"format":"%u%n","unit":"$","separator":".","delimiter":",","precision":2,"significant":false,"strip_insignificant_zeros":false}},"percentage":{"format":{"delimiter":""}},"precision":{"format":{"delimiter":""}},"human":{"format":{"delimiter":"","precision":3,"significant":true,"strip_insignificant_zeros":true},"storage_units":{"format":"%n %u","units":{"byte":{"one":"Byte","other":"Bytes"},"kb":"KB","mb":"MB","gb":"GB","tb":"TB"}},"decimal_units":{"format":"%n %u","units":{"unit":"","thousand":"Thousand","million":"Million","billion":"Billion","trillion":"Trillion","quadrillion":"Quadrillion"}}}},"datetime":{"distance_in_words":{"half_a_minute":"half a minute","less_than_x_seconds":{"one":"less than 1 second","other":"less than %{count} seconds"},"x_seconds":{"one":"1 second","other":"%{count} seconds"},"less_than_x_minutes":{"one":"less than a minute","other":"less than %{count} minutes"},"x_minutes":{"one":"1 minute","other":"%{count} minutes"},"about_x_hours":{"one":"about 1 hour","other":"about %{count} hours"},"x_days":{"one":"1 day","other":"%{count} days"},"about_x_months":{"one":"about 1 month","other":"about %{count} months"},"x_months":{"one":"1 month","other":"%{count} months"},"about_x_years":{"one":"about 1 year","other":"about %{count} years"},"over_x_years":{"one":"over 1 year","other":"over %{count} years"},"almost_x_years":{"one":"almost 1 year","other":"almost %{count} years"}},"prompts":{"year":"Year","month":"Month","day":"Day","hour":"Hour","minute":"Minute","second":"Seconds"}},"helpers":{"select":{"prompt":"Please select"},"submit":{"create":"Create %{model}","update":"Update %{model}","submit":"Save %{model}"}},"lost_i18n_translation":{"missing_label":"Missing translations","present_label":"Present translations"},"hello":"Hello world"}};
2  spec/dummy/vendor/assets/javascripts/translations.js
... ...
@@ -0,0 +1,2 @@
  1
+var I18n = I18n || {};
  2
+I18n.translations = {"en":{"date":{"formats":{"default":"%Y-%m-%d","short":"%b %d","long":"%B %d, %Y"},"day_names":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"abbr_day_names":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"month_names":[null,"January","February","March","April","May","June","July","August","September","October","November","December"],"abbr_month_names":[null,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"order":["year","month","day"]},"time":{"formats":{"default":"%a, %d %b %Y %H:%M:%S %z","short":"%d %b %H:%M","long":"%B %d, %Y %H:%M"},"am":"am","pm":"pm"},"support":{"array":{"words_connector":", ","two_words_connector":" and ","last_word_connector":", and "}},"errors":{"format":"%{attribute} %{message}","messages":{"inclusion":"is not included in the list","exclusion":"is reserved","invalid":"is invalid","confirmation":"doesn't match confirmation","accepted":"must be accepted","empty":"can't be empty","blank":"can't be blank","too_long":"is too long (maximum is %{count} characters)","too_short":"is too short (minimum is %{count} characters)","wrong_length":"is the wrong length (should be %{count} characters)","not_a_number":"is not a number","not_an_integer":"must be an integer","greater_than":"must be greater than %{count}","greater_than_or_equal_to":"must be greater than or equal to %{count}","equal_to":"must be equal to %{count}","less_than":"must be less than %{count}","less_than_or_equal_to":"must be less than or equal to %{count}","odd":"must be odd","even":"must be even"}},"activerecord":{"errors":{"messages":{"taken":"has already been taken","record_invalid":"Validation failed: %{errors}"}}},"number":{"format":{"separator":".","delimiter":",","precision":3,"significant":false,"strip_insignificant_zeros":false},"currency":{"format":{"format":"%u%n","unit":"$","separator":".","delimiter":",","precision":2,"significant":false,"strip_insignificant_zeros":false}},"percentage":{"format":{"delimiter":""}},"precision":{"format":{"delimiter":""}},"human":{"format":{"delimiter":"","precision":3,"significant":true,"strip_insignificant_zeros":true},"storage_units":{"format":"%n %u","units":{"byte":{"one":"Byte","other":"Bytes"},"kb":"KB","mb":"MB","gb":"GB","tb":"TB"}},"decimal_units":{"format":"%n %u","units":{"unit":"","thousand":"Thousand","million":"Million","billion":"Billion","trillion":"Trillion","quadrillion":"Quadrillion"}}}},"datetime":{"distance_in_words":{"half_a_minute":"half a minute","less_than_x_seconds":{"one":"less than 1 second","other":"less than %{count} seconds"},"x_seconds":{"one":"1 second","other":"%{count} seconds"},"less_than_x_minutes":{"one":"less than a minute","other":"less than %{count} minutes"},"x_minutes":{"one":"1 minute","other":"%{count} minutes"},"about_x_hours":{"one":"about 1 hour","other":"about %{count} hours"},"x_days":{"one":"1 day","other":"%{count} days"},"about_x_months":{"one":"about 1 month","other":"about %{count} months"},"x_months":{"one":"1 month","other":"%{count} months"},"about_x_years":{"one":"about 1 year","other":"about %{count} years"},"over_x_years":{"one":"over 1 year","other":"over %{count} years"},"almost_x_years":{"one":"almost 1 year","other":"almost %{count} years"}},"prompts":{"year":"Year","month":"Month","day":"Day","hour":"Hour","minute":"Minute","second":"Seconds"}},"helpers":{"select":{"prompt":"Please select"},"submit":{"create":"Create %{model}","update":"Update %{model}","submit":"Save %{model}"}},"lost_i18n_translation":{"missing_label":"Missing translations","present_label":"Present translations"},"hello":"Hello world"}};
413  vendor/assets/javascripts/i18n.js
... ...
@@ -0,0 +1,413 @@
  1
+// Instantiate the object
  2
+var I18n = I18n || {};
  3
+
  4
+// Set default locale to english
  5
+I18n.defaultLocale = "en";
  6
+
  7
+// Set default separator
  8
+I18n.defaultSeparator = ".";
  9
+
  10
+// Set current locale to null
  11
+I18n.locale = null;
  12
+
  13
+// Set the placeholder format. Accepts `{{placeholder}}` and `%{placeholder}`.
  14
+I18n.PLACEHOLDER = /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm;
  15
+
  16
+I18n.isValidNode = function(obj, node) {
  17
+    // local undefined variable in case another library corrupts window.undefined
  18
+    var undef;
  19
+    return obj[node] !== null && obj[node] !== undef;
  20
+}
  21
+
  22
+I18n.lookup = function(scope, options) {
  23
+  var translations = this.prepareOptions(I18n.translations);
  24
+  var messages = translations[I18n.currentLocale()];
  25
+  options = this.prepareOptions(options);
  26
+
  27
+  if (!messages) {
  28
+    return;
  29
+  }
  30
+
  31
+  if (typeof(scope) == "object") {
  32
+    scope = scope.join(this.defaultSeparator);
  33
+  }
  34
+
  35
+  if (options.scope) {
  36
+    scope = options.scope.toString() + this.defaultSeparator + scope;
  37
+  }
  38
+
  39
+  scope = scope.split(this.defaultSeparator);
  40
+
  41
+  while (scope.length > 0) {
  42
+    var currentScope = scope.shift();
  43
+    messages = messages[currentScope];
  44
+
  45
+    if (!messages) {
  46
+      break;
  47
+    }
  48
+  }
  49
+
  50
+  if (!messages && this.isValidNode(options, "defaultValue")) {
  51
+    messages = options.defaultValue;
  52
+  }
  53
+
  54
+  return messages;
  55
+};
  56
+
  57
+// Merge serveral hash options, checking if value is set before
  58
+// overwriting any value. The precedence is from left to right.
  59
+//
  60
+//   I18n.prepareOptions({name: "John Doe"}, {name: "Mary Doe", role: "user"});
  61
+//   #=> {name: "John Doe", role: "user"}
  62
+//
  63
+I18n.prepareOptions = function() {
  64
+  var options = {};
  65
+  var opts;
  66
+  var count = arguments.length;
  67
+
  68
+  for (var i = 0; i < count; i++) {
  69
+    opts = arguments[i];
  70
+
  71
+    if (!opts) {
  72
+      continue;
  73
+    }
  74
+
  75
+    for (var key in opts) {
  76
+      if (!this.isValidNode(options, key)) {
  77
+        options[key] = opts[key];
  78
+      }
  79
+    }
  80
+  }
  81
+
  82
+  return options;
  83
+};
  84
+
  85
+I18n.interpolate = function(message, options) {
  86
+  options = this.prepareOptions(options);
  87
+  var matches = message.match(this.PLACEHOLDER);
  88
+
  89
+  if (!matches) {
  90
+    return message;
  91
+  }
  92
+
  93
+  var placeholder, value, name;
  94
+
  95
+  for (var i = 0; placeholder = matches[i]; i++) {
  96
+    name = placeholder.replace(this.PLACEHOLDER, "$1");
  97
+
  98
+    value = options[name];
  99
+
  100
+    if (!this.isValidNode(options, name)) {
  101
+      value = "[missing " + placeholder + " value]";
  102
+    }
  103
+
  104
+    regex = new RegExp(placeholder.replace(/\{/gm, "\\{").replace(/\}/gm, "\\}"));
  105
+    message = message.replace(regex, value);
  106
+  }
  107
+
  108
+  return message;
  109
+};
  110
+
  111
+I18n.translate = function(scope, options) {
  112
+  options = this.prepareOptions(options);
  113
+  var translation = this.lookup(scope, options);
  114
+
  115
+  try {
  116
+    if (typeof(translation) == "object") {
  117
+      if (typeof(options.count) == "number") {
  118
+        return this.pluralize(options.count, scope, options);
  119
+      } else {
  120
+        return translation;
  121
+      }
  122
+    } else {
  123
+      return this.interpolate(translation, options);
  124
+    }
  125
+  } catch(err) {
  126
+    return this.missingTranslation(scope);
  127
+  }
  128
+};
  129
+
  130
+I18n.localize = function(scope, value) {
  131
+  switch (scope) {
  132
+    case "currency":
  133
+      return this.toCurrency(value);
  134
+    case "number":
  135
+      scope = this.lookup("number.format");
  136
+      return this.toNumber(value, scope);
  137
+    case "percentage":
  138
+      return this.toPercentage(value);
  139
+    default:
  140
+      if (scope.match(/^(date|time)/)) {
  141
+        return this.toTime(scope, value);
  142
+      } else {
  143
+        return value.toString();
  144
+      }
  145
+  }
  146
+};
  147
+
  148
+I18n.parseDate = function(d) {
  149
+  var matches, date;
  150
+  matches = d.toString().match(/(\d{4})-(\d{2})-(\d{2})(?:[ |T](\d{2}):(\d{2}):(\d{2}))?(Z)?/);
  151
+
  152
+  if (matches) {
  153
+    // date/time strings: yyyy-mm-dd hh:mm:ss or yyyy-mm-dd or yyyy-mm-ddThh:mm:ssZ
  154
+    for (var i = 1; i <= 6; i++) {
  155
+      matches[i] = parseInt(matches[i], 10) || 0;
  156
+    }
  157
+
  158
+    // month starts on 0
  159
+    matches[2] -= 1;
  160
+
  161
+    if (matches[7]) {
  162
+      date = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]));
  163
+    } else {
  164
+      date = new Date(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]);
  165
+    }
  166
+  } else if (typeof(d) == "number") {
  167
+    // UNIX timestamp
  168
+    date = new Date();
  169
+    date.setTime(d);
  170
+  } else {
  171
+    // an arbitrary javascript string
  172
+    date = new Date();
  173
+    date.setTime(Date.parse(d));
  174
+  }
  175
+
  176
+  return date;
  177
+};
  178
+
  179
+I18n.toTime = function(scope, d) {
  180
+  var date = this.parseDate(d);
  181
+  var format = this.lookup(scope);
  182
+
  183
+  if (date.toString().match(/invalid/i)) {
  184
+    return date.toString();
  185
+  }
  186
+
  187
+  if (!format) {
  188
+    return date.toString();
  189
+  }
  190
+
  191
+  return this.strftime(date, format);
  192
+};
  193
+
  194
+I18n.strftime = function(date, format) {
  195
+  var options = this.lookup("date");
  196
+
  197
+  if (!options) {
  198
+    return date.toString();
  199
+  }
  200
+  options.meridian = options.meridian || ["AM", "PM"];
  201
+
  202
+  var weekDay = date.getDay();
  203
+  var day = date.getDate();
  204
+  var year = date.getFullYear();
  205
+  var month = date.getMonth() + 1;
  206
+  var hour = date.getHours();
  207
+  var hour12 = hour;
  208
+  var meridian = hour > 11 ? 1 : 0;
  209
+  var secs = date.getSeconds();
  210
+  var mins = date.getMinutes();
  211
+  var offset = date.getTimezoneOffset();
  212
+  var absOffsetHours = Math.floor(Math.abs(offset / 60));
  213
+  var absOffsetMinutes = Math.abs(offset) - (absOffsetHours * 60);
  214
+  var timezoneoffset = (offset > 0 ? "-" : "+") + (absOffsetHours.toString().length < 2 ? "0" + absOffsetHours : absOffsetHours) + (absOffsetMinutes.toString().length < 2 ? "0" + absOffsetMinutes : absOffsetMinutes);
  215
+
  216
+  if (hour12 > 12) {
  217
+    hour12 = hour12 - 12;
  218
+  } else if (hour12 === 0) {
  219
+    hour12 = 12;
  220
+  }
  221
+
  222
+  var padding = function(n) {
  223
+    var s = "0" + n.toString();
  224
+    return s.substr(s.length - 2);
  225
+  };
  226
+
  227
+  var f = format;
  228
+  f = f.replace("%a", options.abbr_day_names[weekDay]);
  229
+  f = f.replace("%A", options.day_names[weekDay]);
  230
+  f = f.replace("%b", options.abbr_month_names[month]);
  231
+  f = f.replace("%B", options.month_names[month]);
  232
+  f = f.replace("%d", padding(day));
  233
+  f = f.replace("%-d", day);
  234
+  f = f.replace("%H", padding(hour));
  235
+  f = f.replace("%-H", hour);
  236
+  f = f.replace("%I", padding(hour12));
  237
+  f = f.replace("%-I", hour12);
  238
+  f = f.replace("%m", padding(month));
  239
+  f = f.replace("%-m", month);
  240
+  f = f.replace("%M", padding(mins));
  241
+  f = f.replace("%-M", mins);
  242
+  f = f.replace("%p", options.meridian[meridian]);
  243
+  f = f.replace("%S", padding(secs));
  244
+  f = f.replace("%-S", secs);
  245
+  f = f.replace("%w", weekDay);
  246
+  f = f.replace("%y", padding(year));
  247
+  f = f.replace("%-y", padding(year).replace(/^0+/, ""));
  248
+  f = f.replace("%Y", year);
  249
+  f = f.replace("%z", timezoneoffset);
  250
+
  251
+  return f;
  252
+};
  253
+
  254
+I18n.toNumber = function(number, options) {
  255
+  options = this.prepareOptions(
  256
+    options,
  257
+    this.lookup("number.format"),
  258
+    {precision: 3, separator: ".", delimiter: ",", strip_insignificant_zeros: false}
  259
+  );
  260
+
  261
+  var negative = number < 0;
  262
+  var string = Math.abs(number).toFixed(options.precision).toString();
  263
+  var parts = string.split(".");
  264
+
  265
+  number = parts[0];
  266
+  var precision = parts[1];
  267
+
  268
+  var n = [];
  269
+
  270
+  while (number.length > 0) {
  271
+    n.unshift(number.substr(Math.max(0, number.length - 3), 3));
  272
+    number = number.substr(0, number.length -3);
  273
+  }
  274
+
  275
+  var formattedNumber = n.join(options.delimiter);
  276
+
  277
+  if (options.precision > 0) {
  278
+    formattedNumber += options.separator + parts[1];
  279
+  }
  280
+
  281
+  if (negative) {
  282
+    formattedNumber = "-" + formattedNumber;
  283
+  }
  284
+
  285
+  if (options.strip_insignificant_zeros) {
  286
+    var regex = {
  287
+        separator: new RegExp(options.separator.replace(/\./, "\\.") + "$")
  288
+      , zeros: /0+$/
  289
+    };
  290
+
  291
+    formattedNumber = formattedNumber
  292
+      .replace(regex.zeros, "")
  293
+      .replace(regex.separator, "");
  294
+  }
  295
+
  296
+  return formattedNumber;
  297
+};
  298
+
  299
+I18n.toCurrency = function(number, options) {
  300
+  options = this.prepareOptions(
  301
+    options,
  302
+    this.lookup("number.currency.format"),
  303
+    this.lookup("number.format"),
  304
+    {unit: "$", precision: 2, format: "%u%n", delimiter: ",", separator: "."}
  305
+  );
  306
+
  307
+  number = this.toNumber(number, options);
  308
+  number = options.format
  309
+    .replace("%u", options.unit)
  310
+    .replace("%n", number);
  311
+
  312
+  return number;
  313
+};
  314
+
  315
+I18n.toHumanSize = function(number, options) {
  316
+  var kb = 1024
  317
+    , size = number
  318
+    , iterations = 0
  319
+    , unit
  320
+    , precision
  321
+  ;
  322
+
  323
+  while (size >= kb && iterations < 4) {
  324
+    size = size / kb;
  325
+    iterations += 1;
  326
+  }
  327
+
  328
+  if (iterations === 0) {
  329
+    unit = this.t("number.human.storage_units.units.byte", {count: size});
  330
+    precision = 0;
  331
+  } else {
  332
+    unit = this.t("number.human.storage_units.units." + [null, "kb", "mb", "gb", "tb"][iterations]);
  333
+    precision = (size - Math.floor(size) === 0) ? 0 : 1;
  334
+  }
  335
+
  336
+  options = this.prepareOptions(
  337
+    options,
  338
+    {precision: precision, format: "%n%u", delimiter: ""}
  339
+  );
  340
+
  341
+  number = this.toNumber(size, options);
  342
+  number = options.format
  343
+    .replace("%u", unit)
  344
+    .replace("%n", number);
  345
+
  346
+  return number;
  347
+};
  348
+
  349
+I18n.toPercentage = function(number, options) {
  350
+  options = this.prepareOptions(
  351
+    options,
  352
+    this.lookup("number.percentage.format"),
  353
+    this.lookup("number.format"),
  354
+    {precision: 3, separator: ".", delimiter: ""}
  355
+  );
  356
+
  357
+  number = this.toNumber(number, options);
  358
+  return number + "%";
  359
+};
  360
+
  361
+I18n.pluralize = function(count, scope, options) {
  362
+  var translation;
  363
+
  364
+  try {
  365
+    translation = this.lookup(scope, options);
  366
+  } catch (error) {}
  367
+
  368
+  if (!translation) {
  369
+    return this.missingTranslation(scope);
  370
+  }
  371
+
  372
+  var message;
  373
+  options = this.prepareOptions(options);
  374
+  options.count = count.toString();
  375
+
  376
+  switch(Math.abs(count)) {
  377
+    case 0:
  378
+      message = this.isValidNode(translation, "zero") ? translation.zero :
  379
+                this.isValidNode(translation, "none") ? translation.none :
  380
+                this.isValidNode(translation, "other") ? translation.other :
  381
+                this.missingTranslation(scope, "zero");
  382
+      break;
  383
+    case 1:
  384
+      message = this.isValidNode(translation, "one") ? translation.one : this.missingTranslation(scope, "one");
  385
+      break;
  386
+    default:
  387
+      message = this.isValidNode(translation, "other") ? translation.other : this.missingTranslation(scope, "other");
  388
+  }
  389
+
  390
+  return this.interpolate(message, options);
  391
+};
  392
+
  393
+I18n.missingTranslation = function() {
  394
+  var message = '[missing "' + this.currentLocale();
  395
+  var count = arguments.length;
  396
+
  397
+  for (var i = 0; i < count; i++) {
  398
+    message += "." + arguments[i];
  399
+  }
  400
+
  401
+  message += '" translation]';
  402
+
  403
+  return message;
  404
+};
  405
+
  406
+I18n.currentLocale = function() {
  407
+  return (I18n.locale || I18n.defaultLocale);
  408
+};
  409
+
  410
+// shortcuts
  411
+I18n.t = I18n.translate;
  412
+I18n.l = I18n.localize;
  413
+I18n.p = I18n.pluralize;

0 notes on commit 83d18ca

Please sign in to comment.
Something went wrong with that request. Please try again.