UNPKG

zettapi_client

Version:

Client side CRUD operations in angular to use with zettapi_server rest api to get started quickly in any CMS project

1,527 lines (1,406 loc) 127 kB
/*! * angular-translate - v2.13.0 - 2016-10-30 * * Copyright (c) 2016 The angular-translate team, Pascal Precht; Licensed MIT */ (function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module unless amdModuleId is set define([], function () { return (factory()); }); } else if (typeof exports === 'object') { // Node. Does not work with strict CommonJS, but // only CommonJS-like environments that support module.exports, // like Node. module.exports = factory(); } else { factory(); } }(this, function () { /** * @ngdoc overview * @name pascalprecht.translate * * @description * The main module which holds everything together. */ runTranslate.$inject = ['$translate']; $translate.$inject = ['$STORAGE_KEY', '$windowProvider', '$translateSanitizationProvider', 'pascalprechtTranslateOverrider']; $translateDefaultInterpolation.$inject = ['$interpolate', '$translateSanitization']; translateDirective.$inject = ['$translate', '$interpolate', '$compile', '$parse', '$rootScope']; translateAttrDirective.$inject = ['$translate', '$rootScope']; translateCloakDirective.$inject = ['$translate', '$rootScope']; translateFilterFactory.$inject = ['$parse', '$translate']; $translationCache.$inject = ['$cacheFactory']; angular.module('pascalprecht.translate', ['ng']) .run(runTranslate); function runTranslate($translate) { 'use strict'; var key = $translate.storageKey(), storage = $translate.storage(); var fallbackFromIncorrectStorageValue = function () { var preferred = $translate.preferredLanguage(); if (angular.isString(preferred)) { $translate.use(preferred); // $translate.use() will also remember the language. // So, we don't need to call storage.put() here. } else { storage.put(key, $translate.use()); } }; fallbackFromIncorrectStorageValue.displayName = 'fallbackFromIncorrectStorageValue'; if (storage) { if (!storage.get(key)) { fallbackFromIncorrectStorageValue(); } else { $translate.use(storage.get(key))['catch'](fallbackFromIncorrectStorageValue); } } else if (angular.isString($translate.preferredLanguage())) { $translate.use($translate.preferredLanguage()); } } runTranslate.displayName = 'runTranslate'; /** * @ngdoc object * @name pascalprecht.translate.$translateSanitizationProvider * * @description * * Configurations for $translateSanitization */ angular.module('pascalprecht.translate').provider('$translateSanitization', $translateSanitizationProvider); function $translateSanitizationProvider () { 'use strict'; var $sanitize, $sce, currentStrategy = null, // TODO change to either 'sanitize', 'escape' or ['sanitize', 'escapeParameters'] in 3.0. hasConfiguredStrategy = false, hasShownNoStrategyConfiguredWarning = false, strategies; /** * Definition of a sanitization strategy function * @callback StrategyFunction * @param {string|object} value - value to be sanitized (either a string or an interpolated value map) * @param {string} mode - either 'text' for a string (translation) or 'params' for the interpolated params * @return {string|object} */ /** * @ngdoc property * @name strategies * @propertyOf pascalprecht.translate.$translateSanitizationProvider * * @description * Following strategies are built-in: * <dl> * <dt>sanitize</dt> * <dd>Sanitizes HTML in the translation text using $sanitize</dd> * <dt>escape</dt> * <dd>Escapes HTML in the translation</dd> * <dt>sanitizeParameters</dt> * <dd>Sanitizes HTML in the values of the interpolation parameters using $sanitize</dd> * <dt>escapeParameters</dt> * <dd>Escapes HTML in the values of the interpolation parameters</dd> * <dt>escaped</dt> * <dd>Support legacy strategy name 'escaped' for backwards compatibility (will be removed in 3.0)</dd> * </dl> * */ strategies = { sanitize: function (value, mode/*, context*/) { if (mode === 'text') { value = htmlSanitizeValue(value); } return value; }, escape: function (value, mode/*, context*/) { if (mode === 'text') { value = htmlEscapeValue(value); } return value; }, sanitizeParameters: function (value, mode/*, context*/) { if (mode === 'params') { value = mapInterpolationParameters(value, htmlSanitizeValue); } return value; }, escapeParameters: function (value, mode/*, context*/) { if (mode === 'params') { value = mapInterpolationParameters(value, htmlEscapeValue); } return value; }, sce: function (value, mode, context) { if (mode === 'text') { value = htmlTrustValue(value); } else if (mode === 'params') { if (context !== 'filter') { // do html escape in filter context #1101 value = mapInterpolationParameters(value, htmlEscapeValue); } } return value; }, sceParameters: function (value, mode/*, context*/) { if (mode === 'params') { value = mapInterpolationParameters(value, htmlTrustValue); } return value; } }; // Support legacy strategy name 'escaped' for backwards compatibility. // TODO should be removed in 3.0 strategies.escaped = strategies.escapeParameters; /** * @ngdoc function * @name pascalprecht.translate.$translateSanitizationProvider#addStrategy * @methodOf pascalprecht.translate.$translateSanitizationProvider * * @description * Adds a sanitization strategy to the list of known strategies. * * @param {string} strategyName - unique key for a strategy * @param {StrategyFunction} strategyFunction - strategy function * @returns {object} this */ this.addStrategy = function (strategyName, strategyFunction) { strategies[strategyName] = strategyFunction; return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateSanitizationProvider#removeStrategy * @methodOf pascalprecht.translate.$translateSanitizationProvider * * @description * Removes a sanitization strategy from the list of known strategies. * * @param {string} strategyName - unique key for a strategy * @returns {object} this */ this.removeStrategy = function (strategyName) { delete strategies[strategyName]; return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateSanitizationProvider#useStrategy * @methodOf pascalprecht.translate.$translateSanitizationProvider * * @description * Selects a sanitization strategy. When an array is provided the strategies will be executed in order. * * @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. * @returns {object} this */ this.useStrategy = function (strategy) { hasConfiguredStrategy = true; currentStrategy = strategy; return this; }; /** * @ngdoc object * @name pascalprecht.translate.$translateSanitization * @requires $injector * @requires $log * * @description * Sanitizes interpolation parameters and translated texts. * */ this.$get = ['$injector', '$log', function ($injector, $log) { var cachedStrategyMap = {}; var applyStrategies = function (value, mode, context, selectedStrategies) { angular.forEach(selectedStrategies, function (selectedStrategy) { if (angular.isFunction(selectedStrategy)) { value = selectedStrategy(value, mode, context); } else if (angular.isFunction(strategies[selectedStrategy])) { value = strategies[selectedStrategy](value, mode, context); } else if (angular.isString(strategies[selectedStrategy])) { if (!cachedStrategyMap[strategies[selectedStrategy]]) { try { cachedStrategyMap[strategies[selectedStrategy]] = $injector.get(strategies[selectedStrategy]); } catch (e) { cachedStrategyMap[strategies[selectedStrategy]] = function() {}; throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \'' + selectedStrategy + '\''); } } value = cachedStrategyMap[strategies[selectedStrategy]](value, mode, context); } else { throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \'' + selectedStrategy + '\''); } }); return value; }; // TODO: should be removed in 3.0 var showNoStrategyConfiguredWarning = function () { if (!hasConfiguredStrategy && !hasShownNoStrategyConfiguredWarning) { $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.'); hasShownNoStrategyConfiguredWarning = true; } }; if ($injector.has('$sanitize')) { $sanitize = $injector.get('$sanitize'); } if ($injector.has('$sce')) { $sce = $injector.get('$sce'); } return { /** * @ngdoc function * @name pascalprecht.translate.$translateSanitization#useStrategy * @methodOf pascalprecht.translate.$translateSanitization * * @description * Selects a sanitization strategy. When an array is provided the strategies will be executed in order. * * @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. */ useStrategy: (function (self) { return function (strategy) { self.useStrategy(strategy); }; })(this), /** * @ngdoc function * @name pascalprecht.translate.$translateSanitization#sanitize * @methodOf pascalprecht.translate.$translateSanitization * * @description * Sanitizes a value. * * @param {string|object} value The value which should be sanitized. * @param {string} mode The current sanitization mode, either 'params' or 'text'. * @param {string|StrategyFunction|array} [strategy] Optional custom strategy which should be used instead of the currently selected strategy. * @param {string} [context] The context of this call: filter, service. Default is service * @returns {string|object} sanitized value */ sanitize: function (value, mode, strategy, context) { if (!currentStrategy) { showNoStrategyConfiguredWarning(); } if (!strategy && strategy !== null) { strategy = currentStrategy; } if (!strategy) { return value; } if (!context) { context = 'service'; } var selectedStrategies = angular.isArray(strategy) ? strategy : [strategy]; return applyStrategies(value, mode, context, selectedStrategies); } }; }]; var htmlEscapeValue = function (value) { var element = angular.element('<div></div>'); element.text(value); // not chainable, see #1044 return element.html(); }; var htmlSanitizeValue = function (value) { if (!$sanitize) { 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 $sanitize(value); }; var htmlTrustValue = function (value) { if (!$sce) { throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sce service.'); } return $sce.trustAsHtml(value); }; var mapInterpolationParameters = function (value, iteratee, stack) { if (angular.isDate(value)) { return value; } else if (angular.isObject(value)) { var result = angular.isArray(value) ? [] : {}; if (!stack) { stack = []; } else { if (stack.indexOf(value) > -1) { throw new Error('pascalprecht.translate.$translateSanitization: Error cannot interpolate parameter due recursive object'); } } stack.push(value); angular.forEach(value, function (propertyValue, propertyKey) { /* Skipping function properties. */ if (angular.isFunction(propertyValue)) { return; } result[propertyKey] = mapInterpolationParameters(propertyValue, iteratee, stack); }); stack.splice(-1, 1); // remove last return result; } else if (angular.isNumber(value)) { return value; } else { return iteratee(value); } }; } /** * @ngdoc object * @name pascalprecht.translate.$translateProvider * @description * * $translateProvider allows developers to register translation-tables, asynchronous loaders * and similar to configure translation behavior directly inside of a module. * */ angular.module('pascalprecht.translate') .constant('pascalprechtTranslateOverrider', {}) .provider('$translate', $translate); function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvider, pascalprechtTranslateOverrider) { 'use strict'; var $translationTable = {}, $preferredLanguage, $availableLanguageKeys = [], $languageKeyAliases, $fallbackLanguage, $fallbackWasString, $uses, $nextLang, $storageFactory, $storageKey = $STORAGE_KEY, $storagePrefix, $missingTranslationHandlerFactory, $interpolationFactory, $interpolatorFactories = [], $loaderFactory, $cloakClassName = 'translate-cloak', $loaderOptions, $notFoundIndicatorLeft, $notFoundIndicatorRight, $postCompilingEnabled = false, $forceAsyncReloadEnabled = false, $nestedObjectDelimeter = '.', $isReady = false, $keepContent = false, loaderCache, directivePriority = 0, statefulFilter = true, postProcessFn, uniformLanguageTagResolver = 'default', languageTagResolver = { 'default' : function (tag) { return (tag || '').split('-').join('_'); }, java : function (tag) { var temp = (tag || '').split('-').join('_'); var parts = temp.split('_'); return parts.length > 1 ? (parts[0].toLowerCase() + '_' + parts[1].toUpperCase()) : temp; }, bcp47 : function (tag) { var temp = (tag || '').split('_').join('-'); var parts = temp.split('-'); return parts.length > 1 ? (parts[0].toLowerCase() + '-' + parts[1].toUpperCase()) : temp; }, 'iso639-1' : function (tag) { var temp = (tag || '').split('_').join('-'); var parts = temp.split('-'); return parts[0].toLowerCase(); } }; var version = '2.13.0'; // tries to determine the browsers language var getFirstBrowserLanguage = function () { // internal purpose only if (angular.isFunction(pascalprechtTranslateOverrider.getLocale)) { return pascalprechtTranslateOverrider.getLocale(); } var nav = $windowProvider.$get().navigator, browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'], i, language; // support for HTML 5.1 "navigator.languages" if (angular.isArray(nav.languages)) { for (i = 0; i < nav.languages.length; i++) { language = nav.languages[i]; if (language && language.length) { return language; } } } // support for other well known properties in browsers for (i = 0; i < browserLanguagePropertyKeys.length; i++) { language = nav[browserLanguagePropertyKeys[i]]; if (language && language.length) { return language; } } return null; }; getFirstBrowserLanguage.displayName = 'angular-translate/service: getFirstBrowserLanguage'; // tries to determine the browsers locale var getLocale = function () { var locale = getFirstBrowserLanguage() || ''; if (languageTagResolver[uniformLanguageTagResolver]) { locale = languageTagResolver[uniformLanguageTagResolver](locale); } return locale; }; getLocale.displayName = 'angular-translate/service: getLocale'; /** * @name indexOf * @private * * @description * indexOf polyfill. Kinda sorta. * * @param {array} array Array to search in. * @param {string} searchElement Element to search for. * * @returns {int} Index of search element. */ var indexOf = function (array, searchElement) { for (var i = 0, len = array.length; i < len; i++) { if (array[i] === searchElement) { return i; } } return -1; }; /** * @name trim * @private * * @description * trim polyfill * * @returns {string} The string stripped of whitespace from both ends */ var trim = function () { return this.toString().replace(/^\s+|\s+$/g, ''); }; var negotiateLocale = function (preferred) { if (!preferred) { return; } var avail = [], locale = angular.lowercase(preferred), i = 0, n = $availableLanguageKeys.length; for (; i < n; i++) { avail.push(angular.lowercase($availableLanguageKeys[i])); } // Check for an exact match in our list of available keys if (indexOf(avail, locale) > -1) { return preferred; } if ($languageKeyAliases) { var alias; for (var langKeyAlias in $languageKeyAliases) { if ($languageKeyAliases.hasOwnProperty(langKeyAlias)) { var hasWildcardKey = false; var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) && angular.lowercase(langKeyAlias) === angular.lowercase(preferred); if (langKeyAlias.slice(-1) === '*') { hasWildcardKey = langKeyAlias.slice(0, -1) === preferred.slice(0, langKeyAlias.length - 1); } if (hasExactKey || hasWildcardKey) { alias = $languageKeyAliases[langKeyAlias]; if (indexOf(avail, angular.lowercase(alias)) > -1) { return alias; } } } } } // Check for a language code without region var parts = preferred.split('_'); if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) { return parts[0]; } // If everything fails, return undefined. return; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#translations * @methodOf pascalprecht.translate.$translateProvider * * @description * Registers a new translation table for specific language key. * * To register a translation table for specific language, pass a defined language * key as first parameter. * * <pre> * // register translation table for language: 'de_DE' * $translateProvider.translations('de_DE', { * 'GREETING': 'Hallo Welt!' * }); * * // register another one * $translateProvider.translations('en_US', { * 'GREETING': 'Hello world!' * }); * </pre> * * When registering multiple translation tables for for the same language key, * the actual translation table gets extended. This allows you to define module * specific translation which only get added, once a specific module is loaded in * your app. * * Invoking this method with no arguments returns the translation table which was * registered with no language key. Invoking it with a language key returns the * related translation table. * * @param {string} langKey A language key. * @param {object} translationTable A plain old JavaScript object that represents a translation table. * */ var translations = function (langKey, translationTable) { if (!langKey && !translationTable) { return $translationTable; } if (langKey && !translationTable) { if (angular.isString(langKey)) { return $translationTable[langKey]; } } else { if (!angular.isObject($translationTable[langKey])) { $translationTable[langKey] = {}; } angular.extend($translationTable[langKey], flatObject(translationTable)); } return this; }; this.translations = translations; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#cloakClassName * @methodOf pascalprecht.translate.$translateProvider * * @description * * Let's you change the class name for `translate-cloak` directive. * Default class name is `translate-cloak`. * * @param {string} name translate-cloak class name */ this.cloakClassName = function (name) { if (!name) { return $cloakClassName; } $cloakClassName = name; return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#nestedObjectDelimeter * @methodOf pascalprecht.translate.$translateProvider * * @description * * Let's you change the delimiter for namespaced translations. * Default delimiter is `.`. * * @param {string} delimiter namespace separator */ this.nestedObjectDelimeter = function (delimiter) { if (!delimiter) { return $nestedObjectDelimeter; } $nestedObjectDelimeter = delimiter; return this; }; /** * @name flatObject * @private * * @description * Flats an object. This function is used to flatten given translation data with * namespaces, so they are later accessible via dot notation. */ var flatObject = function (data, path, result, prevKey) { var key, keyWithPath, keyWithShortPath, val; if (!path) { path = []; } if (!result) { result = {}; } for (key in data) { if (!Object.prototype.hasOwnProperty.call(data, key)) { continue; } val = data[key]; if (angular.isObject(val)) { flatObject(val, path.concat(key), result, key); } else { keyWithPath = path.length ? ('' + path.join($nestedObjectDelimeter) + $nestedObjectDelimeter + key) : key; if (path.length && key === prevKey) { // Create shortcut path (foo.bar == foo.bar.bar) keyWithShortPath = '' + path.join($nestedObjectDelimeter); // Link it to original path result[keyWithShortPath] = '@:' + keyWithPath; } result[keyWithPath] = val; } } return result; }; flatObject.displayName = 'flatObject'; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#addInterpolation * @methodOf pascalprecht.translate.$translateProvider * * @description * Adds interpolation services to angular-translate, so it can manage them. * * @param {object} factory Interpolation service factory */ this.addInterpolation = function (factory) { $interpolatorFactories.push(factory); return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useMessageFormatInterpolation * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate to use interpolation functionality of messageformat.js. * This is useful when having high level pluralization and gender selection. */ this.useMessageFormatInterpolation = function () { return this.useInterpolation('$translateMessageFormatInterpolation'); }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useInterpolation * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate which interpolation style to use as default, application-wide. * Simply pass a factory/service name. The interpolation service has to implement * the correct interface. * * @param {string} factory Interpolation service name. */ this.useInterpolation = function (factory) { $interpolationFactory = factory; return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useSanitizeStrategy * @methodOf pascalprecht.translate.$translateProvider * * @description * Simply sets a sanitation strategy type. * * @param {string} value Strategy type. */ this.useSanitizeValueStrategy = function (value) { $translateSanitizationProvider.useStrategy(value); return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#preferredLanguage * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells the module which of the registered translation tables to use for translation * at initial startup by passing a language key. Similar to `$translateProvider#use` * only that it says which language to **prefer**. * * @param {string} langKey A language key. */ this.preferredLanguage = function (langKey) { if (langKey) { setupPreferredLanguage(langKey); return this; } return $preferredLanguage; }; var setupPreferredLanguage = function (langKey) { if (langKey) { $preferredLanguage = langKey; } return $preferredLanguage; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicator * @methodOf pascalprecht.translate.$translateProvider * * @description * Sets an indicator which is used when a translation isn't found. E.g. when * setting the indicator as 'X' and one tries to translate a translation id * called `NOT_FOUND`, this will result in `X NOT_FOUND X`. * * Internally this methods sets a left indicator and a right indicator using * `$translateProvider.translationNotFoundIndicatorLeft()` and * `$translateProvider.translationNotFoundIndicatorRight()`. * * **Note**: These methods automatically add a whitespace between the indicators * and the translation id. * * @param {string} indicator An indicator, could be any string. */ this.translationNotFoundIndicator = function (indicator) { this.translationNotFoundIndicatorLeft(indicator); this.translationNotFoundIndicatorRight(indicator); return this; }; /** * ngdoc function * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft * @methodOf pascalprecht.translate.$translateProvider * * @description * Sets an indicator which is used when a translation isn't found left to the * translation id. * * @param {string} indicator An indicator. */ this.translationNotFoundIndicatorLeft = function (indicator) { if (!indicator) { return $notFoundIndicatorLeft; } $notFoundIndicatorLeft = indicator; return this; }; /** * ngdoc function * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft * @methodOf pascalprecht.translate.$translateProvider * * @description * Sets an indicator which is used when a translation isn't found right to the * translation id. * * @param {string} indicator An indicator. */ this.translationNotFoundIndicatorRight = function (indicator) { if (!indicator) { return $notFoundIndicatorRight; } $notFoundIndicatorRight = indicator; return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#fallbackLanguage * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells the module which of the registered translation tables to use when missing translations * at initial startup by passing a language key. Similar to `$translateProvider#use` * only that it says which language to **fallback**. * * @param {string||array} langKey A language key. * */ this.fallbackLanguage = function (langKey) { fallbackStack(langKey); return this; }; var fallbackStack = function (langKey) { if (langKey) { if (angular.isString(langKey)) { $fallbackWasString = true; $fallbackLanguage = [langKey]; } else if (angular.isArray(langKey)) { $fallbackWasString = false; $fallbackLanguage = langKey; } if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) { $fallbackLanguage.push($preferredLanguage); } return this; } else { if ($fallbackWasString) { return $fallbackLanguage[0]; } else { return $fallbackLanguage; } } }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#use * @methodOf pascalprecht.translate.$translateProvider * * @description * Set which translation table to use for translation by given language key. When * trying to 'use' a language which isn't provided, it'll throw an error. * * You actually don't have to use this method since `$translateProvider#preferredLanguage` * does the job too. * * @param {string} langKey A language key. */ this.use = function (langKey) { if (langKey) { if (!$translationTable[langKey] && (!$loaderFactory)) { // only throw an error, when not loading translation data asynchronously throw new Error('$translateProvider couldn\'t find translationTable for langKey: \'' + langKey + '\''); } $uses = langKey; return this; } return $uses; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#resolveClientLocale * @methodOf pascalprecht.translate.$translateProvider * * @description * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver. * * @returns {string} the current client/browser language key */ this.resolveClientLocale = function () { return getLocale(); }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#storageKey * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells the module which key must represent the choosed language by a user in the storage. * * @param {string} key A key for the storage. */ var storageKey = function (key) { if (!key) { if ($storagePrefix) { return $storagePrefix + $storageKey; } return $storageKey; } $storageKey = key; return this; }; this.storageKey = storageKey; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useUrlLoader * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate to use `$translateUrlLoader` extension service as loader. * * @param {string} url Url * @param {Object=} options Optional configuration object */ this.useUrlLoader = function (url, options) { return this.useLoader('$translateUrlLoader', angular.extend({url : url}, options)); }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useStaticFilesLoader * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate to use `$translateStaticFilesLoader` extension service as loader. * * @param {Object=} options Optional configuration object */ this.useStaticFilesLoader = function (options) { return this.useLoader('$translateStaticFilesLoader', options); }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useLoader * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate to use any other service as loader. * * @param {string} loaderFactory Factory name to use * @param {Object=} options Optional configuration object */ this.useLoader = function (loaderFactory, options) { $loaderFactory = loaderFactory; $loaderOptions = options || {}; return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useLocalStorage * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate to use `$translateLocalStorage` service as storage layer. * */ this.useLocalStorage = function () { return this.useStorage('$translateLocalStorage'); }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useCookieStorage * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate to use `$translateCookieStorage` service as storage layer. */ this.useCookieStorage = function () { return this.useStorage('$translateCookieStorage'); }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useStorage * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate to use custom service as storage layer. */ this.useStorage = function (storageFactory) { $storageFactory = storageFactory; return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#storagePrefix * @methodOf pascalprecht.translate.$translateProvider * * @description * Sets prefix for storage key. * * @param {string} prefix Storage key prefix */ this.storagePrefix = function (prefix) { if (!prefix) { return prefix; } $storagePrefix = prefix; return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandlerLog * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate to use built-in log handler when trying to translate * a translation Id which doesn't exist. * * This is actually a shortcut method for `useMissingTranslationHandler()`. * */ this.useMissingTranslationHandlerLog = function () { return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog'); }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandler * @methodOf pascalprecht.translate.$translateProvider * * @description * Expects a factory name which later gets instantiated with `$injector`. * This method can be used to tell angular-translate to use a custom * missingTranslationHandler. Just build a factory which returns a function * and expects a translation id as argument. * * Example: * <pre> * app.config(function ($translateProvider) { * $translateProvider.useMissingTranslationHandler('customHandler'); * }); * * app.factory('customHandler', function (dep1, dep2) { * return function (translationId) { * // something with translationId and dep1 and dep2 * }; * }); * </pre> * * @param {string} factory Factory name */ this.useMissingTranslationHandler = function (factory) { $missingTranslationHandlerFactory = factory; return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#usePostCompiling * @methodOf pascalprecht.translate.$translateProvider * * @description * If post compiling is enabled, all translated values will be processed * again with AngularJS' $compile. * * Example: * <pre> * app.config(function ($translateProvider) { * $translateProvider.usePostCompiling(true); * }); * </pre> * * @param {string} factory Factory name */ this.usePostCompiling = function (value) { $postCompilingEnabled = !(!value); return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#forceAsyncReload * @methodOf pascalprecht.translate.$translateProvider * * @description * If force async reload is enabled, async loader will always be called * even if $translationTable already contains the language key, adding * possible new entries to the $translationTable. * * Example: * <pre> * app.config(function ($translateProvider) { * $translateProvider.forceAsyncReload(true); * }); * </pre> * * @param {boolean} value - valid values are true or false */ this.forceAsyncReload = function (value) { $forceAsyncReloadEnabled = !(!value); return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#uniformLanguageTag * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate which language tag should be used as a result when determining * the current browser language. * * This setting must be set before invoking {@link pascalprecht.translate.$translateProvider#methods_determinePreferredLanguage determinePreferredLanguage()}. * * <pre> * $translateProvider * .uniformLanguageTag('bcp47') * .determinePreferredLanguage() * </pre> * * The resolver currently supports: * * default * (traditionally: hyphens will be converted into underscores, i.e. en-US => en_US) * en-US => en_US * en_US => en_US * en-us => en_us * * java * like default, but the second part will be always in uppercase * en-US => en_US * en_US => en_US * en-us => en_US * * BCP 47 (RFC 4646 & 4647) * en-US => en-US * en_US => en-US * en-us => en-US * * See also: * * http://en.wikipedia.org/wiki/IETF_language_tag * * http://www.w3.org/International/core/langtags/ * * http://tools.ietf.org/html/bcp47 * * @param {string|object} options - options (or standard) * @param {string} options.standard - valid values are 'default', 'bcp47', 'java' */ this.uniformLanguageTag = function (options) { if (!options) { options = {}; } else if (angular.isString(options)) { options = { standard : options }; } uniformLanguageTagResolver = options.standard; return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#determinePreferredLanguage * @methodOf pascalprecht.translate.$translateProvider * * @description * Tells angular-translate to try to determine on its own which language key * to set as preferred language. When `fn` is given, angular-translate uses it * to determine a language key, otherwise it uses the built-in `getLocale()` * method. * * The `getLocale()` returns a language key in the format `[lang]_[country]` or * `[lang]` depending on what the browser provides. * * Use this method at your own risk, since not all browsers return a valid * locale (see {@link pascalprecht.translate.$translateProvider#methods_uniformLanguageTag uniformLanguageTag()}). * * @param {Function=} fn Function to determine a browser's locale */ this.determinePreferredLanguage = function (fn) { var locale = (fn && angular.isFunction(fn)) ? fn() : getLocale(); if (!$availableLanguageKeys.length) { $preferredLanguage = locale; } else { $preferredLanguage = negotiateLocale(locale) || locale; } return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#registerAvailableLanguageKeys * @methodOf pascalprecht.translate.$translateProvider * * @description * Registers a set of language keys the app will work with. Use this method in * combination with * {@link pascalprecht.translate.$translateProvider#determinePreferredLanguage determinePreferredLanguage}. * When available languages keys are registered, angular-translate * tries to find the best fitting language key depending on the browsers locale, * considering your language key convention. * * @param {object} languageKeys Array of language keys the your app will use * @param {object=} aliases Alias map. */ this.registerAvailableLanguageKeys = function (languageKeys, aliases) { if (languageKeys) { $availableLanguageKeys = languageKeys; if (aliases) { $languageKeyAliases = aliases; } return this; } return $availableLanguageKeys; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#useLoaderCache * @methodOf pascalprecht.translate.$translateProvider * * @description * Registers a cache for internal $http based loaders. * {@link pascalprecht.translate.$translationCache $translationCache}. * When false the cache will be disabled (default). When true or undefined * the cache will be a default (see $cacheFactory). When an object it will * be treat as a cache object itself: the usage is $http({cache: cache}) * * @param {object} cache boolean, string or cache-object */ this.useLoaderCache = function (cache) { if (cache === false) { // disable cache loaderCache = undefined; } else if (cache === true) { // enable cache using AJS defaults loaderCache = true; } else if (typeof(cache) === 'undefined') { // enable cache using default loaderCache = '$translationCache'; } else if (cache) { // enable cache using given one (see $cacheFactory) loaderCache = cache; } return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#directivePriority * @methodOf pascalprecht.translate.$translateProvider * * @description * Sets the default priority of the translate directive. The standard value is `0`. * Calling this function without an argument will return the current value. * * @param {number} priority for the translate-directive */ this.directivePriority = function (priority) { if (priority === undefined) { // getter return directivePriority; } else { // setter with chaining directivePriority = priority; return this; } }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#statefulFilter * @methodOf pascalprecht.translate.$translateProvider * * @description * Since AngularJS 1.3, filters which are not stateless (depending at the scope) * have to explicit define this behavior. * Sets whether the translate filter should be stateful or stateless. The standard value is `true` * meaning being stateful. * Calling this function without an argument will return the current value. * * @param {boolean} state - defines the state of the filter */ this.statefulFilter = function (state) { if (state === undefined) { // getter return statefulFilter; } else { // setter with chaining statefulFilter = state; return this; } }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#postProcess * @methodOf pascalprecht.translate.$translateProvider * * @description * The post processor will be intercept right after the translation result. It can modify the result. * * @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 */ this.postProcess = function (fn) { if (fn) { postProcessFn = fn; } else { postProcessFn = undefined; } return this; }; /** * @ngdoc function * @name pascalprecht.translate.$translateProvider#keepContent * @methodOf pascalprecht.translate.$translateProvider * * @description * If keepContent is set to true than translate directive will always use innerHTML * as a default translation * * Example: * <pre> * app.config(function ($translateProvider) { * $translateProvider.keepContent(true); * }); * </pre> * * @param {boolean} value - valid values are true or false */ this.keepContent = function (value) { $keepContent = !(!value); return this; }; /** * @ngdoc object * @name pascalprecht.translate.$translate * @requires $interpolate * @requires $log * @requires $rootScope * @requires $q * * @description * The `$translate` service is the actual core of angular-translate. It expects a translation id * and optional interpolate parameters to translate contents. * * <pre> * $translate('HEADLINE_TEXT').then(function (translation) { * $scope.translatedText = translation; * }); * </pre> * * @param {string|array} translationId A token which represents a translation id * This can be optionally an array of translation ids which * results that the function returns an object where each key * is the translation id and the value the translation. * @param {object=} interpolateParams An object hash for dynamic values * @param {string} interpolationId The id of the interpolation to use * @param {string} defaultTranslationText the optional default translation text that is written as * as default text in case it is not found in any configured language * @param {string} forceLanguage A language to be used instead of the current language * @returns {object} promise */ this.$get = ['$log', '$injector', '$rootScope', '$q', function ($log, $injector, $rootScope, $q) { var Storage, defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'), pendingLoader = false, interpolatorHashMap = {}, langPromises = {}, fallbackIndex, startFallbackIteration; var $translate = function (translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage) { if (!$uses && $preferredLanguage) { $uses = $preferredLanguage; } var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses (negotiateLocale(forceLanguage) || forceLanguage) : $uses; // Check forceLanguage is present if (forceLanguage) { loadTranslationsIfMissing(forceLanguage); } // Duck detection: If the first argument is an array, a bunch of translations was requested. // The result is an object. if (angular.isArray(translationId)) { // Inspired by Q.allSettled by Kris Kowal // https://github.com/kriskowal/q/blob/b0fa72980717dc202ffc3cbf03b936e10ebbb9d7/q.js#L1553-1563 // This transforms all promises regardless resolved or rejected var translateAll = function (translationIds) { var results = {}; // storing the actual results var promises = []; // promises to wait for // Wraps the promise a) being always resolved and b) storing the link id->value var translate = function (translationId) { var deferred = $q.defer(); var regardless = function (value) { results[translationId] = value; deferred.resolve([translationId, value]); }; // we don't care whether the promise was resolved or rejected; just store the values $translate(translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage).then(regardless, regardless); return deferred.promise; }; for (var i = 0, c = translationIds.length; i < c; i++) { promises.push(translate(translationIds[i])); } // wait for all (including storing to results) return $q.all(promises).then(function () { // return the results return results; }); }; return translateAll(translationId); } var deferred = $q.defer(); // trim off any whitespace if (translationId) { translationId = trim.apply(translationId); } var promiseToWaitFor = (function () { var promise = $preferredLanguage ? langPromises[$preferredLanguage] : langPromises[uses]; fallbackIndex = 0; if ($storageFactory && !promise) { // looks like there's no pending promise for $preferredLanguage or // $uses. Maybe there's one pending for a language that comes from // storage. var langKey = Storage.get($storageKey); promise = langPromises[langKey]; if ($fallbackLanguage && $fallbackLanguage.length) { var index = indexOf($fallbackLanguage, langKey); // maybe the language from storage is also defined as fallback language // we increase the fallback language index to not search in that language // as fallback, since it's probably the first used language // in that case the index starts after the first element fallbackIndex = (index === 0) ? 1 : 0; // but we can make sure to ALWAYS fallback to preferred language at least if (indexOf($fallbackLanguage, $preferredLanguage) < 0) { $fallbackLanguage.push($preferredLanguage); } } } return promise; }()); if (!promiseToWaitFor) { // no promise to wait for? okay. Then there's no loader registered // nor is a one pending for language that comes from storage. // We can just translate. determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject); } else { var promiseResolved