Greasy Fork is available in English.
jquery.localizationTool
Этот скрипт недоступен для установки пользователем. Он является библиотекой, которая подключается к другим скриптам мета-ключом // @require https://update.greasyfork.org/scripts/403927/808323/jquerylocalizationTooljs.js
/*** @fileOverview Contains the code for jQuery.localizationTool** @author Savio Dimatteo <[email protected]>*/(function($) {var _keyboardPressed = false;var methods = {/*** Returns the ordinal number corresponding to the given language code,* or throws in case the given language code is not defined.* NOTE: this method operates on the active languages, therefore* $this.data('activeLanguageCodeArray') must be available when the* method is called.** @name _languageCodeToOrdinal* @function* @access private* @param {string} lanuageCode - the language code to convert to ordinal* @returns {number} ordinal - the converted ordinal*/'_languageCodeToOrdinal' : function (languageCode) {var $this = this,activeLanguageCodes = $this.data('activeLanguageCodeArray');var ordinal = $.inArray(languageCode, activeLanguageCodes);if (ordinal === -1) {$.error('Cannot convert ' + languageCode + ' into an ordinal number');}return ordinal;},/*** Returns the language code corresponding to the given ordinal number.* It throws in case the given ordinal number does not correspond to any* language code.* NOTE: this method operates on the active languages, therefore* $this.data('activeLanguageCodeArray') must be available when the* method is called.** @name _ordinalToLanguageCode* @function* @access private* @param {number} ordinal - the ordinal number to convert into a language code* @returns {string} languageCode - the converted language code*/'_ordinalToLanguageCode' : function (ordinal) {var $this = this,activeLanguageCodes = $this.data('activeLanguageCodeArray');if (activeLanguageCodes.length <= ordinal || ordinal < 0) {$.error('Cannot convert ' + ordinal + ' into a language code.');}return activeLanguageCodes[ordinal];},/*** Returns the html representation for the given language code.* @name _languageCodeToHtml* @function* @param {string} languageCode - the language code as defined in the settings object*/'_languageCodeToHtml': function (languageCode) {var $this = this,settings = $this.data('settings'),languagesObj = settings.languages,languageDefinitionObj = languagesObj[languageCode];var htmlClass = '';if (languageDefinitionObj.flag.hasOwnProperty('class')) {htmlClass = ' ' + languageDefinitionObj.flag['class'];}var htmlImage = '';if (languageDefinitionObj.flag.hasOwnProperty('url')) {htmlImage = '<img src="' + languageDefinitionObj.flag.url + '" />';}var languageName = languageDefinitionObj.language;var haveCountry = languageDefinitionObj.hasOwnProperty('country');/** Build up the html*/var html = [];html.push('<li class="ltool-language ', languageCode, '">');if (settings.showFlag) {html.push('<div class="ltool-language-flag', htmlClass, '"></div>');html.push(htmlImage);}var interpolatedTemplate = methods._interpolateTemplate.call($this,haveCountry ? languageDefinitionObj.country : undefined,languageName);html.push(interpolatedTemplate);html.push('</li>');return html.join('');},/*** Interpolates the given country name and language name to the* labelTemplate specified in the settings.** @param {string} countryName* the country name* @param {string} languageName* the language name** @returns {string}* the interpolated template*/_interpolateTemplate: function (countryName, languageName) {var $this = this,settings = $this.data('settings'),template = settings.labelTemplate,countryReplacement = '',languageReplacement = '',haveCountry = typeof countryName === 'string';if (settings.showCountry && haveCountry) {countryReplacement = ['<span class="ltool-language-country">','$1' + countryName.replace(/[$]/g, '$') + '$2','</span>'].join('');}if (settings.showLanguage) {var hasCountryClass = haveCountry ? 'ltool-has-country ' : "";languageReplacement = ['<span class="', hasCountryClass, 'ltool-language-name">','$1' + languageName.replace(/[$]/g, '$') + '$2' ,'</span>'].join('');}return '<span class="ltool-language-countryname">' +template.replace(/{{([^{]*)language([^}]*)}}/g, languageReplacement).replace(/{{([^{]*)country([^}]*)}}/g, countryReplacement) +'</span>';},/*** Displays the given language in the dropdown menu. 在下拉菜单中显示给定的语言。* @name _selectLanguage* @function* @access private* @param {string} languageCode - the language code*/'_selectLanguage': function (languageCode) {var $this = this;$this.find('.ltool-dropdown-label').html($('.ltool-language.' + languageCode).html());$this.data('selectedLanguageCode', languageCode);},/*** Initializes the localization tool widget. 初始化本地化工具小部件。* @name _initializeWidget* @function* @access private* @param {array} languageCodeArray - the language code array of the languages to be displayed*/'_initializeWidget': function (languageCodeArray) {var $this = this,settings = $this.data('settings'),languagesObj = settings.languages;var markupArray = [];markupArray.push('<span tabindex="0" class="ltool-dropdown-label">Change Language</span><div class="ltool-dropdown-label-arrow"></div>');markupArray.push('<ul class="ltool-dropdown-items">');var languageCode, i;for (i=0;languageCode=languageCodeArray[i++];) {if ( languagesObj.hasOwnProperty(languageCode)) {markupArray.push(methods._languageCodeToHtml.call($this, languageCode));}else {$.error('The language \'' + languageCode + '\' must be defined');}}markupArray.push('</ul>');$(markupArray.join('')).appendTo($this);return $this;},/*** Handles dropdown click event. 处理下拉单击事件。* @name _onDropdownClicked* @function* @access private*/'_onDropdownClicked' : function (/*e*/) {var $this = this;var selectedLanguageCode = $this.data('selectedLanguageCode');$this.find('.ltool-language').removeClass('ltool-is-selected');$this.find('.' + selectedLanguageCode).addClass('ltool-is-selected');$this.toggleClass('ltool-is-visible');return $this;},'_closeDropdown' : function () {var $this = this;$this.removeClass('ltool-is-visible');},/*** Handles mouseout on dropdown items.* @name _onMouseout* @function* @access private*/'_onMouseout': function (e) {var $this = this;if ($this.find(e.relatedTarget).length > 0) {// get rid of the current selected item!$this.find('.ltool-is-selected').removeClass('ltool-is-selected');// we will be over an element of ourse.preventDefault();return $this;}/* We will be over another element that doesn't belong to us */$this.removeClass('ltool-is-visible');},/*** Handles user clicks on a certain dropdown item. 处理用户单击某个下拉项。* @name _onLanguageSelected* @function* @param {$element} $item - the jquery item clicked* @access private*/'_onLanguageSelected': function ($item) {var $this = this;// extract language code from the $itemvar languageCode = $item.attr('class').replace('ltool-language', '').replace('ltool-is-selected', '').replace(/ /g, '');//存储当前选择的语言console.log("存储! languageCode: ",languageCode);gc_multiLanguage.saveConfig(languageCode);methods._selectLanguage.call($this, languageCode);methods._mayTranslate.call($this, languageCode);},/*** Select the language before the current language in the list. 在列表中选择当前语言之前的语言。* @name _selectPreviousLanguage* @function* @access private*/'_selectPreviousLanguage' : function () {var $this = this;var currentLanguageCode = $this.data('selectedLanguageCode');var currentLanguageCodeOrdinal = methods._languageCodeToOrdinal.call($this, currentLanguageCode);if (currentLanguageCodeOrdinal === 0) {return; // cannot go before the first language}var nextLanguageCode = methods._ordinalToLanguageCode.call($this, currentLanguageCodeOrdinal-1);// peform the selection$this.find('.ltool-is-selected').removeClass('ltool-is-selected');methods._selectLanguage.call($this, nextLanguageCode);methods._mayTranslate.call($this, nextLanguageCode);$this.find('.' + nextLanguageCode).addClass('ltool-is-selected');return $this;},/*** Select the language after the current language in the list. 选择列表中当前语言之后的语言。* @name _selectPreviousLanguage* @function* @access private*/'_selectNextLanguage' : function () {var $this = this,activeLanguageCodes = $this.data('activeLanguageCodeArray');var currentLanguageCode = $this.data('selectedLanguageCode');var currentLanguageCodeOrdinal = methods._languageCodeToOrdinal.call($this, currentLanguageCode);if (currentLanguageCodeOrdinal + 1 >= activeLanguageCodes.length) {return;}var nextLanguageCode = methods._ordinalToLanguageCode.call($this, currentLanguageCodeOrdinal+1);// peform the selection$this.find('.ltool-is-selected').removeClass('ltool-is-selected');methods._selectLanguage.call($this, nextLanguageCode);methods._mayTranslate.call($this, nextLanguageCode);$this.find('.' + nextLanguageCode).addClass('ltool-is-selected');return $this;},/*** Handles keydown event* @name _onKeydown* @function* @param {event} e - the keydown event* @access private*/'_onKeydown': function (e) {var $this = this;switch (e.keyCode) {case 13: /* enter (open-close menu) */methods._onDropdownClicked.call($this);e.preventDefault();break;case 40: /* down (select next) */methods._selectNextLanguage.call($this);e.preventDefault();break;case 38: /* up (select previous) */methods._selectPreviousLanguage.call($this);e.preventDefault();break;case 27:methods._closeDropdown.call($this);e.preventDefault();break;}return $this;},/*** Binds events to the localization tool widget.* @name _bindEvents* @function* @access private*/'_bindEvents': function () {var $this = this;$this.bind('mousedown.localizationTool', function (e) {_keyboardPressed = false;methods._onKeydown.call($this, e);}).bind('click.localizationTool', function (e) {methods._onDropdownClicked.call($this, e);}).bind('keydown.localizationTool', function (e){_keyboardPressed = true;methods._onKeydown.call($this, e);}).bind('mouseout.localizationTool', function (e) {methods._onMouseout.call($this, e);}).bind('focusout.localizationTool', function () {if (_keyboardPressed) {methods._closeDropdown.call($this);}});$this.find('.ltool-language').bind('click.localizationTool', function (/*e*/) {methods._onLanguageSelected.call($this, $(this));});return $this;},/*** Analizes the input strings object and decomposes its keys in* sections: text strings, id strings, class strings, element strings,* attribute strings.* @name _decomposeStringsForReferenceMapping* @function* @access private* @returns {object} the decomposition object.*/'_decomposeStringsForReferenceMapping' : function () {var decompositionObj = {'idStrings' : [],'classStrings' : [],'elementStrings' : [],'textStrings' : [],'attributeStrings' : []};var $this = this,stringsObj = $this.data('settings').strings;// regexp for attributes matchingvar attrRegexp = new RegExp('^[a-zA-Z-]+?::');var stringKey;for (stringKey in stringsObj) {if (stringsObj.hasOwnProperty(stringKey)) {if (stringKey.match(attrRegexp)) { // NOTE: check first!decompositionObj.attributeStrings.push(stringKey);}else if (stringKey.indexOf('id:') === 0) {decompositionObj.idStrings.push(stringKey);}else if (stringKey.indexOf('class:') === 0) {decompositionObj.classStrings.push(stringKey);}else if (stringKey.indexOf('element:') === 0) {decompositionObj.elementStrings.push(stringKey);}else {decompositionObj.textStrings.push(stringKey);}}}return decompositionObj;},/*** Goes through each text node and builds a string reference mapping.* It is a mapping (an object)* STRING_IDENTIFIER -> <IS_ATTRIBUTE?, ORIGINAL_HTML, [DOM_NODES]>* used later for the translation. See init method for a* reference. The r###lting object is stored internally in* $this.data('refMappingObj') as refMapping.* @name _buildStringReferenceMapping* @function* @access private*/'_buildStringReferenceMapping': function () {var $this = this,refMapping = {},settings = $this.data('settings'),stringsObj = settings.strings;// decompose the initial strings in various bitsvar decompositionObj = methods._decomposeStringsForReferenceMapping.call($this);/** First go through each id*/var idString, i;for (i=0; idString = decompositionObj.idStrings[i++];) {var idStringName = idString.substring('id:'.length);var $idNode = $('#' + idStringName);var contents = $idNode.contents();if (settings.ignoreUnmatchedSelectors === true && contents.length === 0) {continue;}if (contents.length !== 1) {$.error(idString + ' must contain exactly one text node, found ' + contents.length + ' instead');}else if (contents[0].nodeType !== 3) {$.error(idString + ' does not contain a #text node (i.e., type 3)');}else {// add this to the refMappingrefMapping[idString] = {isAttribute : false, // it's an id: selectororiginalText : $idNode.text(),domNodes : [ $idNode ]};}}/** Helper function to not write the same code over again...*/var processMultipleElements = function (prefix, jqueryPrefix, checkForIds, checkForClasses) {var string;var decompositionKeyPrefix = prefix.replace(':','');for (i=0; string = decompositionObj[decompositionKeyPrefix + 'Strings'][i++];) {var stringName = string.substring(prefix.length);// keeps the text of the first dom node in the loop belowvar domNodeText;var domNodesArray = [];var allNodeTextsAreEqual = true;domNodeText = undefined; // note: assigns undefinedvar k=0, node;NODE:for (; node = $(jqueryPrefix + stringName)[k++];) {var $node = $(node);if (checkForIds) {var nodeId = $node.attr('id');// skip any node that was previously translated via an idif (typeof nodeId === 'string' && stringsObj.hasOwnProperty('id:' + nodeId)) {continue NODE;}}if (checkForClasses) {// skip any node that was previously translated via a classvar nodeClasses = $node.attr('class');if (typeof nodeClasses === 'string') {var nodeClassArray = nodeClasses.split(' '),nodeClass,j = 0;for(;nodeClass = nodeClassArray[j++];) {if (typeof nodeClass === 'string' && stringsObj.hasOwnProperty('class:' + nodeClass)) {continue NODE;}}}}// make sure this node contains only one text contentvar nodeContents = $node.contents();if (nodeContents.length === 0 || nodeContents.length > 1) {$.error('A \'' + string + '\' node was found to contain ' + nodeContents.length + ' child nodes. This node must contain exactly one text node!');continue;}if (nodeContents[0].nodeType !== 3) {$.error('A \'' + string + '\' node does not contain a #text node (i.e., type 3)');continue;}// this node is pushable at this point...domNodesArray.push($node);// also check the text is the same across the nodes consideredif (typeof domNodeText === 'undefined') {// ... the first time we store the text of the nodedomNodeText = $node.text();}else if (domNodeText !== $node.text()) {// ... then we keep checking if the text node is the sameallNodeTextsAreEqual = false;}} // end for k loop// make sure that the remaining classes contain the same textif (!allNodeTextsAreEqual) {$.error('Not all text content of elements with ' + string + ' were found to be \'' + domNodeText + '\'. So these elements will be ignored.');}else {// all goodrefMapping[string] = {isAttribute : false, // it's a class: or an element: selectororiginalText : domNodeText,domNodes : domNodesArray};}}}; // end of processMultipleElements/** Then go through classes*/processMultipleElements('class:', '.', true, false);/** Then go through elements*/processMultipleElements('element:', '', true, true);/** Time to process the attributes*/var firstSelectorStringRegex = new RegExp('(class|id|element):[^:]');var attrString;for (i=0; attrString = decompositionObj.attributeStrings[i++];) {// let's extract the attribute name from the element selectorvar splitStringArray = attrString.split("::");var attributeString = splitStringArray.shift();// sanity check on the formatif (splitStringArray.length === 0) {$.error('sorry, you need to specify class:, element: or id: selectors in ' + attrString);}var selectorString = splitStringArray.join('::');if (!splitStringArray[0].match(firstSelectorStringRegex)) {$.error(attrString + "Doesn't look right. Perhaps you've added extra semicolons?");}// turn selector into jQuery selectorselectorString = selectorString.replace('id:', '#');selectorString = selectorString.replace('class:', '.');selectorString = selectorString.replace('element:', '');// find DOM nodesvar $domNodes = $(selectorString + '[' + attributeString + ']');if ($domNodes.length === 0) {$.error('The selector "' + attrString + '" does not point to an existing DOM element');}// avoid using Array.prototype.reduce as it's supported in IE9+var j = 0,allSameAttributeValue = true;var attributeText = $($domNodes[0]).attr(attributeString);var domNodesToAdd = [];for (j=0; j<$domNodes.length; j++) {// check the placeholder text is all the samevar $dom = $($domNodes[j]);if (attributeText !== $dom.attr(attributeString)) {allSameAttributeValue = false;}// also add for later...domNodesToAdd.push($dom);}if (!allSameAttributeValue) {$.error('Not all the attribute values selected via ' + attrString + ' are the same');}// now we have everything in place, we just add it to the rest!refMapping[attrString] = {isAttribute : true, // yes, we are dealing with an attribute hereoriginalText : attributeText,domNodes : domNodesToAdd};}/** Finally find the dom nodes associated to any text searched*/var textString;for (i=0; textString = decompositionObj.textStrings[i++];) {// nodes that will contain the text to translatevar textNodesToAdd = [];var allParentNodes = $(':contains(' + textString + ')');var k, parentNode;for (k=0; parentNode = allParentNodes[k++];) {var nodeContents = $(parentNode).contents();if (nodeContents.length === 1 &&nodeContents[0].nodeType === 3) {textNodesToAdd.push($(parentNode));}}if (textNodesToAdd.length > 0) {// all goodrefMapping[textString] = {isAttribute: false, // no it's just another dom elementoriginalText : textString,domNodes : textNodesToAdd};}}$this.data('refMappingObj', refMapping);return $this;},/*** Calls the user specified callback (if any), then translates the page.* If the user returned 'false' in his/her callback, the translation is* not performed.* @name _mayTranslate* @function* @access private* @param {string} [languageCode] - the language code to translate to*/'_mayTranslate': function (languageCode) {var $this = this,settings = $this.data('settings');if (false !== settings.onLanguageSelected(languageCode)) {methods._translate.call($this, languageCode);}},/*** Returns the code of the language currently selected* @name getSelectedLanguageCode* @function* @access public* @returns {string} [languageCode] - the language code currently selected*/'getSelectedLanguageCode' : function () {var $this = this;return $this.data('selectedLanguageCode');},/*** Translates the current page.* @name translate* @function* @access public* @param {string} [languageCode] - the language to translate to.*/'_translate': function (languageCode) {var $this = this,settings = $this.data('settings'),stringsObj = settings.strings,refMappingObj = $this.data('refMappingObj');var cssDirection = 'ltr';if (typeof languageCode !== 'undefined') {// check if the language code exists actuallyif (!settings.languages.hasOwnProperty(languageCode)) {$.error('The language code ' + languageCode + ' is not defined');return $this;}// check if we are dealing with a right to left languageif (settings.languages[languageCode].hasOwnProperty('cssDirection')) {cssDirection = settings.languages[languageCode].cssDirection;}}// translate everything according to the reference mappingvar string;for (string in refMappingObj) {if (refMappingObj.hasOwnProperty(string)) {// get the translation for this string...var translation;if (typeof languageCode === 'undefined' || languageCode === settings.defaultLanguage) {translation = refMappingObj[string].originalText;}else {translation = stringsObj[string][languageCode];}//console.log("翻译的文本:",translation);//console.log("语言代码:",languageCode);var domNodes = refMappingObj[string].domNodes;var $domNode, i;// attribute caseif (refMappingObj[string].isAttribute === true) {var attributeName = string.split("::", 1)[0];for (i=0; $domNode = domNodes[i++];) {$domNode.attr(attributeName, translation);$domNode.css('direction', cssDirection);}}else {// all other casesfor (i=0; $domNode = domNodes[i++];) {$domNode.html(translation);$domNode.css('direction', cssDirection);}}}}return $this;},/*** Translates according to the widget configuration programmatically.* This is meant to be called by the user. The difference with the* private counterpart _translate method is that the language is* selected in the widget.*/'translate' : function (languageCode) {var $this = this;methods._translate.call($this, languageCode);// must also select the language when translating via the public methodmethods._selectLanguage.call($this, languageCode);return $this;},/*** Destroys the dropdown widget.** @name destroy* @function* @access public**/'destroy' : function () {var $this = this;// remove all data set with .data()$this.removeData();// unbind events$this.unbind('click.localizationTool', function (e) {methods._onDropdownClicked.call($this, e);});$this.find('.ltool-language').unbind('click.localizationTool', function (/*e*/) {methods._onLanguageSelected.call($this, $(this));});$this.unbind('mouseout.localizationTool', function (e) {methods._onMouseout.call($this, e);});// remove markup$this.empty();return $this;},/*** Sorts the given array of countryLanguageCodes by country name.* If a language has no name goes to the bottom of the list.** @name _sortCountryLanguagesByCountryName* @function* @access private* @param {object} languagesDefinition - the array countryLanguageCodes defined during initialization.* @param {array} arrayOfCountryLanguageCodes - the input array countryLanguageCodes.* @returns {array} sortedArrayOfCountryLanguageCodes - the sorted array countryLanguageCodes.*/'_sortCountryLanguagesByCountryName': function (languagesDefinition, arrayOfCountryLanguageCodes) {return arrayOfCountryLanguageCodes.sort(function (a, b) {if (languagesDefinition[a].hasOwnProperty('country') && languagesDefinition[b].hasOwnProperty('country')) {return languagesDefinition[a].country.localeCompare(languagesDefinition[b].country);}else if (languagesDefinition[a].hasOwnProperty('country')) {return languagesDefinition[a].country.localeCompare(languagesDefinition[b].language);}// else if (languagesDefinition[b].hasOwnProperty('country')) {return languagesDefinition[a].language.localeCompare(languagesDefinition[b].country);// }});},/*** Goes through each string defined and extracts the common subset of* languages that actually used. The default language is added to this* subset a priori. The r###lting list is sorted by country name.** @name _findSubsetOfUsedLanguages* @function* @access private* @param {object} stringsObj - the strings to translate* @returns {array} usedLanguageCodes - an array of country codes sorted based on country names.*/'_findSubsetOfUsedLanguages' : function (stringsObj) {var $this = this;var string;var settings = $this.data('settings');// build an histogram of all the used languages in stringsvar usedLanguagesHistogram = {};var howManyDifferentStrings = 0;for (string in stringsObj) {if (stringsObj.hasOwnProperty(string)) {var languages = stringsObj[string],language;for (language in languages) {if (languages.hasOwnProperty(language)) {if (!usedLanguagesHistogram.hasOwnProperty(language)) {usedLanguagesHistogram[language] = 0;}}usedLanguagesHistogram[language]++;}howManyDifferentStrings++;}}// find languages that are guaranteed to appear in all stringsvar guaranteedLanguages = [],languageCode;for (languageCode in usedLanguagesHistogram) {if (usedLanguagesHistogram.hasOwnProperty(languageCode) &&usedLanguagesHistogram[languageCode] === howManyDifferentStrings) {guaranteedLanguages.push(languageCode);}}// delete the default language if it's in the guaranteed languagesvar defaultIdx = $.inArray(settings.defaultLanguage, guaranteedLanguages);if (defaultIdx > -1) {// delete the default language from the arrayguaranteedLanguages.splice(defaultIdx, 1);}// add the default language in frontguaranteedLanguages.unshift(settings.defaultLanguage);return methods._sortCountryLanguagesByCountryName.call(this,settings.languages,guaranteedLanguages);},/*** Initialises the localization tool plugin.* @name init* @function* @param {object} [options] - the user options* @access public* @returns jqueryObject*/'init' : function(options) {// NOTE: "country" is optionalvar knownLanguages = {'en_GB' : {'country' : 'United Kingdom','language': 'English','countryTranslated' : 'United Kingdom','languageTranslated': 'English','flag': {'class' : 'flag flag-gb'}},'de_DE' : {'country' : 'Germany','language' : 'German','countryTranslated' : 'Deutschland','languageTranslated' : 'Deutsch','flag' : {'class' : 'flag flag-de'}},'es_ES' : {'country' : 'Spain','language' : 'Spanish','countryTranslated': 'España','languageTranslated' : 'Español','flag' : {'class' : 'flag flag-es'}},'fr_FR' : {'country' : 'France','language' : 'French','countryTranslated' : 'France','languageTranslated' : 'Français','flag' : {'class' : 'flag flag-fr'}},'ko_KR' : {'country' : 'Korea, Republic of.','language' : 'Korean','countryTranslated' : '대한민국','languageTranslated' : '한국어','flag' : {'class' : 'flag flag-kr'}},'pt_BR' : {'country' : 'Brazil','language' : 'Portuguese','countryTranslated': 'Brasil','languageTranslated' : 'Português','flag' : {'class' : 'flag flag-br'}},'en_AU' : {'country' : 'Australia','language' : 'English','countryTranslated' : 'Australia','languageTranslated' : 'English','flag' : {'class' : 'flag flag-au'}},'en_IN' : {'country' : 'India','language' : 'English','countryTranslated': 'India','languageTranslated': 'English','flag': {'class' : 'flag flag-in'}},'it_IT' : {'country' : 'Italy','language': 'Italian','countryTranslated': 'Italia','languageTranslated': 'Italiano','flag' : {'class' : 'flag flag-it'}},'jp_JP' : {'country' : 'Japan','language': 'Japanese','countryTranslated': '日本','languageTranslated': '日本語','flag' : {'class' : 'flag flag-jp'}},'ar_TN' : {'country' : 'Tunisia','language' : 'Arabic','countryTranslated': 'تونس','languageTranslated': 'عربي','cssDirection': 'rtl','flag' : {'class' : 'flag flag-tn'}},'en_IE' : {'country': 'Ireland','language': 'English','countryTranslated': 'Ireland','languageTranslated' : 'English','flag' : {'class' : 'flag flag-ie'}},'nl_NL': {'country' : 'Netherlands','language': 'Dutch','countryTranslated' : 'Nederland','languageTranslated' : 'Nederlands','flag' : {'class' : 'flag flag-nl'}},'zh_CN': {'country' : '#####','language' : 'Simplified Chinese','countryTranslated': '##','languageTranslated': '简体中文','flag' : {'class' : 'flag flag-cn'}},'zh_TW': {'country' : '######','language' : 'Traditional Chinese','countryTranslated': '##','languageTranslated': '繁體中文','flag' : {'class' : 'flag flag-tw'}},'fi_FI': {'country' : 'Finland','language' : 'Finnish','countryTranslated' : 'Suomi','languageTranslated' : 'Suomi','flag' : {'class' : 'flag flag-fi'}},'pt_PT' : {'country' : 'Portugal','language' : 'Portuguese','countryTranslated': 'Portugal','languageTranslated' : 'Português','flag' : {'class' : 'flag flag-pt'}},'pl_PL': {'country' : 'Poland','language': 'Polish','countryTranslated' : 'Polska','languageTranslated': 'Polski','flag' : {'class' : 'flag flag-pl'}},'ru_RU': {'country' : 'Russia','language' : 'Russian','languageTranslated': 'Русский','countryTranslated' : 'Россия','flag': {'class': 'flag flag-ru'}},'hi_IN': {'country' : 'India','language': 'Hindi','countryTranslated': 'भारत','languageTranslated': 'हिन्द','flag': {'class': 'flag flag-in'}},'ta_IN': {'country' : 'India','language': 'Tamil','countryTranslated': 'இந்தியா','languageTranslated': 'தமிழ்','flag': {'class': 'flag flag-in'}},'tr_TR': {'country' : 'Turkey','language' : 'Turkish','countryTranslated': 'Türkiye','languageTranslated': 'Türkçe','flag': {'class': 'flag flag-tr'}},'he_IL': {'country' : 'Israel','language' : 'Hebrew','countryTranslated' : 'מדינת ישראל','languageTranslated': 'עברית','cssDirection': 'rtl','flag': {'class': 'flag flag-il'}},'da_DK' : {'country' : 'Denmark','language' : 'Danish','countryTranslated': 'Danmark','languageTranslated': 'Dansk','flag' : {'class': 'flag flag-dk'}},'ro_RO': {'country' : 'Romania','language' : 'Romanian','countryTranslated': 'România','languageTranslated': 'Român','flag' : {'class': 'flag flag-ro'}},'eo' : {// NOTE: no country'language' : 'Esperanto','languageTranslated' : 'Esperanto','flag' : {'class': 'flag flag-esperanto'}}};var settings = $.extend({'defaultLanguage' : 'en_GB',/* do not throw error if a selector doesn't match */'ignoreUnmatchedSelectors': false,/* show the flag on the widget */'showFlag' : true,/* show the language on the widget */'showLanguage': true,/* show the country on the widget */'showCountry': true,/* format of the language/country label */'labelTemplate': '{{country}} {{(language)}}','languages' : {/** The format here is <country code>_<language code>.* - list of country codes: http://www.gnu.org/software/gettext/manual/html_node/Country-Codes.html* - list of language codes: http://www.gnu.org/software/gettext/manual/html_node/Usual-Language-Codes.html#Usual-Language-Codes*/},/** Strings are provided by the user of the plugin. Each entry* in the dictionary has the form:** [STRING_IDENTIFIER] : {* [LANGUAGE] : [TRANSLATION]* }** STRING_IDENTIFIER:* id:<html-id-name> OR* class:<html-class-name> OR* element:<html-element-name> OR* <string>** LANGUAGE: one of the languages defined above (e.g., it_IT)** TRANSLATION: <string>**/'strings' : {},/** A callback called whenever the user selects the language* from the dropdown menu. If false is returned, the* translation will not be performed (but just the language* will be selected from the widget).** The countryLanguageCode is a string representing the* selected language identifier like 'en_GB'*/'onLanguageSelected' : function (/*countryLanguageCode*/) { return true; }}, options);// add more languagessettings.languages = $.extend(knownLanguages, settings.languages);// check that the default language is definedif (!settings.languages.hasOwnProperty(settings.defaultLanguage)) {$.error('FATAL: the default language ' + settings.defaultLanguage + ' is not defined in the \'languages\' parameter!');}return this.each(function() {// save settingsvar $this = $(this);$this.data('settings', settings);// language codes common to all translationsvar activeLanguageCodeArray = methods._findSubsetOfUsedLanguages.call($this, settings.strings);$this.data('activeLanguageCodeArray', activeLanguageCodeArray);methods._initializeWidget.call($this, activeLanguageCodeArray);methods._selectLanguage.call($this, settings.defaultLanguage);methods._bindEvents.call($this);methods._buildStringReferenceMapping.call($this);});}};var __name__ = 'localizationTool';/*** jQuery Localization Tool - a jQuery widget to translate web pages** @memberOf jQuery.fn*/$.fn[__name__] = function(method) {/** Just a router for method calls*/if (methods[method]) {if (this.data('initialized') === true) {// call a methodreturn methods[method].apply(this,Array.prototype.slice.call(arguments, 1));}else {throw new Error('method ' + method + ' called on an uninitialized instance of ' + __name__);}}else if (typeof method === 'object' || !method) {// call init, user passed the settings as parametersthis.data('initialized', true);return methods.init.apply(this, arguments);}else {$.error('Cannot call method ' + method);}};})(jQuery);