diff options
Diffstat (limited to 'public/js/i_gettext.js')
-rw-r--r-- | public/js/i_gettext.js | 1487 |
1 files changed, 0 insertions, 1487 deletions
diff --git a/public/js/i_gettext.js b/public/js/i_gettext.js deleted file mode 100644 index bfa2c4c..0000000 --- a/public/js/i_gettext.js +++ /dev/null @@ -1,1487 +0,0 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ -/*================================================================================================================================================= - * Pure Javascript implementation of Uniforum message translation. - * This implementation of GNU Gettext, providing internationalization support for javascript. - * It differs from existing javascript implementations in that it will support all current Gettext features - *(ex. plural and context support), and will also support loading language catalogs from .mo, .po, or preprocessed json files (converter included). - * It use this [2008 - Javascript Gettext](https://sourceforge.net/projects/jsgettext.berlios/?source=navbar) - * Thank to [Joshua I. Miller](mailto:unrtst@cpan.org) for that great work. - *================================================================================================================================================= - -- The following methods are kept in: - - textdomain (domain) - gettext (msgid) - dgettext (domainname, msgid) - dcgettext (domainname, msgid, LC_MESSAGES) - ngettext (msgid, msgid_plural, count) - dngettext (domainname, msgid, msgid_plural, count) - dcngettext (domainname, msgid, msgid_plural, count, LC_MESSAGES) - pgettext (msgctxt, msgid) - dpgettext (domainname, msgctxt, msgid) - dcpgettext (domainname, msgctxt, msgid, LC_MESSAGES) - npgettext (msgctxt, msgid, msgid_plural, count) - dnpgettext (domainname, msgctxt, msgid, msgid_plural, count) - dcnpgettext (domainname, msgctxt, msgid, msgid_plural, count, LC_MESSAGES) - strargs (string, args_array) - -- The following methods are removed - - get_lang_refs (link) - isValidOject () - isArray (Object) - -- The following methods are completely rewritten - - new Gettext () - try_load_lang () - -- The following methods are added - - setlocale (locale) - bindtextdomaine (domain, path_to_locale, type) - try_load_alternative_lang (domain, link) - try_load_mo (data) //not yet ready @TODO put available when it will ready - parse_mo (data) //not yet ready @TODO put available when it will ready - parseHeader (data) //not yet ready @TODO put available when it will ready - -- Some other modifications are done for changes and updates - -The implementation of this library have been made to be more convenient with GNU Gettext references. -In addition, no only "po" or "mo" files can be use to content the messages data, but also "json" files or objects. - -This has been tested on the following browsers. It may work on others, but these are all those to which I have access. - FF1.5, FF2, FF3, IE6, IE7, Opera9, Opera10, Safari3.1, Chrome - *FF = Firefox - *IE = Internet Explorer - -SEE ALSO --------- -po2json (included), -docs/index.html, -test/ -Locale::gettext_pp(3pm), POSIX(3pm), gettext(1), gettext(3) - -*/ - -/** - * Javascript implemenation of GNU Gettext API. - * @class - * @constructs iJS.Gettext - * @returns {iJS.Gettext} - * @example - * //create new instance - * var igt = new iJS.Gettext() ; - * //set the locale in which the messages have to be translated. - * igt.setlocale("fr_FR.utf8") ; // local can also be *fr_FR* or *fr*. - * //Supposing that most users now have browser that support Ajax; - * //also add or register a domain where to get the messages data. - * igt.bindtextdomain("mydomain", "./path_to_locale", "po") ; //"po" can also be "json" or by default "mo". - * //Always do this after a `setlocale` or a `bindtextdomain` call. - * igt.try_load_lang() ; //will load and parse messages data from the setting catalog. - * //Then print your messages - * alert( igt.gettext("Hello world!") ) ; - * - * //Like with GNU gettext, your domain path have to be - * // path_to_locale/LC_MESSAGES/fr_FR.utf8/mydomain.po - * // if "fr_FR.utf8" is not found, "fr_FR" or "fr" will be use for replacement. - * //This is just an overview. See tutoriels for more. - * - * //Optimum caching way to add domain is to use *<script>* tag to load it via *iJS.Gettext*’s json like file. - * //just do this to add or register a domain where to get the messages data. - * igt.locale_data = external_locale_data ; - * igt.bindtextdomain("json-domain") ; //domain can be any domain in *external_locale_date* - * /* Supposing that this declaration have be done:`<SCRIPT language="javascript" src="path_to/gettext_json_file"></SCRIPT>` - * * and the gettext_json_file content structurate object like: - * external_locale_data = { - "json-domain" : { - // po header fields - "" : { - "plural-forms" : "...", - "lang" : "en", - }, - // all the msgid strings and translations - "msgid" : [ "msgid_plural", "translation", "plural_translation" ], - "msgctxt\004msgid" : [ null, "msgstr" ], - }, - "AnotherDomain" : { - }, - }; - */ -iJS.Gettext = function () { - - this.domain = 'messages'; - this.domain_registry = [] ; // will content all the indicated domain and associated paths - // locale_data will be populated when will `try_load_lang` - this.locale_data = undefined; - this.locale_format = null; // will indicate how the locale name is formatted - this.locale = null; - - return this; -} - -/** - * @property {iJS.Gettext} i18n Defined `Gettext` object, to make *iJS gettext* functionalities to be directly use. - * @example - * //set the locale in which the messages will be translated - * iJS.i18n.setlocale("en_US.utf8") ; - * //add domain where to find messages data - * iJS.i18n.bindtextdomain("domain_po", "./path_to_locale", "po") ; - * //add another domain where to find messages data - * iJS.i18n.bindtextdomain("domain_json", "./path_to_locale", "json") ; - * //Always do this after a `setlocale` or a `bindtextdomain` call. - * iJS.i18n.try_load_lang() ; //will load and parse messages data from the setting catalog. - * //set the current domain - * iJS.i18n.textdomain("domain_po") ; - * //now print your messages - * alert( iJS.i18n.gettext("messages to be translated") ) ; - */ -iJS.i18n = new iJS.Gettext() ; - -/** - * Easily translate your messages when use `Gettext` functionalities.<BR/> - * Same as you call `iJS.i18n.gettext()`. See documentation of associated terms for more informations. - * @global - * @param {String} msgid message to be translated - * @returns {String} translated message if is found or `msgid` if not. - * @example - * //set the locale in which the messages will be translated - * iJS.i18n.setlocale("en_US.utf8") ; - * //add domain where to find messages data - * iJS.i18n.bindtextdomain("domain_po", "./path_to_locale", "po") ; - * iJS.i18n.try_load_lang() ; //will load and parse messages data from the setting catalog. - * //now print your messages - * alert( iJS._("messages to be translated") ) ; - */ -iJS._ = function (msgid) { - - return iJS.i18n.gettext( msgid ) ; -} - -/** - * Set the locale in which the messages have to be translated. - * @memberof iJS.Gettext - * @param {String} locale egg: "en", "en_US.utf8", "en_GB" ... - */ -iJS.Gettext.prototype.setlocale = function (locale) { - - if (iJS.isString( locale )) { - - if (/^.._..\./.test( locale )) { - this.locale_format = 2 ; //egg: *en_US.utf8* - - } else if (/^.._..$/.test( locale )) { - this.locale_format = 1 ; //egg: *en_US* - - } else if (/^..$/.test( locale )) { - this.locale_format = 0 ; //egg: *en* - - } else { - this.locale_format = -1 ; //egg: *french* - console.warn("iJS-gettext:'setlocale': It seem like locale: *"+locale+"* do not conform to the **i18n standard format**.") ; - } - - this.locale = locale ; - //alert(this.locale) - } else { - throw new Error("iJS-gettext:'setlocale': Invalid argument: *"+locale+"* have to be a `string`.") ; - } -}; - -/** - * Add or register a domain where to get the messages data - * @memberof iJS.Gettext - * @param {string} domain The Gettext domain, not www.whatev.com. If the .po file was "myapp.po", this would be "myapp". - * @param {string} localePath Path to the locale directory where to find the domain. <BR/> - * <U>egg:</U> "./locale" in which we can have ".locale/LC_MESSAGES/fr_FR.utf8/domain.po". <BR/> - * If omitted, it will mean that domain will be considered in a json Object or file. - * See tutorials for more explanation. - * @param {string} dtype Type of domain file. Supported files are "po", "json" and "mo"(support is planned). - * If omitted, the default value will be "mo". - */ -iJS.Gettext.prototype.bindtextdomain = function (domain, localePath, dtype) { - - var new_domain, new_locale_path, new_dtype ; - - if (iJS.isString( domain )) { - new_domain = domain ; - - } else { - throw new Error("iJS-gettext:'bindtextdomain': a *domaine* have to be defined as argument.") ; - } - - if (iJS.isString( dtype )){ - - if ( dtype == "mo" || dtype == "po" || dtype == "json" ) { - new_dtype = dtype ; - - } else { - throw new Error("iJS-gettext:'bindtextdomain': type: *"+dtype+"* is not supported. Use *mo*, *po* or *json* files.") ; - } - } else { - new_dtype = "mo" ; - }; - - if (iJS.isString( localePath ) ) { - new_locale_path = localePath ; - - } else { - new_locale_path = "" ; - } - - - if ( !iJS.isArray( this.domain_registry ) ) this.domain_registry = []; - - if (!this.domain_registry.length) { //first initialization - this.domain_registry.push( {value: new_domain, path: new_locale_path, type: new_dtype} ) ; - - } else { //attempt to add new domain or reset if it’s already added. - - var isNewDomaine = true ; - - for (var d in this.domain_registry) { - - if (this.domain_registry[d].value == new_domain) { - - console.warn("iJS-gettext:'bindtextdomain': domaine: *"+new_domain+"* is already added and will just be reset") ; - this.domain_registry[d].path = new_locale_path ; - this.domain_registry[d].type = new_dtype ; - isNewDomaine = false ; - break; - } - } - - if (isNewDomaine) this.domain_registry.push( {value: new_domain, path: new_locale_path, type: new_dtype} ) ; - } -}; - -/** - * Use for some concatenation: see for example `iJS.Gettext.prototype.parse_po`. - * @private - * @memberof iJS.Gettext - */ -iJS.Gettext.context_glue = "\004" ; -/** - * json structure of all registered domain with corresponding messages data. - * It depend of setting locale which define the catalog that will be load. - * It will also content messages data that are parsed from developer’s defined json'd portable object. - * @private - * @memberof iJS.Gettext - */ -iJS.Gettext._locale_data = {} ; - -/** - * Load and parse all the messages data from domain in the domain’s registry. - * Data are load depending of the setting catalog or developer’s defined json’d portable object. - * Parsed data are save in a internal json structure, to make them easily accessible, depending of the current domain. - * This method have to be always call after a `setlocale` and `bindtextdomain` call. - * @memberof iJS.Gettext - */ -iJS.Gettext.prototype.try_load_lang = function () { - - if (iJS.isSet( this.domain_registry ) && iJS.isSet( this.locale) ) { - - /* @TODO execept the fact that loaded file are cached by browser, - *so that new reload must be fast, it's better to see how to keep already load messages data; - *and just download those which have to be loaded. - */ - //firstly clean the locale data, assuming that it will content new parsed data. - iJS.Gettext._locale_data = {} ; - - // NOTE: there will be a delay here, as this is async. - // So, any i18n calls made right after page load may not - // get translated. - // XXX: we may want to see if we can "fix" this behavior - var domain = null , - link = null ; - for (var d in this.domain_registry) { - - domain = this.domain_registry[d] ; - //When get *link.href* it return the absolute path, event if it initially define with *relative path*. - //That why is more convenient to define *link* as `HTMLlinkElement` than as `string`. - link = document.createElement("link") ; - if (domain.type == 'json') { - - link.href = domain.path+"/"+this.locale+"/LC_MESSAGES/"+domain.value+".json" ; - if (! this.try_load_lang_json(link.href) ) { - - this.try_load_alternative_lang(domain, link) ; - } - } else if (domain.type == 'po') { - - link.href = domain.path+"/"+this.locale+"/LC_MESSAGES/"+domain.value+".po" ; - if (! this.try_load_lang_po(link.href) ) { - - this.try_load_alternative_lang(domain, link) ; - } - } else { - //if `domain.path` is not define, check to see if language is statically included via a json object. - if (domain.path == "") { - - if (typeof( this.locale_data ) != 'undefined') { - // we're going to reformat it, and overwrite the variable - var locale_data_copy = this.locale_data ; - this.locale_data = undefined ; - this.parse_locale_data(locale_data_copy) ; - - if (typeof( iJS.Gettext._locale_data[domain.value] ) == 'undefined') { - console.error("iJS-gettext:'try_load_lang':'locale_data': does not contain the domain '"+domain.value+"'") ; - } - } - - } else { - // TODO: implement the other types (.mo) - /*link.href = domain.path+"/"+this.locale+"/LC_MESSAGES/"+domain.value+".mo" ; - if (! this.try_load_lang_mo(link.href) ) { - - this.try_load_alternative_lang(domain, link) ; - }//*/ - throw new Error("TODO: link type mo found, support is planned, but not implemented at this time.") ; - } - - } - } - - } else { - console.warn("iJS-gettext:'try_load_lang': Not thing to do. It’s seem like no locale or domain have been register. Use `setlocale` or `bindtextdomain` for that.") ; - } -}; - -/** - * Try to load messages data from alternative catalog when associated catalog of user’s given locale can’t be found. <BR/> - * for example for a given "en_US.UTF8" locale, if associated catalog can’t be found, this will try to find it with "en_US" or "en". - * @private - * @memberof iJS.Gettext - * @param {Object} domain from domain’s registry - * @param {HTMLLinkElement} link content the catalog’s path - */ -iJS.Gettext.prototype.try_load_alternative_lang = function (domain, link) { - - if (iJS.isObject( domain ) && iJS.isHTMLLinkElement( link )) { - - var isCatalogOk = false ; - - switch (this.locale_format) { - - case 2: //locale name format is something like *en_US.utf8*. will try to use *en_US* or *en* format - console.warn("iJS-gettext:'try_load_lang': domaine: *"+domain.value+"* not found with locale: *"+this.locale+"* format. Will try to use *"+this.locale.split('.')[0]+"* format...") ; - link.href = domain.path+"/"+this.locale.split('.')[0]+"/LC_MESSAGES/"+domain.value+"."+domain.type ; - - if (domain.type == "json") - isCatalogOk = (this.try_load_lang_json( link.href )) ? true : false ; - else if (domain.type == "po") - isCatalogOk = (this.try_load_lang_po( link.href )) ? true : false ; - //else - //@TODO it will be by default "mo", not supported yet but it’s plan. - - if (! isCatalogOk) { - - console.warn("iJS-gettext:'try_load_lang': domaine: *"+domain.value+"* not found with locale: *"+this.locale.split('.')[0]+"* format. Will try to use *"+this.locale.split('_')[0]+"* format...") ; - link.href = domain.path+"/"+this.locale.split('_')[0]+"/LC_MESSAGES/"+domain.value+"."+domain.type ; - - if (domain.type == "json") - isCatalogOk = (this.try_load_lang_json( link.href )) ? true : false ; - else if (domain.type == "po") - isCatalogOk = (this.try_load_lang_po( link.href )) ? true : false ; - //else - //@TODO it will be by default "mo", not supported yet but it’s plan. - //isCatalogOk = (this.try_load_lang_mo( link.href )) ? true : false ; - - if (! isCatalogOk) { - - link.href = domain.path+"/"+this.locale+"/LC_MESSAGES/"+domain.value+"."+domain.type; - console.warn("iJS-gettext:'try_load_lang_"+domain.type+"': failed. Unable to exec XMLHttpRequest for link ["+link.href+"]") ; - } - } - break; - - case 1://locale name format is something like *en_US*. will try to use *en* format - console.warn("iJS-gettext:'try_load_lang': domaine: *"+domain.value+"* not found with locale: *"+this.locale+"* format. Will try to use *"+this.locale.split('_')[0]+"* format...") ; - link.href = domain.path+"/"+this.locale.split('_')[0]+"/LC_MESSAGES/"+domain.value+"."+domain.type ; - - if (domain.type == "json") - isCatalogOk = (this.try_load_lang_json( link.href )) ? true : false ; - else if (domain.type == "po") - isCatalogOk = (this.try_load_lang_po( link.href )) ? true : false ; - //else - //@TODO it will be by default "mo", not supported yet but it’s plan. - //isCatalogOk = (this.try_load_lang_mo( link.href )) ? true : false ; - - if (! isCatalogOk) { - - link.href = domain.path+"/"+this.locale+"/LC_MESSAGES/"+domain.value+"."+domain.type; - console.error("iJS-gettext:'try_load_lang_"+domain.type+"': failed. Unable to exec XMLHttpRequest for link ["+link.href+"]") ; - } - break; - - default: - console.error("iJS-gettext:'try_load_lang_"+domain.type+"': failed. Unable to exec XMLHttpRequest for link ["+link.href+"]") ; - break; - } - } else { - - console.warn("iJS-gettext:'try_load_alternative_lang': nothing to do or invalid arguments.") ; - } - -}; - -/** - * This takes a json’d data (a portable object variant) and moves it into an internal form, - * for use in our lib, and puts it in our object as: - * <PRE><CODE> - iJS.Gettext._locale_data = { - domain : { - head : { headfield : headvalue }, - msgs : { - msgid : [ msgid_plural, msgstr, msgstr_plural ], - }, - ... - </CODE></PRE> - * The json’d data have to respect the library specifications for that. - * For details see the script **po2json** in the associated binary directory. - * Also see tutorials for more explanations. - * @private - * @memberof iJS.Gettext - * @param {Object} locale_data json *portable object* - * @returns {Object} [[Description]] - */ -iJS.Gettext.prototype.parse_locale_data = function (locale_data) { - - if (typeof( iJS.Gettext._locale_data ) == 'undefined') { - iJS.Gettext._locale_data = {}; - } - - // suck in every domain defined in the supplied data - for (var domain in locale_data) { - // skip empty specs (flexibly) - if ((! locale_data.hasOwnProperty(domain)) || (! iJS.isSet(locale_data[domain]))) - continue; - // skip if it has no msgid's - var has_msgids = false; - for (var msgid in locale_data[domain]) { - has_msgids = true; - break; - } - if (! has_msgids) continue; - - // grab shortcut to data - var data = locale_data[domain]; - - // if they specifcy a blank domain, default to "messages" - if (domain == "") domain = "messages"; - // init the data structure - if (! iJS.isSet( iJS.Gettext._locale_data[domain]) ) - iJS.Gettext._locale_data[domain] = { }; - if (! iJS.isSet( iJS.Gettext._locale_data[domain].head) ) - iJS.Gettext._locale_data[domain].head = { }; - if (! iJS.isSet( iJS.Gettext._locale_data[domain].msgs) ) - iJS.Gettext._locale_data[domain].msgs = { }; - - for (var key in data) { - if (key == "") { - var header = data[key]; - for (var head in header) { - var h = head.toLowerCase(); - iJS.Gettext._locale_data[domain].head[h] = header[head]; - } - } else { - iJS.Gettext._locale_data[domain].msgs[key] = data[key]; - } - } - } - - // build the plural forms function - for (var domain in iJS.Gettext._locale_data) { - - if (iJS.isSet( iJS.Gettext._locale_data[domain].head['plural-forms'] ) && - typeof( iJS.Gettext._locale_data[domain].head.plural_func ) == 'undefined') { - // untaint data - var plural_forms = iJS.Gettext._locale_data[domain].head['plural-forms']; - var pf_re = new RegExp('^(\\s*nplurals\\s*=\\s*[0-9]+\\s*;\\s*plural\\s*=\\s*(?:\\s|[-\\?\\|&=!<>+*/%:;a-zA-Z0-9_\(\)])+)', 'm'); - if (pf_re.test(plural_forms)) { - //ex english: "Plural-Forms: nplurals=2; plural=(n != 1);\n" - //pf = "nplurals=2; plural=(n != 1);"; - //ex russian: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10< =4 && (n%100<10 or n%100>=20) ? 1 : 2) - //pf = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)"; - - var pf = iJS.Gettext._locale_data[domain].head['plural-forms']; - if (! /;\s*$/.test(pf)) pf = pf.concat(';'); - /* We used to use eval, but it seems IE has issues with it. - * We now use "new Function", though it carries a slightly - * bigger performance hit. - var code = 'function (n) { var plural; var nplurals; '+pf+' return { "nplural" : nplurals, "plural" : (plural === true ? 1 : plural ? plural : 0) }; };'; - iJS.Gettext._locale_data[domain].head.plural_func = eval("("+code+")"); - */ - var code = 'var plural; var nplurals; '+pf+' return { "nplural" : nplurals, "plural" : (plural === true ? 1 : plural ? plural : 0) };'; - iJS.Gettext._locale_data[domain].head.plural_func = new Function("n", code); - - } else { - throw new Error("iJS-gettext:'parse_locale_data': Syntax error in language file. Plural-Forms header is invalid ["+plural_forms+"]"); - } - - // default to english plural form - } else if (typeof( iJS.Gettext._locale_data[domain].head.plural_func ) == 'undefined') { - iJS.Gettext._locale_data[domain].head.plural_func = function (n) { - var p = (n != 1) ? 1 : 0; - return { 'nplural' : 2, 'plural' : p }; - }; - } // else, plural_func already created - } - - return; -}; - - -/** - * Do an ajax call to load in a .po files, language definitions from associated catalog. - * @private - * @memberof iJS.Gettext - * @param {string} uri link to the "po" files - * @returns {number} *1* if the operation is a success, *undefined* if not. - */ -iJS.Gettext.prototype.try_load_lang_po = function (uri) { - - var data = this.sjax(uri); - if (! data) return; - var domain = this.uri_basename(uri); - var parsed = this.parse_po(data); - - var rv = {}; - // munge domain into/outof header - if (parsed) { - if (! parsed[""]) parsed[""] = {}; - if (! parsed[""]["domain"]) parsed[""]["domain"] = domain; - domain = parsed[""]["domain"]; - rv[domain] = parsed; - - this.parse_locale_data(rv); - } - - return 1; -}; - -/** - * Do an ajax call to load in a .mo files, language definitions from associated catalog. - * @NOTE not yet ready - * @TODO put available when it will ready. For problems here see `parso_mo` implementation. - * @private - * @memberof iJS.Gettext - * @param {string} uri link to the "mo" files - * @returns {number} *1* if the operation is a success, *undefined* if not. - */ -iJS.Gettext.prototype.try_load_lang_mo = function (uri) { - - var data = this.sjax(uri); - if (! data) return; - var domain = this.uri_basename(uri); - var parsed = this.parse_mo(data); -//alert(parsed); - var rv = {}; - // munge domain into/outof header - if (parsed) { - if (! parsed[""]) parsed[""] = {}; - if (! parsed[""]["domain"]) parsed[""]["domain"] = domain; - domain = parsed[""]["domain"]; - rv[domain] = parsed; - - this.parse_locale_data(rv); - } - - return 1; -}; - -/** - * Get the base name of an url. - * Needed for know in which domain are loaded the messages data. - * Url’s base name will be considered as domain. - * @private - * @memberof iJS.Gettext - * @param {string} uri an url - * @returns {string} the base name of the given url. - */ -iJS.Gettext.prototype.uri_basename = function (uri) { - - var rv; - if (rv = uri.match(/^(.*\/)?(.*)/)) { - var ext_strip; - if (ext_strip = rv[2].match(/^(.*)\..+$/)) - return ext_strip[1]; - else - return rv[2]; - } else { - return ""; - } -}; - -/** - * Parse po data in a json structure. - * (like the library associated **po2json** perl script). - * @TODO ( also associate a **po2json** nodejs script). - * @private - * @memberof iJS.Gettext - * @param {String} data a portable object content - * @returns {Object} a json parsed data - */ -iJS.Gettext.prototype.parse_po = function (data) { - - var rv = {}; - var buffer = {}; - var lastbuffer = ""; - var errors = []; - var lines = data.split("\n"); - - for (var i=0; i<lines.length; i++) { - // chomp - lines[i] = lines[i].replace(/(\n|\r)+$/, ''); - - var match; - // Empty line / End of an entry. - if (/^$/.test(lines[i])) { - if (typeof( buffer['msgid'] ) != 'undefined') { - var msg_ctxt_id = (typeof( buffer['msgctxt'] ) != 'undefined' && - buffer['msgctxt'].length) ? - buffer['msgctxt']+iJS.Gettext.context_glue+buffer['msgid'] : - buffer['msgid']; - var msgid_plural = (typeof( buffer['msgid_plural'] ) != 'undefined' && - buffer['msgid_plural'].length) ? - buffer['msgid_plural'] : - null; - - // find msgstr_* translations and push them on - var trans = []; - for (var str in buffer) { - var match; - if (match = str.match(/^msgstr_(\d+)/)) - trans[parseInt(match[1])] = buffer[str]; - } - trans.unshift(msgid_plural); - - // only add it if we've got a translation - // NOTE: this doesn't conform to msgfmt specs - if (trans.length > 1) rv[msg_ctxt_id] = trans; - - buffer = {}; - lastbuffer = ""; - } - - // comments - } else if (/^#/.test(lines[i])) { - continue; - - // msgctxt - } else if (match = lines[i].match(/^msgctxt\s+(.*)/)) { - lastbuffer = 'msgctxt'; - buffer[lastbuffer] = this.parse_po_dequote(match[1]); - - // msgid - } else if (match = lines[i].match(/^msgid\s+(.*)/)) { - lastbuffer = 'msgid'; - buffer[lastbuffer] = this.parse_po_dequote(match[1]); - - // msgid_plural - } else if (match = lines[i].match(/^msgid_plural\s+(.*)/)) { - lastbuffer = 'msgid_plural'; - buffer[lastbuffer] = this.parse_po_dequote(match[1]); - - // msgstr - } else if (match = lines[i].match(/^msgstr\s+(.*)/)) { - lastbuffer = 'msgstr_0'; - buffer[lastbuffer] = this.parse_po_dequote(match[1]); - - // msgstr[0] (treak like msgstr) - } else if (match = lines[i].match(/^msgstr\[0\]\s+(.*)/)) { - lastbuffer = 'msgstr_0'; - buffer[lastbuffer] = this.parse_po_dequote(match[1]); - - // msgstr[n] - } else if (match = lines[i].match(/^msgstr\[(\d+)\]\s+(.*)/)) { - lastbuffer = 'msgstr_'+match[1]; - buffer[lastbuffer] = this.parse_po_dequote(match[2]); - - // continued string - } else if (/^"/.test(lines[i])) { - buffer[lastbuffer] += this.parse_po_dequote(lines[i]); - - // something strange - } else { - errors.push("Strange line ["+i+"] : "+lines[i]); - } - } - - // handle the final entry - if (typeof( buffer['msgid'] ) != 'undefined') { - - var msg_ctxt_id = (typeof( buffer['msgctxt'] ) != 'undefined' && buffer['msgctxt'].length) ? - buffer['msgctxt']+iJS.Gettext.context_glue+buffer['msgid'] : buffer['msgid']; - var msgid_plural = (typeof( buffer['msgid_plural'] ) != 'undefined' && - buffer['msgid_plural'].length) ? buffer['msgid_plural'] : null; - - // find msgstr_* translations and push them on - var trans = []; - for (var str in buffer) { - var match; - if (match = str.match(/^msgstr_(\d+)/)) - trans[parseInt(match[1])] = buffer[str]; - } - trans.unshift(msgid_plural); - - // only add it if we've got a translation - // NOTE: this doesn't conform to msgfmt specs - if (trans.length > 1) rv[msg_ctxt_id] = trans; - - buffer = {}; - lastbuffer = ""; - } - - // parse out the header - if (rv[""] && rv[""][1]) { - var cur = {}; - var hlines = rv[""][1].split(/\\n/); - for (var i=0; i<hlines.length; i++) { - if (! hlines.length) continue; - - var pos = hlines[i].indexOf(':', 0); - if (pos != -1) { - var key = hlines[i].substring(0, pos); - var val = hlines[i].substring(pos +1); - var keylow = key.toLowerCase(); - - if (cur[keylow] && cur[keylow].length) { - errors.push("SKIPPING DUPLICATE HEADER LINE: "+hlines[i]); - } else if (/#-#-#-#-#/.test(keylow)) { - errors.push("SKIPPING ERROR MARKER IN HEADER: "+hlines[i]); - } else { - // remove begining spaces if any - val = val.replace(/^\s+/, ''); - cur[keylow] = val; - } - - } else { - errors.push("PROBLEM LINE IN HEADER: "+hlines[i]); - cur[hlines[i]] = ''; - } - } - - // replace header string with assoc array - rv[""] = cur; - } else { - rv[""] = {}; - } - - // TODO: XXX: if there are errors parsing, what do we want to do? - // GNU Gettext silently ignores errors. So will we. - // alert( "Errors parsing po file:\n" + errors.join("\n") ); - - return rv; -}; - -/** - * Unscaled all embedded quotes in a string. Useful when parsing a po messages data. - * @private - * @memberof iJS.Gettext - * @param {String} str string to analyse - * @returns {String} formated string - */ -iJS.Gettext.prototype.parse_po_dequote = function (str) { - - var match; - if (match = str.match(/^"(.*)"/)) { - str = match[1]; - } - // unescale all embedded quotes (fixes bug #17504) - str = str.replace(/\\"/g, "\""); - return str; -}; - - -/** - * @constant {Number} Magic constant to check the endianness of the input file. - * @memberof iJS.Gettext - */ -iJS.Gettext.prototype.MAGIC = 314425327; - -/** - * Parses a header string into an object of key-value pairs - * @memberof iJS.Gettext - * @private - * @param {String} str Header string - * @return {Object} An object of key-value pairs - */ -iJS.Gettext.prototype.parseHeader = function (str) { - - var lines = (str || '').split('\n'), - headers = {}; - - lines.forEach(function(line) { - var parts = line.trim().split(':'), - key = (parts.shift() || '').trim().toLowerCase(), - value = parts.join(':').trim(); - if (!key) { - return; - } - headers[key] = value; - }); - - return headers; -} ; - -/** - * Normalizes charset name. Converts utf8 to utf-8, WIN1257 to windows-1257 etc. - * @TODO see if it really necessary here. - * @memberof iJS.Gettext - * @private - * @param {String} charset Charset name - * @return {String} Normalized charset name - */ -iJS.Gettext.prototype.formatCharset = function (charset, defaultCharset) { - - return (charset || 'iso-8859-1').toString().toLowerCase(). - replace(/^utf[\-_]?(\d+)$/, 'utf-$1'). - replace(/^win(?:dows)?[\-_]?(\d+)$/, 'windows-$1'). - replace(/^latin[\-_]?(\d+)$/, 'iso-8859-$1'). - replace(/^(us[\-_]?)?ascii$/, 'ascii'). - replace(/^charset$/, defaultCharset || 'iso-8859-1'). - trim(); -}; - - -/** - * Parse mo data in a json structure. - * (like the library associated **po2json** perl script). - * @TODO ( also associate a **po2json** nodejs script). - * @NOTE not yet ready. Base on **moparser** of [node-gettext](http://github.com/andris9/node-gettext). - * @TODO put available when it will ready. Problems here (depending of `parso_mo` implementation) - * are detection of magic number for *.mo* buffer and manipulating the considered buffer, - * function of little endian or big endian structure. - * @private - * @memberof iJS.Gettext - * @param {String} data a portable object content - * @returns {Object} a json parsed data - */ -iJS.Gettext.prototype.parse_mo = function (data, defaultCharset) { - - var _fileContents = new iJS.Buffer(data) , - _writeFunc = 'writeUInt32LE' , //Method name for writing int32 values, default littleendian - _readFunc = 'readUInt32LE' , //Method name for reading int32 values, default littleendian - _charset = defaultCharset || 'iso-8859-1', - - _table = { - charset: _charset, - headers: undefined, - translations: {} - }; - - /** - * Checks if number values in the input file are in big- or littleendian format. - */ - //from mopaser _checkMagick function - //alert (_fileContents.readUInt32LE(0)) - //alert (this.MAGIC) - //alert (_fileContents.readUInt32LE(0) == this.MAGIC) - if (_fileContents.readUInt32LE(0) == this.MAGIC) { - _readFunc = 'readUInt32LE'; - _writeFunc = 'writeUInt32LE'; - //return true; - } else if (_fileContents.readUInt32BE(0) === this.MAGIC) { - _readFunc = 'readUInt32BE'; - _writeFunc = 'writeUInt32BE'; - //return true; - } else { - return false; - } - - /** - * GetText revision nr, usually 0 - */ - _revision = _fileContents[_readFunc](4); - - /** - * Total count of translated strings - */ - _total = _fileContents[_readFunc](8); - - /** - * Offset position for original strings table - */ - _offsetOriginals = _fileContents[_readFunc](12); - - /** - * Offset position for translation strings table - */ - _offsetTranslations = _fileContents[_readFunc](16); - - /** - * Read the original strings and translations from the input MO file. Use the - * first translation string in the file as the header. - */ - // Load translations into _translationTable - var offsetOriginals = _offsetOriginals, - offsetTranslations = _offsetTranslations, - position, length, - msgid, msgstr; - - for (var i = 0; i < _total; i++) { - // msgid string - length = _fileContents[_readFunc](offsetOriginals); - offsetOriginals += 4; - position = _fileContents[_readFunc](offsetOriginals); - offsetOriginals += 4; - msgid = _fileContents.slice(position, position + length); - - // matching msgstr - length = _fileContents[_readFunc](offsetTranslations); - offsetTranslations += 4; - position = _fileContents[_readFunc](offsetTranslations); - offsetTranslations += 4; - msgstr = _fileContents.slice(position, position + length); - - if (!i && !msgid.toString()) { - /** - * Detects charset for MO strings from the header - */ - var headersStr = headers.toString(), - match; - - if ((match = headersStr.match(/[; ]charset\s*=\s*([\w\-]+)/i))) { - _charset = _table.charset = this.formatCharset(match[1], _charset); - } - - //headers = encoding.convert(headers, 'utf-8', _charset).toString('utf-8'); - - _table.headers = this.parseHeader(headersStr.toString('utf-8')); - } - - //msgid = encoding.convert(msgid, 'utf-8', _charset).toString('utf-8'); - //msgstr = encoding.convert(msgstr, 'utf-8', _charset).toString('utf-8'); - - /** - * Adds a translation to the translation object - */ - //form mopaser _addString(msgid, msgstr) ; - //alert ("test") - var translation = {}, - parts, msgctxt, msgid_plural; - - msgid = msgid.split('\u0004'); - if (msgid.length > 1) { - msgctxt = msgid.shift(); - translation.msgctxt = msgctxt; - } else { - msgctxt = ''; - } - msgid = msgid.join('\u0004'); - - parts = msgid.split('\u0000'); - msgid = parts.shift(); - - translation.msgid = msgid; - - if ((msgid_plural = parts.join('\u0000'))) { - translation.msgid_plural = msgid_plural; - } - - msgstr = msgstr.split('\u0000'); - translation.msgstr = [].concat(msgstr || []); - - if (!_table.translations[msgctxt]) { - _table.translations[msgctxt] = {}; - } - - _table.translations[msgctxt][msgid] = translation; - } - - // dump the file contents object - _fileContents = null; - - return _table; - -}; - - -/** - * Do an ajax call to load in a .json files, language definitions from associated catalog. - * @private - * @memberof iJS.Gettext - * @param {string} uri link to the "json" files - * @returns {number} *1* if the operation is a success, *undefined* if not. - */ -iJS.Gettext.prototype.try_load_lang_json = function (uri) { - - var data = this.sjax(uri); - if (! data) return; - - var rv = this.JSON(data); - this.parse_locale_data(rv); - - return 1; -}; - -/** - * Set domain for future `gettext()` calls. <BR/> - * If the given domain is not NULL, the current message domain is set to it; - * else the function returns the current message domain. <BR/> - * A message domain is a set of translatable msgid messages. Usually, - * every software package has its own message domain. The domain name is - * used to determine the message catalog where a translation is looked up; - * it must be a non-empty string. - * @memberof iJS.Gettext - * @param {string} domain message domain to set as current. - * @returns {string} current message domain. - */ -iJS.Gettext.prototype.textdomain = function (domain) { - - if (domain && domain.length) this.domain = domain; - return this.domain; -} - - -/** - * Returns the translation for **msgid**.<BR/> - * If translation can’t be found, the unmodified **msgid** is returned. - * @memberof iJS.Gettext - * @param {String} msgid Message to translate - * @returns {String} translated text or the *msgid* if not found - */ -iJS.Gettext.prototype.gettext = function (msgid) { - - var msgctxt; - var msgid_plural; - var n; - var category; - return this.dcnpgettext(null, msgctxt, msgid, msgid_plural, n, category); -}; - - -/** - * Like `gettext()`, but retrieves the message for the specified - * **TEXTDOMAIN** instead of the default domain. - * @memberof iJS.Gettext - * @param {String} domain Domain where translation can be found. - * @param {String} msgid Message to translate - * @returns {String} translated text or the *msgid* if not found - */ -iJS.Gettext.prototype.dgettext = function (domain, msgid) { - - var msgctxt; - var msgid_plural; - var n; - var category; - return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category); -}; - -/** - * Like `dgettext()` but retrieves the message from the specified **CATEGORY** - * instead of the default category "LC_MESSAGES". <BR/> - * <U>NOTE:</U> the categories are really useless in javascript context. This is - * here for GNU Gettext API compatibility. In practice, you'll never need - * to use this. This applies to all the calls including the **CATEGORY**. - * @memberof iJS.Gettext - * @param {String} domain Domain where translation can be found. - * @param {String} msgid Message to translate - * @param {String} category (for now is will always be "LC_MESSAGES") - * @returns {String} translated text or the *msgid* if not found - */ -iJS.Gettext.prototype.dcgettext = function (domain, msgid, category) { - - var msgctxt; - var msgid_plural; - var n; - return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category); -}; - - -/** - * Retrieves the correct translation for **count** items. - * @memberof iJS.Gettext - * @param {String} msgid Message to translate - * @param {String} msgid_plural Plural form of text to translate - * @param {Number} n Counting number - * @returns {String} translated text or the *msgid* if not found - * @example - * //In legacy software you will often find something like: - * alert( count + " file(s) deleted.\n" ); - * //Before ngettext() was introduced, one of best practice for internationalized programs was: - if (count == 1) - alert( iJS._("One file deleted.\n") ); - else ... - - //This is a nuisance for the programmer and often still not sufficient for an adequate translation. - //Many languages have completely different ideas on numerals. Some (French, Italian, ...) treat 0 and 1 alike, - //others make no distinction at all (Japanese, Korean, Chinese, ...), others have two or more plural forms (Russian, - //Latvian, Czech, Polish, ...). The solution is: - - alert( iJS.i18n.ngettext("One file deleted.\n", "%d files deleted.\n", count) ); - */ -iJS.Gettext.prototype.ngettext = function (msgid, msgid_plural, n) { - - var msgctxt; - var category; - return this.dcnpgettext(null, msgctxt, msgid, msgid_plural, n, category); -}; - -/** - * Like `ngettext()` but retrieves the translation from the specified - * textdomain instead of the default domain. - * @memberof iJS.Gettext - * @param {String} domain Domain where translation can be found. - * @param {String} msgid Message to translate - * @param {String} msgid_plural Plural form of text to translate - * @param {Number} n Counting number - * @returns {String} translated text or the *msgid* if not found - */ -iJS.Gettext.prototype.dngettext = function (domain, msgid, msgid_plural, n) { - - var msgctxt; - var category; - return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category); -}; - -/** - * Like `dngettext()` but retrieves the translation from the specified - * category, instead of the default category **LC_MESSAGES**. - * @memberof iJS.Gettext - * @param {String} domain Domain where translation can be found. - * @param {String} msgid Message to translate - * @param {String} msgid_plural Plural form of text to translate - * @param {Number} n Counting number - * @param {String} category (for now is will always be "LC_MESSAGES") - * @returns {String} translated text or the *msgid* if not found - */ -iJS.Gettext.prototype.dcngettext = function (domain, msgid, msgid_plural, n, category) { - - var msgctxt; - return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category, category); -}; - -/** - * Returns the translation of **msgid**, given the context of **msgctxt**.<BR/> - * Both items are used as a unique key into the message catalog. - * This allows the translator to have two entries for words that may - * translate to different foreign words based on their context. - * @memberof iJS.Gettext - * @param {String} msgctxt context of text - * @param {String} msgid Message to translate - * @returns {String} translated text or the *msgid* if not found - * @example - * // The word "View" may be a noun or a verb, which may be - * //used in a menu as File->View or View->Source. - - alert( iJS.i18n.pgettext( "Verb: To View", "View" ) ); - alert( iJS.i18n.pgettext( "Noun: A View", "View" ) ); - * // The above will both lookup different entries in the message catalog. - */ -iJS.Gettext.prototype.pgettext = function (msgctxt, msgid) { - - var msgid_plural; - var n; - var category; - return this.dcnpgettext(null, msgctxt, msgid, msgid_plural, n, category); -}; - -/** - * Like `pgettext()`, but retrieves the message for the specified - * **domain** instead of the default domain. - * @memberof iJS.Gettext - * @param {String} domain Domain where translation can be found. - * @param {String} msgctxt Context of text - * @param {String} msgid Message to translate - * @returns {String} translated text or the *msgid* if not found - */ -iJS.Gettext.prototype.dpgettext = function (domain, msgctxt, msgid) { - - var msgid_plural; - var n; - var category; - return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category); -}; - -/** - * Like `dpgettext()` but retrieves the message from the specified **category** - * instead of the default category **LC_MESSAGES**. - * @memberof iJS.Gettext - * @param {String} domain Domain where translation can be found. - * @param {String} msgctxt Context of text - * @param {String} msgid Message to translate - * @param {String} category (for now is will always be "LC_MESSAGES") - * @returns {String} translated text or the *msgid* if not found - */ -iJS.Gettext.prototype.dcpgettext = function (domain, msgctxt, msgid, category) { - - var msgid_plural; - var n; - return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category); -}; - - -/** - * Like `ngettext()` with the addition of context as in `pgettext()`. <BR/> - * In English, or if no translation can be found, the second argument - * *msgid* is picked if *n* is one, the third one otherwise. - * @memberof iJS.Gettext - * @param {String} msgctxt Context of text - * @param {String} msgid Message to translate - * @param {String} msgid_plural Plural form of text to translate - * @param {Number} n Counting number - * @returns {String} translated text or the *msgid* if not found - */ -iJS.Gettext.prototype.npgettext = function (msgctxt, msgid, msgid_plural, n) { - - var category; - return this.dcnpgettext(null, msgctxt, msgid, msgid_plural, n, category); -}; - -/** - * Like `npgettext()` but retrieves the translation from the specified - * textdomain instead of the default domain. - * @memberof iJS.Gettext - * @param {String} domain Domain where translation can be found. - * @param {String} msgctxt Context of text - * @param {String} msgid Message to translate - * @param {String} msgid_plural Plural form of text to translate - * @param {Number} n Counting number - * @returns {String} translated text or the *msgid* if not found - */ -iJS.Gettext.prototype.dnpgettext = function (domain, msgctxt, msgid, msgid_plural, n) { - - var category; - return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category); -}; - - -// this has all the options, so we use it for all of previous `gettext()`. -/** - * Like `dnpgettext()` but retrieves the translation from the specified - * category, instead of the default category **LC_MESSAGES**. - * @memberof iJS.Gettext - * @param {String} domain Domain where translation can be found. - * @param {String} msgctxt Context of text - * @param {String} msgid Message to translate - * @param {String} msgid_plural Plural form of text to translate - * @param {Number} n - * @param {String} category (for now is will always be "LC_MESSAGES") - * @returns {String} translated text or the *msgid* if not found - */ -iJS.Gettext.prototype.dcnpgettext = function (domain, msgctxt, msgid, msgid_plural, n, category) { - - if (! iJS.isSet(msgid)) return ''; - - var plural = iJS.isSet(msgid_plural); - var msg_ctxt_id = iJS.isSet(msgctxt) ? msgctxt+iJS.Gettext.context_glue+msgid : msgid; - - var domainname = iJS.isSet(domain) ? domain : iJS.isSet(this.domain) ? this.domain : 'messages'; - - // category is always LC_MESSAGES. We ignore all else - var category_name = 'LC_MESSAGES'; - var category = 5; - - var locale_data = new Array(); - if (typeof( iJS.Gettext._locale_data ) != 'undefined' && - iJS.isSet( iJS.Gettext._locale_data[domainname]) ) { - locale_data.push( iJS.Gettext._locale_data[domainname] ); - - } else if (typeof( iJS.Gettext._locale_data ) != 'undefined') { - // didn't find domain we're looking for. Search all of them. - for (var dom in iJS.Gettext._locale_data) { - locale_data.push( iJS.Gettext._locale_data[dom] ); - } - } - - var trans = []; - var found = false; - var domain_used; // so we can find plural-forms if needed - if (locale_data.length) { - for (var i=0; i<locale_data.length; i++) { - var locale = locale_data[i]; - if (iJS.isSet(locale.msgs[msg_ctxt_id])) { - // make copy of that array (cause we'll be destructive) - for (var j=0; j<locale.msgs[msg_ctxt_id].length; j++) { - trans[j] = locale.msgs[msg_ctxt_id][j]; - } - trans.shift(); // throw away the msgid_plural - domain_used = locale; - found = true; - // only break if found translation actually has a translation. - if ( trans.length > 0 && trans[0].length != 0 ) - break; - } - } - } - - // default to english if we lack a match, or match has zero length - if ( trans.length == 0 || trans[0].length == 0 ) { - trans = [ msgid, msgid_plural ]; - } - - var translation = trans[0]; - if (plural) { - var p; - if (found && iJS.isSet(domain_used.head.plural_func) ) { - var rv = domain_used.head.plural_func(n); - if (! rv.plural) rv.plural = 0; - if (! rv.nplural) rv.nplural = 0; - // if plurals returned is out of bound for total plural forms - if (rv.nplural <= rv.plural) rv.plural = 0; - p = rv.plural; - } else { - p = (n != 1) ? 1 : 0; - } - if (iJS.isSet(trans[p])) - translation = trans[p]; - } - - return translation; -}; - - -/** - * This is a utility method to provide some way to support positional parameters within a string, as javascript lacks a printf() method. - * The format is similar to printf(), but greatly simplified (ie. fewer features).<BR/> - * Any percent signs followed by numbers are replaced with the corresponding item from the argument’s array. - * @class - * @constructs Strargs - * @memberof iJS.Gettext - * @param {String} str a string that potentially contains formatting characters - * @param {Array} args an array of positional replacement values - * @returns {String} The formatted text. - * @example - * iJS.i18n.setlocale("fr_FR.UTF8") ; - * iJS.i18n.bindtextdomain("fr_FR.UTF8") ; - * iJS.i18n.try_load_lang() ; - * //One common mistake is to interpolate a variable into the string like this: - * var translated = iJS._("Hello " + full_name); //`iJS._()` can be replace by `iJS.i18n.gettext()` - - * //The interpolation will happen before it's passed to gettext, and it's - * //unlikely you'll have a translation for every "Hello Tom" and "Hello Dick" - * //and "Hellow Harry" that may arise. - - * //Use `strargs()` (see below) to solve this problem: - - * var translated = iJS.Gettext.strargs( iJS._("Hello %1"), [full_name] ); - - /* This is espeically useful when multiple replacements are needed, as they - * may not appear in the same order within the translation. As an English to - * French example: - - * Expected result: "This is the red ball" - * English: "This is the %1 %2" - * French: "C'est le %2 %1" - * Code: iJS.Gettext.strargs( iJS._("This is the %1 %2"), ["red", "ball"] ); - - * (The example show thing that not have to be done because neither color nor text - * will get translated here ...). - - */ -iJS.Gettext.strargs = function (str, args) { - - // make sure args is an array - if ( null == args || 'undefined' == typeof(args) ) { - args = []; - } else if (args.constructor != Array) { - args = [args]; - } - - // NOTE: javascript lacks support for zero length negative look-behind - // in regex, so we must step through w/ index. - // The perl equiv would simply be: - // $string =~ s/(?<!\%)\%([0-9]+)/$args[$1]/g; - // $string =~ s/\%\%/\%/g; # restore escaped percent signs - - var newstr = ""; - while (true) { - var i = str.indexOf('%'); - var match_n; - - // no more found. Append whatever remains - if (i == -1) { - newstr += str; - break; - } - - // we found it, append everything up to that - newstr += str.substr(0, i); - - // check for escpaed %% - if (str.substr(i, 2) == '%%') { - newstr += '%'; - str = str.substr((i+2)); - - // % followed by number - } else if ( match_n = str.substr(i).match(/^%(\d+)/) ) { - var arg_n = parseInt(match_n[1]); - var length_n = match_n[1].length; - if ( arg_n > 0 && args[arg_n -1] != null && typeof(args[arg_n -1]) != 'undefined' ) - newstr += args[arg_n -1]; - str = str.substr( (i + 1 + length_n) ); - - // % followed by some other garbage - just remove the % - } else { - newstr += '%'; - str = str.substr((i+1)); - } - } - - return newstr; -} - - -/** - * instance method wrapper of strargs - * @memberof iJS.Gettext - * @param {String} str a string that potentially contains formatting characters - * @param {Array} args an array of positional replacement values - * @returns {String} The formatted text. - */ -iJS.Gettext.prototype.strargs = function (str, args) { - - return iJS.Gettext.strargs(str, args); -} - -/** - * Synchronously get a response text via an ajax call to a file’s url. - * @private - * @memberof iJS.Gettext - * @param {String} uri file url - * @returns {String} a response text if succeed or *"undefined"* if not. - */ -iJS.Gettext.prototype.sjax = function (uri) { - - var xmlhttp = iJS.newHTTPRequest() ; - - if (! xmlhttp) { - console.error("iJS-gettext:'sjax': Your browser doesn't do Ajax. Unable to support external language files."); - - } else { - - xmlhttp.open('GET', uri, false); - try { xmlhttp.send(null); } - catch (e) { return; } - - // we consider status 200 and 0 as ok. - // 0 happens when we request local file, allowing this to run on local files - var sjax_status = xmlhttp.status; - if (sjax_status == 200 || sjax_status == 0) { - //alert(xmlhttp.responseText) - return xmlhttp.responseText; - } else { - var error = xmlhttp.statusText + " (Error " + xmlhttp.status + ")"; - if (xmlhttp.responseText.length) { - error += "\n" + xmlhttp.responseText; - } - console.error( error ); - return; - } - } - -} - -/** - * Evaluate A string representing a JavaScript expression, statement, or sequence of statements. - * @private - * @param {String} data JavaScript expression - * @returns {Object} [[Description]] - */ -iJS.Gettext.prototype.JSON = function (data) { - return eval('(' + data + ')'); -} - -},{}]},{},[1]); |