Commit a95f7713b55ef27089f49d93816dace8e43c1c67

Authored by 徐烜
1 parent f2dbed8f

angular-translate初始化

src/main/resources/static/assets/bower_components/angular-translate-loader-static-files/.bower.json 0 → 100644
  1 +{
  2 + "name": "angular-translate-loader-static-files",
  3 + "description": "A plugin for Angular Translate",
  4 + "version": "2.17.1",
  5 + "main": "./angular-translate-loader-static-files.js",
  6 + "ignore": [],
  7 + "author": "Pascal Precht",
  8 + "license": "MIT",
  9 + "dependencies": {
  10 + "angular-translate": "~2.17.1"
  11 + },
  12 + "homepage": "https://github.com/PascalPrecht/bower-angular-translate-loader-static-files",
  13 + "_release": "2.17.1",
  14 + "_resolution": {
  15 + "type": "version",
  16 + "tag": "2.17.1",
  17 + "commit": "515b913fadf166d9e3ea541406284753d7242b3a"
  18 + },
  19 + "_source": "https://github.com/PascalPrecht/bower-angular-translate-loader-static-files.git",
  20 + "_target": "2.17.1",
  21 + "_originalSource": "angular-translate-loader-static-files",
  22 + "_direct": true
  23 +}
0 24 \ No newline at end of file
... ...
src/main/resources/static/assets/bower_components/angular-translate-loader-static-files/README.md 0 → 100644
  1 +# angular-translate-loader-static-files (bower shadow repository)
  2 +
  3 +This is the _Bower shadow_ repository for *angular-translate-loader-static-files*.
  4 +
  5 +## Bugs and issues
  6 +
  7 +Please file any issues and bugs in our main repository at [angular-translate/angular-translate](https://github.com/angular-translate/angular-translate/issues).
  8 +
  9 +## Usage
  10 +
  11 +### via Bower
  12 +
  13 +```bash
  14 +$ bower install angular-translate-loader-static-files
  15 +```
  16 +
  17 +### via NPM
  18 +
  19 +```bash
  20 +$ npm install angular-translate-loader-static-files
  21 +```
  22 +
  23 +### via cdnjs
  24 +
  25 +Please have a look at https://cdnjs.com/libraries/angular-translate-loader-static-files for specific versions.
  26 +
  27 +## License
  28 +
  29 +Licensed under MIT. See more details at [angular-translate/angular-translate](https://github.com/angular-translate/angular-translate).
... ...
src/main/resources/static/assets/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js 0 → 100644
  1 +/*!
  2 + * angular-translate - v2.17.1 - 2018-04-16
  3 + *
  4 + * Copyright (c) 2018 The angular-translate team, Pascal Precht; Licensed MIT
  5 + */
  6 +(function (root, factory) {
  7 + if (typeof define === 'function' && define.amd) {
  8 + // AMD. Register as an anonymous module unless amdModuleId is set
  9 + define([], function () {
  10 + return (factory());
  11 + });
  12 + } else if (typeof module === 'object' && module.exports) {
  13 + // Node. Does not work with strict CommonJS, but
  14 + // only CommonJS-like environments that support module.exports,
  15 + // like Node.
  16 + module.exports = factory();
  17 + } else {
  18 + factory();
  19 + }
  20 +}(this, function () {
  21 +
  22 +$translateStaticFilesLoader.$inject = ['$q', '$http'];
  23 +angular.module('pascalprecht.translate')
  24 +/**
  25 + * @ngdoc object
  26 + * @name pascalprecht.translate.$translateStaticFilesLoader
  27 + * @requires $q
  28 + * @requires $http
  29 + *
  30 + * @description
  31 + * Creates a loading function for a typical static file url pattern:
  32 + * "lang-en_US.json", "lang-de_DE.json", etc. Using this builder,
  33 + * the response of these urls must be an object of key-value pairs.
  34 + *
  35 + * @param {object} options Options object, which gets prefix, suffix, key, and fileMap
  36 + */
  37 +.factory('$translateStaticFilesLoader', $translateStaticFilesLoader);
  38 +
  39 +function $translateStaticFilesLoader($q, $http) {
  40 +
  41 + 'use strict';
  42 +
  43 + return function (options) {
  44 +
  45 + if (!options || (!angular.isArray(options.files) && (!angular.isString(options.prefix) || !angular.isString(options.suffix)))) {
  46 + throw new Error('Couldn\'t load static files, no files and prefix or suffix specified!');
  47 + }
  48 +
  49 + if (!options.files) {
  50 + options.files = [{
  51 + prefix: options.prefix,
  52 + suffix: options.suffix
  53 + }];
  54 + }
  55 +
  56 + var load = function (file) {
  57 + if (!file || (!angular.isString(file.prefix) || !angular.isString(file.suffix))) {
  58 + throw new Error('Couldn\'t load static file, no prefix or suffix specified!');
  59 + }
  60 +
  61 + var fileUrl = [
  62 + file.prefix,
  63 + options.key,
  64 + file.suffix
  65 + ].join('');
  66 +
  67 + if (angular.isObject(options.fileMap) && options.fileMap[fileUrl]) {
  68 + fileUrl = options.fileMap[fileUrl];
  69 + }
  70 +
  71 + return $http(angular.extend({
  72 + url: fileUrl,
  73 + method: 'GET'
  74 + }, options.$http))
  75 + .then(function(result) {
  76 + return result.data;
  77 + }, function () {
  78 + return $q.reject(options.key);
  79 + });
  80 + };
  81 +
  82 + var promises = [],
  83 + length = options.files.length;
  84 +
  85 + for (var i = 0; i < length; i++) {
  86 + promises.push(load({
  87 + prefix: options.files[i].prefix,
  88 + key: options.key,
  89 + suffix: options.files[i].suffix
  90 + }));
  91 + }
  92 +
  93 + return $q.all(promises)
  94 + .then(function (data) {
  95 + var length = data.length,
  96 + mergedData = {};
  97 +
  98 + for (var i = 0; i < length; i++) {
  99 + for (var key in data[i]) {
  100 + mergedData[key] = data[i][key];
  101 + }
  102 + }
  103 +
  104 + return mergedData;
  105 + });
  106 + };
  107 +}
  108 +
  109 +$translateStaticFilesLoader.displayName = '$translateStaticFilesLoader';
  110 +return 'pascalprecht.translate';
  111 +
  112 +}));
... ...
src/main/resources/static/assets/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js 0 → 100644
  1 +/*!
  2 + * angular-translate - v2.17.1 - 2018-04-16
  3 + *
  4 + * Copyright (c) 2018 The angular-translate team, Pascal Precht; Licensed MIT
  5 + */
  6 +!function(e,i){"function"==typeof define&&define.amd?define([],function(){return i()}):"object"==typeof module&&module.exports?module.exports=i():i()}(0,function(){function e(e,i){"use strict";return function(r){if(!(r&&(angular.isArray(r.files)||angular.isString(r.prefix)&&angular.isString(r.suffix))))throw new Error("Couldn't load static files, no files and prefix or suffix specified!");r.files||(r.files=[{prefix:r.prefix,suffix:r.suffix}]);for(var t=[],f=r.files.length,n=0;n<f;n++)t.push(function(t){if(!t||!angular.isString(t.prefix)||!angular.isString(t.suffix))throw new Error("Couldn't load static file, no prefix or suffix specified!");var f=[t.prefix,r.key,t.suffix].join("");return angular.isObject(r.fileMap)&&r.fileMap[f]&&(f=r.fileMap[f]),i(angular.extend({url:f,method:"GET"},r.$http)).then(function(e){return e.data},function(){return e.reject(r.key)})}({prefix:r.files[n].prefix,key:r.key,suffix:r.files[n].suffix}));return e.all(t).then(function(e){for(var i=e.length,r={},t=0;t<i;t++)for(var f in e[t])r[f]=e[t][f];return r})}}return e.$inject=["$q","$http"],angular.module("pascalprecht.translate").factory("$translateStaticFilesLoader",e),e.displayName="$translateStaticFilesLoader","pascalprecht.translate"});
0 7 \ No newline at end of file
... ...
src/main/resources/static/assets/bower_components/angular-translate-loader-static-files/bower.json 0 → 100644
  1 +{
  2 + "name": "angular-translate-loader-static-files",
  3 + "description": "A plugin for Angular Translate",
  4 + "version": "2.17.1",
  5 + "main": "./angular-translate-loader-static-files.js",
  6 + "ignore": [],
  7 + "author": "Pascal Precht",
  8 + "license": "MIT",
  9 + "dependencies": {
  10 + "angular-translate": "~2.17.1"
  11 + }
  12 +}
... ...
src/main/resources/static/assets/bower_components/angular-translate-loader-static-files/package.json 0 → 100644
  1 +{
  2 + "name": "angular-translate-loader-static-files",
  3 + "version": "2.17.1",
  4 + "description": "Creates a loading function for a typical static file url pattern: \"lang-en_US.json\", \"lang-de_DE.json\", etc. Using this builder, the response of these urls must be an object of key-value pairs.",
  5 + "main": "angular-translate-loader-static-files.js",
  6 + "repository": {
  7 + "type": "git",
  8 + "url": "https://github.com/angular-translate/bower-angular-translate-loader-static-files.git"
  9 + },
  10 + "keywords": [
  11 + "angular",
  12 + "translate",
  13 + "loader"
  14 + ],
  15 + "author": "Pascal Precht",
  16 + "license": "MIT",
  17 + "bugs": {
  18 + "url": "https://github.com/angular-translate/angular-translate/issues"
  19 + },
  20 + "homepage": "https://angular-translate.github.io",
  21 + "dependencies": {
  22 + "angular-translate": "~2.17.1"
  23 + }
  24 +}
... ...
src/main/resources/static/assets/bower_components/angular-translate/.bower.json 0 → 100644
  1 +{
  2 + "name": "angular-translate",
  3 + "description": "A translation module for AngularJS",
  4 + "version": "2.17.1",
  5 + "main": "./angular-translate.js",
  6 + "ignore": [],
  7 + "author": "Pascal Precht",
  8 + "license": "MIT",
  9 + "dependencies": {
  10 + "angular": ">=1.2.26 <1.7"
  11 + },
  12 + "homepage": "https://github.com/PascalPrecht/bower-angular-translate",
  13 + "_release": "2.17.1",
  14 + "_resolution": {
  15 + "type": "version",
  16 + "tag": "2.17.1",
  17 + "commit": "994d993ff317fc69b85182c890a1f78cfcf2ec01"
  18 + },
  19 + "_source": "https://github.com/PascalPrecht/bower-angular-translate.git",
  20 + "_target": "2.17.1",
  21 + "_originalSource": "angular-translate",
  22 + "_direct": true
  23 +}
0 24 \ No newline at end of file
... ...
src/main/resources/static/assets/bower_components/angular-translate/README.md 0 → 100644
  1 +# angular-translate (bower shadow repository)
  2 +
  3 +This is the _Bower shadow_ repository for *angular-translate*.
  4 +
  5 +## Bugs and issues
  6 +
  7 +Please file any issues and bugs in our main repository at [angular-translate/angular-translate](https://github.com/angular-translate/angular-translate/issues).
  8 +
  9 +## Usage
  10 +
  11 +### via Bower
  12 +
  13 +```bash
  14 +$ bower install angular-translate
  15 +```
  16 +
  17 +### via cdnjs
  18 +
  19 +Please have a look at https://cdnjs.com/libraries/angular-translate for specific versions.
  20 +
  21 +## License
  22 +
  23 +Licensed under MIT. See more details at [angular-translate/angular-translate](https://github.com/angular-translate/angular-translate).
... ...
src/main/resources/static/assets/bower_components/angular-translate/angular-translate.js 0 → 100644
  1 +/*!
  2 + * angular-translate - v2.17.1 - 2018-04-16
  3 + *
  4 + * Copyright (c) 2018 The angular-translate team, Pascal Precht; Licensed MIT
  5 + */
  6 +(function (root, factory) {
  7 + if (typeof define === 'function' && define.amd) {
  8 + // AMD. Register as an anonymous module unless amdModuleId is set
  9 + define([], function () {
  10 + return (factory());
  11 + });
  12 + } else if (typeof module === 'object' && module.exports) {
  13 + // Node. Does not work with strict CommonJS, but
  14 + // only CommonJS-like environments that support module.exports,
  15 + // like Node.
  16 + module.exports = factory();
  17 + } else {
  18 + factory();
  19 + }
  20 +}(this, function () {
  21 +
  22 +/**
  23 + * @ngdoc overview
  24 + * @name pascalprecht.translate
  25 + *
  26 + * @description
  27 + * The main module which holds everything together.
  28 + */
  29 +runTranslate.$inject = ['$translate'];
  30 +$translate.$inject = ['$STORAGE_KEY', '$windowProvider', '$translateSanitizationProvider', 'pascalprechtTranslateOverrider'];
  31 +$translateDefaultInterpolation.$inject = ['$interpolate', '$translateSanitization'];
  32 +translateDirective.$inject = ['$translate', '$interpolate', '$compile', '$parse', '$rootScope'];
  33 +translateAttrDirective.$inject = ['$translate', '$rootScope'];
  34 +translateCloakDirective.$inject = ['$translate', '$rootScope'];
  35 +translateFilterFactory.$inject = ['$parse', '$translate'];
  36 +$translationCache.$inject = ['$cacheFactory'];
  37 +angular.module('pascalprecht.translate', ['ng'])
  38 + .run(runTranslate);
  39 +
  40 +function runTranslate($translate) {
  41 +
  42 + 'use strict';
  43 +
  44 + var key = $translate.storageKey(),
  45 + storage = $translate.storage();
  46 +
  47 + var fallbackFromIncorrectStorageValue = function () {
  48 + var preferred = $translate.preferredLanguage();
  49 + if (angular.isString(preferred)) {
  50 + $translate.use(preferred);
  51 + // $translate.use() will also remember the language.
  52 + // So, we don't need to call storage.put() here.
  53 + } else {
  54 + storage.put(key, $translate.use());
  55 + }
  56 + };
  57 +
  58 + fallbackFromIncorrectStorageValue.displayName = 'fallbackFromIncorrectStorageValue';
  59 +
  60 + if (storage) {
  61 + if (!storage.get(key)) {
  62 + fallbackFromIncorrectStorageValue();
  63 + } else {
  64 + $translate.use(storage.get(key))['catch'](fallbackFromIncorrectStorageValue);
  65 + }
  66 + } else if (angular.isString($translate.preferredLanguage())) {
  67 + $translate.use($translate.preferredLanguage());
  68 + }
  69 +}
  70 +
  71 +runTranslate.displayName = 'runTranslate';
  72 +
  73 +/**
  74 + * @ngdoc object
  75 + * @name pascalprecht.translate.$translateSanitizationProvider
  76 + *
  77 + * @description
  78 + *
  79 + * Configurations for $translateSanitization
  80 + */
  81 +angular.module('pascalprecht.translate').provider('$translateSanitization', $translateSanitizationProvider);
  82 +
  83 +function $translateSanitizationProvider () {
  84 +
  85 + 'use strict';
  86 +
  87 + var $sanitize,
  88 + $sce,
  89 + currentStrategy = null, // TODO change to either 'sanitize', 'escape' or ['sanitize', 'escapeParameters'] in 3.0.
  90 + hasConfiguredStrategy = false,
  91 + hasShownNoStrategyConfiguredWarning = false,
  92 + strategies;
  93 +
  94 + /**
  95 + * Definition of a sanitization strategy function
  96 + * @callback StrategyFunction
  97 + * @param {string|object} value - value to be sanitized (either a string or an interpolated value map)
  98 + * @param {string} mode - either 'text' for a string (translation) or 'params' for the interpolated params
  99 + * @return {string|object}
  100 + */
  101 +
  102 + /**
  103 + * @ngdoc property
  104 + * @name strategies
  105 + * @propertyOf pascalprecht.translate.$translateSanitizationProvider
  106 + *
  107 + * @description
  108 + * Following strategies are built-in:
  109 + * <dl>
  110 + * <dt>sanitize</dt>
  111 + * <dd>Sanitizes HTML in the translation text using $sanitize</dd>
  112 + * <dt>escape</dt>
  113 + * <dd>Escapes HTML in the translation</dd>
  114 + * <dt>sanitizeParameters</dt>
  115 + * <dd>Sanitizes HTML in the values of the interpolation parameters using $sanitize</dd>
  116 + * <dt>escapeParameters</dt>
  117 + * <dd>Escapes HTML in the values of the interpolation parameters</dd>
  118 + * <dt>escaped</dt>
  119 + * <dd>Support legacy strategy name 'escaped' for backwards compatibility (will be removed in 3.0)</dd>
  120 + * </dl>
  121 + *
  122 + */
  123 +
  124 + strategies = {
  125 + sanitize: function (value, mode/*, context*/) {
  126 + if (mode === 'text') {
  127 + value = htmlSanitizeValue(value);
  128 + }
  129 + return value;
  130 + },
  131 + escape: function (value, mode/*, context*/) {
  132 + if (mode === 'text') {
  133 + value = htmlEscapeValue(value);
  134 + }
  135 + return value;
  136 + },
  137 + sanitizeParameters: function (value, mode/*, context*/) {
  138 + if (mode === 'params') {
  139 + value = mapInterpolationParameters(value, htmlSanitizeValue);
  140 + }
  141 + return value;
  142 + },
  143 + escapeParameters: function (value, mode/*, context*/) {
  144 + if (mode === 'params') {
  145 + value = mapInterpolationParameters(value, htmlEscapeValue);
  146 + }
  147 + return value;
  148 + },
  149 + sce: function (value, mode, context) {
  150 + if (mode === 'text') {
  151 + value = htmlTrustValue(value);
  152 + } else if (mode === 'params') {
  153 + if (context !== 'filter') {
  154 + // do html escape in filter context #1101
  155 + value = mapInterpolationParameters(value, htmlEscapeValue);
  156 + }
  157 + }
  158 + return value;
  159 + },
  160 + sceParameters: function (value, mode/*, context*/) {
  161 + if (mode === 'params') {
  162 + value = mapInterpolationParameters(value, htmlTrustValue);
  163 + }
  164 + return value;
  165 + }
  166 + };
  167 + // Support legacy strategy name 'escaped' for backwards compatibility.
  168 + // TODO should be removed in 3.0
  169 + strategies.escaped = strategies.escapeParameters;
  170 +
  171 + /**
  172 + * @ngdoc function
  173 + * @name pascalprecht.translate.$translateSanitizationProvider#addStrategy
  174 + * @methodOf pascalprecht.translate.$translateSanitizationProvider
  175 + *
  176 + * @description
  177 + * Adds a sanitization strategy to the list of known strategies.
  178 + *
  179 + * @param {string} strategyName - unique key for a strategy
  180 + * @param {StrategyFunction} strategyFunction - strategy function
  181 + * @returns {object} this
  182 + */
  183 + this.addStrategy = function (strategyName, strategyFunction) {
  184 + strategies[strategyName] = strategyFunction;
  185 + return this;
  186 + };
  187 +
  188 + /**
  189 + * @ngdoc function
  190 + * @name pascalprecht.translate.$translateSanitizationProvider#removeStrategy
  191 + * @methodOf pascalprecht.translate.$translateSanitizationProvider
  192 + *
  193 + * @description
  194 + * Removes a sanitization strategy from the list of known strategies.
  195 + *
  196 + * @param {string} strategyName - unique key for a strategy
  197 + * @returns {object} this
  198 + */
  199 + this.removeStrategy = function (strategyName) {
  200 + delete strategies[strategyName];
  201 + return this;
  202 + };
  203 +
  204 + /**
  205 + * @ngdoc function
  206 + * @name pascalprecht.translate.$translateSanitizationProvider#useStrategy
  207 + * @methodOf pascalprecht.translate.$translateSanitizationProvider
  208 + *
  209 + * @description
  210 + * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.
  211 + *
  212 + * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.
  213 + * @returns {object} this
  214 + */
  215 + this.useStrategy = function (strategy) {
  216 + hasConfiguredStrategy = true;
  217 + currentStrategy = strategy;
  218 + return this;
  219 + };
  220 +
  221 + /**
  222 + * @ngdoc object
  223 + * @name pascalprecht.translate.$translateSanitization
  224 + * @requires $injector
  225 + * @requires $log
  226 + *
  227 + * @description
  228 + * Sanitizes interpolation parameters and translated texts.
  229 + *
  230 + */
  231 + this.$get = ['$injector', '$log', function ($injector, $log) {
  232 +
  233 + var cachedStrategyMap = {};
  234 +
  235 + var applyStrategies = function (value, mode, context, selectedStrategies) {
  236 + angular.forEach(selectedStrategies, function (selectedStrategy) {
  237 + if (angular.isFunction(selectedStrategy)) {
  238 + value = selectedStrategy(value, mode, context);
  239 + } else if (angular.isFunction(strategies[selectedStrategy])) {
  240 + value = strategies[selectedStrategy](value, mode, context);
  241 + } else if (angular.isString(strategies[selectedStrategy])) {
  242 + if (!cachedStrategyMap[strategies[selectedStrategy]]) {
  243 + try {
  244 + cachedStrategyMap[strategies[selectedStrategy]] = $injector.get(strategies[selectedStrategy]);
  245 + } catch (e) {
  246 + cachedStrategyMap[strategies[selectedStrategy]] = function() {};
  247 + throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \'' + selectedStrategy + '\'');
  248 + }
  249 + }
  250 + value = cachedStrategyMap[strategies[selectedStrategy]](value, mode, context);
  251 + } else {
  252 + throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \'' + selectedStrategy + '\'');
  253 + }
  254 + });
  255 + return value;
  256 + };
  257 +
  258 + // TODO: should be removed in 3.0
  259 + var showNoStrategyConfiguredWarning = function () {
  260 + if (!hasConfiguredStrategy && !hasShownNoStrategyConfiguredWarning) {
  261 + $log.warn('pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details.');
  262 + hasShownNoStrategyConfiguredWarning = true;
  263 + }
  264 + };
  265 +
  266 + if ($injector.has('$sanitize')) {
  267 + $sanitize = $injector.get('$sanitize');
  268 + }
  269 + if ($injector.has('$sce')) {
  270 + $sce = $injector.get('$sce');
  271 + }
  272 +
  273 + return {
  274 + /**
  275 + * @ngdoc function
  276 + * @name pascalprecht.translate.$translateSanitization#useStrategy
  277 + * @methodOf pascalprecht.translate.$translateSanitization
  278 + *
  279 + * @description
  280 + * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.
  281 + *
  282 + * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.
  283 + */
  284 + useStrategy: (function (self) {
  285 + return function (strategy) {
  286 + self.useStrategy(strategy);
  287 + };
  288 + })(this),
  289 +
  290 + /**
  291 + * @ngdoc function
  292 + * @name pascalprecht.translate.$translateSanitization#sanitize
  293 + * @methodOf pascalprecht.translate.$translateSanitization
  294 + *
  295 + * @description
  296 + * Sanitizes a value.
  297 + *
  298 + * @param {string|object} value The value which should be sanitized.
  299 + * @param {string} mode The current sanitization mode, either 'params' or 'text'.
  300 + * @param {string|StrategyFunction|array} [strategy] Optional custom strategy which should be used instead of the currently selected strategy.
  301 + * @param {string} [context] The context of this call: filter, service. Default is service
  302 + * @returns {string|object} sanitized value
  303 + */
  304 + sanitize: function (value, mode, strategy, context) {
  305 + if (!currentStrategy) {
  306 + showNoStrategyConfiguredWarning();
  307 + }
  308 +
  309 + if (!strategy && strategy !== null) {
  310 + strategy = currentStrategy;
  311 + }
  312 +
  313 + if (!strategy) {
  314 + return value;
  315 + }
  316 +
  317 + if (!context) {
  318 + context = 'service';
  319 + }
  320 +
  321 + var selectedStrategies = angular.isArray(strategy) ? strategy : [strategy];
  322 + return applyStrategies(value, mode, context, selectedStrategies);
  323 + }
  324 + };
  325 + }];
  326 +
  327 + var htmlEscapeValue = function (value) {
  328 + var element = angular.element('<div></div>');
  329 + element.text(value); // not chainable, see #1044
  330 + return element.html();
  331 + };
  332 +
  333 + var htmlSanitizeValue = function (value) {
  334 + if (!$sanitize) {
  335 + throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as \'escape\'.');
  336 + }
  337 + return $sanitize(value);
  338 + };
  339 +
  340 + var htmlTrustValue = function (value) {
  341 + if (!$sce) {
  342 + throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sce service.');
  343 + }
  344 + return $sce.trustAsHtml(value);
  345 + };
  346 +
  347 + var mapInterpolationParameters = function (value, iteratee, stack) {
  348 + if (angular.isDate(value)) {
  349 + return value;
  350 + } else if (angular.isObject(value)) {
  351 + var result = angular.isArray(value) ? [] : {};
  352 +
  353 + if (!stack) {
  354 + stack = [];
  355 + } else {
  356 + if (stack.indexOf(value) > -1) {
  357 + throw new Error('pascalprecht.translate.$translateSanitization: Error cannot interpolate parameter due recursive object');
  358 + }
  359 + }
  360 +
  361 + stack.push(value);
  362 + angular.forEach(value, function (propertyValue, propertyKey) {
  363 +
  364 + /* Skipping function properties. */
  365 + if (angular.isFunction(propertyValue)) {
  366 + return;
  367 + }
  368 +
  369 + result[propertyKey] = mapInterpolationParameters(propertyValue, iteratee, stack);
  370 + });
  371 + stack.splice(-1, 1); // remove last
  372 +
  373 + return result;
  374 + } else if (angular.isNumber(value)) {
  375 + return value;
  376 + } else if (value === true || value === false) {
  377 + return value;
  378 + } else if (!angular.isUndefined(value) && value !== null) {
  379 + return iteratee(value);
  380 + } else {
  381 + return value;
  382 + }
  383 + };
  384 +}
  385 +
  386 +/**
  387 + * @ngdoc object
  388 + * @name pascalprecht.translate.$translateProvider
  389 + * @description
  390 + *
  391 + * $translateProvider allows developers to register translation-tables, asynchronous loaders
  392 + * and similar to configure translation behavior directly inside of a module.
  393 + *
  394 + */
  395 +angular.module('pascalprecht.translate')
  396 + .constant('pascalprechtTranslateOverrider', {})
  397 + .provider('$translate', $translate);
  398 +
  399 +function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvider, pascalprechtTranslateOverrider) {
  400 +
  401 + 'use strict';
  402 +
  403 + var $translationTable = {},
  404 + $preferredLanguage,
  405 + $availableLanguageKeys = [],
  406 + $languageKeyAliases,
  407 + $fallbackLanguage,
  408 + $fallbackWasString,
  409 + $uses,
  410 + $nextLang,
  411 + $storageFactory,
  412 + $storageKey = $STORAGE_KEY,
  413 + $storagePrefix,
  414 + $missingTranslationHandlerFactory,
  415 + $interpolationFactory,
  416 + $interpolatorFactories = [],
  417 + $loaderFactory,
  418 + $cloakClassName = 'translate-cloak',
  419 + $loaderOptions,
  420 + $notFoundIndicatorLeft,
  421 + $notFoundIndicatorRight,
  422 + $postCompilingEnabled = false,
  423 + $forceAsyncReloadEnabled = false,
  424 + $nestedObjectDelimeter = '.',
  425 + $isReady = false,
  426 + $keepContent = false,
  427 + loaderCache,
  428 + directivePriority = 0,
  429 + statefulFilter = true,
  430 + postProcessFn,
  431 + uniformLanguageTagResolver = 'default',
  432 + languageTagResolver = {
  433 + 'default' : function (tag) {
  434 + return (tag || '').split('-').join('_');
  435 + },
  436 + java : function (tag) {
  437 + var temp = (tag || '').split('-').join('_');
  438 + var parts = temp.split('_');
  439 + return parts.length > 1 ? (parts[0].toLowerCase() + '_' + parts[1].toUpperCase()) : temp;
  440 + },
  441 + bcp47 : function (tag) {
  442 + var temp = (tag || '').split('_').join('-');
  443 + var parts = temp.split('-');
  444 +
  445 + switch (parts.length) {
  446 + case 1: // language only
  447 + parts[0] = parts[0].toLowerCase();
  448 + break;
  449 + case 2: // language-script or language-region
  450 + parts[0] = parts[0].toLowerCase();
  451 + if (parts[1].length === 4) { // parts[1] is script
  452 + parts[1] = parts[1].charAt(0).toUpperCase() + parts[1].slice(1).toLowerCase();
  453 + } else { // parts[1] is region
  454 + parts[1] = parts[1].toUpperCase();
  455 + }
  456 + break;
  457 + case 3: // language-script-region
  458 + parts[0] = parts[0].toLowerCase();
  459 + parts[1] = parts[1].charAt(0).toUpperCase() + parts[1].slice(1).toLowerCase();
  460 + parts[2] = parts[2].toUpperCase();
  461 + break;
  462 + default:
  463 + return temp;
  464 + }
  465 +
  466 + return parts.join('-');
  467 + },
  468 + 'iso639-1' : function (tag) {
  469 + var temp = (tag || '').split('_').join('-');
  470 + var parts = temp.split('-');
  471 + return parts[0].toLowerCase();
  472 + }
  473 + };
  474 +
  475 + var version = '2.17.1';
  476 +
  477 + // tries to determine the browsers language
  478 + var getFirstBrowserLanguage = function () {
  479 +
  480 + // internal purpose only
  481 + if (angular.isFunction(pascalprechtTranslateOverrider.getLocale)) {
  482 + return pascalprechtTranslateOverrider.getLocale();
  483 + }
  484 +
  485 + var nav = $windowProvider.$get().navigator,
  486 + browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],
  487 + i,
  488 + language;
  489 +
  490 + // support for HTML 5.1 "navigator.languages"
  491 + if (angular.isArray(nav.languages)) {
  492 + for (i = 0; i < nav.languages.length; i++) {
  493 + language = nav.languages[i];
  494 + if (language && language.length) {
  495 + return language;
  496 + }
  497 + }
  498 + }
  499 +
  500 + // support for other well known properties in browsers
  501 + for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
  502 + language = nav[browserLanguagePropertyKeys[i]];
  503 + if (language && language.length) {
  504 + return language;
  505 + }
  506 + }
  507 +
  508 + return null;
  509 + };
  510 + getFirstBrowserLanguage.displayName = 'angular-translate/service: getFirstBrowserLanguage';
  511 +
  512 + // tries to determine the browsers locale
  513 + var getLocale = function () {
  514 + var locale = getFirstBrowserLanguage() || '';
  515 + if (languageTagResolver[uniformLanguageTagResolver]) {
  516 + locale = languageTagResolver[uniformLanguageTagResolver](locale);
  517 + }
  518 + return locale;
  519 + };
  520 + getLocale.displayName = 'angular-translate/service: getLocale';
  521 +
  522 + /**
  523 + * @name indexOf
  524 + * @private
  525 + *
  526 + * @description
  527 + * indexOf polyfill. Kinda sorta.
  528 + *
  529 + * @param {array} array Array to search in.
  530 + * @param {string} searchElement Element to search for.
  531 + *
  532 + * @returns {int} Index of search element.
  533 + */
  534 + var indexOf = function (array, searchElement) {
  535 + for (var i = 0, len = array.length; i < len; i++) {
  536 + if (array[i] === searchElement) {
  537 + return i;
  538 + }
  539 + }
  540 + return -1;
  541 + };
  542 +
  543 + /**
  544 + * @name trim
  545 + * @private
  546 + *
  547 + * @description
  548 + * trim polyfill
  549 + *
  550 + * @returns {string} The string stripped of whitespace from both ends
  551 + */
  552 + var trim = function () {
  553 + return this.toString().replace(/^\s+|\s+$/g, '');
  554 + };
  555 +
  556 + /**
  557 + * @name lowercase
  558 + * @private
  559 + *
  560 + * @description
  561 + * Return the lowercase string only if the type is string
  562 + *
  563 + * @returns {string} The string all in lowercase
  564 + */
  565 + var lowercase = function (string) {
  566 + return angular.isString(string) ? string.toLowerCase() : string;
  567 + };
  568 +
  569 + var negotiateLocale = function (preferred) {
  570 + if (!preferred) {
  571 + return;
  572 + }
  573 +
  574 + var avail = [],
  575 + locale = lowercase(preferred),
  576 + i = 0,
  577 + n = $availableLanguageKeys.length;
  578 +
  579 + for (; i < n; i++) {
  580 + avail.push(lowercase($availableLanguageKeys[i]));
  581 + }
  582 +
  583 + // Check for an exact match in our list of available keys
  584 + i = indexOf(avail, locale);
  585 + if (i > -1) {
  586 + return $availableLanguageKeys[i];
  587 + }
  588 +
  589 + if ($languageKeyAliases) {
  590 + var alias;
  591 + for (var langKeyAlias in $languageKeyAliases) {
  592 + if ($languageKeyAliases.hasOwnProperty(langKeyAlias)) {
  593 + var hasWildcardKey = false;
  594 + var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) &&
  595 + lowercase(langKeyAlias) === lowercase(preferred);
  596 +
  597 + if (langKeyAlias.slice(-1) === '*') {
  598 + hasWildcardKey = lowercase(langKeyAlias.slice(0, -1)) === lowercase(preferred.slice(0, langKeyAlias.length - 1));
  599 + }
  600 + if (hasExactKey || hasWildcardKey) {
  601 + alias = $languageKeyAliases[langKeyAlias];
  602 + if (indexOf(avail, lowercase(alias)) > -1) {
  603 + return alias;
  604 + }
  605 + }
  606 + }
  607 + }
  608 + }
  609 +
  610 + // Check for a language code without region
  611 + var parts = preferred.split('_');
  612 +
  613 + if (parts.length > 1 && indexOf(avail, lowercase(parts[0])) > -1) {
  614 + return parts[0];
  615 + }
  616 +
  617 + // If everything fails, return undefined.
  618 + return;
  619 + };
  620 +
  621 + /**
  622 + * @ngdoc function
  623 + * @name pascalprecht.translate.$translateProvider#translations
  624 + * @methodOf pascalprecht.translate.$translateProvider
  625 + *
  626 + * @description
  627 + * Registers a new translation table for specific language key.
  628 + *
  629 + * To register a translation table for specific language, pass a defined language
  630 + * key as first parameter.
  631 + *
  632 + * <pre>
  633 + * // register translation table for language: 'de_DE'
  634 + * $translateProvider.translations('de_DE', {
  635 + * 'GREETING': 'Hallo Welt!'
  636 + * });
  637 + *
  638 + * // register another one
  639 + * $translateProvider.translations('en_US', {
  640 + * 'GREETING': 'Hello world!'
  641 + * });
  642 + * </pre>
  643 + *
  644 + * When registering multiple translation tables for for the same language key,
  645 + * the actual translation table gets extended. This allows you to define module
  646 + * specific translation which only get added, once a specific module is loaded in
  647 + * your app.
  648 + *
  649 + * Invoking this method with no arguments returns the translation table which was
  650 + * registered with no language key. Invoking it with a language key returns the
  651 + * related translation table.
  652 + *
  653 + * @param {string} langKey A language key.
  654 + * @param {object} translationTable A plain old JavaScript object that represents a translation table.
  655 + *
  656 + */
  657 + var translations = function (langKey, translationTable) {
  658 +
  659 + if (!langKey && !translationTable) {
  660 + return $translationTable;
  661 + }
  662 +
  663 + if (langKey && !translationTable) {
  664 + if (angular.isString(langKey)) {
  665 + return $translationTable[langKey];
  666 + }
  667 + } else {
  668 + if (!angular.isObject($translationTable[langKey])) {
  669 + $translationTable[langKey] = {};
  670 + }
  671 + angular.extend($translationTable[langKey], flatObject(translationTable));
  672 + }
  673 + return this;
  674 + };
  675 +
  676 + this.translations = translations;
  677 +
  678 + /**
  679 + * @ngdoc function
  680 + * @name pascalprecht.translate.$translateProvider#cloakClassName
  681 + * @methodOf pascalprecht.translate.$translateProvider
  682 + *
  683 + * @description
  684 + *
  685 + * Let's you change the class name for `translate-cloak` directive.
  686 + * Default class name is `translate-cloak`.
  687 + *
  688 + * @param {string} name translate-cloak class name
  689 + */
  690 + this.cloakClassName = function (name) {
  691 + if (!name) {
  692 + return $cloakClassName;
  693 + }
  694 + $cloakClassName = name;
  695 + return this;
  696 + };
  697 +
  698 + /**
  699 + * @ngdoc function
  700 + * @name pascalprecht.translate.$translateProvider#nestedObjectDelimeter
  701 + * @methodOf pascalprecht.translate.$translateProvider
  702 + *
  703 + * @description
  704 + *
  705 + * Let's you change the delimiter for namespaced translations.
  706 + * Default delimiter is `.`.
  707 + *
  708 + * @param {string} delimiter namespace separator
  709 + */
  710 + this.nestedObjectDelimeter = function (delimiter) {
  711 + if (!delimiter) {
  712 + return $nestedObjectDelimeter;
  713 + }
  714 + $nestedObjectDelimeter = delimiter;
  715 + return this;
  716 + };
  717 +
  718 + /**
  719 + * @name flatObject
  720 + * @private
  721 + *
  722 + * @description
  723 + * Flats an object. This function is used to flatten given translation data with
  724 + * namespaces, so they are later accessible via dot notation.
  725 + */
  726 + var flatObject = function (data, path, result, prevKey) {
  727 + var key, keyWithPath, keyWithShortPath, val;
  728 +
  729 + if (!path) {
  730 + path = [];
  731 + }
  732 + if (!result) {
  733 + result = {};
  734 + }
  735 + for (key in data) {
  736 + if (!Object.prototype.hasOwnProperty.call(data, key)) {
  737 + continue;
  738 + }
  739 + val = data[key];
  740 + if (angular.isObject(val)) {
  741 + flatObject(val, path.concat(key), result, key);
  742 + } else {
  743 + keyWithPath = path.length ? ('' + path.join($nestedObjectDelimeter) + $nestedObjectDelimeter + key) : key;
  744 + if (path.length && key === prevKey) {
  745 + // Create shortcut path (foo.bar == foo.bar.bar)
  746 + keyWithShortPath = '' + path.join($nestedObjectDelimeter);
  747 + // Link it to original path
  748 + result[keyWithShortPath] = '@:' + keyWithPath;
  749 + }
  750 + result[keyWithPath] = val;
  751 + }
  752 + }
  753 + return result;
  754 + };
  755 + flatObject.displayName = 'flatObject';
  756 +
  757 + /**
  758 + * @ngdoc function
  759 + * @name pascalprecht.translate.$translateProvider#addInterpolation
  760 + * @methodOf pascalprecht.translate.$translateProvider
  761 + *
  762 + * @description
  763 + * Adds interpolation services to angular-translate, so it can manage them.
  764 + *
  765 + * @param {object} factory Interpolation service factory
  766 + */
  767 + this.addInterpolation = function (factory) {
  768 + $interpolatorFactories.push(factory);
  769 + return this;
  770 + };
  771 +
  772 + /**
  773 + * @ngdoc function
  774 + * @name pascalprecht.translate.$translateProvider#useMessageFormatInterpolation
  775 + * @methodOf pascalprecht.translate.$translateProvider
  776 + *
  777 + * @description
  778 + * Tells angular-translate to use interpolation functionality of messageformat.js.
  779 + * This is useful when having high level pluralization and gender selection.
  780 + */
  781 + this.useMessageFormatInterpolation = function () {
  782 + return this.useInterpolation('$translateMessageFormatInterpolation');
  783 + };
  784 +
  785 + /**
  786 + * @ngdoc function
  787 + * @name pascalprecht.translate.$translateProvider#useInterpolation
  788 + * @methodOf pascalprecht.translate.$translateProvider
  789 + *
  790 + * @description
  791 + * Tells angular-translate which interpolation style to use as default, application-wide.
  792 + * Simply pass a factory/service name. The interpolation service has to implement
  793 + * the correct interface.
  794 + *
  795 + * @param {string} factory Interpolation service name.
  796 + */
  797 + this.useInterpolation = function (factory) {
  798 + $interpolationFactory = factory;
  799 + return this;
  800 + };
  801 +
  802 + /**
  803 + * @ngdoc function
  804 + * @name pascalprecht.translate.$translateProvider#useSanitizeStrategy
  805 + * @methodOf pascalprecht.translate.$translateProvider
  806 + *
  807 + * @description
  808 + * Simply sets a sanitation strategy type.
  809 + *
  810 + * @param {string} value Strategy type.
  811 + */
  812 + this.useSanitizeValueStrategy = function (value) {
  813 + $translateSanitizationProvider.useStrategy(value);
  814 + return this;
  815 + };
  816 +
  817 + /**
  818 + * @ngdoc function
  819 + * @name pascalprecht.translate.$translateProvider#preferredLanguage
  820 + * @methodOf pascalprecht.translate.$translateProvider
  821 + *
  822 + * @description
  823 + * Tells the module which of the registered translation tables to use for translation
  824 + * at initial startup by passing a language key. Similar to `$translateProvider#use`
  825 + * only that it says which language to **prefer**.
  826 + * It is recommended to call this after {@link pascalprecht.translate.$translate#fallbackLanguage fallbackLanguage()}.
  827 + *
  828 + * @param {string} langKey A language key.
  829 + */
  830 + this.preferredLanguage = function (langKey) {
  831 + if (langKey) {
  832 + setupPreferredLanguage(langKey);
  833 + return this;
  834 + }
  835 + return $preferredLanguage;
  836 + };
  837 + var setupPreferredLanguage = function (langKey) {
  838 + if (langKey) {
  839 + $preferredLanguage = langKey;
  840 + }
  841 + return $preferredLanguage;
  842 + };
  843 + /**
  844 + * @ngdoc function
  845 + * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicator
  846 + * @methodOf pascalprecht.translate.$translateProvider
  847 + *
  848 + * @description
  849 + * Sets an indicator which is used when a translation isn't found. E.g. when
  850 + * setting the indicator as 'X' and one tries to translate a translation id
  851 + * called `NOT_FOUND`, this will result in `X NOT_FOUND X`.
  852 + *
  853 + * Internally this methods sets a left indicator and a right indicator using
  854 + * `$translateProvider.translationNotFoundIndicatorLeft()` and
  855 + * `$translateProvider.translationNotFoundIndicatorRight()`.
  856 + *
  857 + * **Note**: These methods automatically add a whitespace between the indicators
  858 + * and the translation id.
  859 + *
  860 + * @param {string} indicator An indicator, could be any string.
  861 + */
  862 + this.translationNotFoundIndicator = function (indicator) {
  863 + this.translationNotFoundIndicatorLeft(indicator);
  864 + this.translationNotFoundIndicatorRight(indicator);
  865 + return this;
  866 + };
  867 +
  868 + /**
  869 + * ngdoc function
  870 + * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft
  871 + * @methodOf pascalprecht.translate.$translateProvider
  872 + *
  873 + * @description
  874 + * Sets an indicator which is used when a translation isn't found left to the
  875 + * translation id.
  876 + *
  877 + * @param {string} indicator An indicator.
  878 + */
  879 + this.translationNotFoundIndicatorLeft = function (indicator) {
  880 + if (!indicator) {
  881 + return $notFoundIndicatorLeft;
  882 + }
  883 + $notFoundIndicatorLeft = indicator;
  884 + return this;
  885 + };
  886 +
  887 + /**
  888 + * ngdoc function
  889 + * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft
  890 + * @methodOf pascalprecht.translate.$translateProvider
  891 + *
  892 + * @description
  893 + * Sets an indicator which is used when a translation isn't found right to the
  894 + * translation id.
  895 + *
  896 + * @param {string} indicator An indicator.
  897 + */
  898 + this.translationNotFoundIndicatorRight = function (indicator) {
  899 + if (!indicator) {
  900 + return $notFoundIndicatorRight;
  901 + }
  902 + $notFoundIndicatorRight = indicator;
  903 + return this;
  904 + };
  905 +
  906 + /**
  907 + * @ngdoc function
  908 + * @name pascalprecht.translate.$translateProvider#fallbackLanguage
  909 + * @methodOf pascalprecht.translate.$translateProvider
  910 + *
  911 + * @description
  912 + * Tells the module which of the registered translation tables to use when missing translations
  913 + * at initial startup by passing a language key. Similar to `$translateProvider#use`
  914 + * only that it says which language to **fallback**.
  915 + *
  916 + * @param {string||array} langKey A language key.
  917 + *
  918 + */
  919 + this.fallbackLanguage = function (langKey) {
  920 + fallbackStack(langKey);
  921 + return this;
  922 + };
  923 +
  924 + var fallbackStack = function (langKey) {
  925 + if (langKey) {
  926 + if (angular.isString(langKey)) {
  927 + $fallbackWasString = true;
  928 + $fallbackLanguage = [langKey];
  929 + } else if (angular.isArray(langKey)) {
  930 + $fallbackWasString = false;
  931 + $fallbackLanguage = langKey;
  932 + }
  933 + if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) {
  934 + $fallbackLanguage.push($preferredLanguage);
  935 + }
  936 +
  937 + return this;
  938 + } else {
  939 + if ($fallbackWasString) {
  940 + return $fallbackLanguage[0];
  941 + } else {
  942 + return $fallbackLanguage;
  943 + }
  944 + }
  945 + };
  946 +
  947 + /**
  948 + * @ngdoc function
  949 + * @name pascalprecht.translate.$translateProvider#use
  950 + * @methodOf pascalprecht.translate.$translateProvider
  951 + *
  952 + * @description
  953 + * Set which translation table to use for translation by given language key. When
  954 + * trying to 'use' a language which isn't provided, it'll throw an error.
  955 + *
  956 + * You actually don't have to use this method since `$translateProvider#preferredLanguage`
  957 + * does the job too.
  958 + *
  959 + * @param {string} langKey A language key.
  960 + */
  961 + this.use = function (langKey) {
  962 + if (langKey) {
  963 + if (!$translationTable[langKey] && (!$loaderFactory)) {
  964 + // only throw an error, when not loading translation data asynchronously
  965 + throw new Error('$translateProvider couldn\'t find translationTable for langKey: \'' + langKey + '\'');
  966 + }
  967 + $uses = langKey;
  968 + return this;
  969 + }
  970 + return $uses;
  971 + };
  972 +
  973 + /**
  974 + * @ngdoc function
  975 + * @name pascalprecht.translate.$translateProvider#resolveClientLocale
  976 + * @methodOf pascalprecht.translate.$translateProvider
  977 + *
  978 + * @description
  979 + * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.
  980 + *
  981 + * @returns {string} the current client/browser language key
  982 + */
  983 + this.resolveClientLocale = function () {
  984 + return getLocale();
  985 + };
  986 +
  987 + /**
  988 + * @ngdoc function
  989 + * @name pascalprecht.translate.$translateProvider#storageKey
  990 + * @methodOf pascalprecht.translate.$translateProvider
  991 + *
  992 + * @description
  993 + * Tells the module which key must represent the choosed language by a user in the storage.
  994 + *
  995 + * @param {string} key A key for the storage.
  996 + */
  997 + var storageKey = function (key) {
  998 + if (!key) {
  999 + if ($storagePrefix) {
  1000 + return $storagePrefix + $storageKey;
  1001 + }
  1002 + return $storageKey;
  1003 + }
  1004 + $storageKey = key;
  1005 + return this;
  1006 + };
  1007 +
  1008 + this.storageKey = storageKey;
  1009 +
  1010 + /**
  1011 + * @ngdoc function
  1012 + * @name pascalprecht.translate.$translateProvider#useUrlLoader
  1013 + * @methodOf pascalprecht.translate.$translateProvider
  1014 + *
  1015 + * @description
  1016 + * Tells angular-translate to use `$translateUrlLoader` extension service as loader.
  1017 + *
  1018 + * @param {string} url Url
  1019 + * @param {Object=} options Optional configuration object
  1020 + */
  1021 + this.useUrlLoader = function (url, options) {
  1022 + return this.useLoader('$translateUrlLoader', angular.extend({url : url}, options));
  1023 + };
  1024 +
  1025 + /**
  1026 + * @ngdoc function
  1027 + * @name pascalprecht.translate.$translateProvider#useStaticFilesLoader
  1028 + * @methodOf pascalprecht.translate.$translateProvider
  1029 + *
  1030 + * @description
  1031 + * Tells angular-translate to use `$translateStaticFilesLoader` extension service as loader.
  1032 + *
  1033 + * @param {Object=} options Optional configuration object
  1034 + */
  1035 + this.useStaticFilesLoader = function (options) {
  1036 + return this.useLoader('$translateStaticFilesLoader', options);
  1037 + };
  1038 +
  1039 + /**
  1040 + * @ngdoc function
  1041 + * @name pascalprecht.translate.$translateProvider#useLoader
  1042 + * @methodOf pascalprecht.translate.$translateProvider
  1043 + *
  1044 + * @description
  1045 + * Tells angular-translate to use any other service as loader.
  1046 + *
  1047 + * @param {string} loaderFactory Factory name to use
  1048 + * @param {Object=} options Optional configuration object
  1049 + */
  1050 + this.useLoader = function (loaderFactory, options) {
  1051 + $loaderFactory = loaderFactory;
  1052 + $loaderOptions = options || {};
  1053 + return this;
  1054 + };
  1055 +
  1056 + /**
  1057 + * @ngdoc function
  1058 + * @name pascalprecht.translate.$translateProvider#useLocalStorage
  1059 + * @methodOf pascalprecht.translate.$translateProvider
  1060 + *
  1061 + * @description
  1062 + * Tells angular-translate to use `$translateLocalStorage` service as storage layer.
  1063 + *
  1064 + */
  1065 + this.useLocalStorage = function () {
  1066 + return this.useStorage('$translateLocalStorage');
  1067 + };
  1068 +
  1069 + /**
  1070 + * @ngdoc function
  1071 + * @name pascalprecht.translate.$translateProvider#useCookieStorage
  1072 + * @methodOf pascalprecht.translate.$translateProvider
  1073 + *
  1074 + * @description
  1075 + * Tells angular-translate to use `$translateCookieStorage` service as storage layer.
  1076 + */
  1077 + this.useCookieStorage = function () {
  1078 + return this.useStorage('$translateCookieStorage');
  1079 + };
  1080 +
  1081 + /**
  1082 + * @ngdoc function
  1083 + * @name pascalprecht.translate.$translateProvider#useStorage
  1084 + * @methodOf pascalprecht.translate.$translateProvider
  1085 + *
  1086 + * @description
  1087 + * Tells angular-translate to use custom service as storage layer.
  1088 + */
  1089 + this.useStorage = function (storageFactory) {
  1090 + $storageFactory = storageFactory;
  1091 + return this;
  1092 + };
  1093 +
  1094 + /**
  1095 + * @ngdoc function
  1096 + * @name pascalprecht.translate.$translateProvider#storagePrefix
  1097 + * @methodOf pascalprecht.translate.$translateProvider
  1098 + *
  1099 + * @description
  1100 + * Sets prefix for storage key.
  1101 + *
  1102 + * @param {string} prefix Storage key prefix
  1103 + */
  1104 + this.storagePrefix = function (prefix) {
  1105 + if (!prefix) {
  1106 + return prefix;
  1107 + }
  1108 + $storagePrefix = prefix;
  1109 + return this;
  1110 + };
  1111 +
  1112 + /**
  1113 + * @ngdoc function
  1114 + * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandlerLog
  1115 + * @methodOf pascalprecht.translate.$translateProvider
  1116 + *
  1117 + * @description
  1118 + * Tells angular-translate to use built-in log handler when trying to translate
  1119 + * a translation Id which doesn't exist.
  1120 + *
  1121 + * This is actually a shortcut method for `useMissingTranslationHandler()`.
  1122 + *
  1123 + */
  1124 + this.useMissingTranslationHandlerLog = function () {
  1125 + return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog');
  1126 + };
  1127 +
  1128 + /**
  1129 + * @ngdoc function
  1130 + * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandler
  1131 + * @methodOf pascalprecht.translate.$translateProvider
  1132 + *
  1133 + * @description
  1134 + * Expects a factory name which later gets instantiated with `$injector`.
  1135 + * This method can be used to tell angular-translate to use a custom
  1136 + * missingTranslationHandler. Just build a factory which returns a function
  1137 + * and expects a translation id as argument.
  1138 + *
  1139 + * Example:
  1140 + * <pre>
  1141 + * app.config(function ($translateProvider) {
  1142 + * $translateProvider.useMissingTranslationHandler('customHandler');
  1143 + * });
  1144 + *
  1145 + * app.factory('customHandler', function (dep1, dep2) {
  1146 + * return function (translationId) {
  1147 + * // something with translationId and dep1 and dep2
  1148 + * };
  1149 + * });
  1150 + * </pre>
  1151 + *
  1152 + * @param {string} factory Factory name
  1153 + */
  1154 + this.useMissingTranslationHandler = function (factory) {
  1155 + $missingTranslationHandlerFactory = factory;
  1156 + return this;
  1157 + };
  1158 +
  1159 + /**
  1160 + * @ngdoc function
  1161 + * @name pascalprecht.translate.$translateProvider#usePostCompiling
  1162 + * @methodOf pascalprecht.translate.$translateProvider
  1163 + *
  1164 + * @description
  1165 + * If post compiling is enabled, all translated values will be processed
  1166 + * again with AngularJS' $compile.
  1167 + *
  1168 + * Example:
  1169 + * <pre>
  1170 + * app.config(function ($translateProvider) {
  1171 + * $translateProvider.usePostCompiling(true);
  1172 + * });
  1173 + * </pre>
  1174 + *
  1175 + * @param {string} factory Factory name
  1176 + */
  1177 + this.usePostCompiling = function (value) {
  1178 + $postCompilingEnabled = !(!value);
  1179 + return this;
  1180 + };
  1181 +
  1182 + /**
  1183 + * @ngdoc function
  1184 + * @name pascalprecht.translate.$translateProvider#forceAsyncReload
  1185 + * @methodOf pascalprecht.translate.$translateProvider
  1186 + *
  1187 + * @description
  1188 + * If force async reload is enabled, async loader will always be called
  1189 + * even if $translationTable already contains the language key, adding
  1190 + * possible new entries to the $translationTable.
  1191 + *
  1192 + * Example:
  1193 + * <pre>
  1194 + * app.config(function ($translateProvider) {
  1195 + * $translateProvider.forceAsyncReload(true);
  1196 + * });
  1197 + * </pre>
  1198 + *
  1199 + * @param {boolean} value - valid values are true or false
  1200 + */
  1201 + this.forceAsyncReload = function (value) {
  1202 + $forceAsyncReloadEnabled = !(!value);
  1203 + return this;
  1204 + };
  1205 +
  1206 + /**
  1207 + * @ngdoc function
  1208 + * @name pascalprecht.translate.$translateProvider#uniformLanguageTag
  1209 + * @methodOf pascalprecht.translate.$translateProvider
  1210 + *
  1211 + * @description
  1212 + * Tells angular-translate which language tag should be used as a result when determining
  1213 + * the current browser language.
  1214 + *
  1215 + * This setting must be set before invoking {@link pascalprecht.translate.$translateProvider#methods_determinePreferredLanguage determinePreferredLanguage()}.
  1216 + *
  1217 + * <pre>
  1218 + * $translateProvider
  1219 + * .uniformLanguageTag('bcp47')
  1220 + * .determinePreferredLanguage()
  1221 + * </pre>
  1222 + *
  1223 + * The resolver currently supports:
  1224 + * * default
  1225 + * (traditionally: hyphens will be converted into underscores, i.e. en-US => en_US)
  1226 + * en-US => en_US
  1227 + * en_US => en_US
  1228 + * en-us => en_us
  1229 + * * java
  1230 + * like default, but the second part will be always in uppercase
  1231 + * en-US => en_US
  1232 + * en_US => en_US
  1233 + * en-us => en_US
  1234 + * * BCP 47 (RFC 4646 & 4647)
  1235 + * EN => en
  1236 + * en-US => en-US
  1237 + * en_US => en-US
  1238 + * en-us => en-US
  1239 + * sr-latn => sr-Latn
  1240 + * sr-latn-rs => sr-Latn-RS
  1241 + *
  1242 + * See also:
  1243 + * * http://en.wikipedia.org/wiki/IETF_language_tag
  1244 + * * http://www.w3.org/International/core/langtags/
  1245 + * * http://tools.ietf.org/html/bcp47
  1246 + *
  1247 + * @param {string|object} options - options (or standard)
  1248 + * @param {string} options.standard - valid values are 'default', 'bcp47', 'java'
  1249 + */
  1250 + this.uniformLanguageTag = function (options) {
  1251 +
  1252 + if (!options) {
  1253 + options = {};
  1254 + } else if (angular.isString(options)) {
  1255 + options = {
  1256 + standard : options
  1257 + };
  1258 + }
  1259 +
  1260 + uniformLanguageTagResolver = options.standard;
  1261 +
  1262 + return this;
  1263 + };
  1264 +
  1265 + /**
  1266 + * @ngdoc function
  1267 + * @name pascalprecht.translate.$translateProvider#determinePreferredLanguage
  1268 + * @methodOf pascalprecht.translate.$translateProvider
  1269 + *
  1270 + * @description
  1271 + * Tells angular-translate to try to determine on its own which language key
  1272 + * to set as preferred language. When `fn` is given, angular-translate uses it
  1273 + * to determine a language key, otherwise it uses the built-in `getLocale()`
  1274 + * method.
  1275 + *
  1276 + * The `getLocale()` returns a language key in the format `[lang]_[country]` or
  1277 + * `[lang]` depending on what the browser provides.
  1278 + *
  1279 + * Use this method at your own risk, since not all browsers return a valid
  1280 + * locale (see {@link pascalprecht.translate.$translateProvider#methods_uniformLanguageTag uniformLanguageTag()}).
  1281 + *
  1282 + * @param {Function=} fn Function to determine a browser's locale
  1283 + */
  1284 + this.determinePreferredLanguage = function (fn) {
  1285 +
  1286 + var locale = (fn && angular.isFunction(fn)) ? fn() : getLocale();
  1287 +
  1288 + if (!$availableLanguageKeys.length) {
  1289 + $preferredLanguage = locale;
  1290 + } else {
  1291 + $preferredLanguage = negotiateLocale(locale) || locale;
  1292 + }
  1293 +
  1294 + return this;
  1295 + };
  1296 +
  1297 + /**
  1298 + * @ngdoc function
  1299 + * @name pascalprecht.translate.$translateProvider#registerAvailableLanguageKeys
  1300 + * @methodOf pascalprecht.translate.$translateProvider
  1301 + *
  1302 + * @description
  1303 + * Registers a set of language keys the app will work with. Use this method in
  1304 + * combination with
  1305 + * {@link pascalprecht.translate.$translateProvider#determinePreferredLanguage determinePreferredLanguage}.
  1306 + * When available languages keys are registered, angular-translate
  1307 + * tries to find the best fitting language key depending on the browsers locale,
  1308 + * considering your language key convention.
  1309 + *
  1310 + * @param {object} languageKeys Array of language keys the your app will use
  1311 + * @param {object=} aliases Alias map.
  1312 + */
  1313 + this.registerAvailableLanguageKeys = function (languageKeys, aliases) {
  1314 + if (languageKeys) {
  1315 + $availableLanguageKeys = languageKeys;
  1316 + if (aliases) {
  1317 + $languageKeyAliases = aliases;
  1318 + }
  1319 + return this;
  1320 + }
  1321 + return $availableLanguageKeys;
  1322 + };
  1323 +
  1324 + /**
  1325 + * @ngdoc function
  1326 + * @name pascalprecht.translate.$translateProvider#useLoaderCache
  1327 + * @methodOf pascalprecht.translate.$translateProvider
  1328 + *
  1329 + * @description
  1330 + * Registers a cache for internal $http based loaders.
  1331 + * {@link pascalprecht.translate.$translationCache $translationCache}.
  1332 + * When false the cache will be disabled (default). When true or undefined
  1333 + * the cache will be a default (see $cacheFactory). When an object it will
  1334 + * be treat as a cache object itself: the usage is $http({cache: cache})
  1335 + *
  1336 + * @param {object} cache boolean, string or cache-object
  1337 + */
  1338 + this.useLoaderCache = function (cache) {
  1339 + if (cache === false) {
  1340 + // disable cache
  1341 + loaderCache = undefined;
  1342 + } else if (cache === true) {
  1343 + // enable cache using AJS defaults
  1344 + loaderCache = true;
  1345 + } else if (typeof(cache) === 'undefined') {
  1346 + // enable cache using default
  1347 + loaderCache = '$translationCache';
  1348 + } else if (cache) {
  1349 + // enable cache using given one (see $cacheFactory)
  1350 + loaderCache = cache;
  1351 + }
  1352 + return this;
  1353 + };
  1354 +
  1355 + /**
  1356 + * @ngdoc function
  1357 + * @name pascalprecht.translate.$translateProvider#directivePriority
  1358 + * @methodOf pascalprecht.translate.$translateProvider
  1359 + *
  1360 + * @description
  1361 + * Sets the default priority of the translate directive. The standard value is `0`.
  1362 + * Calling this function without an argument will return the current value.
  1363 + *
  1364 + * @param {number} priority for the translate-directive
  1365 + */
  1366 + this.directivePriority = function (priority) {
  1367 + if (priority === undefined) {
  1368 + // getter
  1369 + return directivePriority;
  1370 + } else {
  1371 + // setter with chaining
  1372 + directivePriority = priority;
  1373 + return this;
  1374 + }
  1375 + };
  1376 +
  1377 + /**
  1378 + * @ngdoc function
  1379 + * @name pascalprecht.translate.$translateProvider#statefulFilter
  1380 + * @methodOf pascalprecht.translate.$translateProvider
  1381 + *
  1382 + * @description
  1383 + * Since AngularJS 1.3, filters which are not stateless (depending at the scope)
  1384 + * have to explicit define this behavior.
  1385 + * Sets whether the translate filter should be stateful or stateless. The standard value is `true`
  1386 + * meaning being stateful.
  1387 + * Calling this function without an argument will return the current value.
  1388 + *
  1389 + * @param {boolean} state - defines the state of the filter
  1390 + */
  1391 + this.statefulFilter = function (state) {
  1392 + if (state === undefined) {
  1393 + // getter
  1394 + return statefulFilter;
  1395 + } else {
  1396 + // setter with chaining
  1397 + statefulFilter = state;
  1398 + return this;
  1399 + }
  1400 + };
  1401 +
  1402 + /**
  1403 + * @ngdoc function
  1404 + * @name pascalprecht.translate.$translateProvider#postProcess
  1405 + * @methodOf pascalprecht.translate.$translateProvider
  1406 + *
  1407 + * @description
  1408 + * The post processor will be intercept right after the translation result. It can modify the result.
  1409 + *
  1410 + * @param {object} fn Function or service name (string) to be called after the translation value has been set / resolved. The function itself will enrich every value being processed and then continue the normal resolver process
  1411 + */
  1412 + this.postProcess = function (fn) {
  1413 + if (fn) {
  1414 + postProcessFn = fn;
  1415 + } else {
  1416 + postProcessFn = undefined;
  1417 + }
  1418 + return this;
  1419 + };
  1420 +
  1421 + /**
  1422 + * @ngdoc function
  1423 + * @name pascalprecht.translate.$translateProvider#keepContent
  1424 + * @methodOf pascalprecht.translate.$translateProvider
  1425 + *
  1426 + * @description
  1427 + * If keepContent is set to true than translate directive will always use innerHTML
  1428 + * as a default translation
  1429 + *
  1430 + * Example:
  1431 + * <pre>
  1432 + * app.config(function ($translateProvider) {
  1433 + * $translateProvider.keepContent(true);
  1434 + * });
  1435 + * </pre>
  1436 + *
  1437 + * @param {boolean} value - valid values are true or false
  1438 + */
  1439 + this.keepContent = function (value) {
  1440 + $keepContent = !(!value);
  1441 + return this;
  1442 + };
  1443 +
  1444 + /**
  1445 + * @ngdoc object
  1446 + * @name pascalprecht.translate.$translate
  1447 + * @requires $interpolate
  1448 + * @requires $log
  1449 + * @requires $rootScope
  1450 + * @requires $q
  1451 + *
  1452 + * @description
  1453 + * The `$translate` service is the actual core of angular-translate. It expects a translation id
  1454 + * and optional interpolate parameters to translate contents.
  1455 + *
  1456 + * <pre>
  1457 + * $translate('HEADLINE_TEXT').then(function (translation) {
  1458 + * $scope.translatedText = translation;
  1459 + * });
  1460 + * </pre>
  1461 + *
  1462 + * @param {string|array} translationId A token which represents a translation id
  1463 + * This can be optionally an array of translation ids which
  1464 + * results that the function returns an object where each key
  1465 + * is the translation id and the value the translation.
  1466 + * @param {object=} [interpolateParams={}] An object hash for dynamic values
  1467 + * @param {string=} [interpolationId=undefined] The id of the interpolation to use (use default unless set via useInterpolation())
  1468 + * @param {string=} [defaultTranslationText=undefined] the optional default translation text that is written as
  1469 + * as default text in case it is not found in any configured language
  1470 + * @param {string=} [forceLanguage=false] A language to be used instead of the current language
  1471 + * @param {string=} [sanitizeStrategy=undefined] force sanitize strategy for this call instead of using the configured one (use default unless set)
  1472 + * @returns {object} promise
  1473 + */
  1474 + this.$get = ['$log', '$injector', '$rootScope', '$q', function ($log, $injector, $rootScope, $q) {
  1475 +
  1476 + var Storage,
  1477 + defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'),
  1478 + pendingLoader = false,
  1479 + interpolatorHashMap = {},
  1480 + langPromises = {},
  1481 + fallbackIndex,
  1482 + startFallbackIteration;
  1483 +
  1484 + var $translate = function (translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage, sanitizeStrategy) {
  1485 + if (!$uses && $preferredLanguage) {
  1486 + $uses = $preferredLanguage;
  1487 + }
  1488 + var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses
  1489 + (negotiateLocale(forceLanguage) || forceLanguage) : $uses;
  1490 +
  1491 + // Check forceLanguage is present
  1492 + if (forceLanguage) {
  1493 + loadTranslationsIfMissing(forceLanguage);
  1494 + }
  1495 +
  1496 + // Duck detection: If the first argument is an array, a bunch of translations was requested.
  1497 + // The result is an object.
  1498 + if (angular.isArray(translationId)) {
  1499 + // Inspired by Q.allSettled by Kris Kowal
  1500 + // https://github.com/kriskowal/q/blob/b0fa72980717dc202ffc3cbf03b936e10ebbb9d7/q.js#L1553-1563
  1501 + // This transforms all promises regardless resolved or rejected
  1502 + var translateAll = function (translationIds) {
  1503 + var results = {}; // storing the actual results
  1504 + var promises = []; // promises to wait for
  1505 + // Wraps the promise a) being always resolved and b) storing the link id->value
  1506 + var translate = function (translationId) {
  1507 + var deferred = $q.defer();
  1508 + var regardless = function (value) {
  1509 + results[translationId] = value;
  1510 + deferred.resolve([translationId, value]);
  1511 + };
  1512 + // we don't care whether the promise was resolved or rejected; just store the values
  1513 + $translate(translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage, sanitizeStrategy).then(regardless, regardless);
  1514 + return deferred.promise;
  1515 + };
  1516 + for (var i = 0, c = translationIds.length; i < c; i++) {
  1517 + promises.push(translate(translationIds[i]));
  1518 + }
  1519 + // wait for all (including storing to results)
  1520 + return $q.all(promises).then(function () {
  1521 + // return the results
  1522 + return results;
  1523 + });
  1524 + };
  1525 + return translateAll(translationId);
  1526 + }
  1527 +
  1528 + var deferred = $q.defer();
  1529 +
  1530 + // trim off any whitespace
  1531 + if (translationId) {
  1532 + translationId = trim.apply(translationId);
  1533 + }
  1534 +
  1535 + var promiseToWaitFor = (function () {
  1536 + var promise = langPromises[uses] || langPromises[$preferredLanguage];
  1537 +
  1538 + fallbackIndex = 0;
  1539 +
  1540 + if ($storageFactory && !promise) {
  1541 + // looks like there's no pending promise for $preferredLanguage or
  1542 + // $uses. Maybe there's one pending for a language that comes from
  1543 + // storage.
  1544 + var langKey = Storage.get($storageKey);
  1545 + promise = langPromises[langKey];
  1546 +
  1547 + if ($fallbackLanguage && $fallbackLanguage.length) {
  1548 + var index = indexOf($fallbackLanguage, langKey);
  1549 + // maybe the language from storage is also defined as fallback language
  1550 + // we increase the fallback language index to not search in that language
  1551 + // as fallback, since it's probably the first used language
  1552 + // in that case the index starts after the first element
  1553 + fallbackIndex = (index === 0) ? 1 : 0;
  1554 +
  1555 + // but we can make sure to ALWAYS fallback to preferred language at least
  1556 + if (indexOf($fallbackLanguage, $preferredLanguage) < 0) {
  1557 + $fallbackLanguage.push($preferredLanguage);
  1558 + }
  1559 + }
  1560 + }
  1561 + return promise;
  1562 + }());
  1563 +
  1564 + if (!promiseToWaitFor) {
  1565 + // no promise to wait for? okay. Then there's no loader registered
  1566 + // nor is a one pending for language that comes from storage.
  1567 + // We can just translate.
  1568 + determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy).then(deferred.resolve, deferred.reject);
  1569 + } else {
  1570 + var promiseResolved = function () {
  1571 + // $uses may have changed while waiting
  1572 + if (!forceLanguage) {
  1573 + uses = $uses;
  1574 + }
  1575 + determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy).then(deferred.resolve, deferred.reject);
  1576 + };
  1577 + promiseResolved.displayName = 'promiseResolved';
  1578 +
  1579 + promiseToWaitFor['finally'](promiseResolved)['catch'](angular.noop); // we don't care about errors here, already handled
  1580 + }
  1581 + return deferred.promise;
  1582 + };
  1583 +
  1584 + /**
  1585 + * @name applyNotFoundIndicators
  1586 + * @private
  1587 + *
  1588 + * @description
  1589 + * Applies not fount indicators to given translation id, if needed.
  1590 + * This function gets only executed, if a translation id doesn't exist,
  1591 + * which is why a translation id is expected as argument.
  1592 + *
  1593 + * @param {string} translationId Translation id.
  1594 + * @returns {string} Same as given translation id but applied with not found
  1595 + * indicators.
  1596 + */
  1597 + var applyNotFoundIndicators = function (translationId) {
  1598 + // applying notFoundIndicators
  1599 + if ($notFoundIndicatorLeft) {
  1600 + translationId = [$notFoundIndicatorLeft, translationId].join(' ');
  1601 + }
  1602 + if ($notFoundIndicatorRight) {
  1603 + translationId = [translationId, $notFoundIndicatorRight].join(' ');
  1604 + }
  1605 + return translationId;
  1606 + };
  1607 +
  1608 + /**
  1609 + * @name useLanguage
  1610 + * @private
  1611 + *
  1612 + * @description
  1613 + * Makes actual use of a language by setting a given language key as used
  1614 + * language and informs registered interpolators to also use the given
  1615 + * key as locale.
  1616 + *
  1617 + * @param {string} key Locale key.
  1618 + */
  1619 + var useLanguage = function (key) {
  1620 + $uses = key;
  1621 +
  1622 + // make sure to store new language key before triggering success event
  1623 + if ($storageFactory) {
  1624 + Storage.put($translate.storageKey(), $uses);
  1625 + }
  1626 +
  1627 + $rootScope.$emit('$translateChangeSuccess', {language : key});
  1628 +
  1629 + // inform default interpolator
  1630 + defaultInterpolator.setLocale($uses);
  1631 +
  1632 + var eachInterpolator = function (interpolator, id) {
  1633 + interpolatorHashMap[id].setLocale($uses);
  1634 + };
  1635 + eachInterpolator.displayName = 'eachInterpolatorLocaleSetter';
  1636 +
  1637 + // inform all others too!
  1638 + angular.forEach(interpolatorHashMap, eachInterpolator);
  1639 + $rootScope.$emit('$translateChangeEnd', {language : key});
  1640 + };
  1641 +
  1642 + /**
  1643 + * @name loadAsync
  1644 + * @private
  1645 + *
  1646 + * @description
  1647 + * Kicks off registered async loader using `$injector` and applies existing
  1648 + * loader options. When resolved, it updates translation tables accordingly
  1649 + * or rejects with given language key.
  1650 + *
  1651 + * @param {string} key Language key.
  1652 + * @return {Promise} A promise.
  1653 + */
  1654 + var loadAsync = function (key) {
  1655 + if (!key) {
  1656 + throw 'No language key specified for loading.';
  1657 + }
  1658 +
  1659 + var deferred = $q.defer();
  1660 +
  1661 + $rootScope.$emit('$translateLoadingStart', {language : key});
  1662 + pendingLoader = true;
  1663 +
  1664 + var cache = loaderCache;
  1665 + if (typeof(cache) === 'string') {
  1666 + // getting on-demand instance of loader
  1667 + cache = $injector.get(cache);
  1668 + }
  1669 +
  1670 + var loaderOptions = angular.extend({}, $loaderOptions, {
  1671 + key : key,
  1672 + $http : angular.extend({}, {
  1673 + cache : cache
  1674 + }, $loaderOptions.$http)
  1675 + });
  1676 +
  1677 + var onLoaderSuccess = function (data) {
  1678 + var translationTable = {};
  1679 + $rootScope.$emit('$translateLoadingSuccess', {language : key});
  1680 +
  1681 + if (angular.isArray(data)) {
  1682 + angular.forEach(data, function (table) {
  1683 + angular.extend(translationTable, flatObject(table));
  1684 + });
  1685 + } else {
  1686 + angular.extend(translationTable, flatObject(data));
  1687 + }
  1688 + pendingLoader = false;
  1689 + deferred.resolve({
  1690 + key : key,
  1691 + table : translationTable
  1692 + });
  1693 + $rootScope.$emit('$translateLoadingEnd', {language : key});
  1694 + };
  1695 + onLoaderSuccess.displayName = 'onLoaderSuccess';
  1696 +
  1697 + var onLoaderError = function (key) {
  1698 + $rootScope.$emit('$translateLoadingError', {language : key});
  1699 + deferred.reject(key);
  1700 + $rootScope.$emit('$translateLoadingEnd', {language : key});
  1701 + };
  1702 + onLoaderError.displayName = 'onLoaderError';
  1703 +
  1704 + $injector.get($loaderFactory)(loaderOptions)
  1705 + .then(onLoaderSuccess, onLoaderError);
  1706 +
  1707 + return deferred.promise;
  1708 + };
  1709 +
  1710 + if ($storageFactory) {
  1711 + Storage = $injector.get($storageFactory);
  1712 +
  1713 + if (!Storage.get || !Storage.put) {
  1714 + throw new Error('Couldn\'t use storage \'' + $storageFactory + '\', missing get() or put() method!');
  1715 + }
  1716 + }
  1717 +
  1718 + // if we have additional interpolations that were added via
  1719 + // $translateProvider.addInterpolation(), we have to map'em
  1720 + if ($interpolatorFactories.length) {
  1721 + var eachInterpolationFactory = function (interpolatorFactory) {
  1722 + var interpolator = $injector.get(interpolatorFactory);
  1723 + // setting initial locale for each interpolation service
  1724 + interpolator.setLocale($preferredLanguage || $uses);
  1725 + // make'em recognizable through id
  1726 + interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;
  1727 + };
  1728 + eachInterpolationFactory.displayName = 'interpolationFactoryAdder';
  1729 +
  1730 + angular.forEach($interpolatorFactories, eachInterpolationFactory);
  1731 + }
  1732 +
  1733 + /**
  1734 + * @name getTranslationTable
  1735 + * @private
  1736 + *
  1737 + * @description
  1738 + * Returns a promise that resolves to the translation table
  1739 + * or is rejected if an error occurred.
  1740 + *
  1741 + * @param langKey
  1742 + * @returns {Q.promise}
  1743 + */
  1744 + var getTranslationTable = function (langKey) {
  1745 + var deferred = $q.defer();
  1746 + if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) {
  1747 + deferred.resolve($translationTable[langKey]);
  1748 + } else if (langPromises[langKey]) {
  1749 + var onResolve = function (data) {
  1750 + translations(data.key, data.table);
  1751 + deferred.resolve(data.table);
  1752 + };
  1753 + onResolve.displayName = 'translationTableResolver';
  1754 + langPromises[langKey].then(onResolve, deferred.reject);
  1755 + } else {
  1756 + deferred.reject();
  1757 + }
  1758 + return deferred.promise;
  1759 + };
  1760 +
  1761 + /**
  1762 + * @name getFallbackTranslation
  1763 + * @private
  1764 + *
  1765 + * @description
  1766 + * Returns a promise that will resolve to the translation
  1767 + * or be rejected if no translation was found for the language.
  1768 + * This function is currently only used for fallback language translation.
  1769 + *
  1770 + * @param langKey The language to translate to.
  1771 + * @param translationId
  1772 + * @param interpolateParams
  1773 + * @param Interpolator
  1774 + * @param sanitizeStrategy
  1775 + * @returns {Q.promise}
  1776 + */
  1777 + var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {
  1778 + var deferred = $q.defer();
  1779 +
  1780 + var onResolve = function (translationTable) {
  1781 + if (Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {
  1782 + Interpolator.setLocale(langKey);
  1783 + var translation = translationTable[translationId];
  1784 + if (translation.substr(0, 2) === '@:') {
  1785 + getFallbackTranslation(langKey, translation.substr(2), interpolateParams, Interpolator, sanitizeStrategy)
  1786 + .then(deferred.resolve, deferred.reject);
  1787 + } else {
  1788 + var interpolatedValue = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'service', sanitizeStrategy, translationId);
  1789 + interpolatedValue = applyPostProcessing(translationId, translationTable[translationId], interpolatedValue, interpolateParams, langKey);
  1790 +
  1791 + deferred.resolve(interpolatedValue);
  1792 +
  1793 + }
  1794 + Interpolator.setLocale($uses);
  1795 + } else {
  1796 + deferred.reject();
  1797 + }
  1798 + };
  1799 + onResolve.displayName = 'fallbackTranslationResolver';
  1800 +
  1801 + getTranslationTable(langKey).then(onResolve, deferred.reject);
  1802 +
  1803 + return deferred.promise;
  1804 + };
  1805 +
  1806 + /**
  1807 + * @name getFallbackTranslationInstant
  1808 + * @private
  1809 + *
  1810 + * @description
  1811 + * Returns a translation
  1812 + * This function is currently only used for fallback language translation.
  1813 + *
  1814 + * @param langKey The language to translate to.
  1815 + * @param translationId
  1816 + * @param interpolateParams
  1817 + * @param Interpolator
  1818 + * @param sanitizeStrategy sanitize strategy override
  1819 + *
  1820 + * @returns {string} translation
  1821 + */
  1822 + var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {
  1823 + var result, translationTable = $translationTable[langKey];
  1824 +
  1825 + if (translationTable && Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {
  1826 + Interpolator.setLocale(langKey);
  1827 + result = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'filter', sanitizeStrategy, translationId);
  1828 + result = applyPostProcessing(translationId, translationTable[translationId], result, interpolateParams, langKey, sanitizeStrategy);
  1829 + // workaround for TrustedValueHolderType
  1830 + if (!angular.isString(result) && angular.isFunction(result.$$unwrapTrustedValue)) {
  1831 + var result2 = result.$$unwrapTrustedValue();
  1832 + if (result2.substr(0, 2) === '@:') {
  1833 + return getFallbackTranslationInstant(langKey, result2.substr(2), interpolateParams, Interpolator, sanitizeStrategy);
  1834 + }
  1835 + } else if (result.substr(0, 2) === '@:') {
  1836 + return getFallbackTranslationInstant(langKey, result.substr(2), interpolateParams, Interpolator, sanitizeStrategy);
  1837 + }
  1838 + Interpolator.setLocale($uses);
  1839 + }
  1840 +
  1841 + return result;
  1842 + };
  1843 +
  1844 +
  1845 + /**
  1846 + * @name translateByHandler
  1847 + * @private
  1848 + *
  1849 + * Translate by missing translation handler.
  1850 + *
  1851 + * @param translationId
  1852 + * @param interpolateParams
  1853 + * @param defaultTranslationText
  1854 + * @param sanitizeStrategy sanitize strategy override
  1855 + *
  1856 + * @returns translation created by $missingTranslationHandler or translationId is $missingTranslationHandler is
  1857 + * absent
  1858 + */
  1859 + var translateByHandler = function (translationId, interpolateParams, defaultTranslationText, sanitizeStrategy) {
  1860 + // If we have a handler factory - we might also call it here to determine if it provides
  1861 + // a default text for a translationid that can't be found anywhere in our tables
  1862 + if ($missingTranslationHandlerFactory) {
  1863 + return $injector.get($missingTranslationHandlerFactory)(translationId, $uses, interpolateParams, defaultTranslationText, sanitizeStrategy);
  1864 + } else {
  1865 + return translationId;
  1866 + }
  1867 + };
  1868 +
  1869 + /**
  1870 + * @name resolveForFallbackLanguage
  1871 + * @private
  1872 + *
  1873 + * Recursive helper function for fallbackTranslation that will sequentially look
  1874 + * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.
  1875 + *
  1876 + * @param fallbackLanguageIndex
  1877 + * @param translationId
  1878 + * @param interpolateParams
  1879 + * @param Interpolator
  1880 + * @param defaultTranslationText
  1881 + * @param sanitizeStrategy
  1882 + * @returns {Q.promise} Promise that will resolve to the translation.
  1883 + */
  1884 + var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {
  1885 + var deferred = $q.defer();
  1886 +
  1887 + if (fallbackLanguageIndex < $fallbackLanguage.length) {
  1888 + var langKey = $fallbackLanguage[fallbackLanguageIndex];
  1889 + getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy).then(
  1890 + function (data) {
  1891 + deferred.resolve(data);
  1892 + },
  1893 + function () {
  1894 + // Look in the next fallback language for a translation.
  1895 + // It delays the resolving by passing another promise to resolve.
  1896 + return resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy).then(deferred.resolve, deferred.reject);
  1897 + }
  1898 + );
  1899 + } else {
  1900 + // No translation found in any fallback language
  1901 + // if a default translation text is set in the directive, then return this as a result
  1902 + if (defaultTranslationText) {
  1903 + deferred.resolve(defaultTranslationText);
  1904 + } else {
  1905 + var missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);
  1906 +
  1907 + // if no default translation is set and an error handler is defined, send it to the handler
  1908 + // and then return the result if it isn't undefined
  1909 + if ($missingTranslationHandlerFactory && missingTranslationHandlerTranslation) {
  1910 + deferred.resolve(missingTranslationHandlerTranslation);
  1911 + } else {
  1912 + deferred.reject(applyNotFoundIndicators(translationId));
  1913 + }
  1914 + }
  1915 + }
  1916 + return deferred.promise;
  1917 + };
  1918 +
  1919 + /**
  1920 + * @name resolveForFallbackLanguageInstant
  1921 + * @private
  1922 + *
  1923 + * Recursive helper function for fallbackTranslation that will sequentially look
  1924 + * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.
  1925 + *
  1926 + * @param fallbackLanguageIndex
  1927 + * @param translationId
  1928 + * @param interpolateParams
  1929 + * @param Interpolator
  1930 + * @param sanitizeStrategy
  1931 + * @returns {string} translation
  1932 + */
  1933 + var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, sanitizeStrategy) {
  1934 + var result;
  1935 +
  1936 + if (fallbackLanguageIndex < $fallbackLanguage.length) {
  1937 + var langKey = $fallbackLanguage[fallbackLanguageIndex];
  1938 + result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy);
  1939 + if (!result && result !== '') {
  1940 + result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);
  1941 + }
  1942 + }
  1943 + return result;
  1944 + };
  1945 +
  1946 + /**
  1947 + * Translates with the usage of the fallback languages.
  1948 + *
  1949 + * @param translationId
  1950 + * @param interpolateParams
  1951 + * @param Interpolator
  1952 + * @param defaultTranslationText
  1953 + * @param sanitizeStrategy
  1954 + * @returns {Q.promise} Promise, that resolves to the translation.
  1955 + */
  1956 + var fallbackTranslation = function (translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {
  1957 + // Start with the fallbackLanguage with index 0
  1958 + return resolveForFallbackLanguage((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy);
  1959 + };
  1960 +
  1961 + /**
  1962 + * Translates with the usage of the fallback languages.
  1963 + *
  1964 + * @param translationId
  1965 + * @param interpolateParams
  1966 + * @param Interpolator
  1967 + * @param sanitizeStrategy
  1968 + * @returns {String} translation
  1969 + */
  1970 + var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator, sanitizeStrategy) {
  1971 + // Start with the fallbackLanguage with index 0
  1972 + return resolveForFallbackLanguageInstant((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, sanitizeStrategy);
  1973 + };
  1974 +
  1975 + var determineTranslation = function (translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy) {
  1976 +
  1977 + var deferred = $q.defer();
  1978 +
  1979 + var table = uses ? $translationTable[uses] : $translationTable,
  1980 + Interpolator = (interpolationId) ? interpolatorHashMap[interpolationId] : defaultInterpolator;
  1981 +
  1982 + // if the translation id exists, we can just interpolate it
  1983 + if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {
  1984 + var translation = table[translationId];
  1985 +
  1986 + // If using link, rerun $translate with linked translationId and return it
  1987 + if (translation.substr(0, 2) === '@:') {
  1988 +
  1989 + $translate(translation.substr(2), interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy)
  1990 + .then(deferred.resolve, deferred.reject);
  1991 + } else {
  1992 + //
  1993 + var resolvedTranslation = Interpolator.interpolate(translation, interpolateParams, 'service', sanitizeStrategy, translationId);
  1994 + resolvedTranslation = applyPostProcessing(translationId, translation, resolvedTranslation, interpolateParams, uses);
  1995 + deferred.resolve(resolvedTranslation);
  1996 + }
  1997 + } else {
  1998 + var missingTranslationHandlerTranslation;
  1999 + // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise
  2000 + if ($missingTranslationHandlerFactory && !pendingLoader) {
  2001 + missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);
  2002 + }
  2003 +
  2004 + // since we couldn't translate the inital requested translation id,
  2005 + // we try it now with one or more fallback languages, if fallback language(s) is
  2006 + // configured.
  2007 + if (uses && $fallbackLanguage && $fallbackLanguage.length) {
  2008 + fallbackTranslation(translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy)
  2009 + .then(function (translation) {
  2010 + deferred.resolve(translation);
  2011 + }, function (_translationId) {
  2012 + deferred.reject(applyNotFoundIndicators(_translationId));
  2013 + });
  2014 + } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
  2015 + // looks like the requested translation id doesn't exists.
  2016 + // Now, if there is a registered handler for missing translations and no
  2017 + // asyncLoader is pending, we execute the handler
  2018 + if (defaultTranslationText) {
  2019 + deferred.resolve(defaultTranslationText);
  2020 + } else {
  2021 + deferred.resolve(missingTranslationHandlerTranslation);
  2022 + }
  2023 + } else {
  2024 + if (defaultTranslationText) {
  2025 + deferred.resolve(defaultTranslationText);
  2026 + } else {
  2027 + deferred.reject(applyNotFoundIndicators(translationId));
  2028 + }
  2029 + }
  2030 + }
  2031 + return deferred.promise;
  2032 + };
  2033 +
  2034 + var determineTranslationInstant = function (translationId, interpolateParams, interpolationId, uses, sanitizeStrategy) {
  2035 +
  2036 + var result, table = uses ? $translationTable[uses] : $translationTable,
  2037 + Interpolator = defaultInterpolator;
  2038 +
  2039 + // if the interpolation id exists use custom interpolator
  2040 + if (interpolatorHashMap && Object.prototype.hasOwnProperty.call(interpolatorHashMap, interpolationId)) {
  2041 + Interpolator = interpolatorHashMap[interpolationId];
  2042 + }
  2043 +
  2044 + // if the translation id exists, we can just interpolate it
  2045 + if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {
  2046 + var translation = table[translationId];
  2047 +
  2048 + // If using link, rerun $translate with linked translationId and return it
  2049 + if (translation.substr(0, 2) === '@:') {
  2050 + result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId, uses, sanitizeStrategy);
  2051 + } else {
  2052 + result = Interpolator.interpolate(translation, interpolateParams, 'filter', sanitizeStrategy, translationId);
  2053 + result = applyPostProcessing(translationId, translation, result, interpolateParams, uses, sanitizeStrategy);
  2054 + }
  2055 + } else {
  2056 + var missingTranslationHandlerTranslation;
  2057 + // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise
  2058 + if ($missingTranslationHandlerFactory && !pendingLoader) {
  2059 + missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);
  2060 + }
  2061 +
  2062 + // since we couldn't translate the inital requested translation id,
  2063 + // we try it now with one or more fallback languages, if fallback language(s) is
  2064 + // configured.
  2065 + if (uses && $fallbackLanguage && $fallbackLanguage.length) {
  2066 + fallbackIndex = 0;
  2067 + result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator, sanitizeStrategy);
  2068 + } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
  2069 + // looks like the requested translation id doesn't exists.
  2070 + // Now, if there is a registered handler for missing translations and no
  2071 + // asyncLoader is pending, we execute the handler
  2072 + result = missingTranslationHandlerTranslation;
  2073 + } else {
  2074 + result = applyNotFoundIndicators(translationId);
  2075 + }
  2076 + }
  2077 +
  2078 + return result;
  2079 + };
  2080 +
  2081 + var clearNextLangAndPromise = function (key) {
  2082 + if ($nextLang === key) {
  2083 + $nextLang = undefined;
  2084 + }
  2085 + langPromises[key] = undefined;
  2086 + };
  2087 +
  2088 + var applyPostProcessing = function (translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy) {
  2089 + var fn = postProcessFn;
  2090 +
  2091 + if (fn) {
  2092 +
  2093 + if (typeof(fn) === 'string') {
  2094 + // getting on-demand instance
  2095 + fn = $injector.get(fn);
  2096 + }
  2097 + if (fn) {
  2098 + return fn(translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy);
  2099 + }
  2100 + }
  2101 +
  2102 + return resolvedTranslation;
  2103 + };
  2104 +
  2105 + var loadTranslationsIfMissing = function (key) {
  2106 + if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {
  2107 + langPromises[key] = loadAsync(key).then(function (translation) {
  2108 + translations(translation.key, translation.table);
  2109 + return translation;
  2110 + });
  2111 + }
  2112 + };
  2113 +
  2114 + /**
  2115 + * @ngdoc function
  2116 + * @name pascalprecht.translate.$translate#preferredLanguage
  2117 + * @methodOf pascalprecht.translate.$translate
  2118 + *
  2119 + * @description
  2120 + * Returns the language key for the preferred language.
  2121 + *
  2122 + * @param {string} langKey language String or Array to be used as preferredLanguage (changing at runtime)
  2123 + *
  2124 + * @return {string} preferred language key
  2125 + */
  2126 + $translate.preferredLanguage = function (langKey) {
  2127 + if (langKey) {
  2128 + setupPreferredLanguage(langKey);
  2129 + }
  2130 + return $preferredLanguage;
  2131 + };
  2132 +
  2133 + /**
  2134 + * @ngdoc function
  2135 + * @name pascalprecht.translate.$translate#cloakClassName
  2136 + * @methodOf pascalprecht.translate.$translate
  2137 + *
  2138 + * @description
  2139 + * Returns the configured class name for `translate-cloak` directive.
  2140 + *
  2141 + * @return {string} cloakClassName
  2142 + */
  2143 + $translate.cloakClassName = function () {
  2144 + return $cloakClassName;
  2145 + };
  2146 +
  2147 + /**
  2148 + * @ngdoc function
  2149 + * @name pascalprecht.translate.$translate#nestedObjectDelimeter
  2150 + * @methodOf pascalprecht.translate.$translate
  2151 + *
  2152 + * @description
  2153 + * Returns the configured delimiter for nested namespaces.
  2154 + *
  2155 + * @return {string} nestedObjectDelimeter
  2156 + */
  2157 + $translate.nestedObjectDelimeter = function () {
  2158 + return $nestedObjectDelimeter;
  2159 + };
  2160 +
  2161 + /**
  2162 + * @ngdoc function
  2163 + * @name pascalprecht.translate.$translate#fallbackLanguage
  2164 + * @methodOf pascalprecht.translate.$translate
  2165 + *
  2166 + * @description
  2167 + * Returns the language key for the fallback languages or sets a new fallback stack.
  2168 + * It is recommended to call this before {@link pascalprecht.translate.$translateProvider#preferredLanguage preferredLanguage()}.
  2169 + *
  2170 + * @param {string=} langKey language String or Array of fallback languages to be used (to change stack at runtime)
  2171 + *
  2172 + * @return {string||array} fallback language key
  2173 + */
  2174 + $translate.fallbackLanguage = function (langKey) {
  2175 + if (langKey !== undefined && langKey !== null) {
  2176 + fallbackStack(langKey);
  2177 +
  2178 + // as we might have an async loader initiated and a new translation language might have been defined
  2179 + // we need to add the promise to the stack also. So - iterate.
  2180 + if ($loaderFactory) {
  2181 + if ($fallbackLanguage && $fallbackLanguage.length) {
  2182 + for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {
  2183 + if (!langPromises[$fallbackLanguage[i]]) {
  2184 + langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]);
  2185 + }
  2186 + }
  2187 + }
  2188 + }
  2189 + $translate.use($translate.use());
  2190 + }
  2191 + if ($fallbackWasString) {
  2192 + return $fallbackLanguage[0];
  2193 + } else {
  2194 + return $fallbackLanguage;
  2195 + }
  2196 +
  2197 + };
  2198 +
  2199 + /**
  2200 + * @ngdoc function
  2201 + * @name pascalprecht.translate.$translate#useFallbackLanguage
  2202 + * @methodOf pascalprecht.translate.$translate
  2203 + *
  2204 + * @description
  2205 + * Sets the first key of the fallback language stack to be used for translation.
  2206 + * Therefore all languages in the fallback array BEFORE this key will be skipped!
  2207 + *
  2208 + * @param {string=} langKey Contains the langKey the iteration shall start with. Set to false if you want to
  2209 + * get back to the whole stack
  2210 + */
  2211 + $translate.useFallbackLanguage = function (langKey) {
  2212 + if (langKey !== undefined && langKey !== null) {
  2213 + if (!langKey) {
  2214 + startFallbackIteration = 0;
  2215 + } else {
  2216 + var langKeyPosition = indexOf($fallbackLanguage, langKey);
  2217 + if (langKeyPosition > -1) {
  2218 + startFallbackIteration = langKeyPosition;
  2219 + }
  2220 + }
  2221 +
  2222 + }
  2223 +
  2224 + };
  2225 +
  2226 + /**
  2227 + * @ngdoc function
  2228 + * @name pascalprecht.translate.$translate#proposedLanguage
  2229 + * @methodOf pascalprecht.translate.$translate
  2230 + *
  2231 + * @description
  2232 + * Returns the language key of language that is currently loaded asynchronously.
  2233 + *
  2234 + * @return {string} language key
  2235 + */
  2236 + $translate.proposedLanguage = function () {
  2237 + return $nextLang;
  2238 + };
  2239 +
  2240 + /**
  2241 + * @ngdoc function
  2242 + * @name pascalprecht.translate.$translate#storage
  2243 + * @methodOf pascalprecht.translate.$translate
  2244 + *
  2245 + * @description
  2246 + * Returns registered storage.
  2247 + *
  2248 + * @return {object} Storage
  2249 + */
  2250 + $translate.storage = function () {
  2251 + return Storage;
  2252 + };
  2253 +
  2254 + /**
  2255 + * @ngdoc function
  2256 + * @name pascalprecht.translate.$translate#negotiateLocale
  2257 + * @methodOf pascalprecht.translate.$translate
  2258 + *
  2259 + * @description
  2260 + * Returns a language key based on available languages and language aliases. If a
  2261 + * language key cannot be resolved, returns undefined.
  2262 + *
  2263 + * If no or a falsy key is given, returns undefined.
  2264 + *
  2265 + * @param {string} [key] Language key
  2266 + * @return {string|undefined} Language key or undefined if no language key is found.
  2267 + */
  2268 + $translate.negotiateLocale = negotiateLocale;
  2269 +
  2270 + /**
  2271 + * @ngdoc function
  2272 + * @name pascalprecht.translate.$translate#use
  2273 + * @methodOf pascalprecht.translate.$translate
  2274 + *
  2275 + * @description
  2276 + * Tells angular-translate which language to use by given language key. This method is
  2277 + * used to change language at runtime. It also takes care of storing the language
  2278 + * key in a configured store to let your app remember the choosed language.
  2279 + *
  2280 + * When trying to 'use' a language which isn't available it tries to load it
  2281 + * asynchronously with registered loaders.
  2282 + *
  2283 + * Returns promise object with loaded language file data or string of the currently used language.
  2284 + *
  2285 + * If no or a falsy key is given it returns the currently used language key.
  2286 + * The returned string will be ```undefined``` if setting up $translate hasn't finished.
  2287 + * @example
  2288 + * $translate.use("en_US").then(function(data){
  2289 + * $scope.text = $translate("HELLO");
  2290 + * });
  2291 + *
  2292 + * @param {string=} key Language key
  2293 + * @return {object|string} Promise with loaded language data or the language key if a falsy param was given.
  2294 + */
  2295 + $translate.use = function (key) {
  2296 + if (!key) {
  2297 + return $uses;
  2298 + }
  2299 +
  2300 + var deferred = $q.defer();
  2301 + deferred.promise.then(null, angular.noop); // AJS "Possibly unhandled rejection"
  2302 +
  2303 + $rootScope.$emit('$translateChangeStart', {language : key});
  2304 +
  2305 + // Try to get the aliased language key
  2306 + var aliasedKey = negotiateLocale(key);
  2307 + // Ensure only registered language keys will be loaded
  2308 + if ($availableLanguageKeys.length > 0 && !aliasedKey) {
  2309 + return $q.reject(key);
  2310 + }
  2311 +
  2312 + if (aliasedKey) {
  2313 + key = aliasedKey;
  2314 + }
  2315 +
  2316 + // if there isn't a translation table for the language we've requested,
  2317 + // we load it asynchronously
  2318 + $nextLang = key;
  2319 + if (($forceAsyncReloadEnabled || !$translationTable[key]) && $loaderFactory && !langPromises[key]) {
  2320 + langPromises[key] = loadAsync(key).then(function (translation) {
  2321 + translations(translation.key, translation.table);
  2322 + deferred.resolve(translation.key);
  2323 + if ($nextLang === key) {
  2324 + useLanguage(translation.key);
  2325 + }
  2326 + return translation;
  2327 + }, function (key) {
  2328 + $rootScope.$emit('$translateChangeError', {language : key});
  2329 + deferred.reject(key);
  2330 + $rootScope.$emit('$translateChangeEnd', {language : key});
  2331 + return $q.reject(key);
  2332 + });
  2333 + langPromises[key]['finally'](function () {
  2334 + clearNextLangAndPromise(key);
  2335 + })['catch'](angular.noop); // we don't care about errors (clearing)
  2336 + } else if (langPromises[key]) {
  2337 + // we are already loading this asynchronously
  2338 + // resolve our new deferred when the old langPromise is resolved
  2339 + langPromises[key].then(function (translation) {
  2340 + if ($nextLang === translation.key) {
  2341 + useLanguage(translation.key);
  2342 + }
  2343 + deferred.resolve(translation.key);
  2344 + return translation;
  2345 + }, function (key) {
  2346 + // find first available fallback language if that request has failed
  2347 + if (!$uses && $fallbackLanguage && $fallbackLanguage.length > 0 && $fallbackLanguage[0] !== key) {
  2348 + return $translate.use($fallbackLanguage[0]).then(deferred.resolve, deferred.reject);
  2349 + } else {
  2350 + return deferred.reject(key);
  2351 + }
  2352 + });
  2353 + } else {
  2354 + deferred.resolve(key);
  2355 + useLanguage(key);
  2356 + }
  2357 +
  2358 + return deferred.promise;
  2359 + };
  2360 +
  2361 + /**
  2362 + * @ngdoc function
  2363 + * @name pascalprecht.translate.$translate#resolveClientLocale
  2364 + * @methodOf pascalprecht.translate.$translate
  2365 + *
  2366 + * @description
  2367 + * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.
  2368 + *
  2369 + * @returns {string} the current client/browser language key
  2370 + */
  2371 + $translate.resolveClientLocale = function () {
  2372 + return getLocale();
  2373 + };
  2374 +
  2375 + /**
  2376 + * @ngdoc function
  2377 + * @name pascalprecht.translate.$translate#storageKey
  2378 + * @methodOf pascalprecht.translate.$translate
  2379 + *
  2380 + * @description
  2381 + * Returns the key for the storage.
  2382 + *
  2383 + * @return {string} storage key
  2384 + */
  2385 + $translate.storageKey = function () {
  2386 + return storageKey();
  2387 + };
  2388 +
  2389 + /**
  2390 + * @ngdoc function
  2391 + * @name pascalprecht.translate.$translate#isPostCompilingEnabled
  2392 + * @methodOf pascalprecht.translate.$translate
  2393 + *
  2394 + * @description
  2395 + * Returns whether post compiling is enabled or not
  2396 + *
  2397 + * @return {bool} storage key
  2398 + */
  2399 + $translate.isPostCompilingEnabled = function () {
  2400 + return $postCompilingEnabled;
  2401 + };
  2402 +
  2403 + /**
  2404 + * @ngdoc function
  2405 + * @name pascalprecht.translate.$translate#isForceAsyncReloadEnabled
  2406 + * @methodOf pascalprecht.translate.$translate
  2407 + *
  2408 + * @description
  2409 + * Returns whether force async reload is enabled or not
  2410 + *
  2411 + * @return {boolean} forceAsyncReload value
  2412 + */
  2413 + $translate.isForceAsyncReloadEnabled = function () {
  2414 + return $forceAsyncReloadEnabled;
  2415 + };
  2416 +
  2417 + /**
  2418 + * @ngdoc function
  2419 + * @name pascalprecht.translate.$translate#isKeepContent
  2420 + * @methodOf pascalprecht.translate.$translate
  2421 + *
  2422 + * @description
  2423 + * Returns whether keepContent or not
  2424 + *
  2425 + * @return {boolean} keepContent value
  2426 + */
  2427 + $translate.isKeepContent = function () {
  2428 + return $keepContent;
  2429 + };
  2430 +
  2431 + /**
  2432 + * @ngdoc function
  2433 + * @name pascalprecht.translate.$translate#refresh
  2434 + * @methodOf pascalprecht.translate.$translate
  2435 + *
  2436 + * @description
  2437 + * Refreshes a translation table pointed by the given langKey. If langKey is not specified,
  2438 + * the module will drop all existent translation tables and load new version of those which
  2439 + * are currently in use.
  2440 + *
  2441 + * Refresh means that the module will drop target translation table and try to load it again.
  2442 + *
  2443 + * In case there are no loaders registered the refresh() method will throw an Error.
  2444 + *
  2445 + * If the module is able to refresh translation tables refresh() method will broadcast
  2446 + * $translateRefreshStart and $translateRefreshEnd events.
  2447 + *
  2448 + * @example
  2449 + * // this will drop all currently existent translation tables and reload those which are
  2450 + * // currently in use
  2451 + * $translate.refresh();
  2452 + * // this will refresh a translation table for the en_US language
  2453 + * $translate.refresh('en_US');
  2454 + *
  2455 + * @param {string} langKey A language key of the table, which has to be refreshed
  2456 + *
  2457 + * @return {promise} Promise, which will be resolved in case a translation tables refreshing
  2458 + * process is finished successfully, and reject if not.
  2459 + */
  2460 + $translate.refresh = function (langKey) {
  2461 + if (!$loaderFactory) {
  2462 + throw new Error('Couldn\'t refresh translation table, no loader registered!');
  2463 + }
  2464 +
  2465 + $rootScope.$emit('$translateRefreshStart', {language : langKey});
  2466 +
  2467 + var deferred = $q.defer(), updatedLanguages = {};
  2468 +
  2469 + //private helper
  2470 + function loadNewData(languageKey) {
  2471 + var promise = loadAsync(languageKey);
  2472 + //update the load promise cache for this language
  2473 + langPromises[languageKey] = promise;
  2474 + //register a data handler for the promise
  2475 + promise.then(function (data) {
  2476 + //clear the cache for this language
  2477 + $translationTable[languageKey] = {};
  2478 + //add the new data for this language
  2479 + translations(languageKey, data.table);
  2480 + //track that we updated this language
  2481 + updatedLanguages[languageKey] = true;
  2482 + },
  2483 + //handle rejection to appease the $q validation
  2484 + angular.noop);
  2485 + return promise;
  2486 + }
  2487 +
  2488 + //set up post-processing
  2489 + deferred.promise.then(
  2490 + function () {
  2491 + for (var key in $translationTable) {
  2492 + if ($translationTable.hasOwnProperty(key)) {
  2493 + //delete cache entries that were not updated
  2494 + if (!(key in updatedLanguages)) {
  2495 + delete $translationTable[key];
  2496 + }
  2497 + }
  2498 + }
  2499 + if ($uses) {
  2500 + useLanguage($uses);
  2501 + }
  2502 + },
  2503 + //handle rejection to appease the $q validation
  2504 + angular.noop
  2505 + )['finally'](
  2506 + function () {
  2507 + $rootScope.$emit('$translateRefreshEnd', {language : langKey});
  2508 + }
  2509 + );
  2510 +
  2511 + if (!langKey) {
  2512 + // if there's no language key specified we refresh ALL THE THINGS!
  2513 + var languagesToReload = $fallbackLanguage && $fallbackLanguage.slice() || [];
  2514 + if ($uses && languagesToReload.indexOf($uses) === -1) {
  2515 + languagesToReload.push($uses);
  2516 + }
  2517 + $q.all(languagesToReload.map(loadNewData)).then(deferred.resolve, deferred.reject);
  2518 +
  2519 + } else if ($translationTable[langKey]) {
  2520 + //just refresh the specified language cache
  2521 + loadNewData(langKey).then(deferred.resolve, deferred.reject);
  2522 +
  2523 + } else {
  2524 + deferred.reject();
  2525 + }
  2526 +
  2527 + return deferred.promise;
  2528 + };
  2529 +
  2530 + /**
  2531 + * @ngdoc function
  2532 + * @name pascalprecht.translate.$translate#instant
  2533 + * @methodOf pascalprecht.translate.$translate
  2534 + *
  2535 + * @description
  2536 + * Returns a translation instantly from the internal state of loaded translation. All rules
  2537 + * regarding the current language, the preferred language of even fallback languages will be
  2538 + * used except any promise handling. If a language was not found, an asynchronous loading
  2539 + * will be invoked in the background.
  2540 + *
  2541 + * @param {string|array} translationId A token which represents a translation id
  2542 + * This can be optionally an array of translation ids which
  2543 + * results that the function's promise returns an object where
  2544 + * each key is the translation id and the value the translation.
  2545 + * @param {object=} [interpolateParams={}] Params
  2546 + * @param {string=} [interpolationId=undefined] The id of the interpolation to use (use default unless set via useInterpolation())
  2547 + * @param {string=} [forceLanguage=false] A language to be used instead of the current language
  2548 + * @param {string=} [sanitizeStrategy=undefined] force sanitize strategy for this call instead of using the configured one (use default unless set)
  2549 + *
  2550 + * @return {string|object} translation
  2551 + */
  2552 + $translate.instant = function (translationId, interpolateParams, interpolationId, forceLanguage, sanitizeStrategy) {
  2553 +
  2554 + // we don't want to re-negotiate $uses
  2555 + var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses
  2556 + (negotiateLocale(forceLanguage) || forceLanguage) : $uses;
  2557 +
  2558 + // Detect undefined and null values to shorten the execution and prevent exceptions
  2559 + if (translationId === null || angular.isUndefined(translationId)) {
  2560 + return translationId;
  2561 + }
  2562 +
  2563 + // Check forceLanguage is present
  2564 + if (forceLanguage) {
  2565 + loadTranslationsIfMissing(forceLanguage);
  2566 + }
  2567 +
  2568 + // Duck detection: If the first argument is an array, a bunch of translations was requested.
  2569 + // The result is an object.
  2570 + if (angular.isArray(translationId)) {
  2571 + var results = {};
  2572 + for (var i = 0, c = translationId.length; i < c; i++) {
  2573 + results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId, forceLanguage, sanitizeStrategy);
  2574 + }
  2575 + return results;
  2576 + }
  2577 +
  2578 + // We discarded unacceptable values. So we just need to verify if translationId is empty String
  2579 + if (angular.isString(translationId) && translationId.length < 1) {
  2580 + return translationId;
  2581 + }
  2582 +
  2583 + // trim off any whitespace
  2584 + if (translationId) {
  2585 + translationId = trim.apply(translationId);
  2586 + }
  2587 +
  2588 + var result, possibleLangKeys = [];
  2589 + if ($preferredLanguage) {
  2590 + possibleLangKeys.push($preferredLanguage);
  2591 + }
  2592 + if (uses) {
  2593 + possibleLangKeys.push(uses);
  2594 + }
  2595 + if ($fallbackLanguage && $fallbackLanguage.length) {
  2596 + possibleLangKeys = possibleLangKeys.concat($fallbackLanguage);
  2597 + }
  2598 + for (var j = 0, d = possibleLangKeys.length; j < d; j++) {
  2599 + var possibleLangKey = possibleLangKeys[j];
  2600 + if ($translationTable[possibleLangKey]) {
  2601 + if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') {
  2602 + result = determineTranslationInstant(translationId, interpolateParams, interpolationId, uses, sanitizeStrategy);
  2603 + }
  2604 + }
  2605 + if (typeof result !== 'undefined') {
  2606 + break;
  2607 + }
  2608 + }
  2609 +
  2610 + if (!result && result !== '') {
  2611 + if ($notFoundIndicatorLeft || $notFoundIndicatorRight) {
  2612 + result = applyNotFoundIndicators(translationId);
  2613 + } else {
  2614 + // Return translation of default interpolator if not found anything.
  2615 + result = defaultInterpolator.interpolate(translationId, interpolateParams, 'filter', sanitizeStrategy);
  2616 +
  2617 + // looks like the requested translation id doesn't exists.
  2618 + // Now, if there is a registered handler for missing translations and no
  2619 + // asyncLoader is pending, we execute the handler
  2620 + var missingTranslationHandlerTranslation;
  2621 + if ($missingTranslationHandlerFactory && !pendingLoader) {
  2622 + missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);
  2623 + }
  2624 +
  2625 + if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
  2626 + result = missingTranslationHandlerTranslation;
  2627 + }
  2628 + }
  2629 + }
  2630 +
  2631 + return result;
  2632 + };
  2633 +
  2634 + /**
  2635 + * @ngdoc function
  2636 + * @name pascalprecht.translate.$translate#versionInfo
  2637 + * @methodOf pascalprecht.translate.$translate
  2638 + *
  2639 + * @description
  2640 + * Returns the current version information for the angular-translate library
  2641 + *
  2642 + * @return {string} angular-translate version
  2643 + */
  2644 + $translate.versionInfo = function () {
  2645 + return version;
  2646 + };
  2647 +
  2648 + /**
  2649 + * @ngdoc function
  2650 + * @name pascalprecht.translate.$translate#loaderCache
  2651 + * @methodOf pascalprecht.translate.$translate
  2652 + *
  2653 + * @description
  2654 + * Returns the defined loaderCache.
  2655 + *
  2656 + * @return {boolean|string|object} current value of loaderCache
  2657 + */
  2658 + $translate.loaderCache = function () {
  2659 + return loaderCache;
  2660 + };
  2661 +
  2662 + // internal purpose only
  2663 + $translate.directivePriority = function () {
  2664 + return directivePriority;
  2665 + };
  2666 +
  2667 + // internal purpose only
  2668 + $translate.statefulFilter = function () {
  2669 + return statefulFilter;
  2670 + };
  2671 +
  2672 + /**
  2673 + * @ngdoc function
  2674 + * @name pascalprecht.translate.$translate#isReady
  2675 + * @methodOf pascalprecht.translate.$translate
  2676 + *
  2677 + * @description
  2678 + * Returns whether the service is "ready" to translate (i.e. loading 1st language).
  2679 + *
  2680 + * See also {@link pascalprecht.translate.$translate#methods_onReady onReady()}.
  2681 + *
  2682 + * @return {boolean} current value of ready
  2683 + */
  2684 + $translate.isReady = function () {
  2685 + return $isReady;
  2686 + };
  2687 +
  2688 + var $onReadyDeferred = $q.defer();
  2689 + $onReadyDeferred.promise.then(function () {
  2690 + $isReady = true;
  2691 + });
  2692 +
  2693 + /**
  2694 + * @ngdoc function
  2695 + * @name pascalprecht.translate.$translate#onReady
  2696 + * @methodOf pascalprecht.translate.$translate
  2697 + *
  2698 + * @description
  2699 + * Calls the function provided or resolved the returned promise after the service is "ready" to translate (i.e. loading 1st language).
  2700 + *
  2701 + * See also {@link pascalprecht.translate.$translate#methods_isReady isReady()}.
  2702 + *
  2703 + * @param {Function=} fn Function to invoke when service is ready
  2704 + * @return {object} Promise resolved when service is ready
  2705 + */
  2706 + $translate.onReady = function (fn) {
  2707 + var deferred = $q.defer();
  2708 + if (angular.isFunction(fn)) {
  2709 + deferred.promise.then(fn);
  2710 + }
  2711 + if ($isReady) {
  2712 + deferred.resolve();
  2713 + } else {
  2714 + $onReadyDeferred.promise.then(deferred.resolve);
  2715 + }
  2716 + return deferred.promise;
  2717 + };
  2718 +
  2719 + /**
  2720 + * @ngdoc function
  2721 + * @name pascalprecht.translate.$translate#getAvailableLanguageKeys
  2722 + * @methodOf pascalprecht.translate.$translate
  2723 + *
  2724 + * @description
  2725 + * This function simply returns the registered language keys being defined before in the config phase
  2726 + * With this, an application can use the array to provide a language selection dropdown or similar
  2727 + * without any additional effort
  2728 + *
  2729 + * @returns {object} returns the list of possibly registered language keys and mapping or null if not defined
  2730 + */
  2731 + $translate.getAvailableLanguageKeys = function () {
  2732 + if ($availableLanguageKeys.length > 0) {
  2733 + return $availableLanguageKeys;
  2734 + }
  2735 + return null;
  2736 + };
  2737 +
  2738 + /**
  2739 + * @ngdoc function
  2740 + * @name pascalprecht.translate.$translate#getTranslationTable
  2741 + * @methodOf pascalprecht.translate.$translate
  2742 + *
  2743 + * @description
  2744 + * Returns translation table by the given language key.
  2745 + *
  2746 + * Unless a language is provided it returns a translation table of the current one.
  2747 + * Note: If translation dictionary is currently downloading or in progress
  2748 + * it will return null.
  2749 + *
  2750 + * @param {string} langKey A token which represents a translation id
  2751 + *
  2752 + * @return {object} a copy of angular-translate $translationTable
  2753 + */
  2754 + $translate.getTranslationTable = function (langKey) {
  2755 + langKey = langKey || $translate.use();
  2756 + if (langKey && $translationTable[langKey]) {
  2757 + return angular.copy($translationTable[langKey]);
  2758 + }
  2759 + return null;
  2760 + };
  2761 +
  2762 + // Whenever $translateReady is being fired, this will ensure the state of $isReady
  2763 + var globalOnReadyListener = $rootScope.$on('$translateReady', function () {
  2764 + $onReadyDeferred.resolve();
  2765 + globalOnReadyListener(); // one time only
  2766 + globalOnReadyListener = null;
  2767 + });
  2768 + var globalOnChangeListener = $rootScope.$on('$translateChangeEnd', function () {
  2769 + $onReadyDeferred.resolve();
  2770 + globalOnChangeListener(); // one time only
  2771 + globalOnChangeListener = null;
  2772 + });
  2773 +
  2774 + if ($loaderFactory) {
  2775 +
  2776 + // If at least one async loader is defined and there are no
  2777 + // (default) translations available we should try to load them.
  2778 + if (angular.equals($translationTable, {})) {
  2779 + if ($translate.use()) {
  2780 + $translate.use($translate.use());
  2781 + }
  2782 + }
  2783 +
  2784 + // Also, if there are any fallback language registered, we start
  2785 + // loading them asynchronously as soon as we can.
  2786 + if ($fallbackLanguage && $fallbackLanguage.length) {
  2787 + var processAsyncResult = function (translation) {
  2788 + translations(translation.key, translation.table);
  2789 + $rootScope.$emit('$translateChangeEnd', {language : translation.key});
  2790 + return translation;
  2791 + };
  2792 + for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {
  2793 + var fallbackLanguageId = $fallbackLanguage[i];
  2794 + if ($forceAsyncReloadEnabled || !$translationTable[fallbackLanguageId]) {
  2795 + langPromises[fallbackLanguageId] = loadAsync(fallbackLanguageId).then(processAsyncResult);
  2796 + }
  2797 + }
  2798 + }
  2799 + } else {
  2800 + $rootScope.$emit('$translateReady', {language : $translate.use()});
  2801 + }
  2802 +
  2803 + return $translate;
  2804 + }];
  2805 +}
  2806 +
  2807 +$translate.displayName = 'displayName';
  2808 +
  2809 +/**
  2810 + * @ngdoc object
  2811 + * @name pascalprecht.translate.$translateDefaultInterpolation
  2812 + * @requires $interpolate
  2813 + *
  2814 + * @description
  2815 + * Uses angular's `$interpolate` services to interpolate strings against some values.
  2816 + *
  2817 + * Be aware to configure a proper sanitization strategy.
  2818 + *
  2819 + * See also:
  2820 + * * {@link pascalprecht.translate.$translateSanitization}
  2821 + *
  2822 + * @return {object} $translateDefaultInterpolation Interpolator service
  2823 + */
  2824 +angular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', $translateDefaultInterpolation);
  2825 +
  2826 +function $translateDefaultInterpolation ($interpolate, $translateSanitization) {
  2827 +
  2828 + 'use strict';
  2829 +
  2830 + var $translateInterpolator = {},
  2831 + $locale,
  2832 + $identifier = 'default';
  2833 +
  2834 + /**
  2835 + * @ngdoc function
  2836 + * @name pascalprecht.translate.$translateDefaultInterpolation#setLocale
  2837 + * @methodOf pascalprecht.translate.$translateDefaultInterpolation
  2838 + *
  2839 + * @description
  2840 + * Sets current locale (this is currently not use in this interpolation).
  2841 + *
  2842 + * @param {string} locale Language key or locale.
  2843 + */
  2844 + $translateInterpolator.setLocale = function (locale) {
  2845 + $locale = locale;
  2846 + };
  2847 +
  2848 + /**
  2849 + * @ngdoc function
  2850 + * @name pascalprecht.translate.$translateDefaultInterpolation#getInterpolationIdentifier
  2851 + * @methodOf pascalprecht.translate.$translateDefaultInterpolation
  2852 + *
  2853 + * @description
  2854 + * Returns an identifier for this interpolation service.
  2855 + *
  2856 + * @returns {string} $identifier
  2857 + */
  2858 + $translateInterpolator.getInterpolationIdentifier = function () {
  2859 + return $identifier;
  2860 + };
  2861 +
  2862 + /**
  2863 + * @deprecated will be removed in 3.0
  2864 + * @see {@link pascalprecht.translate.$translateSanitization}
  2865 + */
  2866 + $translateInterpolator.useSanitizeValueStrategy = function (value) {
  2867 + $translateSanitization.useStrategy(value);
  2868 + return this;
  2869 + };
  2870 +
  2871 + /**
  2872 + * @ngdoc function
  2873 + * @name pascalprecht.translate.$translateDefaultInterpolation#interpolate
  2874 + * @methodOf pascalprecht.translate.$translateDefaultInterpolation
  2875 + *
  2876 + * @description
  2877 + * Interpolates given value agains given interpolate params using angulars
  2878 + * `$interpolate` service.
  2879 + *
  2880 + * Since AngularJS 1.5, `value` must not be a string but can be anything input.
  2881 + *
  2882 + * @param {string} value translation
  2883 + * @param {object} [interpolationParams={}] interpolation params
  2884 + * @param {string} [context=undefined] current context (filter, directive, service)
  2885 + * @param {string} [sanitizeStrategy=undefined] sanitize strategy (use default unless set)
  2886 + * @param {string} translationId current translationId
  2887 + *
  2888 + * @returns {string} interpolated string
  2889 + */
  2890 + $translateInterpolator.interpolate = function (value, interpolationParams, context, sanitizeStrategy, translationId) { // jshint ignore:line
  2891 + interpolationParams = interpolationParams || {};
  2892 + interpolationParams = $translateSanitization.sanitize(interpolationParams, 'params', sanitizeStrategy, context);
  2893 +
  2894 + var interpolatedText;
  2895 + if (angular.isNumber(value)) {
  2896 + // numbers are safe
  2897 + interpolatedText = '' + value;
  2898 + } else if (angular.isString(value)) {
  2899 + // strings must be interpolated (that's the job here)
  2900 + interpolatedText = $interpolate(value)(interpolationParams);
  2901 + interpolatedText = $translateSanitization.sanitize(interpolatedText, 'text', sanitizeStrategy, context);
  2902 + } else {
  2903 + // neither a number or a string, cant interpolate => empty string
  2904 + interpolatedText = '';
  2905 + }
  2906 +
  2907 + return interpolatedText;
  2908 + };
  2909 +
  2910 + return $translateInterpolator;
  2911 +}
  2912 +
  2913 +$translateDefaultInterpolation.displayName = '$translateDefaultInterpolation';
  2914 +
  2915 +angular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY');
  2916 +
  2917 +angular.module('pascalprecht.translate')
  2918 +/**
  2919 + * @ngdoc directive
  2920 + * @name pascalprecht.translate.directive:translate
  2921 + * @requires $interpolate,
  2922 + * @requires $compile,
  2923 + * @requires $parse,
  2924 + * @requires $rootScope
  2925 + * @restrict AE
  2926 + *
  2927 + * @description
  2928 + * Translates given translation id either through attribute or DOM content.
  2929 + * Internally it uses $translate service to translate the translation id. It possible to
  2930 + * pass an optional `translate-values` object literal as string into translation id.
  2931 + *
  2932 + * @param {string=} translate Translation id which could be either string or interpolated string.
  2933 + * @param {string=} translate-values Values to pass into translation id. Can be passed as object literal string or interpolated object.
  2934 + * @param {string=} translate-attr-ATTR translate Translation id and put it into ATTR attribute.
  2935 + * @param {string=} translate-default will be used unless translation was successful
  2936 + * @param {string=} translate-sanitize-strategy defines locally sanitize strategy
  2937 + * @param {boolean=} translate-compile (default true if present) defines locally activation of {@link pascalprecht.translate.$translateProvider#methods_usePostCompiling}
  2938 + * @param {boolean=} translate-keep-content (default true if present) defines that in case a KEY could not be translated, that the existing content is left in the innerHTML}
  2939 + *
  2940 + * @example
  2941 + <example module="ngView">
  2942 + <file name="index.html">
  2943 + <div ng-controller="TranslateCtrl">
  2944 +
  2945 + <pre translate="TRANSLATION_ID"></pre>
  2946 + <pre translate>TRANSLATION_ID</pre>
  2947 + <pre translate translate-attr-title="TRANSLATION_ID"></pre>
  2948 + <pre translate="{{translationId}}"></pre>
  2949 + <pre translate>{{translationId}}</pre>
  2950 + <pre translate="WITH_VALUES" translate-values="{value: 5}"></pre>
  2951 + <pre translate translate-values="{value: 5}">WITH_VALUES</pre>
  2952 + <pre translate="WITH_VALUES" translate-values="{{values}}"></pre>
  2953 + <pre translate translate-values="{{values}}">WITH_VALUES</pre>
  2954 + <pre translate translate-attr-title="WITH_VALUES" translate-values="{{values}}"></pre>
  2955 + <pre translate="WITH_CAMEL_CASE_KEY" translate-value-camel-case-key="Hi"></pre>
  2956 +
  2957 + </div>
  2958 + </file>
  2959 + <file name="script.js">
  2960 + angular.module('ngView', ['pascalprecht.translate'])
  2961 +
  2962 + .config(function ($translateProvider) {
  2963 +
  2964 + $translateProvider.translations('en',{
  2965 + 'TRANSLATION_ID': 'Hello there!',
  2966 + 'WITH_VALUES': 'The following value is dynamic: {{value}}',
  2967 + 'WITH_CAMEL_CASE_KEY': 'The interpolation key is camel cased: {{camelCaseKey}}'
  2968 + }).preferredLanguage('en');
  2969 +
  2970 + });
  2971 +
  2972 + angular.module('ngView').controller('TranslateCtrl', function ($scope) {
  2973 + $scope.translationId = 'TRANSLATION_ID';
  2974 +
  2975 + $scope.values = {
  2976 + value: 78
  2977 + };
  2978 + });
  2979 + </file>
  2980 + <file name="scenario.js">
  2981 + it('should translate', function () {
  2982 + inject(function ($rootScope, $compile) {
  2983 + $rootScope.translationId = 'TRANSLATION_ID';
  2984 +
  2985 + element = $compile('<p translate="TRANSLATION_ID"></p>')($rootScope);
  2986 + $rootScope.$digest();
  2987 + expect(element.text()).toBe('Hello there!');
  2988 +
  2989 + element = $compile('<p translate="{{translationId}}"></p>')($rootScope);
  2990 + $rootScope.$digest();
  2991 + expect(element.text()).toBe('Hello there!');
  2992 +
  2993 + element = $compile('<p translate>TRANSLATION_ID</p>')($rootScope);
  2994 + $rootScope.$digest();
  2995 + expect(element.text()).toBe('Hello there!');
  2996 +
  2997 + element = $compile('<p translate>{{translationId}}</p>')($rootScope);
  2998 + $rootScope.$digest();
  2999 + expect(element.text()).toBe('Hello there!');
  3000 +
  3001 + element = $compile('<p translate translate-attr-title="TRANSLATION_ID"></p>')($rootScope);
  3002 + $rootScope.$digest();
  3003 + expect(element.attr('title')).toBe('Hello there!');
  3004 +
  3005 + element = $compile('<p translate="WITH_CAMEL_CASE_KEY" translate-value-camel-case-key="Hello"></p>')($rootScope);
  3006 + $rootScope.$digest();
  3007 + expect(element.text()).toBe('The interpolation key is camel cased: Hello');
  3008 + });
  3009 + });
  3010 + </file>
  3011 + </example>
  3012 + */
  3013 +.directive('translate', translateDirective);
  3014 +function translateDirective($translate, $interpolate, $compile, $parse, $rootScope) {
  3015 +
  3016 + 'use strict';
  3017 +
  3018 + /**
  3019 + * @name trim
  3020 + * @private
  3021 + *
  3022 + * @description
  3023 + * trim polyfill
  3024 + *
  3025 + * @returns {string} The string stripped of whitespace from both ends
  3026 + */
  3027 + var trim = function() {
  3028 + return this.toString().replace(/^\s+|\s+$/g, '');
  3029 + };
  3030 +
  3031 + /**
  3032 + * @name lowercase
  3033 + * @private
  3034 + *
  3035 + * @description
  3036 + * Return the lowercase string only if the type is string
  3037 + *
  3038 + * @returns {string} The string all in lowercase
  3039 + */
  3040 + var lowercase = function (string) {
  3041 + return angular.isString(string) ? string.toLowerCase() : string;
  3042 + };
  3043 +
  3044 + return {
  3045 + restrict: 'AE',
  3046 + scope: true,
  3047 + priority: $translate.directivePriority(),
  3048 + compile: function (tElement, tAttr) {
  3049 +
  3050 + var translateValuesExist = (tAttr.translateValues) ?
  3051 + tAttr.translateValues : undefined;
  3052 +
  3053 + var translateInterpolation = (tAttr.translateInterpolation) ?
  3054 + tAttr.translateInterpolation : undefined;
  3055 +
  3056 + var translateSanitizeStrategyExist = (tAttr.translateSanitizeStrategy) ?
  3057 + tAttr.translateSanitizeStrategy : undefined;
  3058 +
  3059 + var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i);
  3060 +
  3061 + var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)',
  3062 + watcherRegExp = '^(.*)' + $interpolate.startSymbol() + '(.*)' + $interpolate.endSymbol() + '(.*)';
  3063 +
  3064 + return function linkFn(scope, iElement, iAttr) {
  3065 +
  3066 + scope.interpolateParams = {};
  3067 + scope.preText = '';
  3068 + scope.postText = '';
  3069 + scope.translateNamespace = getTranslateNamespace(scope);
  3070 + var translationIds = {};
  3071 +
  3072 + var initInterpolationParams = function (interpolateParams, iAttr, tAttr) {
  3073 + // initial setup
  3074 + if (iAttr.translateValues) {
  3075 + angular.extend(interpolateParams, $parse(iAttr.translateValues)(scope.$parent));
  3076 + }
  3077 + // initially fetch all attributes if existing and fill the params
  3078 + if (translateValueExist) {
  3079 + for (var attr in tAttr) {
  3080 + if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {
  3081 + var attributeName = lowercase(attr.substr(14, 1)) + attr.substr(15);
  3082 + interpolateParams[attributeName] = tAttr[attr];
  3083 + }
  3084 + }
  3085 + }
  3086 + };
  3087 +
  3088 + // Ensures any change of the attribute "translate" containing the id will
  3089 + // be re-stored to the scope's "translationId".
  3090 + // If the attribute has no content, the element's text value (white spaces trimmed off) will be used.
  3091 + var observeElementTranslation = function (translationId) {
  3092 +
  3093 + // Remove any old watcher
  3094 + if (angular.isFunction(observeElementTranslation._unwatchOld)) {
  3095 + observeElementTranslation._unwatchOld();
  3096 + observeElementTranslation._unwatchOld = undefined;
  3097 + }
  3098 +
  3099 + if (angular.equals(translationId , '') || !angular.isDefined(translationId)) {
  3100 + var iElementText = trim.apply(iElement.text());
  3101 +
  3102 + // Resolve translation id by inner html if required
  3103 + var interpolateMatches = iElementText.match(interpolateRegExp);
  3104 + // Interpolate translation id if required
  3105 + if (angular.isArray(interpolateMatches)) {
  3106 + scope.preText = interpolateMatches[1];
  3107 + scope.postText = interpolateMatches[3];
  3108 + translationIds.translate = $interpolate(interpolateMatches[2])(scope.$parent);
  3109 + var watcherMatches = iElementText.match(watcherRegExp);
  3110 + if (angular.isArray(watcherMatches) && watcherMatches[2] && watcherMatches[2].length) {
  3111 + observeElementTranslation._unwatchOld = scope.$watch(watcherMatches[2], function (newValue) {
  3112 + translationIds.translate = newValue;
  3113 + updateTranslations();
  3114 + });
  3115 + }
  3116 + } else {
  3117 + // do not assigne the translation id if it is empty.
  3118 + translationIds.translate = !iElementText ? undefined : iElementText;
  3119 + }
  3120 + } else {
  3121 + translationIds.translate = translationId;
  3122 + }
  3123 + updateTranslations();
  3124 + };
  3125 +
  3126 + var observeAttributeTranslation = function (translateAttr) {
  3127 + iAttr.$observe(translateAttr, function (translationId) {
  3128 + translationIds[translateAttr] = translationId;
  3129 + updateTranslations();
  3130 + });
  3131 + };
  3132 +
  3133 + // initial setup with values
  3134 + initInterpolationParams(scope.interpolateParams, iAttr, tAttr);
  3135 +
  3136 + var firstAttributeChangedEvent = true;
  3137 + iAttr.$observe('translate', function (translationId) {
  3138 + if (typeof translationId === 'undefined') {
  3139 + // case of element "<translate>xyz</translate>"
  3140 + observeElementTranslation('');
  3141 + } else {
  3142 + // case of regular attribute
  3143 + if (translationId !== '' || !firstAttributeChangedEvent) {
  3144 + translationIds.translate = translationId;
  3145 + updateTranslations();
  3146 + }
  3147 + }
  3148 + firstAttributeChangedEvent = false;
  3149 + });
  3150 +
  3151 + for (var translateAttr in iAttr) {
  3152 + if (iAttr.hasOwnProperty(translateAttr) && translateAttr.substr(0, 13) === 'translateAttr' && translateAttr.length > 13) {
  3153 + observeAttributeTranslation(translateAttr);
  3154 + }
  3155 + }
  3156 +
  3157 + iAttr.$observe('translateDefault', function (value) {
  3158 + scope.defaultText = value;
  3159 + updateTranslations();
  3160 + });
  3161 +
  3162 + if (translateSanitizeStrategyExist) {
  3163 + iAttr.$observe('translateSanitizeStrategy', function (value) {
  3164 + scope.sanitizeStrategy = $parse(value)(scope.$parent);
  3165 + updateTranslations();
  3166 + });
  3167 + }
  3168 +
  3169 + if (translateValuesExist) {
  3170 + iAttr.$observe('translateValues', function (interpolateParams) {
  3171 + if (interpolateParams) {
  3172 + scope.$parent.$watch(function () {
  3173 + angular.extend(scope.interpolateParams, $parse(interpolateParams)(scope.$parent));
  3174 + });
  3175 + }
  3176 + });
  3177 + }
  3178 +
  3179 + if (translateValueExist) {
  3180 + var observeValueAttribute = function (attrName) {
  3181 + iAttr.$observe(attrName, function (value) {
  3182 + var attributeName = lowercase(attrName.substr(14, 1)) + attrName.substr(15);
  3183 + scope.interpolateParams[attributeName] = value;
  3184 + });
  3185 + };
  3186 + for (var attr in iAttr) {
  3187 + if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {
  3188 + observeValueAttribute(attr);
  3189 + }
  3190 + }
  3191 + }
  3192 +
  3193 + // Master update function
  3194 + var updateTranslations = function () {
  3195 + for (var key in translationIds) {
  3196 + if (translationIds.hasOwnProperty(key) && translationIds[key] !== undefined) {
  3197 + updateTranslation(key, translationIds[key], scope, scope.interpolateParams, scope.defaultText, scope.translateNamespace);
  3198 + }
  3199 + }
  3200 + };
  3201 +
  3202 + // Put translation processing function outside loop
  3203 + var updateTranslation = function(translateAttr, translationId, scope, interpolateParams, defaultTranslationText, translateNamespace) {
  3204 + if (translationId) {
  3205 + // if translation id starts with '.' and translateNamespace given, prepend namespace
  3206 + if (translateNamespace && translationId.charAt(0) === '.') {
  3207 + translationId = translateNamespace + translationId;
  3208 + }
  3209 +
  3210 + $translate(translationId, interpolateParams, translateInterpolation, defaultTranslationText, scope.translateLanguage, scope.sanitizeStrategy)
  3211 + .then(function (translation) {
  3212 + applyTranslation(translation, scope, true, translateAttr);
  3213 + }, function (translationId) {
  3214 + applyTranslation(translationId, scope, false, translateAttr);
  3215 + });
  3216 + } else {
  3217 + // as an empty string cannot be translated, we can solve this using successful=false
  3218 + applyTranslation(translationId, scope, false, translateAttr);
  3219 + }
  3220 + };
  3221 +
  3222 + var applyTranslation = function (value, scope, successful, translateAttr) {
  3223 + if (!successful) {
  3224 + if (typeof scope.defaultText !== 'undefined') {
  3225 + value = scope.defaultText;
  3226 + }
  3227 + }
  3228 + if (translateAttr === 'translate') {
  3229 + // default translate into innerHTML
  3230 + if (successful || (!successful && !$translate.isKeepContent() && typeof iAttr.translateKeepContent === 'undefined')) {
  3231 + iElement.empty().append(scope.preText + value + scope.postText);
  3232 + }
  3233 + var globallyEnabled = $translate.isPostCompilingEnabled();
  3234 + var locallyDefined = typeof tAttr.translateCompile !== 'undefined';
  3235 + var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false';
  3236 + if ((globallyEnabled && !locallyDefined) || locallyEnabled) {
  3237 + $compile(iElement.contents())(scope);
  3238 + }
  3239 + } else {
  3240 + // translate attribute
  3241 + var attributeName = iAttr.$attr[translateAttr];
  3242 + if (attributeName.substr(0, 5) === 'data-') {
  3243 + // ensure html5 data prefix is stripped
  3244 + attributeName = attributeName.substr(5);
  3245 + }
  3246 + attributeName = attributeName.substr(15);
  3247 + iElement.attr(attributeName, value);
  3248 + }
  3249 + };
  3250 +
  3251 + if (translateValuesExist || translateValueExist || iAttr.translateDefault) {
  3252 + scope.$watch('interpolateParams', updateTranslations, true);
  3253 + }
  3254 +
  3255 + // Replaced watcher on translateLanguage with event listener
  3256 + scope.$on('translateLanguageChanged', updateTranslations);
  3257 +
  3258 + // Ensures the text will be refreshed after the current language was changed
  3259 + // w/ $translate.use(...)
  3260 + var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);
  3261 +
  3262 + // ensure translation will be looked up at least one
  3263 + if (iElement.text().length) {
  3264 + if (iAttr.translate) {
  3265 + observeElementTranslation(iAttr.translate);
  3266 + } else {
  3267 + observeElementTranslation('');
  3268 + }
  3269 + } else if (iAttr.translate) {
  3270 + // ensure attribute will be not skipped
  3271 + observeElementTranslation(iAttr.translate);
  3272 + }
  3273 + updateTranslations();
  3274 + scope.$on('$destroy', unbind);
  3275 + };
  3276 + }
  3277 + };
  3278 +}
  3279 +
  3280 +/**
  3281 + * Returns the scope's namespace.
  3282 + * @private
  3283 + * @param scope
  3284 + * @returns {string}
  3285 + */
  3286 +function getTranslateNamespace(scope) {
  3287 + 'use strict';
  3288 + if (scope.translateNamespace) {
  3289 + return scope.translateNamespace;
  3290 + }
  3291 + if (scope.$parent) {
  3292 + return getTranslateNamespace(scope.$parent);
  3293 + }
  3294 +}
  3295 +
  3296 +translateDirective.displayName = 'translateDirective';
  3297 +
  3298 +angular.module('pascalprecht.translate')
  3299 +/**
  3300 + * @ngdoc directive
  3301 + * @name pascalprecht.translate.directive:translate-attr
  3302 + * @restrict A
  3303 + *
  3304 + * @description
  3305 + * Translates attributes like translate-attr-ATTR, but with an object like ng-class.
  3306 + * Internally it uses `translate` service to translate translation id. It possible to
  3307 + * pass an optional `translate-values` object literal as string into translation id.
  3308 + *
  3309 + * @param {string=} translate-attr Object literal mapping attributes to translation ids.
  3310 + * @param {string=} translate-values Values to pass into the translation ids. Can be passed as object literal string.
  3311 + * @param {string=} translate-sanitize-strategy defines locally sanitize strategy
  3312 + *
  3313 + * @example
  3314 + <example module="ngView">
  3315 + <file name="index.html">
  3316 + <div ng-controller="TranslateCtrl">
  3317 +
  3318 + <input translate-attr="{ placeholder: translationId, title: 'WITH_VALUES' }" translate-values="{value: 5}" />
  3319 +
  3320 + </div>
  3321 + </file>
  3322 + <file name="script.js">
  3323 + angular.module('ngView', ['pascalprecht.translate'])
  3324 +
  3325 + .config(function ($translateProvider) {
  3326 +
  3327 + $translateProvider.translations('en',{
  3328 + 'TRANSLATION_ID': 'Hello there!',
  3329 + 'WITH_VALUES': 'The following value is dynamic: {{value}}',
  3330 + }).preferredLanguage('en');
  3331 +
  3332 + });
  3333 +
  3334 + angular.module('ngView').controller('TranslateCtrl', function ($scope) {
  3335 + $scope.translationId = 'TRANSLATION_ID';
  3336 +
  3337 + $scope.values = {
  3338 + value: 78
  3339 + };
  3340 + });
  3341 + </file>
  3342 + <file name="scenario.js">
  3343 + it('should translate', function () {
  3344 + inject(function ($rootScope, $compile) {
  3345 + $rootScope.translationId = 'TRANSLATION_ID';
  3346 +
  3347 + element = $compile('<input translate-attr="{ placeholder: translationId, title: 'WITH_VALUES' }" translate-values="{ value: 5 }" />')($rootScope);
  3348 + $rootScope.$digest();
  3349 + expect(element.attr('placeholder)).toBe('Hello there!');
  3350 + expect(element.attr('title)).toBe('The following value is dynamic: 5');
  3351 + });
  3352 + });
  3353 + </file>
  3354 + </example>
  3355 + */
  3356 +.directive('translateAttr', translateAttrDirective);
  3357 +function translateAttrDirective($translate, $rootScope) {
  3358 +
  3359 + 'use strict';
  3360 +
  3361 + return {
  3362 + restrict: 'A',
  3363 + priority: $translate.directivePriority(),
  3364 + link: function linkFn(scope, element, attr) {
  3365 +
  3366 + var translateAttr,
  3367 + translateValues,
  3368 + translateSanitizeStrategy,
  3369 + previousAttributes = {};
  3370 +
  3371 + // Main update translations function
  3372 + var updateTranslations = function () {
  3373 + angular.forEach(translateAttr, function (translationId, attributeName) {
  3374 + if (!translationId) {
  3375 + return;
  3376 + }
  3377 + previousAttributes[attributeName] = true;
  3378 +
  3379 + // if translation id starts with '.' and translateNamespace given, prepend namespace
  3380 + if (scope.translateNamespace && translationId.charAt(0) === '.') {
  3381 + translationId = scope.translateNamespace + translationId;
  3382 + }
  3383 + $translate(translationId, translateValues, attr.translateInterpolation, undefined, scope.translateLanguage, translateSanitizeStrategy)
  3384 + .then(function (translation) {
  3385 + element.attr(attributeName, translation);
  3386 + }, function (translationId) {
  3387 + element.attr(attributeName, translationId);
  3388 + });
  3389 + });
  3390 +
  3391 + // Removing unused attributes that were previously used
  3392 + angular.forEach(previousAttributes, function (flag, attributeName) {
  3393 + if (!translateAttr[attributeName]) {
  3394 + element.removeAttr(attributeName);
  3395 + delete previousAttributes[attributeName];
  3396 + }
  3397 + });
  3398 + };
  3399 +
  3400 + // Watch for attribute changes
  3401 + watchAttribute(
  3402 + scope,
  3403 + attr.translateAttr,
  3404 + function (newValue) { translateAttr = newValue; },
  3405 + updateTranslations
  3406 + );
  3407 + // Watch for value changes
  3408 + watchAttribute(
  3409 + scope,
  3410 + attr.translateValues,
  3411 + function (newValue) { translateValues = newValue; },
  3412 + updateTranslations
  3413 + );
  3414 + // Watch for sanitize strategy changes
  3415 + watchAttribute(
  3416 + scope,
  3417 + attr.translateSanitizeStrategy,
  3418 + function (newValue) { translateSanitizeStrategy = newValue; },
  3419 + updateTranslations
  3420 + );
  3421 +
  3422 + if (attr.translateValues) {
  3423 + scope.$watch(attr.translateValues, updateTranslations, true);
  3424 + }
  3425 +
  3426 + // Replaced watcher on translateLanguage with event listener
  3427 + scope.$on('translateLanguageChanged', updateTranslations);
  3428 +
  3429 + // Ensures the text will be refreshed after the current language was changed
  3430 + // w/ $translate.use(...)
  3431 + var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);
  3432 +
  3433 + updateTranslations();
  3434 + scope.$on('$destroy', unbind);
  3435 + }
  3436 + };
  3437 +}
  3438 +
  3439 +function watchAttribute(scope, attribute, valueCallback, changeCallback) {
  3440 + 'use strict';
  3441 + if (!attribute) {
  3442 + return;
  3443 + }
  3444 + if (attribute.substr(0, 2) === '::') {
  3445 + attribute = attribute.substr(2);
  3446 + } else {
  3447 + scope.$watch(attribute, function(newValue) {
  3448 + valueCallback(newValue);
  3449 + changeCallback();
  3450 + }, true);
  3451 + }
  3452 + valueCallback(scope.$eval(attribute));
  3453 +}
  3454 +
  3455 +translateAttrDirective.displayName = 'translateAttrDirective';
  3456 +
  3457 +angular.module('pascalprecht.translate')
  3458 +/**
  3459 + * @ngdoc directive
  3460 + * @name pascalprecht.translate.directive:translateCloak
  3461 + * @requires $translate
  3462 + * @restrict A
  3463 + *
  3464 + * $description
  3465 + * Adds a `translate-cloak` class name to the given element where this directive
  3466 + * is applied initially and removes it, once a loader has finished loading.
  3467 + *
  3468 + * This directive can be used to prevent initial flickering when loading translation
  3469 + * data asynchronously.
  3470 + *
  3471 + * The class name is defined in
  3472 + * {@link pascalprecht.translate.$translateProvider#cloakClassName $translate.cloakClassName()}.
  3473 + *
  3474 + * @param {string=} translate-cloak If a translationId is provided, it will be used for showing
  3475 + * or hiding the cloak. Basically it relies on the translation
  3476 + * resolve.
  3477 + */
  3478 +.directive('translateCloak', translateCloakDirective);
  3479 +
  3480 +function translateCloakDirective($translate, $rootScope) {
  3481 +
  3482 + 'use strict';
  3483 +
  3484 + return {
  3485 + compile : function (tElement) {
  3486 + var applyCloak = function (element) {
  3487 + element.addClass($translate.cloakClassName());
  3488 + },
  3489 + removeCloak = function (element) {
  3490 + element.removeClass($translate.cloakClassName());
  3491 + };
  3492 + applyCloak(tElement);
  3493 +
  3494 + return function linkFn(scope, iElement, iAttr) {
  3495 + //Create bound functions that incorporate the active DOM element.
  3496 + var iRemoveCloak = removeCloak.bind(this, iElement), iApplyCloak = applyCloak.bind(this, iElement);
  3497 + if (iAttr.translateCloak && iAttr.translateCloak.length) {
  3498 + // Register a watcher for the defined translation allowing a fine tuned cloak
  3499 + iAttr.$observe('translateCloak', function (translationId) {
  3500 + $translate(translationId).then(iRemoveCloak, iApplyCloak);
  3501 + });
  3502 + $rootScope.$on('$translateChangeSuccess', function () {
  3503 + $translate(iAttr.translateCloak).then(iRemoveCloak, iApplyCloak);
  3504 + });
  3505 + } else {
  3506 + $translate.onReady(iRemoveCloak);
  3507 + }
  3508 + };
  3509 + }
  3510 + };
  3511 +}
  3512 +
  3513 +translateCloakDirective.displayName = 'translateCloakDirective';
  3514 +
  3515 +angular.module('pascalprecht.translate')
  3516 +/**
  3517 + * @ngdoc directive
  3518 + * @name pascalprecht.translate.directive:translateNamespace
  3519 + * @restrict A
  3520 + *
  3521 + * @description
  3522 + * Translates given translation id either through attribute or DOM content.
  3523 + * Internally it uses `translate` filter to translate translation id. It is possible to
  3524 + * pass an optional `translate-values` object literal as string into translation id.
  3525 + *
  3526 + * @param {string=} translate namespace name which could be either string or interpolated string.
  3527 + *
  3528 + * @example
  3529 + <example module="ngView">
  3530 + <file name="index.html">
  3531 + <div translate-namespace="CONTENT">
  3532 +
  3533 + <div>
  3534 + <h1 translate>.HEADERS.TITLE</h1>
  3535 + <h1 translate>.HEADERS.WELCOME</h1>
  3536 + </div>
  3537 +
  3538 + <div translate-namespace=".HEADERS">
  3539 + <h1 translate>.TITLE</h1>
  3540 + <h1 translate>.WELCOME</h1>
  3541 + </div>
  3542 +
  3543 + </div>
  3544 + </file>
  3545 + <file name="script.js">
  3546 + angular.module('ngView', ['pascalprecht.translate'])
  3547 +
  3548 + .config(function ($translateProvider) {
  3549 +
  3550 + $translateProvider.translations('en',{
  3551 + 'TRANSLATION_ID': 'Hello there!',
  3552 + 'CONTENT': {
  3553 + 'HEADERS': {
  3554 + TITLE: 'Title'
  3555 + }
  3556 + },
  3557 + 'CONTENT.HEADERS.WELCOME': 'Welcome'
  3558 + }).preferredLanguage('en');
  3559 +
  3560 + });
  3561 +
  3562 + </file>
  3563 + </example>
  3564 + */
  3565 +.directive('translateNamespace', translateNamespaceDirective);
  3566 +
  3567 +function translateNamespaceDirective() {
  3568 +
  3569 + 'use strict';
  3570 +
  3571 + return {
  3572 + restrict: 'A',
  3573 + scope: true,
  3574 + compile: function () {
  3575 + return {
  3576 + pre: function (scope, iElement, iAttrs) {
  3577 + scope.translateNamespace = _getTranslateNamespace(scope);
  3578 +
  3579 + if (scope.translateNamespace && iAttrs.translateNamespace.charAt(0) === '.') {
  3580 + scope.translateNamespace += iAttrs.translateNamespace;
  3581 + } else {
  3582 + scope.translateNamespace = iAttrs.translateNamespace;
  3583 + }
  3584 + }
  3585 + };
  3586 + }
  3587 + };
  3588 +}
  3589 +
  3590 +/**
  3591 + * Returns the scope's namespace.
  3592 + * @private
  3593 + * @param scope
  3594 + * @returns {string}
  3595 + */
  3596 +function _getTranslateNamespace(scope) {
  3597 + 'use strict';
  3598 + if (scope.translateNamespace) {
  3599 + return scope.translateNamespace;
  3600 + }
  3601 + if (scope.$parent) {
  3602 + return _getTranslateNamespace(scope.$parent);
  3603 + }
  3604 +}
  3605 +
  3606 +translateNamespaceDirective.displayName = 'translateNamespaceDirective';
  3607 +
  3608 +angular.module('pascalprecht.translate')
  3609 +/**
  3610 + * @ngdoc directive
  3611 + * @name pascalprecht.translate.directive:translateLanguage
  3612 + * @restrict A
  3613 + *
  3614 + * @description
  3615 + * Forces the language to the directives in the underlying scope.
  3616 + *
  3617 + * @param {string=} translate language that will be negotiated.
  3618 + *
  3619 + * @example
  3620 + <example module="ngView">
  3621 + <file name="index.html">
  3622 + <div>
  3623 +
  3624 + <div>
  3625 + <h1 translate>HELLO</h1>
  3626 + </div>
  3627 +
  3628 + <div translate-language="de">
  3629 + <h1 translate>HELLO</h1>
  3630 + </div>
  3631 +
  3632 + </div>
  3633 + </file>
  3634 + <file name="script.js">
  3635 + angular.module('ngView', ['pascalprecht.translate'])
  3636 +
  3637 + .config(function ($translateProvider) {
  3638 +
  3639 + $translateProvider
  3640 + .translations('en',{
  3641 + 'HELLO': 'Hello world!'
  3642 + })
  3643 + .translations('de',{
  3644 + 'HELLO': 'Hallo Welt!'
  3645 + })
  3646 + .preferredLanguage('en');
  3647 +
  3648 + });
  3649 +
  3650 + </file>
  3651 + </example>
  3652 + */
  3653 +.directive('translateLanguage', translateLanguageDirective);
  3654 +
  3655 +function translateLanguageDirective() {
  3656 +
  3657 + 'use strict';
  3658 +
  3659 + return {
  3660 + restrict: 'A',
  3661 + scope: true,
  3662 + compile: function () {
  3663 + return function linkFn(scope, iElement, iAttrs) {
  3664 +
  3665 + iAttrs.$observe('translateLanguage', function (newTranslateLanguage) {
  3666 + scope.translateLanguage = newTranslateLanguage;
  3667 + });
  3668 +
  3669 + scope.$watch('translateLanguage', function(){
  3670 + scope.$broadcast('translateLanguageChanged');
  3671 + });
  3672 + };
  3673 + }
  3674 + };
  3675 +}
  3676 +
  3677 +translateLanguageDirective.displayName = 'translateLanguageDirective';
  3678 +
  3679 +angular.module('pascalprecht.translate')
  3680 +/**
  3681 + * @ngdoc filter
  3682 + * @name pascalprecht.translate.filter:translate
  3683 + * @requires $parse
  3684 + * @requires pascalprecht.translate.$translate
  3685 + * @function
  3686 + *
  3687 + * @description
  3688 + * Uses `$translate` service to translate contents. Accepts interpolate parameters
  3689 + * to pass dynamized values though translation.
  3690 + *
  3691 + * @param {string} translationId A translation id to be translated.
  3692 + * @param {*=} interpolateParams Optional object literal (as hash or string) to pass values into translation.
  3693 + *
  3694 + * @returns {string} Translated text.
  3695 + *
  3696 + * @example
  3697 + <example module="ngView">
  3698 + <file name="index.html">
  3699 + <div ng-controller="TranslateCtrl">
  3700 +
  3701 + <pre>{{ 'TRANSLATION_ID' | translate }}</pre>
  3702 + <pre>{{ translationId | translate }}</pre>
  3703 + <pre>{{ 'WITH_VALUES' | translate:'{value: 5}' }}</pre>
  3704 + <pre>{{ 'WITH_VALUES' | translate:values }}</pre>
  3705 +
  3706 + </div>
  3707 + </file>
  3708 + <file name="script.js">
  3709 + angular.module('ngView', ['pascalprecht.translate'])
  3710 +
  3711 + .config(function ($translateProvider) {
  3712 +
  3713 + $translateProvider.translations('en', {
  3714 + 'TRANSLATION_ID': 'Hello there!',
  3715 + 'WITH_VALUES': 'The following value is dynamic: {{value}}'
  3716 + });
  3717 + $translateProvider.preferredLanguage('en');
  3718 +
  3719 + });
  3720 +
  3721 + angular.module('ngView').controller('TranslateCtrl', function ($scope) {
  3722 + $scope.translationId = 'TRANSLATION_ID';
  3723 +
  3724 + $scope.values = {
  3725 + value: 78
  3726 + };
  3727 + });
  3728 + </file>
  3729 + </example>
  3730 + */
  3731 +.filter('translate', translateFilterFactory);
  3732 +
  3733 +function translateFilterFactory($parse, $translate) {
  3734 +
  3735 + 'use strict';
  3736 +
  3737 + var translateFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {
  3738 + if (!angular.isObject(interpolateParams)) {
  3739 + var ctx = this || {
  3740 + '__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'
  3741 + };
  3742 + interpolateParams = $parse(interpolateParams)(ctx);
  3743 + }
  3744 +
  3745 + return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);
  3746 + };
  3747 +
  3748 + if ($translate.statefulFilter()) {
  3749 + translateFilter.$stateful = true;
  3750 + }
  3751 +
  3752 + return translateFilter;
  3753 +}
  3754 +
  3755 +translateFilterFactory.displayName = 'translateFilterFactory';
  3756 +
  3757 +angular.module('pascalprecht.translate')
  3758 +
  3759 +/**
  3760 + * @ngdoc object
  3761 + * @name pascalprecht.translate.$translationCache
  3762 + * @requires $cacheFactory
  3763 + *
  3764 + * @description
  3765 + * The first time a translation table is used, it is loaded in the translation cache for quick retrieval. You
  3766 + * can load translation tables directly into the cache by consuming the
  3767 + * `$translationCache` service directly.
  3768 + *
  3769 + * @return {object} $cacheFactory object.
  3770 + */
  3771 + .factory('$translationCache', $translationCache);
  3772 +
  3773 +function $translationCache($cacheFactory) {
  3774 +
  3775 + 'use strict';
  3776 +
  3777 + return $cacheFactory('translations');
  3778 +}
  3779 +
  3780 +$translationCache.displayName = '$translationCache';
  3781 +return 'pascalprecht.translate';
  3782 +
  3783 +}));
... ...
src/main/resources/static/assets/bower_components/angular-translate/angular-translate.min.js 0 → 100644
  1 +/*!
  2 + * angular-translate - v2.17.1 - 2018-04-16
  3 + *
  4 + * Copyright (c) 2018 The angular-translate team, Pascal Precht; Licensed MIT
  5 + */
  6 +!function(t,e){"function"==typeof define&&define.amd?define([],function(){return e()}):"object"==typeof module&&module.exports?module.exports=e():e()}(0,function(){function t(t){"use strict";var e=t.storageKey(),n=t.storage(),a=function(){var a=t.preferredLanguage();angular.isString(a)?t.use(a):n.put(e,t.use())};a.displayName="fallbackFromIncorrectStorageValue",n?n.get(e)?t.use(n.get(e)).catch(a):a():angular.isString(t.preferredLanguage())&&t.use(t.preferredLanguage())}function e(t,e,n,a){"use strict";var r,i,s,o,u,l,c,f,g,p,h,d,v,m,$,y,b={},S=[],L=t,j=[],w="translate-cloak",C=!1,N=!1,O=".",E=!1,k=!1,P=0,A=!0,z="default",T={default:function(t){return(t||"").split("-").join("_")},java:function(t){var e=(t||"").split("-").join("_"),n=e.split("_");return n.length>1?n[0].toLowerCase()+"_"+n[1].toUpperCase():e},bcp47:function(t){var e=(t||"").split("_").join("-"),n=e.split("-");switch(n.length){case 1:n[0]=n[0].toLowerCase();break;case 2:n[0]=n[0].toLowerCase(),4===n[1].length?n[1]=n[1].charAt(0).toUpperCase()+n[1].slice(1).toLowerCase():n[1]=n[1].toUpperCase();break;case 3:n[0]=n[0].toLowerCase(),n[1]=n[1].charAt(0).toUpperCase()+n[1].slice(1).toLowerCase(),n[2]=n[2].toUpperCase();break;default:return e}return n.join("-")},"iso639-1":function(t){return(t||"").split("_").join("-").split("-")[0].toLowerCase()}},x=function(){if(angular.isFunction(a.getLocale))return a.getLocale();var t,n,r=e.$get().navigator,i=["language","browserLanguage","systemLanguage","userLanguage"];if(angular.isArray(r.languages))for(t=0;t<r.languages.length;t++)if((n=r.languages[t])&&n.length)return n;for(t=0;t<i.length;t++)if((n=r[i[t]])&&n.length)return n;return null};x.displayName="angular-translate/service: getFirstBrowserLanguage";var F=function(){var t=x()||"";return T[z]&&(t=T[z](t)),t};F.displayName="angular-translate/service: getLocale";var I=function(t,e){for(var n=0,a=t.length;n<a;n++)if(t[n]===e)return n;return-1},_=function(){return this.toString().replace(/^\s+|\s+$/g,"")},V=function(t){return angular.isString(t)?t.toLowerCase():t},R=function(t){if(t){for(var e=[],n=V(t),a=0,r=S.length;a<r;a++)e.push(V(S[a]));if((a=I(e,n))>-1)return S[a];if(i){var s;for(var o in i)if(i.hasOwnProperty(o)){var u=!1,l=Object.prototype.hasOwnProperty.call(i,o)&&V(o)===V(t);if("*"===o.slice(-1)&&(u=V(o.slice(0,-1))===V(t.slice(0,o.length-1))),(l||u)&&(s=i[o],I(e,V(s))>-1))return s}}var c=t.split("_");return c.length>1&&I(e,V(c[0]))>-1?c[0]:void 0}},D=function(t,e){if(!t&&!e)return b;if(t&&!e){if(angular.isString(t))return b[t]}else angular.isObject(b[t])||(b[t]={}),angular.extend(b[t],K(e));return this};this.translations=D,this.cloakClassName=function(t){return t?(w=t,this):w},this.nestedObjectDelimeter=function(t){return t?(O=t,this):O};var K=function(t,e,n,a){var r,i,s;e||(e=[]),n||(n={});for(r in t)Object.prototype.hasOwnProperty.call(t,r)&&(s=t[r],angular.isObject(s)?K(s,e.concat(r),n,r):(i=e.length?""+e.join(O)+O+r:r,e.length&&r===a&&(n[""+e.join(O)]="@:"+i),n[i]=s));return n};K.displayName="flatObject",this.addInterpolation=function(t){return j.push(t),this},this.useMessageFormatInterpolation=function(){return this.useInterpolation("$translateMessageFormatInterpolation")},this.useInterpolation=function(t){return p=t,this},this.useSanitizeValueStrategy=function(t){return n.useStrategy(t),this},this.preferredLanguage=function(t){return t?(U(t),this):r};var U=function(t){return t&&(r=t),r};this.translationNotFoundIndicator=function(t){return this.translationNotFoundIndicatorLeft(t),this.translationNotFoundIndicatorRight(t),this},this.translationNotFoundIndicatorLeft=function(t){return t?(v=t,this):v},this.translationNotFoundIndicatorRight=function(t){return t?(m=t,this):m},this.fallbackLanguage=function(t){return M(t),this};var M=function(t){return t?(angular.isString(t)?(o=!0,s=[t]):angular.isArray(t)&&(o=!1,s=t),angular.isString(r)&&I(s,r)<0&&s.push(r),this):o?s[0]:s};this.use=function(t){if(t){if(!b[t]&&!h)throw new Error("$translateProvider couldn't find translationTable for langKey: '"+t+"'");return u=t,this}return u},this.resolveClientLocale=function(){return F()};var H=function(t){return t?(L=t,this):f?f+L:L};this.storageKey=H,this.useUrlLoader=function(t,e){return this.useLoader("$translateUrlLoader",angular.extend({url:t},e))},this.useStaticFilesLoader=function(t){return this.useLoader("$translateStaticFilesLoader",t)},this.useLoader=function(t,e){return h=t,d=e||{},this},this.useLocalStorage=function(){return this.useStorage("$translateLocalStorage")},this.useCookieStorage=function(){return this.useStorage("$translateCookieStorage")},this.useStorage=function(t){return c=t,this},this.storagePrefix=function(t){return t?(f=t,this):t},this.useMissingTranslationHandlerLog=function(){return this.useMissingTranslationHandler("$translateMissingTranslationHandlerLog")},this.useMissingTranslationHandler=function(t){return g=t,this},this.usePostCompiling=function(t){return C=!!t,this},this.forceAsyncReload=function(t){return N=!!t,this},this.uniformLanguageTag=function(t){return t?angular.isString(t)&&(t={standard:t}):t={},z=t.standard,this},this.determinePreferredLanguage=function(t){var e=t&&angular.isFunction(t)?t():F();return r=S.length?R(e)||e:e,this},this.registerAvailableLanguageKeys=function(t,e){return t?(S=t,e&&(i=e),this):S},this.useLoaderCache=function(t){return!1===t?$=void 0:!0===t?$=!0:void 0===t?$="$translationCache":t&&($=t),this},this.directivePriority=function(t){return void 0===t?P:(P=t,this)},this.statefulFilter=function(t){return void 0===t?A:(A=t,this)},this.postProcess=function(t){return y=t||void 0,this},this.keepContent=function(t){return k=!!t,this},this.$get=["$log","$injector","$rootScope","$q",function(t,e,n,a){var i,f,z,T=e.get(p||"$translateDefaultInterpolation"),x=!1,V={},G={},q=function(t,e,n,o,l,g){!u&&r&&(u=r);var p=l&&l!==u?R(l)||l:u;if(l&&lt(l),angular.isArray(t)){return function(t){for(var r={},i=[],s=0,u=t.length;s<u;s++)i.push(function(t){var i=a.defer(),s=function(e){r[t]=e,i.resolve([t,e])};return q(t,e,n,o,l,g).then(s,s),i.promise}(t[s]));return a.all(i).then(function(){return r})}(t)}var h=a.defer();t&&(t=_.apply(t));var d=function(){var t=G[p]||G[r];if(f=0,c&&!t){var e=i.get(L);if(t=G[e],s&&s.length){var n=I(s,e);f=0===n?1:0,I(s,r)<0&&s.push(r)}}return t}();if(d){var v=function(){l||(p=u),it(t,e,n,o,p,g).then(h.resolve,h.reject)};v.displayName="promiseResolved",d.finally(v).catch(angular.noop)}else it(t,e,n,o,p,g).then(h.resolve,h.reject);return h.promise},Y=function(t){return v&&(t=[v,t].join(" ")),m&&(t=[t,m].join(" ")),t},B=function(t){u=t,c&&i.put(q.storageKey(),u),n.$emit("$translateChangeSuccess",{language:t}),T.setLocale(u);var e=function(t,e){V[e].setLocale(u)};e.displayName="eachInterpolatorLocaleSetter",angular.forEach(V,e),n.$emit("$translateChangeEnd",{language:t})},J=function(t){if(!t)throw"No language key specified for loading.";var r=a.defer();n.$emit("$translateLoadingStart",{language:t}),x=!0;var i=$;"string"==typeof i&&(i=e.get(i));var s=angular.extend({},d,{key:t,$http:angular.extend({},{cache:i},d.$http)}),o=function(e){var a={};n.$emit("$translateLoadingSuccess",{language:t}),angular.isArray(e)?angular.forEach(e,function(t){angular.extend(a,K(t))}):angular.extend(a,K(e)),x=!1,r.resolve({key:t,table:a}),n.$emit("$translateLoadingEnd",{language:t})};o.displayName="onLoaderSuccess";var u=function(t){n.$emit("$translateLoadingError",{language:t}),r.reject(t),n.$emit("$translateLoadingEnd",{language:t})};return u.displayName="onLoaderError",e.get(h)(s).then(o,u),r.promise};if(c&&(!(i=e.get(c)).get||!i.put))throw new Error("Couldn't use storage '"+c+"', missing get() or put() method!");if(j.length){var Q=function(t){var n=e.get(t);n.setLocale(r||u),V[n.getInterpolationIdentifier()]=n};Q.displayName="interpolationFactoryAdder",angular.forEach(j,Q)}var W=function(t){var e=a.defer();if(Object.prototype.hasOwnProperty.call(b,t))e.resolve(b[t]);else if(G[t]){var n=function(t){D(t.key,t.table),e.resolve(t.table)};n.displayName="translationTableResolver",G[t].then(n,e.reject)}else e.reject();return e.promise},X=function(t,e,n,r,i){var s=a.defer(),o=function(a){if(Object.prototype.hasOwnProperty.call(a,e)&&null!==a[e]){r.setLocale(t);var o=a[e];if("@:"===o.substr(0,2))X(t,o.substr(2),n,r,i).then(s.resolve,s.reject);else{var l=r.interpolate(a[e],n,"service",i,e);l=ut(e,a[e],l,n,t),s.resolve(l)}r.setLocale(u)}else s.reject()};return o.displayName="fallbackTranslationResolver",W(t).then(o,s.reject),s.promise},Z=function(t,e,n,a,r){var i,s=b[t];if(s&&Object.prototype.hasOwnProperty.call(s,e)&&null!==s[e]){if(a.setLocale(t),i=a.interpolate(s[e],n,"filter",r,e),i=ut(e,s[e],i,n,t,r),!angular.isString(i)&&angular.isFunction(i.$$unwrapTrustedValue)){var o=i.$$unwrapTrustedValue();if("@:"===o.substr(0,2))return Z(t,o.substr(2),n,a,r)}else if("@:"===i.substr(0,2))return Z(t,i.substr(2),n,a,r);a.setLocale(u)}return i},tt=function(t,n,a,r){return g?e.get(g)(t,u,n,a,r):t},et=function(t,e,n,r,i,o){var u=a.defer();if(t<s.length){var l=s[t];X(l,e,n,r,o).then(function(t){u.resolve(t)},function(){return et(t+1,e,n,r,i,o).then(u.resolve,u.reject)})}else if(i)u.resolve(i);else{var c=tt(e,n,i);g&&c?u.resolve(c):u.reject(Y(e))}return u.promise},nt=function(t,e,n,a,r){var i;if(t<s.length){var o=s[t];(i=Z(o,e,n,a,r))||""===i||(i=nt(t+1,e,n,a))}return i},at=function(t,e,n,a,r){return et(z>0?z:f,t,e,n,a,r)},rt=function(t,e,n,a){return nt(z>0?z:f,t,e,n,a)},it=function(t,e,n,r,i,o){var u=a.defer(),l=i?b[i]:b,c=n?V[n]:T;if(l&&Object.prototype.hasOwnProperty.call(l,t)&&null!==l[t]){var f=l[t];if("@:"===f.substr(0,2))q(f.substr(2),e,n,r,i,o).then(u.resolve,u.reject);else{var p=c.interpolate(f,e,"service",o,t);p=ut(t,f,p,e,i),u.resolve(p)}}else{var h;g&&!x&&(h=tt(t,e,r)),i&&s&&s.length?at(t,e,c,r,o).then(function(t){u.resolve(t)},function(t){u.reject(Y(t))}):g&&!x&&h?r?u.resolve(r):u.resolve(h):r?u.resolve(r):u.reject(Y(t))}return u.promise},st=function(t,e,n,a,r){var i,o=a?b[a]:b,u=T;if(V&&Object.prototype.hasOwnProperty.call(V,n)&&(u=V[n]),o&&Object.prototype.hasOwnProperty.call(o,t)&&null!==o[t]){var l=o[t];"@:"===l.substr(0,2)?i=st(l.substr(2),e,n,a,r):(i=u.interpolate(l,e,"filter",r,t),i=ut(t,l,i,e,a,r))}else{var c;g&&!x&&(c=tt(t,e,r)),a&&s&&s.length?(f=0,i=rt(t,e,u,r)):i=g&&!x&&c?c:Y(t)}return i},ot=function(t){l===t&&(l=void 0),G[t]=void 0},ut=function(t,n,a,r,i,s){var o=y;return o&&("string"==typeof o&&(o=e.get(o)),o)?o(t,n,a,r,i,s):a},lt=function(t){b[t]||!h||G[t]||(G[t]=J(t).then(function(t){return D(t.key,t.table),t}))};q.preferredLanguage=function(t){return t&&U(t),r},q.cloakClassName=function(){return w},q.nestedObjectDelimeter=function(){return O},q.fallbackLanguage=function(t){if(void 0!==t&&null!==t){if(M(t),h&&s&&s.length)for(var e=0,n=s.length;e<n;e++)G[s[e]]||(G[s[e]]=J(s[e]));q.use(q.use())}return o?s[0]:s},q.useFallbackLanguage=function(t){if(void 0!==t&&null!==t)if(t){var e=I(s,t);e>-1&&(z=e)}else z=0},q.proposedLanguage=function(){return l},q.storage=function(){return i},q.negotiateLocale=R,q.use=function(t){if(!t)return u;var e=a.defer();e.promise.then(null,angular.noop),n.$emit("$translateChangeStart",{language:t});var r=R(t);return S.length>0&&!r?a.reject(t):(r&&(t=r),l=t,!N&&b[t]||!h||G[t]?G[t]?G[t].then(function(t){return l===t.key&&B(t.key),e.resolve(t.key),t},function(t){return!u&&s&&s.length>0&&s[0]!==t?q.use(s[0]).then(e.resolve,e.reject):e.reject(t)}):(e.resolve(t),B(t)):(G[t]=J(t).then(function(n){return D(n.key,n.table),e.resolve(n.key),l===t&&B(n.key),n},function(t){return n.$emit("$translateChangeError",{language:t}),e.reject(t),n.$emit("$translateChangeEnd",{language:t}),a.reject(t)}),G[t].finally(function(){ot(t)}).catch(angular.noop)),e.promise)},q.resolveClientLocale=function(){return F()},q.storageKey=function(){return H()},q.isPostCompilingEnabled=function(){return C},q.isForceAsyncReloadEnabled=function(){return N},q.isKeepContent=function(){return k},q.refresh=function(t){function e(t){var e=J(t);return G[t]=e,e.then(function(e){b[t]={},D(t,e.table),i[t]=!0},angular.noop),e}if(!h)throw new Error("Couldn't refresh translation table, no loader registered!");n.$emit("$translateRefreshStart",{language:t});var r=a.defer(),i={};if(r.promise.then(function(){for(var t in b)b.hasOwnProperty(t)&&(t in i||delete b[t]);u&&B(u)},angular.noop).finally(function(){n.$emit("$translateRefreshEnd",{language:t})}),t)b[t]?e(t).then(r.resolve,r.reject):r.reject();else{var o=s&&s.slice()||[];u&&-1===o.indexOf(u)&&o.push(u),a.all(o.map(e)).then(r.resolve,r.reject)}return r.promise},q.instant=function(t,e,n,a,i){var o=a&&a!==u?R(a)||a:u;if(null===t||angular.isUndefined(t))return t;if(a&&lt(a),angular.isArray(t)){for(var l={},c=0,f=t.length;c<f;c++)l[t[c]]=q.instant(t[c],e,n,a,i);return l}if(angular.isString(t)&&t.length<1)return t;t&&(t=_.apply(t));var p,h=[];r&&h.push(r),o&&h.push(o),s&&s.length&&(h=h.concat(s));for(var d=0,$=h.length;d<$;d++){var y=h[d];if(b[y]&&void 0!==b[y][t]&&(p=st(t,e,n,o,i)),void 0!==p)break}if(!p&&""!==p)if(v||m)p=Y(t);else{p=T.interpolate(t,e,"filter",i);var S;g&&!x&&(S=tt(t,e,i)),g&&!x&&S&&(p=S)}return p},q.versionInfo=function(){return"2.17.1"},q.loaderCache=function(){return $},q.directivePriority=function(){return P},q.statefulFilter=function(){return A},q.isReady=function(){return E};var ct=a.defer();ct.promise.then(function(){E=!0}),q.onReady=function(t){var e=a.defer();return angular.isFunction(t)&&e.promise.then(t),E?e.resolve():ct.promise.then(e.resolve),e.promise},q.getAvailableLanguageKeys=function(){return S.length>0?S:null},q.getTranslationTable=function(t){return(t=t||q.use())&&b[t]?angular.copy(b[t]):null};var ft=n.$on("$translateReady",function(){ct.resolve(),ft(),ft=null}),gt=n.$on("$translateChangeEnd",function(){ct.resolve(),gt(),gt=null});if(h){if(angular.equals(b,{})&&q.use()&&q.use(q.use()),s&&s.length)for(var pt=0,ht=s.length;pt<ht;pt++){var dt=s[pt];!N&&b[dt]||(G[dt]=J(dt).then(function(t){return D(t.key,t.table),n.$emit("$translateChangeEnd",{language:t.key}),t}))}}else n.$emit("$translateReady",{language:q.use()});return q}]}function n(t,e){"use strict";var n,a={};return a.setLocale=function(t){n=t},a.getInterpolationIdentifier=function(){return"default"},a.useSanitizeValueStrategy=function(t){return e.useStrategy(t),this},a.interpolate=function(n,a,r,i,s){a=a||{},a=e.sanitize(a,"params",i,r);var o;return angular.isNumber(n)?o=""+n:angular.isString(n)?(o=t(n)(a),o=e.sanitize(o,"text",i,r)):o="",o},a}function a(t,e,n,a,i){"use strict";var s=function(){return this.toString().replace(/^\s+|\s+$/g,"")},o=function(t){return angular.isString(t)?t.toLowerCase():t};return{restrict:"AE",scope:!0,priority:t.directivePriority(),compile:function(u,l){var c=l.translateValues?l.translateValues:void 0,f=l.translateInterpolation?l.translateInterpolation:void 0,g=l.translateSanitizeStrategy?l.translateSanitizeStrategy:void 0,p=u[0].outerHTML.match(/translate-value-+/i),h="^(.*)("+e.startSymbol()+".*"+e.endSymbol()+")(.*)",d="^(.*)"+e.startSymbol()+"(.*)"+e.endSymbol()+"(.*)";return function(u,v,m){u.interpolateParams={},u.preText="",u.postText="",u.translateNamespace=r(u);var $={},y=function(t){if(angular.isFunction(y._unwatchOld)&&(y._unwatchOld(),y._unwatchOld=void 0),angular.equals(t,"")||!angular.isDefined(t)){var n=s.apply(v.text()),a=n.match(h);if(angular.isArray(a)){u.preText=a[1],u.postText=a[3],$.translate=e(a[2])(u.$parent);var r=n.match(d);angular.isArray(r)&&r[2]&&r[2].length&&(y._unwatchOld=u.$watch(r[2],function(t){$.translate=t,j()}))}else $.translate=n||void 0}else $.translate=t;j()};!function(t,e,n){if(e.translateValues&&angular.extend(t,a(e.translateValues)(u.$parent)),p)for(var r in n)Object.prototype.hasOwnProperty.call(e,r)&&"translateValue"===r.substr(0,14)&&"translateValues"!==r&&(t[o(r.substr(14,1))+r.substr(15)]=n[r])}(u.interpolateParams,m,l);var b=!0;m.$observe("translate",function(t){void 0===t?y(""):""===t&&b||($.translate=t,j()),b=!1});for(var S in m)m.hasOwnProperty(S)&&"translateAttr"===S.substr(0,13)&&S.length>13&&function(t){m.$observe(t,function(e){$[t]=e,j()})}(S);if(m.$observe("translateDefault",function(t){u.defaultText=t,j()}),g&&m.$observe("translateSanitizeStrategy",function(t){u.sanitizeStrategy=a(t)(u.$parent),j()}),c&&m.$observe("translateValues",function(t){t&&u.$parent.$watch(function(){angular.extend(u.interpolateParams,a(t)(u.$parent))})}),p){for(var L in m)Object.prototype.hasOwnProperty.call(m,L)&&"translateValue"===L.substr(0,14)&&"translateValues"!==L&&function(t){m.$observe(t,function(e){var n=o(t.substr(14,1))+t.substr(15);u.interpolateParams[n]=e})}(L)}var j=function(){for(var t in $)$.hasOwnProperty(t)&&void 0!==$[t]&&w(t,$[t],u,u.interpolateParams,u.defaultText,u.translateNamespace)},w=function(e,n,a,r,i,s){n?(s&&"."===n.charAt(0)&&(n=s+n),t(n,r,f,i,a.translateLanguage,a.sanitizeStrategy).then(function(t){C(t,a,!0,e)},function(t){C(t,a,!1,e)})):C(n,a,!1,e)},C=function(e,a,r,i){if(r||void 0!==a.defaultText&&(e=a.defaultText),"translate"===i){(r||!r&&!t.isKeepContent()&&void 0===m.translateKeepContent)&&v.empty().append(a.preText+e+a.postText);var s=t.isPostCompilingEnabled(),o=void 0!==l.translateCompile,u=o&&"false"!==l.translateCompile;(s&&!o||u)&&n(v.contents())(a)}else{var c=m.$attr[i];"data-"===c.substr(0,5)&&(c=c.substr(5)),c=c.substr(15),v.attr(c,e)}};(c||p||m.translateDefault)&&u.$watch("interpolateParams",j,!0),u.$on("translateLanguageChanged",j);var N=i.$on("$translateChangeSuccess",j);v.text().length?y(m.translate?m.translate:""):m.translate&&y(m.translate),j(),u.$on("$destroy",N)}}}}function r(t){"use strict";return t.translateNamespace?t.translateNamespace:t.$parent?r(t.$parent):void 0}function i(t,e){"use strict";return{restrict:"A",priority:t.directivePriority(),link:function(n,a,r){var i,o,u,l={},c=function(){angular.forEach(i,function(e,i){e&&(l[i]=!0,n.translateNamespace&&"."===e.charAt(0)&&(e=n.translateNamespace+e),t(e,o,r.translateInterpolation,void 0,n.translateLanguage,u).then(function(t){a.attr(i,t)},function(t){a.attr(i,t)}))}),angular.forEach(l,function(t,e){i[e]||(a.removeAttr(e),delete l[e])})};s(n,r.translateAttr,function(t){i=t},c),s(n,r.translateValues,function(t){o=t},c),s(n,r.translateSanitizeStrategy,function(t){u=t},c),r.translateValues&&n.$watch(r.translateValues,c,!0),n.$on("translateLanguageChanged",c);var f=e.$on("$translateChangeSuccess",c);c(),n.$on("$destroy",f)}}}function s(t,e,n,a){"use strict";e&&("::"===e.substr(0,2)?e=e.substr(2):t.$watch(e,function(t){n(t),a()},!0),n(t.$eval(e)))}function o(t,e){"use strict";return{compile:function(n){var a=function(e){e.addClass(t.cloakClassName())},r=function(e){e.removeClass(t.cloakClassName())};return a(n),function(n,i,s){var o=r.bind(this,i),u=a.bind(this,i);s.translateCloak&&s.translateCloak.length?(s.$observe("translateCloak",function(e){t(e).then(o,u)}),e.$on("$translateChangeSuccess",function(){t(s.translateCloak).then(o,u)})):t.onReady(o)}}}}function u(){"use strict";return{restrict:"A",scope:!0,compile:function(){return{pre:function(t,e,n){t.translateNamespace=l(t),t.translateNamespace&&"."===n.translateNamespace.charAt(0)?t.translateNamespace+=n.translateNamespace:t.translateNamespace=n.translateNamespace}}}}}function l(t){"use strict";return t.translateNamespace?t.translateNamespace:t.$parent?l(t.$parent):void 0}function c(){"use strict";return{restrict:"A",scope:!0,compile:function(){return function(t,e,n){n.$observe("translateLanguage",function(e){t.translateLanguage=e}),t.$watch("translateLanguage",function(){t.$broadcast("translateLanguageChanged")})}}}}function f(t,e){"use strict";var n=function(n,a,r,i){if(!angular.isObject(a)){var s=this||{__SCOPE_IS_NOT_AVAILABLE:"More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f"};a=t(a)(s)}return e.instant(n,a,r,i)};return e.statefulFilter()&&(n.$stateful=!0),n}function g(t){"use strict";return t("translations")}return t.$inject=["$translate"],e.$inject=["$STORAGE_KEY","$windowProvider","$translateSanitizationProvider","pascalprechtTranslateOverrider"],n.$inject=["$interpolate","$translateSanitization"],a.$inject=["$translate","$interpolate","$compile","$parse","$rootScope"],i.$inject=["$translate","$rootScope"],o.$inject=["$translate","$rootScope"],f.$inject=["$parse","$translate"],g.$inject=["$cacheFactory"],angular.module("pascalprecht.translate",["ng"]).run(t),t.displayName="runTranslate",angular.module("pascalprecht.translate").provider("$translateSanitization",function(){"use strict";var t,e,n,a=null,r=!1,i=!1;(n={sanitize:function(t,e){return"text"===e&&(t=o(t)),t},escape:function(t,e){return"text"===e&&(t=s(t)),t},sanitizeParameters:function(t,e){return"params"===e&&(t=l(t,o)),t},escapeParameters:function(t,e){return"params"===e&&(t=l(t,s)),t},sce:function(t,e,n){return"text"===e?t=u(t):"params"===e&&"filter"!==n&&(t=l(t,s)),t},sceParameters:function(t,e){return"params"===e&&(t=l(t,u)),t}}).escaped=n.escapeParameters,this.addStrategy=function(t,e){return n[t]=e,this},this.removeStrategy=function(t){return delete n[t],this},this.useStrategy=function(t){return r=!0,a=t,this},this.$get=["$injector","$log",function(s,o){var u={},l=function(t,e,a,r){return angular.forEach(r,function(r){if(angular.isFunction(r))t=r(t,e,a);else if(angular.isFunction(n[r]))t=n[r](t,e,a);else{if(!angular.isString(n[r]))throw new Error("pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: '"+r+"'");if(!u[n[r]])try{u[n[r]]=s.get(n[r])}catch(t){throw u[n[r]]=function(){},new Error("pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: '"+r+"'")}t=u[n[r]](t,e,a)}}),t},c=function(){r||i||(o.warn("pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details."),i=!0)};return s.has("$sanitize")&&(t=s.get("$sanitize")),s.has("$sce")&&(e=s.get("$sce")),{useStrategy:function(t){return function(e){t.useStrategy(e)}}(this),sanitize:function(t,e,n,r){if(a||c(),n||null===n||(n=a),!n)return t;r||(r="service");var i=angular.isArray(n)?n:[n];return l(t,e,r,i)}}}];var s=function(t){var e=angular.element("<div></div>");return e.text(t),e.html()},o=function(e){if(!t)throw new Error("pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as 'escape'.");return t(e)},u=function(t){if(!e)throw new Error("pascalprecht.translate.$translateSanitization: Error cannot find $sce service.");return e.trustAsHtml(t)},l=function(t,e,n){if(angular.isDate(t))return t;if(angular.isObject(t)){var a=angular.isArray(t)?[]:{};if(n){if(n.indexOf(t)>-1)throw new Error("pascalprecht.translate.$translateSanitization: Error cannot interpolate parameter due recursive object")}else n=[];return n.push(t),angular.forEach(t,function(t,r){angular.isFunction(t)||(a[r]=l(t,e,n))}),n.splice(-1,1),a}return angular.isNumber(t)?t:!0===t||!1===t?t:angular.isUndefined(t)||null===t?t:e(t)}}),angular.module("pascalprecht.translate").constant("pascalprechtTranslateOverrider",{}).provider("$translate",e),e.displayName="displayName",angular.module("pascalprecht.translate").factory("$translateDefaultInterpolation",n),n.displayName="$translateDefaultInterpolation",angular.module("pascalprecht.translate").constant("$STORAGE_KEY","NG_TRANSLATE_LANG_KEY"),angular.module("pascalprecht.translate").directive("translate",a),a.displayName="translateDirective",angular.module("pascalprecht.translate").directive("translateAttr",i),i.displayName="translateAttrDirective",angular.module("pascalprecht.translate").directive("translateCloak",o),o.displayName="translateCloakDirective",angular.module("pascalprecht.translate").directive("translateNamespace",u),u.displayName="translateNamespaceDirective",angular.module("pascalprecht.translate").directive("translateLanguage",c),c.displayName="translateLanguageDirective",angular.module("pascalprecht.translate").filter("translate",f),f.displayName="translateFilterFactory",angular.module("pascalprecht.translate").factory("$translationCache",g),g.displayName="$translationCache","pascalprecht.translate"});
0 7 \ No newline at end of file
... ...
src/main/resources/static/assets/bower_components/angular-translate/bower.json 0 → 100644
  1 +{
  2 + "name": "angular-translate",
  3 + "description": "A translation module for AngularJS",
  4 + "version": "2.17.1",
  5 + "main": "./angular-translate.js",
  6 + "ignore": [],
  7 + "author": "Pascal Precht",
  8 + "license": "MIT",
  9 + "dependencies": {
  10 + "angular": ">=1.2.26 <1.7"
  11 + }
  12 +}
... ...