ember-rails-i18n 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +339 -0
- data/README.md +64 -0
- data/Rakefile +1 -0
- data/ember-rails-i18n.gemspec +26 -0
- data/lib/ember-rails-i18n.rb +15 -0
- data/lib/ember-rails-i18n/helper.rb +29 -0
- data/lib/ember-rails-i18n/version.rb +3 -0
- data/lib/javascripts/moment.js +2489 -0
- data/lib/javascripts/moment_locale/ar-ma.js +56 -0
- data/lib/javascripts/moment_locale/ar.js +56 -0
- data/lib/javascripts/moment_locale/bg.js +86 -0
- data/lib/javascripts/moment_locale/br.js +107 -0
- data/lib/javascripts/moment_locale/bs.js +139 -0
- data/lib/javascripts/moment_locale/ca.js +66 -0
- data/lib/javascripts/moment_locale/cs.js +155 -0
- data/lib/javascripts/moment_locale/cv.js +59 -0
- data/lib/javascripts/moment_locale/cy.js +77 -0
- data/lib/javascripts/moment_locale/da.js +56 -0
- data/lib/javascripts/moment_locale/de.js +71 -0
- data/lib/javascripts/moment_locale/el.js +79 -0
- data/lib/javascripts/moment_locale/en-au.js +62 -0
- data/lib/javascripts/moment_locale/en-ca.js +59 -0
- data/lib/javascripts/moment_locale/en-gb.js +63 -0
- data/lib/javascripts/moment_locale/eo.js +65 -0
- data/lib/javascripts/moment_locale/es.js +75 -0
- data/lib/javascripts/moment_locale/et.js +76 -0
- data/lib/javascripts/moment_locale/eu.js +60 -0
- data/lib/javascripts/moment_locale/fa.js +97 -0
- data/lib/javascripts/moment_locale/fi.js +103 -0
- data/lib/javascripts/moment_locale/fo.js +56 -0
- data/lib/javascripts/moment_locale/fr-ca.js +54 -0
- data/lib/javascripts/moment_locale/fr.js +58 -0
- data/lib/javascripts/moment_locale/gl.js +71 -0
- data/lib/javascripts/moment_locale/he.js +77 -0
- data/lib/javascripts/moment_locale/hi.js +105 -0
- data/lib/javascripts/moment_locale/hr.js +140 -0
- data/lib/javascripts/moment_locale/hu.js +105 -0
- data/lib/javascripts/moment_locale/hy-am.js +113 -0
- data/lib/javascripts/moment_locale/id.js +67 -0
- data/lib/javascripts/moment_locale/is.js +124 -0
- data/lib/javascripts/moment_locale/it.js +59 -0
- data/lib/javascripts/moment_locale/ja.js +58 -0
- data/lib/javascripts/moment_locale/ka.js +108 -0
- data/lib/javascripts/moment_locale/km.js +55 -0
- data/lib/javascripts/moment_locale/ko.js +63 -0
- data/lib/javascripts/moment_locale/lb.js +160 -0
- data/lib/javascripts/moment_locale/lt.js +118 -0
- data/lib/javascripts/moment_locale/lv.js +77 -0
- data/lib/javascripts/moment_locale/mk.js +86 -0
- data/lib/javascripts/moment_locale/ml.js +64 -0
- data/lib/javascripts/moment_locale/mr.js +104 -0
- data/lib/javascripts/moment_locale/ms-my.js +66 -0
- data/lib/javascripts/moment_locale/nb.js +57 -0
- data/lib/javascripts/moment_locale/ne.js +105 -0
- data/lib/javascripts/moment_locale/nl.js +67 -0
- data/lib/javascripts/moment_locale/nn.js +56 -0
- data/lib/javascripts/moment_locale/pl.js +98 -0
- data/lib/javascripts/moment_locale/pt-br.js +56 -0
- data/lib/javascripts/moment_locale/pt.js +60 -0
- data/lib/javascripts/moment_locale/ro.js +72 -0
- data/lib/javascripts/moment_locale/ru.js +163 -0
- data/lib/javascripts/moment_locale/sk.js +156 -0
- data/lib/javascripts/moment_locale/sl.js +144 -0
- data/lib/javascripts/moment_locale/sq.js +61 -0
- data/lib/javascripts/moment_locale/sr-cyr.js +106 -0
- data/lib/javascripts/moment_locale/sr.js +106 -0
- data/lib/javascripts/moment_locale/sv.js +63 -0
- data/lib/javascripts/moment_locale/ta.js +112 -0
- data/lib/javascripts/moment_locale/th.js +58 -0
- data/lib/javascripts/moment_locale/tl-ph.js +58 -0
- data/lib/javascripts/moment_locale/tr.js +93 -0
- data/lib/javascripts/moment_locale/tzm-la.js +55 -0
- data/lib/javascripts/moment_locale/tzm.js +55 -0
- data/lib/javascripts/moment_locale/uk.js +157 -0
- data/lib/javascripts/moment_locale/uz.js +55 -0
- data/lib/javascripts/moment_locale/vi.js +62 -0
- data/lib/javascripts/moment_locale/zh-cn.js +108 -0
- data/lib/javascripts/moment_locale/zh-tw.js +84 -0
- data/vendor/assets/javascripts/locales/i18n.js +598 -0
- data/vendor/assets/javascripts/locales/test.js.erb +3 -0
- metadata +182 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
// moment.js language configuration
|
2
|
+
// language : traditional chinese (zh-tw)
|
3
|
+
// author : Ben : https://github.com/ben-lin
|
4
|
+
|
5
|
+
(function (factory) {
|
6
|
+
if (typeof define === 'function' && define.amd) {
|
7
|
+
define(['moment'], factory); // AMD
|
8
|
+
} else if (typeof exports === 'object') {
|
9
|
+
module.exports = factory(require('../moment')); // Node
|
10
|
+
} else {
|
11
|
+
factory(window.moment); // Browser global
|
12
|
+
}
|
13
|
+
}(function (moment) {
|
14
|
+
return moment.lang('zh-tw', {
|
15
|
+
months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
|
16
|
+
monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
|
17
|
+
weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
|
18
|
+
weekdaysShort : "週日_週一_週二_週三_週四_週五_週六".split("_"),
|
19
|
+
weekdaysMin : "日_一_二_三_四_五_六".split("_"),
|
20
|
+
longDateFormat : {
|
21
|
+
LT : "Ah點mm",
|
22
|
+
L : "YYYY年MMMD日",
|
23
|
+
LL : "YYYY年MMMD日",
|
24
|
+
LLL : "YYYY年MMMD日LT",
|
25
|
+
LLLL : "YYYY年MMMD日ddddLT",
|
26
|
+
l : "YYYY年MMMD日",
|
27
|
+
ll : "YYYY年MMMD日",
|
28
|
+
lll : "YYYY年MMMD日LT",
|
29
|
+
llll : "YYYY年MMMD日ddddLT"
|
30
|
+
},
|
31
|
+
meridiem : function (hour, minute, isLower) {
|
32
|
+
var hm = hour * 100 + minute;
|
33
|
+
if (hm < 900) {
|
34
|
+
return "早上";
|
35
|
+
} else if (hm < 1130) {
|
36
|
+
return "上午";
|
37
|
+
} else if (hm < 1230) {
|
38
|
+
return "中午";
|
39
|
+
} else if (hm < 1800) {
|
40
|
+
return "下午";
|
41
|
+
} else {
|
42
|
+
return "晚上";
|
43
|
+
}
|
44
|
+
},
|
45
|
+
calendar : {
|
46
|
+
sameDay : '[今天]LT',
|
47
|
+
nextDay : '[明天]LT',
|
48
|
+
nextWeek : '[下]ddddLT',
|
49
|
+
lastDay : '[昨天]LT',
|
50
|
+
lastWeek : '[上]ddddLT',
|
51
|
+
sameElse : 'L'
|
52
|
+
},
|
53
|
+
ordinal : function (number, period) {
|
54
|
+
switch (period) {
|
55
|
+
case "d" :
|
56
|
+
case "D" :
|
57
|
+
case "DDD" :
|
58
|
+
return number + "日";
|
59
|
+
case "M" :
|
60
|
+
return number + "月";
|
61
|
+
case "w" :
|
62
|
+
case "W" :
|
63
|
+
return number + "週";
|
64
|
+
default :
|
65
|
+
return number;
|
66
|
+
}
|
67
|
+
},
|
68
|
+
relativeTime : {
|
69
|
+
future : "%s內",
|
70
|
+
past : "%s前",
|
71
|
+
s : "幾秒",
|
72
|
+
m : "一分鐘",
|
73
|
+
mm : "%d分鐘",
|
74
|
+
h : "一小時",
|
75
|
+
hh : "%d小時",
|
76
|
+
d : "一天",
|
77
|
+
dd : "%d天",
|
78
|
+
M : "一個月",
|
79
|
+
MM : "%d個月",
|
80
|
+
y : "一年",
|
81
|
+
yy : "%d年"
|
82
|
+
}
|
83
|
+
});
|
84
|
+
}));
|
@@ -0,0 +1,598 @@
|
|
1
|
+
/*global I18n:true */
|
2
|
+
|
3
|
+
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
|
4
|
+
if (!Array.prototype.indexOf) {
|
5
|
+
Array.prototype.indexOf = function (searchElement, fromIndex) {
|
6
|
+
if ( this === undefined || this === null ) {
|
7
|
+
throw new TypeError( '"this" is null or not defined' );
|
8
|
+
}
|
9
|
+
|
10
|
+
var length = this.length >>> 0; // Hack to convert object.length to a UInt32
|
11
|
+
|
12
|
+
fromIndex = +fromIndex || 0;
|
13
|
+
|
14
|
+
if (Math.abs(fromIndex) === Infinity) {
|
15
|
+
fromIndex = 0;
|
16
|
+
}
|
17
|
+
|
18
|
+
if (fromIndex < 0) {
|
19
|
+
fromIndex += length;
|
20
|
+
if (fromIndex < 0) {
|
21
|
+
fromIndex = 0;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
for (;fromIndex < length; fromIndex++) {
|
26
|
+
if (this[fromIndex] === searchElement) {
|
27
|
+
return fromIndex;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
return -1;
|
32
|
+
};
|
33
|
+
}
|
34
|
+
|
35
|
+
// Instantiate the object
|
36
|
+
var I18n = I18n || {};
|
37
|
+
|
38
|
+
// Set default locale to english
|
39
|
+
I18n.defaultLocale = "en";
|
40
|
+
|
41
|
+
// Set default handling of translation fallbacks to false
|
42
|
+
I18n.fallbacks = false;
|
43
|
+
|
44
|
+
// Set default separator
|
45
|
+
I18n.defaultSeparator = ".";
|
46
|
+
|
47
|
+
// Set current locale to null
|
48
|
+
I18n.locale = null;
|
49
|
+
|
50
|
+
// Set the placeholder format. Accepts `{{placeholder}}` and `%{placeholder}`.
|
51
|
+
I18n.PLACEHOLDER = /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm;
|
52
|
+
|
53
|
+
I18n.fallbackRules = {};
|
54
|
+
|
55
|
+
I18n.pluralizationRules = {
|
56
|
+
en: function(n) {
|
57
|
+
return n === 0 ? ["zero", "none", "other"] : n === 1 ? "one" : "other";
|
58
|
+
},
|
59
|
+
"zh_CN": function(n) {
|
60
|
+
return n === 0 ? ["zero", "none", "other"] : "other";
|
61
|
+
},
|
62
|
+
"zh_TW": function(n) {
|
63
|
+
return n === 0 ? ["zero", "none", "other"] : "other";
|
64
|
+
}
|
65
|
+
};
|
66
|
+
|
67
|
+
I18n.getFallbacks = function(locale) {
|
68
|
+
if (locale === I18n.defaultLocale) {
|
69
|
+
return [];
|
70
|
+
} else if (!I18n.fallbackRules[locale]) {
|
71
|
+
var rules = [],
|
72
|
+
components = locale.split("-");
|
73
|
+
|
74
|
+
for (var l = 1; l < components.length; l++) {
|
75
|
+
rules.push(components.slice(0, l).join("-"));
|
76
|
+
}
|
77
|
+
|
78
|
+
rules.push(I18n.defaultLocale);
|
79
|
+
|
80
|
+
I18n.fallbackRules[locale] = rules;
|
81
|
+
}
|
82
|
+
|
83
|
+
return I18n.fallbackRules[locale];
|
84
|
+
};
|
85
|
+
|
86
|
+
I18n.isValidNode = function(obj, node, undefined) {
|
87
|
+
return obj[node] !== null && obj[node] !== undefined;
|
88
|
+
};
|
89
|
+
|
90
|
+
I18n.lookup = function(scope, options) {
|
91
|
+
options = options || {};
|
92
|
+
var lookupInitialScope = scope,
|
93
|
+
translations = this.prepareOptions(I18n.translations),
|
94
|
+
locale = options.locale || I18n.currentLocale(),
|
95
|
+
messages = translations[locale] || {},
|
96
|
+
currentScope;
|
97
|
+
|
98
|
+
options = this.prepareOptions(options);
|
99
|
+
|
100
|
+
if (typeof scope === "object") {
|
101
|
+
scope = scope.join(this.defaultSeparator);
|
102
|
+
}
|
103
|
+
|
104
|
+
if (options.scope) {
|
105
|
+
scope = options.scope.toString() + this.defaultSeparator + scope;
|
106
|
+
}
|
107
|
+
|
108
|
+
scope = scope.split(this.defaultSeparator);
|
109
|
+
|
110
|
+
while (messages && scope.length > 0) {
|
111
|
+
currentScope = scope.shift();
|
112
|
+
messages = messages[currentScope];
|
113
|
+
}
|
114
|
+
|
115
|
+
if (!messages) {
|
116
|
+
if (I18n.fallbacks) {
|
117
|
+
var fallbacks = this.getFallbacks(locale);
|
118
|
+
for (var fallback = 0; fallback < fallbacks.length; fallbacks++) {
|
119
|
+
messages = I18n.lookup(lookupInitialScope, this.prepareOptions({locale: fallbacks[fallback]}, options));
|
120
|
+
if (messages) {
|
121
|
+
break;
|
122
|
+
}
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
if (!messages && this.isValidNode(options, "defaultValue")) {
|
127
|
+
messages = options.defaultValue;
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
return messages;
|
132
|
+
};
|
133
|
+
|
134
|
+
// Merge serveral hash options, checking if value is set before
|
135
|
+
// overwriting any value. The precedence is from left to right.
|
136
|
+
//
|
137
|
+
// I18n.prepareOptions({name: "John Doe"}, {name: "Mary Doe", role: "user"});
|
138
|
+
// #=> {name: "John Doe", role: "user"}
|
139
|
+
//
|
140
|
+
I18n.prepareOptions = function() {
|
141
|
+
var options = {},
|
142
|
+
opts,
|
143
|
+
count = arguments.length;
|
144
|
+
|
145
|
+
for (var i = 0; i < count; i++) {
|
146
|
+
opts = arguments[i];
|
147
|
+
|
148
|
+
if (!opts) {
|
149
|
+
continue;
|
150
|
+
}
|
151
|
+
|
152
|
+
for (var key in opts) {
|
153
|
+
if (!this.isValidNode(options, key)) {
|
154
|
+
options[key] = opts[key];
|
155
|
+
}
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
return options;
|
160
|
+
};
|
161
|
+
|
162
|
+
I18n.interpolate = function(message, options) {
|
163
|
+
options = this.prepareOptions(options);
|
164
|
+
var matches = message.match(this.PLACEHOLDER),
|
165
|
+
placeholder,
|
166
|
+
value,
|
167
|
+
name;
|
168
|
+
|
169
|
+
if (!matches) {
|
170
|
+
return message;
|
171
|
+
}
|
172
|
+
|
173
|
+
for (var i = 0; placeholder = matches[i]; i++) {
|
174
|
+
name = placeholder.replace(this.PLACEHOLDER, "$1");
|
175
|
+
|
176
|
+
value = options[name];
|
177
|
+
|
178
|
+
if (!this.isValidNode(options, name)) {
|
179
|
+
value = "[missing " + placeholder + " value]";
|
180
|
+
}
|
181
|
+
|
182
|
+
var regex = new RegExp(placeholder.replace(/\{/gm, "\\{").replace(/\}/gm, "\\}"));
|
183
|
+
message = message.replace(regex, value);
|
184
|
+
}
|
185
|
+
|
186
|
+
return message;
|
187
|
+
};
|
188
|
+
|
189
|
+
I18n.translate = function(scope, options) {
|
190
|
+
options = this.prepareOptions(options);
|
191
|
+
var translation = this.lookup(scope, options);
|
192
|
+
|
193
|
+
try {
|
194
|
+
if (typeof translation === "object") {
|
195
|
+
if (typeof options.count === "number") {
|
196
|
+
return this.pluralize(options.count, scope, options);
|
197
|
+
} else {
|
198
|
+
return translation;
|
199
|
+
}
|
200
|
+
} else {
|
201
|
+
return this.interpolate(translation, options);
|
202
|
+
}
|
203
|
+
} catch (error) {
|
204
|
+
return this.missingTranslation(scope);
|
205
|
+
}
|
206
|
+
};
|
207
|
+
|
208
|
+
I18n.localize = function(scope, value) {
|
209
|
+
switch (scope) {
|
210
|
+
case "currency":
|
211
|
+
return this.toCurrency(value);
|
212
|
+
case "number":
|
213
|
+
scope = this.lookup("number.format");
|
214
|
+
return this.toNumber(value, scope);
|
215
|
+
case "percentage":
|
216
|
+
return this.toPercentage(value);
|
217
|
+
default:
|
218
|
+
if (scope.match(/^(date|time)/)) {
|
219
|
+
return this.toTime(scope, value);
|
220
|
+
} else {
|
221
|
+
return value.toString();
|
222
|
+
}
|
223
|
+
}
|
224
|
+
};
|
225
|
+
|
226
|
+
I18n.parseDate = function(date) {
|
227
|
+
var matches, convertedDate;
|
228
|
+
|
229
|
+
// we have a date, so just return it.
|
230
|
+
if (typeof date === "object") {
|
231
|
+
return date;
|
232
|
+
}
|
233
|
+
|
234
|
+
// it matches the following formats:
|
235
|
+
// yyyy-mm-dd
|
236
|
+
// yyyy-mm-dd[ T]hh:mm::ss
|
237
|
+
// yyyy-mm-dd[ T]hh:mm::ss
|
238
|
+
// yyyy-mm-dd[ T]hh:mm::ssZ
|
239
|
+
// yyyy-mm-dd[ T]hh:mm::ss+0000
|
240
|
+
//
|
241
|
+
matches = date.toString().match(/(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2}))?(Z|\+0000)?/);
|
242
|
+
|
243
|
+
if (matches) {
|
244
|
+
for (var i = 1; i <= 6; i++) {
|
245
|
+
matches[i] = parseInt(matches[i], 10) || 0;
|
246
|
+
}
|
247
|
+
|
248
|
+
// month starts on 0
|
249
|
+
matches[2] -= 1;
|
250
|
+
|
251
|
+
if (matches[7]) {
|
252
|
+
convertedDate = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]));
|
253
|
+
} else {
|
254
|
+
convertedDate = new Date(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]);
|
255
|
+
}
|
256
|
+
} else if (typeof date === "number") {
|
257
|
+
// UNIX timestamp
|
258
|
+
convertedDate = new Date();
|
259
|
+
convertedDate.setTime(date);
|
260
|
+
} else if (date.match(/\d+ \d+:\d+:\d+ [+-]\d+ \d+/)) {
|
261
|
+
// a valid javascript format with timezone info
|
262
|
+
convertedDate = new Date();
|
263
|
+
convertedDate.setTime(Date.parse(date));
|
264
|
+
} else {
|
265
|
+
// an arbitrary javascript string
|
266
|
+
convertedDate = new Date();
|
267
|
+
convertedDate.setTime(Date.parse(date));
|
268
|
+
}
|
269
|
+
|
270
|
+
return convertedDate;
|
271
|
+
};
|
272
|
+
|
273
|
+
I18n.toTime = function(scope, d) {
|
274
|
+
var date = this.parseDate(d),
|
275
|
+
format = this.lookup(scope);
|
276
|
+
|
277
|
+
if (date.toString().match(/invalid/i)) {
|
278
|
+
return date.toString();
|
279
|
+
}
|
280
|
+
|
281
|
+
if (!format) {
|
282
|
+
return date.toString();
|
283
|
+
}
|
284
|
+
|
285
|
+
return this.strftime(date, format);
|
286
|
+
};
|
287
|
+
|
288
|
+
I18n.strftime = function(date, format) {
|
289
|
+
var options = this.lookup("date");
|
290
|
+
|
291
|
+
if (!options) {
|
292
|
+
return date.toString();
|
293
|
+
}
|
294
|
+
|
295
|
+
options.meridian = options.meridian || ["AM", "PM"];
|
296
|
+
|
297
|
+
var weekDay = date.getDay(),
|
298
|
+
day = date.getDate(),
|
299
|
+
year = date.getFullYear(),
|
300
|
+
month = date.getMonth() + 1,
|
301
|
+
hour = date.getHours(),
|
302
|
+
hour12 = hour,
|
303
|
+
meridian = hour > 11 ? 1 : 0,
|
304
|
+
secs = date.getSeconds(),
|
305
|
+
mins = date.getMinutes(),
|
306
|
+
offset = date.getTimezoneOffset(),
|
307
|
+
absOffsetHours = Math.floor(Math.abs(offset / 60)),
|
308
|
+
absOffsetMinutes = Math.abs(offset) - (absOffsetHours * 60),
|
309
|
+
timezoneoffset = (offset > 0 ? "-" : "+") + (absOffsetHours.toString().length < 2 ? "0" + absOffsetHours : absOffsetHours) + (absOffsetMinutes.toString().length < 2 ? "0" + absOffsetMinutes : absOffsetMinutes);
|
310
|
+
|
311
|
+
if (hour12 > 12) {
|
312
|
+
hour12 = hour12 - 12;
|
313
|
+
} else if (hour12 === 0) {
|
314
|
+
hour12 = 12;
|
315
|
+
}
|
316
|
+
|
317
|
+
var padding = function(n) {
|
318
|
+
var s = "0" + n.toString();
|
319
|
+
return s.substr(s.length - 2);
|
320
|
+
};
|
321
|
+
|
322
|
+
var f = format;
|
323
|
+
f = f.replace("%a", options.abbr_day_names[weekDay]);
|
324
|
+
f = f.replace("%A", options.day_names[weekDay]);
|
325
|
+
f = f.replace("%b", options.abbr_month_names[month]);
|
326
|
+
f = f.replace("%B", options.month_names[month]);
|
327
|
+
f = f.replace("%d", padding(day));
|
328
|
+
f = f.replace("%e", day);
|
329
|
+
f = f.replace("%-d", day);
|
330
|
+
f = f.replace("%H", padding(hour));
|
331
|
+
f = f.replace("%-H", hour);
|
332
|
+
f = f.replace("%I", padding(hour12));
|
333
|
+
f = f.replace("%-I", hour12);
|
334
|
+
f = f.replace("%m", padding(month));
|
335
|
+
f = f.replace("%-m", month);
|
336
|
+
f = f.replace("%M", padding(mins));
|
337
|
+
f = f.replace("%-M", mins);
|
338
|
+
f = f.replace("%p", options.meridian[meridian]);
|
339
|
+
f = f.replace("%S", padding(secs));
|
340
|
+
f = f.replace("%-S", secs);
|
341
|
+
f = f.replace("%w", weekDay);
|
342
|
+
f = f.replace("%y", padding(year));
|
343
|
+
f = f.replace("%-y", padding(year).replace(/^0+/, ""));
|
344
|
+
f = f.replace("%Y", year);
|
345
|
+
f = f.replace("%z", timezoneoffset);
|
346
|
+
|
347
|
+
return f;
|
348
|
+
};
|
349
|
+
|
350
|
+
I18n.toNumber = function(number, options) {
|
351
|
+
options = this.prepareOptions(
|
352
|
+
options,
|
353
|
+
this.lookup("number.format"),
|
354
|
+
{precision: 3, separator: ".", delimiter: ",", strip_insignificant_zeros: false}
|
355
|
+
);
|
356
|
+
|
357
|
+
var negative = number < 0,
|
358
|
+
string = Math.abs(number).toFixed(options.precision).toString(),
|
359
|
+
parts = string.split("."),
|
360
|
+
precision,
|
361
|
+
buffer = [],
|
362
|
+
formattedNumber;
|
363
|
+
|
364
|
+
number = parts[0];
|
365
|
+
precision = parts[1];
|
366
|
+
|
367
|
+
while (number.length > 0) {
|
368
|
+
buffer.unshift(number.substr(Math.max(0, number.length - 3), 3));
|
369
|
+
number = number.substr(0, number.length -3);
|
370
|
+
}
|
371
|
+
|
372
|
+
formattedNumber = buffer.join(options.delimiter);
|
373
|
+
|
374
|
+
if (options.precision > 0) {
|
375
|
+
formattedNumber += options.separator + parts[1];
|
376
|
+
}
|
377
|
+
|
378
|
+
if (negative) {
|
379
|
+
formattedNumber = "-" + formattedNumber;
|
380
|
+
}
|
381
|
+
|
382
|
+
if (options.strip_insignificant_zeros) {
|
383
|
+
var regex = {
|
384
|
+
separator: new RegExp(options.separator.replace(/\./, "\\.") + "$"),
|
385
|
+
zeros: /0+$/
|
386
|
+
};
|
387
|
+
|
388
|
+
formattedNumber = formattedNumber
|
389
|
+
.replace(regex.zeros, "")
|
390
|
+
.replace(regex.separator, "")
|
391
|
+
;
|
392
|
+
}
|
393
|
+
|
394
|
+
return formattedNumber;
|
395
|
+
};
|
396
|
+
|
397
|
+
I18n.toCurrency = function(number, options) {
|
398
|
+
options = this.prepareOptions(
|
399
|
+
options,
|
400
|
+
this.lookup("number.currency.format"),
|
401
|
+
this.lookup("number.format"),
|
402
|
+
{unit: "$", precision: 2, format: "%u%n", delimiter: ",", separator: "."}
|
403
|
+
);
|
404
|
+
|
405
|
+
number = this.toNumber(number, options);
|
406
|
+
number = options.format
|
407
|
+
.replace("%u", options.unit)
|
408
|
+
.replace("%n", number)
|
409
|
+
;
|
410
|
+
|
411
|
+
return number;
|
412
|
+
};
|
413
|
+
|
414
|
+
I18n.toHumanSize = function(number, options) {
|
415
|
+
var kb = 1024,
|
416
|
+
size = number,
|
417
|
+
iterations = 0,
|
418
|
+
unit,
|
419
|
+
precision;
|
420
|
+
|
421
|
+
while (size >= kb && iterations < 4) {
|
422
|
+
size = size / kb;
|
423
|
+
iterations += 1;
|
424
|
+
}
|
425
|
+
|
426
|
+
if (iterations === 0) {
|
427
|
+
unit = this.t("number.human.storage_units.units.byte", {count: size});
|
428
|
+
precision = 0;
|
429
|
+
} else {
|
430
|
+
unit = this.t("number.human.storage_units.units." + [null, "kb", "mb", "gb", "tb"][iterations]);
|
431
|
+
precision = (size - Math.floor(size) === 0) ? 0 : 1;
|
432
|
+
}
|
433
|
+
|
434
|
+
options = this.prepareOptions(
|
435
|
+
options,
|
436
|
+
{precision: precision, format: "%n%u", delimiter: ""}
|
437
|
+
);
|
438
|
+
|
439
|
+
number = this.toNumber(size, options);
|
440
|
+
number = options.format
|
441
|
+
.replace("%u", unit)
|
442
|
+
.replace("%n", number)
|
443
|
+
;
|
444
|
+
|
445
|
+
return number;
|
446
|
+
};
|
447
|
+
|
448
|
+
I18n.toPercentage = function(number, options) {
|
449
|
+
options = this.prepareOptions(
|
450
|
+
options,
|
451
|
+
this.lookup("number.percentage.format"),
|
452
|
+
this.lookup("number.format"),
|
453
|
+
{precision: 3, separator: ".", delimiter: ""}
|
454
|
+
);
|
455
|
+
|
456
|
+
number = this.toNumber(number, options);
|
457
|
+
return number + "%";
|
458
|
+
};
|
459
|
+
|
460
|
+
I18n.pluralizer = function(locale) {
|
461
|
+
var pluralizer = this.pluralizationRules[locale];
|
462
|
+
if (pluralizer !== undefined) return pluralizer;
|
463
|
+
return this.pluralizationRules["en"];
|
464
|
+
};
|
465
|
+
|
466
|
+
I18n.findAndTranslateValidNode = function(keys, translation) {
|
467
|
+
for (var i = 0; i < keys.length; i++) {
|
468
|
+
var key = keys[i];
|
469
|
+
if (this.isValidNode(translation, key)) return translation[key];
|
470
|
+
}
|
471
|
+
return null;
|
472
|
+
};
|
473
|
+
|
474
|
+
I18n.pluralize = function(count, scope, options) {
|
475
|
+
var translation;
|
476
|
+
|
477
|
+
try { translation = this.lookup(scope, options); } catch (error) {}
|
478
|
+
if (!translation) { return this.missingTranslation(scope); }
|
479
|
+
|
480
|
+
options = this.prepareOptions(options);
|
481
|
+
options.count = count.toString();
|
482
|
+
|
483
|
+
var pluralizer = this.pluralizer(this.currentLocale());
|
484
|
+
var key = pluralizer(Math.abs(count));
|
485
|
+
var keys = ((typeof key === "object") && (key instanceof Array)) ? key : [key];
|
486
|
+
|
487
|
+
var message = this.findAndTranslateValidNode(keys, translation);
|
488
|
+
if (message == null) message = this.missingTranslation(scope, keys[0]);
|
489
|
+
|
490
|
+
return this.interpolate(message, options);
|
491
|
+
};
|
492
|
+
|
493
|
+
I18n.missingTranslation = function(scope, key) {
|
494
|
+
var message = '[' + this.currentLocale() + "." + scope;
|
495
|
+
if (key) { message += "." + key; }
|
496
|
+
return message + ']';
|
497
|
+
};
|
498
|
+
|
499
|
+
I18n.currentLocale = function() {
|
500
|
+
return (I18n.locale || I18n.defaultLocale);
|
501
|
+
};
|
502
|
+
|
503
|
+
// shortcuts
|
504
|
+
I18n.t = I18n.translate;
|
505
|
+
I18n.l = I18n.localize;
|
506
|
+
I18n.p = I18n.pluralize;
|
507
|
+
|
508
|
+
/**
|
509
|
+
Default format for storage units
|
510
|
+
**/
|
511
|
+
var oldI18ntoHumanSize = I18n.toHumanSize;
|
512
|
+
I18n.toHumanSize = function(number, options) {
|
513
|
+
options = options || {};
|
514
|
+
options.format = I18n.t("number.human.storage_units.format");
|
515
|
+
return oldI18ntoHumanSize.apply(this, [number, options]);
|
516
|
+
};
|
517
|
+
|
518
|
+
/**
|
519
|
+
* Ember I18n helpers
|
520
|
+
*/
|
521
|
+
if (typeof(Ember) !== "undefined") {
|
522
|
+
I18n.normalizeHash = function(hash, hashTypes) {
|
523
|
+
for (var prop in hash) {
|
524
|
+
if (hashTypes[prop] === 'ID') {
|
525
|
+
hash[prop + 'Binding'] = hash[prop];
|
526
|
+
delete hash[prop];
|
527
|
+
}
|
528
|
+
}
|
529
|
+
};
|
530
|
+
|
531
|
+
Ember.View.reopenClass({
|
532
|
+
registerHelper: function(helperName, helperClass) {
|
533
|
+
Ember.Handlebars.registerHelper(helperName, function(options) {
|
534
|
+
var hash = options.hash,
|
535
|
+
types = options.hashTypes;
|
536
|
+
|
537
|
+
I18n.normalizeHash(hash, types);
|
538
|
+
return Ember.Handlebars.helpers.view.call(this, helperClass, options);
|
539
|
+
});
|
540
|
+
},
|
541
|
+
|
542
|
+
renderIfChanged: function() {
|
543
|
+
var args = Array.prototype.slice.call(arguments, 0);
|
544
|
+
args.unshift(function () { this.rerender(); });
|
545
|
+
return Ember.observer.apply(this, args);
|
546
|
+
}
|
547
|
+
});
|
548
|
+
|
549
|
+
/**
|
550
|
+
Look up a translation for an i18n key in our dictionary.
|
551
|
+
|
552
|
+
@method i18n
|
553
|
+
@for Handlebars
|
554
|
+
**/
|
555
|
+
Ember.Handlebars.registerHelper('i18n', function(property, options) {
|
556
|
+
// Resolve any properties
|
557
|
+
var params = options.hash,
|
558
|
+
self = this;
|
559
|
+
|
560
|
+
_.each(params, function(value, key) {
|
561
|
+
params[key] = Em.Handlebars.get(self, value, options);
|
562
|
+
});
|
563
|
+
|
564
|
+
return I18n.t(property, params);
|
565
|
+
});
|
566
|
+
|
567
|
+
/**
|
568
|
+
Bound version of i18n helper.
|
569
|
+
**/
|
570
|
+
Ember.Handlebars.registerBoundHelper("boundI18n", function(property, options) {
|
571
|
+
return new Handlebars.SafeString(I18n.t(property, options.hash));
|
572
|
+
});
|
573
|
+
|
574
|
+
/**
|
575
|
+
Set up an i18n binding that will update as a count changes, complete with pluralization.
|
576
|
+
|
577
|
+
@method countI18n
|
578
|
+
@for Handlebars
|
579
|
+
**/
|
580
|
+
Ember.Handlebars.registerHelper('countI18n', function(key, options) {
|
581
|
+
var view = Ember.View.extend({
|
582
|
+
tagName: 'span',
|
583
|
+
shouldRerender: Ember.View.renderIfChanged('count'),
|
584
|
+
|
585
|
+
render: function(buffer) {
|
586
|
+
buffer.push(I18n.t(key, { count: this.get('count') }));
|
587
|
+
}
|
588
|
+
|
589
|
+
});
|
590
|
+
return Ember.Handlebars.helpers.view.call(this, view, options);
|
591
|
+
});
|
592
|
+
|
593
|
+
if (Ember.EXTEND_PROTOTYPES) {
|
594
|
+
String.prototype.i18n = function(options) {
|
595
|
+
return I18n.t(String(this), options);
|
596
|
+
};
|
597
|
+
}
|
598
|
+
}
|