diff --git a/guacamole/pom.xml b/guacamole/pom.xml index 1d99627cf..c07e8b308 100644 --- a/guacamole/pom.xml +++ b/guacamole/pom.xml @@ -135,9 +135,11 @@ lib/plugins/angular-route.js lib/plugins/angular-translate.js lib/plugins/angular-translate-loader-static-files.js + lib/plugins/angular-translate-interpolation-messageformat.js lib/plugins/modal.min.js lib/blob/blob.js lib/filesaver/filesaver.js + lib/messageformat/messageformat.js license.txt guacamole-common-js/all.js scripts/session.js diff --git a/guacamole/src/main/webapp/app/index/config/indexTranslationConfig.js b/guacamole/src/main/webapp/app/index/config/indexTranslationConfig.js index 237112493..658b45288 100644 --- a/guacamole/src/main/webapp/app/index/config/indexTranslationConfig.js +++ b/guacamole/src/main/webapp/app/index/config/indexTranslationConfig.js @@ -24,10 +24,17 @@ * The configuration block for setting up everything having to do with i18n. */ angular.module('index').config(['$translateProvider', function($translateProvider) { + + // Use US English by default $translateProvider.preferredLanguage('en_US'); + // Load translations from static JSON files $translateProvider.useStaticFilesLoader({ prefix: 'translations/', suffix: '.json' }); + + // Provide pluralization, etc. via messageformat.js + $translateProvider.useMessageFormatInterpolation(); + }]); \ No newline at end of file diff --git a/guacamole/src/main/webapp/lib/messageformat/messageformat.js b/guacamole/src/main/webapp/lib/messageformat/messageformat.js new file mode 100644 index 000000000..b8ba9e3b3 --- /dev/null +++ b/guacamole/src/main/webapp/lib/messageformat/messageformat.js @@ -0,0 +1,1593 @@ +/** + * messageformat.js + * + * ICU PluralFormat + SelectFormat for JavaScript + * + * @author Alex Sexton - @SlexAxton + * @version 0.1.7 + * @license WTFPL + * @contributor_license Dojo CLA +*/ +(function ( root ) { + + // Create the contructor function + function MessageFormat ( locale, pluralFunc ) { + var fallbackLocale; + + if ( locale && pluralFunc ) { + MessageFormat.locale[ locale ] = pluralFunc; + } + + // Defaults + fallbackLocale = locale = locale || "en"; + pluralFunc = pluralFunc || MessageFormat.locale[ fallbackLocale = MessageFormat.Utils.getFallbackLocale( locale ) ]; + + if ( ! pluralFunc ) { + throw new Error( "Plural Function not found for locale: " + locale ); + } + + // Own Properties + this.pluralFunc = pluralFunc; + this.locale = locale; + this.fallbackLocale = fallbackLocale; + } + + // Set up the locales object. Add in english by default + MessageFormat.locale = { + "en" : function ( n ) { + if ( n === 1 ) { + return "one"; + } + return "other"; + } + }; + + // Build out our basic SafeString type + // more or less stolen from Handlebars by @wycats + MessageFormat.SafeString = function( string ) { + this.string = string; + }; + + MessageFormat.SafeString.prototype.toString = function () { + return this.string.toString(); + }; + + MessageFormat.Utils = { + numSub : function ( string, key, depth ) { + // make sure that it's not an escaped octothorpe + return string.replace( /^#|[^\\]#/g, function (m) { + var prefix = m && m.length === 2 ? m.charAt(0) : ''; + return prefix + '" + (function(){ var x = ' + + key+';\nif( isNaN(x) ){\nthrow new Error("MessageFormat: `"+lastkey_'+depth+'+"` isnt a number.");\n}\nreturn x;\n})() + "'; + }); + }, + escapeExpression : function (string) { + var escape = { + "\n": "\\n", + "\"": '\\"' + }, + badChars = /[\n"]/g, + possible = /[\n"]/, + escapeChar = function(chr) { + return escape[chr] || "&"; + }; + + // Don't escape SafeStrings, since they're already safe + if ( string instanceof MessageFormat.SafeString ) { + return string.toString(); + } + else if ( string === null || string === false ) { + return ""; + } + + if ( ! possible.test( string ) ) { + return string; + } + return string.replace( badChars, escapeChar ); + }, + getFallbackLocale: function( locale ) { + var tagSeparator = locale.indexOf("-") >= 0 ? "-" : "_"; + + // Lets just be friends, fallback through the language tags + while ( ! MessageFormat.locale.hasOwnProperty( locale ) ) { + locale = locale.substring(0, locale.lastIndexOf( tagSeparator )); + if (locale.length === 0) { + return null; + } + } + + return locale; + } + }; + + // This is generated and pulled in for browsers. + var mparser = (function(){ + /* + * Generated by PEG.js 0.7.0. + * + * http://pegjs.majda.cz/ + */ + + function quote(s) { + /* + * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a + * string literal except for the closing quote character, backslash, + * carriage return, line separator, paragraph separator, and line feed. + * Any character may appear in the form of an escape sequence. + * + * For portability, we also escape escape all control and non-ASCII + * characters. Note that "\0" and "\v" escape sequences are not used + * because JSHint does not like the first and IE the second. + */ + return '"' + s + .replace(/\\/g, '\\\\') // backslash + .replace(/"/g, '\\"') // closing quote character + .replace(/\x08/g, '\\b') // backspace + .replace(/\t/g, '\\t') // horizontal tab + .replace(/\n/g, '\\n') // line feed + .replace(/\f/g, '\\f') // form feed + .replace(/\r/g, '\\r') // carriage return + .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape) + + '"'; + } + + var result = { + /* + * Parses the input with a generated parser. If the parsing is successfull, + * returns a value explicitly or implicitly specified by the grammar from + * which the parser was generated (see |PEG.buildParser|). If the parsing is + * unsuccessful, throws |PEG.parser.SyntaxError| describing the error. + */ + parse: function(input, startRule) { + var parseFunctions = { + "start": parse_start, + "messageFormatPattern": parse_messageFormatPattern, + "messageFormatPatternRight": parse_messageFormatPatternRight, + "messageFormatElement": parse_messageFormatElement, + "elementFormat": parse_elementFormat, + "pluralStyle": parse_pluralStyle, + "selectStyle": parse_selectStyle, + "pluralFormatPattern": parse_pluralFormatPattern, + "offsetPattern": parse_offsetPattern, + "selectFormatPattern": parse_selectFormatPattern, + "pluralForms": parse_pluralForms, + "stringKey": parse_stringKey, + "string": parse_string, + "id": parse_id, + "chars": parse_chars, + "char": parse_char, + "digits": parse_digits, + "hexDigit": parse_hexDigit, + "_": parse__, + "whitespace": parse_whitespace + }; + + if (startRule !== undefined) { + if (parseFunctions[startRule] === undefined) { + throw new Error("Invalid rule name: " + quote(startRule) + "."); + } + } else { + startRule = "start"; + } + + var pos = 0; + var reportFailures = 0; + var rightmostFailuresPos = 0; + var rightmostFailuresExpected = []; + + function padLeft(input, padding, length) { + var result = input; + + var padLength = length - input.length; + for (var i = 0; i < padLength; i++) { + result = padding + result; + } + + return result; + } + + function escape(ch) { + var charCode = ch.charCodeAt(0); + var escapeChar; + var length; + + if (charCode <= 0xFF) { + escapeChar = 'x'; + length = 2; + } else { + escapeChar = 'u'; + length = 4; + } + + return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length); + } + + function matchFailed(failure) { + if (pos < rightmostFailuresPos) { + return; + } + + if (pos > rightmostFailuresPos) { + rightmostFailuresPos = pos; + rightmostFailuresExpected = []; + } + + rightmostFailuresExpected.push(failure); + } + + function parse_start() { + var result0; + var pos0; + + pos0 = pos; + result0 = parse_messageFormatPattern(); + if (result0 !== null) { + result0 = (function(offset, messageFormatPattern) { return { type: "program", program: messageFormatPattern }; })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_messageFormatPattern() { + var result0, result1, result2; + var pos0, pos1; + + pos0 = pos; + pos1 = pos; + result0 = parse_string(); + if (result0 !== null) { + result1 = []; + result2 = parse_messageFormatPatternRight(); + while (result2 !== null) { + result1.push(result2); + result2 = parse_messageFormatPatternRight(); + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, s1, inner) { + var st = []; + if ( s1 && s1.val ) { + st.push( s1 ); + } + for( var i in inner ){ + if ( inner.hasOwnProperty( i ) ) { + st.push( inner[ i ] ); + } + } + return { type: 'messageFormatPattern', statements: st }; + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_messageFormatPatternRight() { + var result0, result1, result2, result3, result4, result5; + var pos0, pos1; + + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 123) { + result0 = "{"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"{\""); + } + } + if (result0 !== null) { + result1 = parse__(); + if (result1 !== null) { + result2 = parse_messageFormatElement(); + if (result2 !== null) { + result3 = parse__(); + if (result3 !== null) { + if (input.charCodeAt(pos) === 125) { + result4 = "}"; + pos++; + } else { + result4 = null; + if (reportFailures === 0) { + matchFailed("\"}\""); + } + } + if (result4 !== null) { + result5 = parse_string(); + if (result5 !== null) { + result0 = [result0, result1, result2, result3, result4, result5]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, mfe, s1) { + var res = []; + if ( mfe ) { + res.push(mfe); + } + if ( s1 && s1.val ) { + res.push( s1 ); + } + return { type: "messageFormatPatternRight", statements : res }; + })(pos0, result0[2], result0[5]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_messageFormatElement() { + var result0, result1, result2; + var pos0, pos1, pos2; + + pos0 = pos; + pos1 = pos; + result0 = parse_id(); + if (result0 !== null) { + pos2 = pos; + if (input.charCodeAt(pos) === 44) { + result1 = ","; + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\",\""); + } + } + if (result1 !== null) { + result2 = parse_elementFormat(); + if (result2 !== null) { + result1 = [result1, result2]; + } else { + result1 = null; + pos = pos2; + } + } else { + result1 = null; + pos = pos2; + } + result1 = result1 !== null ? result1 : ""; + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, argIdx, efmt) { + var res = { + type: "messageFormatElement", + argumentIndex: argIdx + }; + if ( efmt && efmt.length ) { + res.elementFormat = efmt[1]; + } + else { + res.output = true; + } + return res; + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_elementFormat() { + var result0, result1, result2, result3, result4, result5, result6; + var pos0, pos1; + + pos0 = pos; + pos1 = pos; + result0 = parse__(); + if (result0 !== null) { + if (input.substr(pos, 6) === "plural") { + result1 = "plural"; + pos += 6; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\"plural\""); + } + } + if (result1 !== null) { + result2 = parse__(); + if (result2 !== null) { + if (input.charCodeAt(pos) === 44) { + result3 = ","; + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\",\""); + } + } + if (result3 !== null) { + result4 = parse__(); + if (result4 !== null) { + result5 = parse_pluralStyle(); + if (result5 !== null) { + result6 = parse__(); + if (result6 !== null) { + result0 = [result0, result1, result2, result3, result4, result5, result6]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, t, s) { + return { + type : "elementFormat", + key : t, + val : s.val + }; + })(pos0, result0[1], result0[5]); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + pos1 = pos; + result0 = parse__(); + if (result0 !== null) { + if (input.substr(pos, 6) === "select") { + result1 = "select"; + pos += 6; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\"select\""); + } + } + if (result1 !== null) { + result2 = parse__(); + if (result2 !== null) { + if (input.charCodeAt(pos) === 44) { + result3 = ","; + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\",\""); + } + } + if (result3 !== null) { + result4 = parse__(); + if (result4 !== null) { + result5 = parse_selectStyle(); + if (result5 !== null) { + result6 = parse__(); + if (result6 !== null) { + result0 = [result0, result1, result2, result3, result4, result5, result6]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, t, s) { + return { + type : "elementFormat", + key : t, + val : s.val + }; + })(pos0, result0[1], result0[5]); + } + if (result0 === null) { + pos = pos0; + } + } + return result0; + } + + function parse_pluralStyle() { + var result0; + var pos0; + + pos0 = pos; + result0 = parse_pluralFormatPattern(); + if (result0 !== null) { + result0 = (function(offset, pfp) { + return { type: "pluralStyle", val: pfp }; + })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_selectStyle() { + var result0; + var pos0; + + pos0 = pos; + result0 = parse_selectFormatPattern(); + if (result0 !== null) { + result0 = (function(offset, sfp) { + return { type: "selectStyle", val: sfp }; + })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_pluralFormatPattern() { + var result0, result1, result2; + var pos0, pos1; + + pos0 = pos; + pos1 = pos; + result0 = parse_offsetPattern(); + result0 = result0 !== null ? result0 : ""; + if (result0 !== null) { + result1 = []; + result2 = parse_pluralForms(); + while (result2 !== null) { + result1.push(result2); + result2 = parse_pluralForms(); + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, op, pf) { + var res = { + type: "pluralFormatPattern", + pluralForms: pf + }; + if ( op ) { + res.offset = op; + } + else { + res.offset = 0; + } + return res; + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_offsetPattern() { + var result0, result1, result2, result3, result4, result5, result6; + var pos0, pos1; + + pos0 = pos; + pos1 = pos; + result0 = parse__(); + if (result0 !== null) { + if (input.substr(pos, 6) === "offset") { + result1 = "offset"; + pos += 6; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\"offset\""); + } + } + if (result1 !== null) { + result2 = parse__(); + if (result2 !== null) { + if (input.charCodeAt(pos) === 58) { + result3 = ":"; + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\":\""); + } + } + if (result3 !== null) { + result4 = parse__(); + if (result4 !== null) { + result5 = parse_digits(); + if (result5 !== null) { + result6 = parse__(); + if (result6 !== null) { + result0 = [result0, result1, result2, result3, result4, result5, result6]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, d) { + return d; + })(pos0, result0[5]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_selectFormatPattern() { + var result0, result1; + var pos0; + + pos0 = pos; + result0 = []; + result1 = parse_pluralForms(); + while (result1 !== null) { + result0.push(result1); + result1 = parse_pluralForms(); + } + if (result0 !== null) { + result0 = (function(offset, pf) { + return { + type: "selectFormatPattern", + pluralForms: pf + }; + })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_pluralForms() { + var result0, result1, result2, result3, result4, result5, result6, result7; + var pos0, pos1; + + pos0 = pos; + pos1 = pos; + result0 = parse__(); + if (result0 !== null) { + result1 = parse_stringKey(); + if (result1 !== null) { + result2 = parse__(); + if (result2 !== null) { + if (input.charCodeAt(pos) === 123) { + result3 = "{"; + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\"{\""); + } + } + if (result3 !== null) { + result4 = parse__(); + if (result4 !== null) { + result5 = parse_messageFormatPattern(); + if (result5 !== null) { + result6 = parse__(); + if (result6 !== null) { + if (input.charCodeAt(pos) === 125) { + result7 = "}"; + pos++; + } else { + result7 = null; + if (reportFailures === 0) { + matchFailed("\"}\""); + } + } + if (result7 !== null) { + result0 = [result0, result1, result2, result3, result4, result5, result6, result7]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, k, mfp) { + return { + type: "pluralForms", + key: k, + val: mfp + }; + })(pos0, result0[1], result0[5]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_stringKey() { + var result0, result1; + var pos0, pos1; + + pos0 = pos; + result0 = parse_id(); + if (result0 !== null) { + result0 = (function(offset, i) { + return i; + })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 61) { + result0 = "="; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"=\""); + } + } + if (result0 !== null) { + result1 = parse_digits(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, d) { + return d; + })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + } + return result0; + } + + function parse_string() { + var result0, result1, result2, result3, result4; + var pos0, pos1, pos2; + + pos0 = pos; + pos1 = pos; + result0 = parse__(); + if (result0 !== null) { + result1 = []; + pos2 = pos; + result2 = parse__(); + if (result2 !== null) { + result3 = parse_chars(); + if (result3 !== null) { + result4 = parse__(); + if (result4 !== null) { + result2 = [result2, result3, result4]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + while (result2 !== null) { + result1.push(result2); + pos2 = pos; + result2 = parse__(); + if (result2 !== null) { + result3 = parse_chars(); + if (result3 !== null) { + result4 = parse__(); + if (result4 !== null) { + result2 = [result2, result3, result4]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, ws, s) { + var tmp = []; + for( var i = 0; i < s.length; ++i ) { + for( var j = 0; j < s[ i ].length; ++j ) { + tmp.push(s[i][j]); + } + } + return { + type: "string", + val: ws + tmp.join('') + }; + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_id() { + var result0, result1, result2, result3; + var pos0, pos1; + + pos0 = pos; + pos1 = pos; + result0 = parse__(); + if (result0 !== null) { + if (/^[a-zA-Z$_]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z$_]"); + } + } + if (result1 !== null) { + result2 = []; + if (/^[^ \t\n\r,.+={}]/.test(input.charAt(pos))) { + result3 = input.charAt(pos); + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[^ \\t\\n\\r,.+={}]"); + } + } + while (result3 !== null) { + result2.push(result3); + if (/^[^ \t\n\r,.+={}]/.test(input.charAt(pos))) { + result3 = input.charAt(pos); + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[^ \\t\\n\\r,.+={}]"); + } + } + } + if (result2 !== null) { + result3 = parse__(); + if (result3 !== null) { + result0 = [result0, result1, result2, result3]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, s1, s2) { + return s1 + (s2 ? s2.join('') : ''); + })(pos0, result0[1], result0[2]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_chars() { + var result0, result1; + var pos0; + + pos0 = pos; + result1 = parse_char(); + if (result1 !== null) { + result0 = []; + while (result1 !== null) { + result0.push(result1); + result1 = parse_char(); + } + } else { + result0 = null; + } + if (result0 !== null) { + result0 = (function(offset, chars) { return chars.join(''); })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_char() { + var result0, result1, result2, result3, result4; + var pos0, pos1; + + pos0 = pos; + if (/^[^{}\\\0-\x1F \t\n\r]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[^{}\\\\\\0-\\x1F \\t\\n\\r]"); + } + } + if (result0 !== null) { + result0 = (function(offset, x) { + return x; + })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + if (input.substr(pos, 2) === "\\#") { + result0 = "\\#"; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\\\#\""); + } + } + if (result0 !== null) { + result0 = (function(offset) { + return "\\#"; + })(pos0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + if (input.substr(pos, 2) === "\\{") { + result0 = "\\{"; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\\\{\""); + } + } + if (result0 !== null) { + result0 = (function(offset) { + return "\u007B"; + })(pos0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + if (input.substr(pos, 2) === "\\}") { + result0 = "\\}"; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\\\}\""); + } + } + if (result0 !== null) { + result0 = (function(offset) { + return "\u007D"; + })(pos0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + pos1 = pos; + if (input.substr(pos, 2) === "\\u") { + result0 = "\\u"; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\\\u\""); + } + } + if (result0 !== null) { + result1 = parse_hexDigit(); + if (result1 !== null) { + result2 = parse_hexDigit(); + if (result2 !== null) { + result3 = parse_hexDigit(); + if (result3 !== null) { + result4 = parse_hexDigit(); + if (result4 !== null) { + result0 = [result0, result1, result2, result3, result4]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, h1, h2, h3, h4) { + return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); + })(pos0, result0[1], result0[2], result0[3], result0[4]); + } + if (result0 === null) { + pos = pos0; + } + } + } + } + } + return result0; + } + + function parse_digits() { + var result0, result1; + var pos0; + + pos0 = pos; + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result1 !== null) { + result0 = []; + while (result1 !== null) { + result0.push(result1); + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result0 = null; + } + if (result0 !== null) { + result0 = (function(offset, ds) { + return parseInt((ds.join('')), 10); + })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_hexDigit() { + var result0; + + if (/^[0-9a-fA-F]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[0-9a-fA-F]"); + } + } + return result0; + } + + function parse__() { + var result0, result1; + var pos0; + + reportFailures++; + pos0 = pos; + result0 = []; + result1 = parse_whitespace(); + while (result1 !== null) { + result0.push(result1); + result1 = parse_whitespace(); + } + if (result0 !== null) { + result0 = (function(offset, w) { return w.join(''); })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("whitespace"); + } + return result0; + } + + function parse_whitespace() { + var result0; + + if (/^[ \t\n\r]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[ \\t\\n\\r]"); + } + } + return result0; + } + + + function cleanupExpected(expected) { + expected.sort(); + + var lastExpected = null; + var cleanExpected = []; + for (var i = 0; i < expected.length; i++) { + if (expected[i] !== lastExpected) { + cleanExpected.push(expected[i]); + lastExpected = expected[i]; + } + } + return cleanExpected; + } + + function computeErrorPosition() { + /* + * The first idea was to use |String.split| to break the input up to the + * error position along newlines and derive the line and column from + * there. However IE's |split| implementation is so broken that it was + * enough to prevent it. + */ + + var line = 1; + var column = 1; + var seenCR = false; + + for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) { + var ch = input.charAt(i); + if (ch === "\n") { + if (!seenCR) { line++; } + column = 1; + seenCR = false; + } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { + line++; + column = 1; + seenCR = true; + } else { + column++; + seenCR = false; + } + } + + return { line: line, column: column }; + } + + + var result = parseFunctions[startRule](); + + /* + * The parser is now in one of the following three states: + * + * 1. The parser successfully parsed the whole input. + * + * - |result !== null| + * - |pos === input.length| + * - |rightmostFailuresExpected| may or may not contain something + * + * 2. The parser successfully parsed only a part of the input. + * + * - |result !== null| + * - |pos < input.length| + * - |rightmostFailuresExpected| may or may not contain something + * + * 3. The parser did not successfully parse any part of the input. + * + * - |result === null| + * - |pos === 0| + * - |rightmostFailuresExpected| contains at least one failure + * + * All code following this comment (including called functions) must + * handle these states. + */ + if (result === null || pos !== input.length) { + var offset = Math.max(pos, rightmostFailuresPos); + var found = offset < input.length ? input.charAt(offset) : null; + var errorPosition = computeErrorPosition(); + + throw new this.SyntaxError( + cleanupExpected(rightmostFailuresExpected), + found, + offset, + errorPosition.line, + errorPosition.column + ); + } + + return result; + }, + + /* Returns the parser source code. */ + toSource: function() { return this._source; } + }; + + /* Thrown when a parser encounters a syntax error. */ + + result.SyntaxError = function(expected, found, offset, line, column) { + function buildMessage(expected, found) { + var expectedHumanized, foundHumanized; + + switch (expected.length) { + case 0: + expectedHumanized = "end of input"; + break; + case 1: + expectedHumanized = expected[0]; + break; + default: + expectedHumanized = expected.slice(0, expected.length - 1).join(", ") + + " or " + + expected[expected.length - 1]; + } + + foundHumanized = found ? quote(found) : "end of input"; + + return "Expected " + expectedHumanized + " but " + foundHumanized + " found."; + } + + this.name = "SyntaxError"; + this.expected = expected; + this.found = found; + this.message = buildMessage(expected, found); + this.offset = offset; + this.line = line; + this.column = column; + }; + + result.SyntaxError.prototype = Error.prototype; + + return result; + })(); + + MessageFormat.prototype.parse = function () { + // Bind to itself so error handling works + return mparser.parse.apply( mparser, arguments ); + }; + + MessageFormat.prototype.precompile = function ( ast ) { + var self = this, + needOther = false, + fp = { + begin: 'function(d){\nvar r = "";\n', + end : "return r;\n}" + }; + + function interpMFP ( ast, data ) { + // Set some default data + data = data || {}; + var s = '', i, tmp, lastkeyname; + + switch ( ast.type ) { + case 'program': + return interpMFP( ast.program ); + case 'messageFormatPattern': + for ( i = 0; i < ast.statements.length; ++i ) { + s += interpMFP( ast.statements[i], data ); + } + return fp.begin + s + fp.end; + case 'messageFormatPatternRight': + for ( i = 0; i < ast.statements.length; ++i ) { + s += interpMFP( ast.statements[i], data ); + } + return s; + case 'messageFormatElement': + data.pf_count = data.pf_count || 0; + s += 'if(!d){\nthrow new Error("MessageFormat: No data passed to function.");\n}\n'; + if ( ast.output ) { + s += 'r += d["' + ast.argumentIndex + '"];\n'; + } + else { + lastkeyname = 'lastkey_'+(data.pf_count+1); + s += 'var '+lastkeyname+' = "'+ast.argumentIndex+'";\n'; + s += 'var k_'+(data.pf_count+1)+'=d['+lastkeyname+'];\n'; + s += interpMFP( ast.elementFormat, data ); + } + return s; + case 'elementFormat': + if ( ast.key === 'select' ) { + s += interpMFP( ast.val, data ); + s += 'r += (pf_' + + data.pf_count + + '[ k_' + (data.pf_count+1) + ' ] || pf_'+data.pf_count+'[ "other" ])( d );\n'; + } + else if ( ast.key === 'plural' ) { + s += interpMFP( ast.val, data ); + s += 'if ( pf_'+(data.pf_count)+'[ k_'+(data.pf_count+1)+' + "" ] ) {\n'; + s += 'r += pf_'+data.pf_count+'[ k_'+(data.pf_count+1)+' + "" ]( d ); \n'; + s += '}\nelse {\n'; + s += 'r += (pf_' + + data.pf_count + + '[ MessageFormat.locale["' + + self.fallbackLocale + + '"]( k_'+(data.pf_count+1)+' - off_'+(data.pf_count)+' ) ] || pf_'+data.pf_count+'[ "other" ] )( d );\n'; + s += '}\n'; + } + return s; + /* // Unreachable cases. + case 'pluralStyle': + case 'selectStyle':*/ + case 'pluralFormatPattern': + data.pf_count = data.pf_count || 0; + s += 'var off_'+data.pf_count+' = '+ast.offset+';\n'; + s += 'var pf_' + data.pf_count + ' = { \n'; + needOther = true; + // We're going to simultaneously check to make sure we hit the required 'other' option. + + for ( i = 0; i < ast.pluralForms.length; ++i ) { + if ( ast.pluralForms[ i ].key === 'other' ) { + needOther = false; + } + if ( tmp ) { + s += ',\n'; + } + else{ + tmp = 1; + } + s += '"' + ast.pluralForms[ i ].key + '" : ' + interpMFP( ast.pluralForms[ i ].val, + (function(){ var res = JSON.parse(JSON.stringify(data)); res.pf_count++; return res; })() ); + } + s += '\n};\n'; + if ( needOther ) { + throw new Error("No 'other' form found in pluralFormatPattern " + data.pf_count); + } + return s; + case 'selectFormatPattern': + + data.pf_count = data.pf_count || 0; + s += 'var off_'+data.pf_count+' = 0;\n'; + s += 'var pf_' + data.pf_count + ' = { \n'; + needOther = true; + + for ( i = 0; i < ast.pluralForms.length; ++i ) { + if ( ast.pluralForms[ i ].key === 'other' ) { + needOther = false; + } + if ( tmp ) { + s += ',\n'; + } + else{ + tmp = 1; + } + s += '"' + ast.pluralForms[ i ].key + '" : ' + interpMFP( ast.pluralForms[ i ].val, + (function(){ + var res = JSON.parse( JSON.stringify( data ) ); + res.pf_count++; + return res; + })() + ); + } + s += '\n};\n'; + if ( needOther ) { + throw new Error("No 'other' form found in selectFormatPattern " + data.pf_count); + } + return s; + /* // Unreachable + case 'pluralForms': + */ + case 'string': + return 'r += "' + MessageFormat.Utils.numSub( + MessageFormat.Utils.escapeExpression( ast.val ), + 'k_' + data.pf_count + ' - off_' + ( data.pf_count - 1 ), + data.pf_count + ) + '";\n'; + default: + throw new Error( 'Bad AST type: ' + ast.type ); + } + } + return interpMFP( ast ); + }; + + MessageFormat.prototype.compile = function ( message ) { + return (new Function( 'MessageFormat', + 'return ' + + this.precompile( + this.parse( message ) + ) + ))(MessageFormat); + }; + + + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = MessageFormat; + } + exports.MessageFormat = MessageFormat; + } + else if (typeof define === 'function' && define.amd) { + define(function() { + return MessageFormat; + }); + } + else { + root['MessageFormat'] = MessageFormat; + } + +})( this ); diff --git a/guacamole/src/main/webapp/lib/plugins/angular-translate-interpolation-messageformat.js b/guacamole/src/main/webapp/lib/plugins/angular-translate-interpolation-messageformat.js new file mode 100644 index 000000000..2aa9470be --- /dev/null +++ b/guacamole/src/main/webapp/lib/plugins/angular-translate-interpolation-messageformat.js @@ -0,0 +1,62 @@ +/*! + * angular-translate - v2.2.0 - 2014-06-03 + * http://github.com/PascalPrecht/angular-translate + * Copyright (c) 2014 ; Licensed MIT + */ +angular.module('pascalprecht.translate').constant('TRANSLATE_MF_INTERPOLATION_CACHE', '$translateMessageFormatInterpolation').factory('$translateMessageFormatInterpolation', [ + '$cacheFactory', + 'TRANSLATE_MF_INTERPOLATION_CACHE', + function ($cacheFactory, TRANSLATE_MF_INTERPOLATION_CACHE) { + var $translateInterpolator = {}, $cache = $cacheFactory.get(TRANSLATE_MF_INTERPOLATION_CACHE), $mf = new MessageFormat(), $identifier = 'messageformat', $sanitizeValueStrategy = null, sanitizeValueStrategies = { + escaped: function (params) { + var result = {}; + for (var key in params) { + if (params.hasOwnProperty(key)) { + result[key] = angular.element('
').text(params[key]).html(); + } + } + return result; + } + }; + var sanitizeParams = function (params) { + var result; + if (angular.isFunction(sanitizeValueStrategies[$sanitizeValueStrategy])) { + result = sanitizeValueStrategies[$sanitizeValueStrategy](params); + } else { + result = params; + } + return result; + }; + if (!$cache) { + $cache = $cacheFactory(TRANSLATE_MF_INTERPOLATION_CACHE); + } + $cache.put('en', $mf); + $translateInterpolator.setLocale = function (locale) { + $mf = $cache.get(locale); + if (!$mf) { + $mf = new MessageFormat(locale); + $cache.put(locale, $mf); + } + }; + $translateInterpolator.getInterpolationIdentifier = function () { + return $identifier; + }; + $translateInterpolator.useSanitizeValueStrategy = function (value) { + $sanitizeValueStrategy = value; + return this; + }; + $translateInterpolator.interpolate = function (string, interpolateParams) { + interpolateParams = interpolateParams || {}; + if ($sanitizeValueStrategy) { + interpolateParams = sanitizeParams(interpolateParams); + } + var interpolatedText = $cache.get(string + angular.toJson(interpolateParams)); + if (!interpolatedText) { + interpolatedText = $mf.compile(string)(interpolateParams); + $cache.put(string + angular.toJson(interpolateParams), interpolatedText); + } + return interpolatedText; + }; + return $translateInterpolator; + } +]); \ No newline at end of file