ExposeTranslationBundle[Symfony2] A pretty nice way to expose your translation messages to your JavaScript. | |
| Resources/public/js/translation.js |
|
Define Translation class.
|
$.ExposeTranslation = $.ExposeTranslation || {};
(function(Translation, $, undefined) {
$.extend(Translation, (function() {
var _messages = {},
_sPluralRegex = /^\w+\: +(.+)$/,
_cPluralRegex = /^(({\s*(\-?\d+[\s*,\s*\-?\d+]*)\s*})|([\[\]])\s*(-Inf|\-?\d+)\s*,\s*(\+?Inf|\-?\d+)\s*([\[\]]))\s+(.+?)$/,
_iPluralRegex = /^({\s*(\-?\d+[\s*,\s*\-?\d+]*)\s*})|([\[\]])\s*(-Inf|\-?\d+)\s*,\s*(\+?Inf|\-?\d+)\s*([\[\]])/;
|
|
replace placeholders in given message.
WARNING: used placeholders are removed.
param: String message The translated message. param: Object placeholders The placeholders to replace. return: String A human readable message. api: private
|
function replace_placeholders(message, placeholders) {
var _i,
_message = message,
_prefix = Translation.placeHolderPrefix,
_suffix = Translation.placeHolderSuffix;
for (_i in placeholders) {
var _r = new RegExp(_prefix + _i + _suffix, 'g');
if (_r.test(_message)) {
_message = _message.replace(_r, placeholders[_i]);
delete(placeholders[_i]);
}
}
return _message;
}
|
|
Guess the domain if you don't specify it, based on
given default domains.
|
function guess_domain(key) {
var _k,
_key = key,
_defaultDomains = Translation.defaultDomains;
if (!$.isArray(Translation.defaultDomains)) {
_defaultDomains = [Translation.defaultDomains];
}
for (_k in _defaultDomains) {
if (Translation.has(_defaultDomains[_k] + ':' + key)) {
return Translation.get(_defaultDomains[_k] + ':' + key);
}
}
return undefined;
}
|
|
The logic comes from the Symfony2 PHP Framework.
Given a message with different plural translations separated by a
pipe (|), this method returns the correct portion of the message based
on the given number, the current locale and the pluralization rules
in the message itself.
The message supports two different types of pluralization rules:
interval: {0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples
indexed: There is one apple|There is %count% apples
The indexed solution can also contain labels (e.g. one: There is one apple).
This is purely for making the translations more clear - it does not
affect the functionality.
The two methods can also be mixed:
{0} There is no apples|one: There is one apple|more: There is %count% apples
param: String message The message. param: Number number The number. return: String The message part to use for translation. api: private
|
function pluralize(message, number) {
var _p,
_r,
_number = number,
_explicitRules = [],
_standardRules = [],
_parts = message.split(Translation.pluralSeparator);
for (_p in _parts) {
var _part = _parts[_p];
var _rc = new RegExp(_cPluralRegex);
var _rs = new RegExp(_sPluralRegex);
if (_rc.test(_part)) {
var _matches = _part.match(_rc);
_explicitRules[_matches[0]] = _matches[_matches.length - 1];
} else if (_rs.test(_part)) {
var _matches = _part.match(_rs);
_standardRules.push(_matches[1]);
} else {
_standardRules.push(_part);
}
}
for (_e in _explicitRules) {
var _r = new RegExp(_iPluralRegex);
if (_r.test(_e)) {
var _matches = _e.match(_r);
if (_matches[1]) {
var _ns = _matches[2].split(',');
for (_n in _ns) {
if (_number == _ns[_n]) {
return _explicitRules[_e];
}
}
} else {
var _leftNumber = convert_number(_matches[4]);
var _rightNumber = convert_number(_matches[5]);
if (('[' === _matches[3] ? _number >= _leftNumber : _number > _leftNumber) &&
(']' === _matches[6] ? _number <= _rightNumber : _number < _rightNumber))
{
return _explicitRules[_e];
}
}
}
}
return _standardRules[plural_position(number)] || undefined;
}
|
|
The logic comes from the Symfony2 PHP Framework.
Convert number as String, "Inf" and "-Inf"
values to number values.
|
function convert_number(number) {
if ('-Inf' === number) {
return Math.log(0);
} else if ('+Inf' === number || 'Inf' === number) {
return -Math.log(0);
}
return parseInt(number);
}
|
|
The logic comes from the Symfony2 PHP Framework.
Returns the plural position to use for the given locale and number.
|
function plural_position(number) {
var _locale = Translation.locale || Translation.fallback;
if ('pt_BR' === _locale) {
_locale = 'xbr';
}
if (_locale.length > 3) {
_locale = _locale.split('_')[0];
}
switch (_locale) {
case 'bo':
case 'dz':
case 'id':
case 'ja':
case 'jv':
case 'ka':
case 'km':
case 'kn':
case 'ko':
case 'ms':
case 'th':
case 'tr':
case 'vi':
case 'zh':
return 0;
break;
case 'af':
case 'az':
case 'bn':
case 'bg':
case 'ca':
case 'da':
case 'de':
case 'el':
case 'en':
case 'eo':
case 'es':
case 'et':
case 'eu':
case 'fa':
case 'fi':
case 'fo':
case 'fur':
case 'fy':
case 'gl':
case 'gu':
case 'ha':
case 'he':
case 'hu':
case 'is':
case 'it':
case 'ku':
case 'lb':
case 'ml':
case 'mn':
case 'mr':
case 'nah':
case 'nb':
case 'ne':
case 'nl':
case 'nn':
case 'no':
case 'om':
case 'or':
case 'pa':
case 'pap':
case 'ps':
case 'pt':
case 'so':
case 'sq':
case 'sv':
case 'sw':
case 'ta':
case 'te':
case 'tk':
case 'ur':
case 'zu':
return (number == 1) ? 0 : 1;
case 'am':
case 'bh':
case 'fil':
case 'fr':
case 'gun':
case 'hi':
case 'ln':
case 'mg':
case 'nso':
case 'xbr':
case 'ti':
case 'wa':
return ((number == 0) || (number == 1)) ? 0 : 1;
case 'be':
case 'bs':
case 'hr':
case 'ru':
case 'sr':
case 'uk':
return ((number % 10 == 1) && (number % 100 != 11)) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2);
case 'cs':
case 'sk':
return (number == 1) ? 0 : (((number >= 2) && (number <= 4)) ? 1 : 2);
case 'ga':
return (number == 1) ? 0 : ((number == 2) ? 1 : 2);
case 'lt':
return ((number % 10 == 1) && (number % 100 != 11)) ? 0 : (((number % 10 >= 2) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2);
case 'sl':
return (number % 100 == 1) ? 0 : ((number % 100 == 2) ? 1 : (((number % 100 == 3) || (number % 100 == 4)) ? 2 : 3));
case 'mk':
return (number % 10 == 1) ? 0 : 1;
case 'mt':
return (number == 1) ? 0 : (((number == 0) || ((number % 100 > 1) && (number % 100 < 11))) ? 1 : (((number % 100 > 10) && (number % 100 < 20)) ? 2 : 3));
case 'lv':
return (number == 0) ? 0 : (((number % 10 == 1) && (number % 100 != 11)) ? 1 : 2);
case 'pl':
return (number == 1) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 12) || (number % 100 > 14))) ? 1 : 2);
case 'cy':
return (number == 1) ? 0 : ((number == 2) ? 1 : (((number == 8) || (number == 11)) ? 2 : 3));
case 'ro':
return (number == 1) ? 0 : (((number == 0) || ((number % 100 > 0) && (number % 100 < 20))) ? 1 : 2);
case 'ar':
return (number == 0) ? 0 : ((number == 1) ? 1 : ((number == 2) ? 2 : (((number >= 3) && (number <= 10)) ? 3 : (((number >= 11) && (number <= 99)) ? 4 : 5))));
default:
return 0;
}
}
return {
|
|
The current locale.
|
locale: '',
|
|
Fallback locale.
|
fallback: 'en',
|
|
Placeholder prefix.
|
placeHolderPrefix: '%',
|
|
Placeholder suffix.
|
placeHolderSuffix: '%',
|
|
Default domains.
type: String | Array api: public
|
defaultDomains: [],
|
|
Plurar separator.
|
pluralSeparator: '|',
|
|
Add a translation entry.
param: String key A translation key. param: String message A message for this key. return: Object Translation. api: public
|
add: function(key, message) {
_messages[key] = message;
return Translation;
},
|
|
Get the translated message for the given key.
param: String key A translation key. param: Object placeholders Placeholders. param: Number number A number of objects being described. return: String The corresponding message if the key exists.
|
get: function(key, placeholders, number) {
var _message = _messages[key] || guess_domain(key),
_number = parseInt(number),
_placeholders = $.extend({}, placeholders || {});
if (_message && !isNaN(_number)) {
_message = pluralize(_message, _number);
}
if (!_message) {
return key;
}
_message = replace_placeholders(_message, _placeholders);
return _message;
},
|
|
Determines wether a message is registered or not.
|
has: function(key) {
return (_messages[key] ? true : false);
}
};
})());
})($.ExposeTranslation, jQuery);
|