var gettext = function(translations, pluralfunction) { this.catalog = translations; this.gettext = function(msgid) { var msgstr = this.catalog[msgid]; if ('undefined' == typeof(msgstr)) { return msgid; } return msgstr; } this.ngettext = function(singular, plural, count) { /* nobody will have a \0 in their strings (hopefully) */ var msgstr = this.catalog[singular+'\0'+plural]; if ('undefined' == typeof(msgstr)) { if (1 == count) { return singular; } else { return plural; } } else { return msgstr[this.pluralfunction(count)]; } } this.simplepluralfunction = function(count) { if (1 == count) { return 0; } else { return 1; } } this.pluralfunction = ('function' == typeof(pluralfunction))? pluralfunction : this.simplepluralfunction; this.add = function(additional) { for (key in additional) { this.catalog[key] = additional[key]; } } } /** * Makes a template subtitute function f(fmt, values), which * replaces all indices of values, surrounded by PREFIX and SUFFIX * with the corresponding value from VALUES. * * In FMT, any unwanted placeholders can be escaped by doubling the SUFFIX. * * NOTE: prefix and suffix should be different! * * TODO: escape special regex characters from prefix and suffix */ gettext.formatterBuilder = function(prefix, suffix) { var re = new RegExp('(?:'+prefix+'([^'+(prefix==suffix?prefix:prefix+suffix)+']+)'+suffix+')(?!'+suffix+')', 'g'); var format = function(fmt, values) { var convert = function(whole, name) { var sub = values[name]; return ('undefined' == typeof(sub))? whole : sub; } return fmt.replace(re, convert); } return format; } gettext.format = gettext.formatterBuilder('{', '}'); gettext.boundmethod = function(obj, meth) { return function() { return meth.apply(obj, arguments); } } gettext.attribute_escape = function(s) { s = s.replace(/&&/g, '&&'); s = s.replace(/&&/g, '&&'); s = s.replace(/&(?:$|([^#])(?![a-z1-4]{1,8};))/g, '&$1'); s = s.replace(//g, '>'); s = s.replace(/"/g, '"'); s = s.replace(/'/g, '''); return s; } String.prototype.format = function(values) { return gettext.format(this, values); } String.prototype.attribute_escape = function() { return gettext.attribute_escape(this); }