f1db5e1c96
Moved i18n config to config.js App is booted after locale data is fully downloaded The app needs reload after locale change
127 lines
3.8 KiB
JavaScript
127 lines
3.8 KiB
JavaScript
'use strict';
|
|
|
|
angular.module('myApp.i18n', ['izhukov.utils'])
|
|
.factory('_', [function() {
|
|
var locale = Config.I18n.locale;
|
|
var messages = Config.I18n.messages;
|
|
var fallbackMessages = Config.I18n.fallback_messages;
|
|
var paramRegEx = /\{\s*([a-zA-Z\d\--]+)(?:\s*:\s*(.*?))?\s*\}/g;
|
|
|
|
function insertParams(msgstr, params) {
|
|
return msgstr.replace(paramRegEx, function ($0, paramKey, nestedMsgStr) {
|
|
var param = params[paramKey];
|
|
if (param === undefined) {
|
|
console.warn('[i18n] missing param ' + paramKey + ' for message "' + msgstr + '"');
|
|
return '';
|
|
}
|
|
if (nestedMsgStr !== undefined) {
|
|
param = insertParams(param, nestedMsgStr.split('|'));
|
|
}
|
|
return param.toString().trim();
|
|
});
|
|
}
|
|
|
|
function encodeEntities(value) {
|
|
return value.
|
|
replace(/&/g, '&').
|
|
replace(/([^\#-~| |!])/g, function (value) { // non-alphanumeric
|
|
return '&#' + value.charCodeAt(0) + ';';
|
|
}).
|
|
replace(/</g, '<').
|
|
replace(/>/g, '>');
|
|
}
|
|
|
|
function parseMarkdownString(msgstr, msgid) {
|
|
msgstr = msgstr.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
|
|
.replace(/\n/g, "<br/>");
|
|
return msgstr;
|
|
}
|
|
|
|
function _(msgid, params) {
|
|
var raw = false;
|
|
var msgstr = msgid;
|
|
|
|
if (msgid.substr(-4) === '_raw') {
|
|
raw = true;
|
|
msgid = msgid.substr(0, msgid.length - 4);
|
|
}
|
|
|
|
if (messages.hasOwnProperty(msgid)) {
|
|
msgstr = messages[msgid];
|
|
} else if (fallbackMessages.hasOwnProperty(msgid)) {
|
|
msgstr = fallbackMessages[msgid];
|
|
console.warn('[i18n] missing locale key ' + locale + ' / ' + msgid);
|
|
} else {
|
|
console.warn('[i18n] missing key ' + msgid);
|
|
return msgid;
|
|
}
|
|
|
|
if (!raw) {
|
|
msgstr = encodeEntities(msgstr);
|
|
}
|
|
|
|
if (msgid.substr(-3) == '_md') {
|
|
msgstr = parseMarkdownString(msgstr);
|
|
}
|
|
|
|
if (arguments.length > 1) {
|
|
if (typeof params == 'string') {
|
|
Array.prototype.shift.apply(arguments);
|
|
msgstr = insertParams(msgstr, arguments);
|
|
} else {
|
|
msgstr = insertParams(msgstr, params);
|
|
}
|
|
}
|
|
|
|
return msgstr;
|
|
}
|
|
|
|
_.supported = function () {
|
|
return Config.I18n.supported;
|
|
};
|
|
|
|
_.locale = function () {
|
|
return locale;
|
|
};
|
|
|
|
return _;
|
|
}])
|
|
|
|
.filter('i18n', ['_', function(_) {
|
|
return _;
|
|
}])
|
|
|
|
.directive('ngPluralize', ['_', function(_) {
|
|
return {
|
|
restrict: 'EA',
|
|
priority: 1, // execute before built-in ngPluralize
|
|
compile: function(element) {
|
|
var msgid = element.attr('when');
|
|
var msgstr = _(msgid);
|
|
element.attr('when', msgstr);
|
|
}
|
|
}
|
|
}])
|
|
|
|
.directive('myI18n', ['_', function(_) {
|
|
return {
|
|
restrict: 'EA',
|
|
compile: function(element) {
|
|
var params = element.children('my-i18n-param:not([name]), [my-i18n-param=""]:not([name])').map(function(index, param) {
|
|
return param.outerHTML;
|
|
}).toArray();
|
|
element.children('my-i18n-param[name], [my-i18n-param]:not([my-i18n-param=""]), [my-i18n-param][name]').each(function(i, param) {
|
|
params[angular.element(param).attr('my-i18n-param') || angular.element(param).attr('name')] = param.outerHTML;
|
|
});
|
|
element.children('my-i18n-param').remove();
|
|
var formats = element.attr("my-i18n") || element.attr("msgid") ? element : element.children('my-i18n-format, [my-i18n-format]');
|
|
formats.each(function(index, element) {
|
|
var format = angular.element(element);
|
|
var msgid = format.attr("my-i18n") || format.attr("msgid") || format.attr("my-i18n-format") || format.html().replace(/\s+/g, ' ').trim();
|
|
var msgstr = _(msgid, params);
|
|
format.html(msgstr);
|
|
});
|
|
}
|
|
}
|
|
}]);
|