12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360 |
- /*!
- * angular-translate - v2.6.1 - 2015-03-01
- * http://github.com/angular-translate/angular-translate
- * Copyright (c) 2015 ; Licensed MIT
- */
- /**
- * @ngdoc overview
- * @name pascalprecht.translate
- *
- * @description
- * The main module which holds everything together.
- */
- angular.module('pascalprecht.translate', ['ng'])
- .run(['$translate', function ($translate) {
- 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());
- }
- };
- 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());
- }
- }]);
- /**
- * @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').provider('$translate', ['$STORAGE_KEY', '$windowProvider', function ($STORAGE_KEY, $windowProvider) {
- var $translationTable = {},
- $preferredLanguage,
- $availableLanguageKeys = [],
- $languageKeyAliases,
- $fallbackLanguage,
- $fallbackWasString,
- $uses,
- $nextLang,
- $storageFactory,
- $storageKey = $STORAGE_KEY,
- $storagePrefix,
- $missingTranslationHandlerFactory,
- $interpolationFactory,
- $interpolatorFactories = [],
- $interpolationSanitizationStrategy = false,
- $loaderFactory,
- $cloakClassName = 'translate-cloak',
- $loaderOptions,
- $notFoundIndicatorLeft,
- $notFoundIndicatorRight,
- $postCompilingEnabled = false,
- NESTED_OBJECT_DELIMITER = '.',
- loaderCache,
- directivePriority = 0;
- var version = '2.6.1';
- // tries to determine the browsers language
- var getFirstBrowserLanguage = function () {
- 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 () {
- return (getFirstBrowserLanguage() || '').split('-').join('_');
- };
- 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.replace(/^\s+|\s+$/g, '');
- };
- var negotiateLocale = function (preferred) {
- var avail = [],
- locale = angular.lowercase(preferred),
- i = 0,
- n = $availableLanguageKeys.length;
- for (; i < n; i++) {
- avail.push(angular.lowercase($availableLanguageKeys[i]));
- }
- if (indexOf(avail, locale) > -1) {
- return preferred;
- }
- if ($languageKeyAliases) {
- var alias;
- for (var langKeyAlias in $languageKeyAliases) {
- 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;
- }
- }
- }
- }
- var parts = preferred.split('_');
- if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) {
- return parts[0];
- }
- // If everything fails, just return the preferred, unchanged.
- return preferred;
- };
- /**
- * @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} key 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;
- };
- /**
- * @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(NESTED_OBJECT_DELIMITER) + NESTED_OBJECT_DELIMITER + key) : key;
- if(path.length && key === prevKey){
- // Create shortcut path (foo.bar == foo.bar.bar)
- keyWithShortPath = '' + path.join(NESTED_OBJECT_DELIMITER);
- // Link it to original path
- result[keyWithShortPath] = '@:' + keyWithPath;
- }
- result[keyWithPath] = val;
- }
- }
- return result;
- };
- /**
- * @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) {
- $interpolationSanitizationStrategy = 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) {
- setupPreferredLanguage(langKey);
- return this;
- };
- 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#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;
- };
- 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#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.
- *
- * @param {object=} 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);
- }
- 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.$translateProvider#determinePreferredLanguage determinePreferredLanguage}.
- * 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 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
- * @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) {
- // 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).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).then(deferred.resolve, deferred.reject);
- } else {
- promiseToWaitFor.then(function () {
- determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText).then(deferred.resolve, deferred.reject);
- }, deferred.reject);
- }
- return deferred.promise;
- };
- /**
- * @name applyNotFoundIndicators
- * @private
- *
- * @description
- * Applies not fount indicators to given translation id, if needed.
- * This function gets only executed, if a translation id doesn't exist,
- * which is why a translation id is expected as argument.
- *
- * @param {string} translationId Translation id.
- * @returns {string} Same as given translation id but applied with not found
- * indicators.
- */
- var applyNotFoundIndicators = function (translationId) {
- // applying notFoundIndicators
- if ($notFoundIndicatorLeft) {
- translationId = [$notFoundIndicatorLeft, translationId].join(' ');
- }
- if ($notFoundIndicatorRight) {
- translationId = [translationId, $notFoundIndicatorRight].join(' ');
- }
- return translationId;
- };
- /**
- * @name useLanguage
- * @private
- *
- * @description
- * Makes actual use of a language by setting a given language key as used
- * language and informs registered interpolators to also use the given
- * key as locale.
- *
- * @param {key} Locale key.
- */
- var useLanguage = function (key) {
- $uses = key;
- $rootScope.$emit('$translateChangeSuccess', {language: key});
- if ($storageFactory) {
- Storage.put($translate.storageKey(), $uses);
- }
- // inform default interpolator
- defaultInterpolator.setLocale($uses);
- // inform all others too!
- angular.forEach(interpolatorHashMap, function (interpolator, id) {
- interpolatorHashMap[id].setLocale($uses);
- });
- $rootScope.$emit('$translateChangeEnd', {language: key});
- };
- /**
- * @name loadAsync
- * @private
- *
- * @description
- * Kicks of registered async loader using `$injector` and applies existing
- * loader options. When resolved, it updates translation tables accordingly
- * or rejects with given language key.
- *
- * @param {string} key Language key.
- * @return {Promise} A promise.
- */
- var loadAsync = function (key) {
- if (!key) {
- throw 'No language key specified for loading.';
- }
- var deferred = $q.defer();
- $rootScope.$emit('$translateLoadingStart', {language: key});
- pendingLoader = true;
- var cache = loaderCache;
- if (typeof(cache) === 'string') {
- // getting on-demand instance of loader
- cache = $injector.get(cache);
- }
- var loaderOptions = angular.extend({}, $loaderOptions, {
- key: key,
- $http: angular.extend({}, {
- cache: cache
- }, $loaderOptions.$http)
- });
- $injector.get($loaderFactory)(loaderOptions).then(function (data) {
- var translationTable = {};
- $rootScope.$emit('$translateLoadingSuccess', {language: key});
- if (angular.isArray(data)) {
- angular.forEach(data, function (table) {
- angular.extend(translationTable, flatObject(table));
- });
- } else {
- angular.extend(translationTable, flatObject(data));
- }
- pendingLoader = false;
- deferred.resolve({
- key: key,
- table: translationTable
- });
- $rootScope.$emit('$translateLoadingEnd', {language: key});
- }, function (key) {
- $rootScope.$emit('$translateLoadingError', {language: key});
- deferred.reject(key);
- $rootScope.$emit('$translateLoadingEnd', {language: key});
- });
- return deferred.promise;
- };
- if ($storageFactory) {
- Storage = $injector.get($storageFactory);
- if (!Storage.get || !Storage.put) {
- throw new Error('Couldn\'t use storage \'' + $storageFactory + '\', missing get() or put() method!');
- }
- }
- // apply additional settings
- if (angular.isFunction(defaultInterpolator.useSanitizeValueStrategy)) {
- defaultInterpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy);
- }
- // if we have additional interpolations that were added via
- // $translateProvider.addInterpolation(), we have to map'em
- if ($interpolatorFactories.length) {
- angular.forEach($interpolatorFactories, function (interpolatorFactory) {
- var interpolator = $injector.get(interpolatorFactory);
- // setting initial locale for each interpolation service
- interpolator.setLocale($preferredLanguage || $uses);
- // apply additional settings
- if (angular.isFunction(interpolator.useSanitizeValueStrategy)) {
- interpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy);
- }
- // make'em recognizable through id
- interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;
- });
- }
- /**
- * @name getTranslationTable
- * @private
- *
- * @description
- * Returns a promise that resolves to the translation table
- * or is rejected if an error occurred.
- *
- * @param langKey
- * @returns {Q.promise}
- */
- var getTranslationTable = function (langKey) {
- var deferred = $q.defer();
- if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) {
- deferred.resolve($translationTable[langKey]);
- } else if (langPromises[langKey]) {
- langPromises[langKey].then(function (data) {
- translations(data.key, data.table);
- deferred.resolve(data.table);
- }, deferred.reject);
- } else {
- deferred.reject();
- }
- return deferred.promise;
- };
- /**
- * @name getFallbackTranslation
- * @private
- *
- * @description
- * Returns a promise that will resolve to the translation
- * or be rejected if no translation was found for the language.
- * This function is currently only used for fallback language translation.
- *
- * @param langKey The language to translate to.
- * @param translationId
- * @param interpolateParams
- * @param Interpolator
- * @returns {Q.promise}
- */
- var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator) {
- var deferred = $q.defer();
- getTranslationTable(langKey).then(function (translationTable) {
- if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) {
- Interpolator.setLocale(langKey);
- var translation = translationTable[translationId];
- if (translation.substr(0, 2) === '@:') {
- getFallbackTranslation(langKey, translation.substr(2), interpolateParams, Interpolator)
- .then(deferred.resolve, deferred.reject);
- } else {
- deferred.resolve(Interpolator.interpolate(translationTable[translationId], interpolateParams));
- }
- Interpolator.setLocale($uses);
- } else {
- deferred.reject();
- }
- }, deferred.reject);
- return deferred.promise;
- };
- /**
- * @name getFallbackTranslationInstant
- * @private
- *
- * @description
- * Returns a translation
- * This function is currently only used for fallback language translation.
- *
- * @param langKey The language to translate to.
- * @param translationId
- * @param interpolateParams
- * @param Interpolator
- * @returns {string} translation
- */
- var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator) {
- var result, translationTable = $translationTable[langKey];
- if (translationTable && Object.prototype.hasOwnProperty.call(translationTable, translationId)) {
- Interpolator.setLocale(langKey);
- result = Interpolator.interpolate(translationTable[translationId], interpolateParams);
- if (result.substr(0, 2) === '@:') {
- return getFallbackTranslationInstant(langKey, result.substr(2), interpolateParams, Interpolator);
- }
- Interpolator.setLocale($uses);
- }
- return result;
- };
- /**
- * @name translateByHandler
- * @private
- *
- * Translate by missing translation handler.
- *
- * @param translationId
- * @returns translation created by $missingTranslationHandler or translationId is $missingTranslationHandler is
- * absent
- */
- var translateByHandler = function (translationId) {
- // If we have a handler factory - we might also call it here to determine if it provides
- // a default text for a translationid that can't be found anywhere in our tables
- if ($missingTranslationHandlerFactory) {
- var resultString = $injector.get($missingTranslationHandlerFactory)(translationId, $uses);
- if (resultString !== undefined) {
- return resultString;
- } else {
- return translationId;
- }
- } else {
- return translationId;
- }
- };
- /**
- * @name resolveForFallbackLanguage
- * @private
- *
- * Recursive helper function for fallbackTranslation that will sequentially look
- * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.
- *
- * @param fallbackLanguageIndex
- * @param translationId
- * @param interpolateParams
- * @param Interpolator
- * @returns {Q.promise} Promise that will resolve to the translation.
- */
- var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, defaultTranslationText) {
- var deferred = $q.defer();
- if (fallbackLanguageIndex < $fallbackLanguage.length) {
- var langKey = $fallbackLanguage[fallbackLanguageIndex];
- getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator).then(
- deferred.resolve,
- function () {
- // Look in the next fallback language for a translation.
- // It delays the resolving by passing another promise to resolve.
- resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator, defaultTranslationText).then(deferred.resolve);
- }
- );
- } else {
- // No translation found in any fallback language
- // if a default translation text is set in the directive, then return this as a result
- if (defaultTranslationText) {
- deferred.resolve(defaultTranslationText);
- } else {
- // if no default translation is set and an error handler is defined, send it to the handler
- // and then return the result
- deferred.resolve(translateByHandler(translationId));
- }
- }
- return deferred.promise;
- };
- /**
- * @name resolveForFallbackLanguageInstant
- * @private
- *
- * Recursive helper function for fallbackTranslation that will sequentially look
- * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.
- *
- * @param fallbackLanguageIndex
- * @param translationId
- * @param interpolateParams
- * @param Interpolator
- * @returns {string} translation
- */
- var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) {
- var result;
- if (fallbackLanguageIndex < $fallbackLanguage.length) {
- var langKey = $fallbackLanguage[fallbackLanguageIndex];
- result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator);
- if (!result) {
- result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);
- }
- }
- return result;
- };
- /**
- * Translates with the usage of the fallback languages.
- *
- * @param translationId
- * @param interpolateParams
- * @param Interpolator
- * @returns {Q.promise} Promise, that resolves to the translation.
- */
- var fallbackTranslation = function (translationId, interpolateParams, Interpolator, defaultTranslationText) {
- // Start with the fallbackLanguage with index 0
- return resolveForFallbackLanguage((startFallbackIteration>0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, defaultTranslationText);
- };
- /**
- * Translates with the usage of the fallback languages.
- *
- * @param translationId
- * @param interpolateParams
- * @param Interpolator
- * @returns {String} translation
- */
- var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator) {
- // Start with the fallbackLanguage with index 0
- return resolveForFallbackLanguageInstant((startFallbackIteration>0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator);
- };
- var determineTranslation = function (translationId, interpolateParams, interpolationId, defaultTranslationText) {
- var deferred = $q.defer();
- var table = $uses ? $translationTable[$uses] : $translationTable,
- Interpolator = (interpolationId) ? interpolatorHashMap[interpolationId] : defaultInterpolator;
- // if the translation id exists, we can just interpolate it
- if (table && Object.prototype.hasOwnProperty.call(table, translationId)) {
- var translation = table[translationId];
- // If using link, rerun $translate with linked translationId and return it
- if (translation.substr(0, 2) === '@:') {
- $translate(translation.substr(2), interpolateParams, interpolationId, defaultTranslationText)
- .then(deferred.resolve, deferred.reject);
- } else {
- deferred.resolve(Interpolator.interpolate(translation, interpolateParams));
- }
- } else {
- var missingTranslationHandlerTranslation;
- // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise
- if ($missingTranslationHandlerFactory && !pendingLoader) {
- missingTranslationHandlerTranslation = translateByHandler(translationId);
- }
- // since we couldn't translate the inital requested translation id,
- // we try it now with one or more fallback languages, if fallback language(s) is
- // configured.
- if ($uses && $fallbackLanguage && $fallbackLanguage.length) {
- fallbackTranslation(translationId, interpolateParams, Interpolator, defaultTranslationText)
- .then(function (translation) {
- deferred.resolve(translation);
- }, function (_translationId) {
- deferred.reject(applyNotFoundIndicators(_translationId));
- });
- } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
- // looks like the requested translation id doesn't exists.
- // Now, if there is a registered handler for missing translations and no
- // asyncLoader is pending, we execute the handler
- if (defaultTranslationText) {
- deferred.resolve(defaultTranslationText);
- } else {
- deferred.resolve(missingTranslationHandlerTranslation);
- }
- } else {
- if (defaultTranslationText) {
- deferred.resolve(defaultTranslationText);
- } else {
- deferred.reject(applyNotFoundIndicators(translationId));
- }
- }
- }
- return deferred.promise;
- };
- var determineTranslationInstant = function (translationId, interpolateParams, interpolationId) {
- var result, table = $uses ? $translationTable[$uses] : $translationTable,
- Interpolator = defaultInterpolator;
- // if the interpolation id exists use custom interpolator
- if (interpolatorHashMap && Object.prototype.hasOwnProperty.call(interpolatorHashMap, interpolationId)) {
- Interpolator = interpolatorHashMap[interpolationId];
- }
- // if the translation id exists, we can just interpolate it
- if (table && Object.prototype.hasOwnProperty.call(table, translationId)) {
- var translation = table[translationId];
- // If using link, rerun $translate with linked translationId and return it
- if (translation.substr(0, 2) === '@:') {
- result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId);
- } else {
- result = Interpolator.interpolate(translation, interpolateParams);
- }
- } else {
- var missingTranslationHandlerTranslation;
- // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise
- if ($missingTranslationHandlerFactory && !pendingLoader) {
- missingTranslationHandlerTranslation = translateByHandler(translationId);
- }
- // since we couldn't translate the inital requested translation id,
- // we try it now with one or more fallback languages, if fallback language(s) is
- // configured.
- if ($uses && $fallbackLanguage && $fallbackLanguage.length) {
- fallbackIndex = 0;
- result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator);
- } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
- // looks like the requested translation id doesn't exists.
- // Now, if there is a registered handler for missing translations and no
- // asyncLoader is pending, we execute the handler
- result = missingTranslationHandlerTranslation;
- } else {
- result = applyNotFoundIndicators(translationId);
- }
- }
- return result;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#preferredLanguage
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Returns the language key for the preferred language.
- *
- * @param {string} langKey language String or Array to be used as preferredLanguage (changing at runtime)
- *
- * @return {string} preferred language key
- */
- $translate.preferredLanguage = function (langKey) {
- if(langKey) {
- setupPreferredLanguage(langKey);
- }
- return $preferredLanguage;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#cloakClassName
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Returns the configured class name for `translate-cloak` directive.
- *
- * @return {string} cloakClassName
- */
- $translate.cloakClassName = function () {
- return $cloakClassName;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#fallbackLanguage
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Returns the language key for the fallback languages or sets a new fallback stack.
- *
- * @param {string=} langKey language String or Array of fallback languages to be used (to change stack at runtime)
- *
- * @return {string||array} fallback language key
- */
- $translate.fallbackLanguage = function (langKey) {
- if (langKey !== undefined && langKey !== null) {
- fallbackStack(langKey);
- // as we might have an async loader initiated and a new translation language might have been defined
- // we need to add the promise to the stack also. So - iterate.
- if ($loaderFactory) {
- if ($fallbackLanguage && $fallbackLanguage.length) {
- for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {
- if (!langPromises[$fallbackLanguage[i]]) {
- langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]);
- }
- }
- }
- }
- $translate.use($translate.use());
- }
- if ($fallbackWasString) {
- return $fallbackLanguage[0];
- } else {
- return $fallbackLanguage;
- }
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#useFallbackLanguage
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Sets the first key of the fallback language stack to be used for translation.
- * Therefore all languages in the fallback array BEFORE this key will be skipped!
- *
- * @param {string=} langKey Contains the langKey the iteration shall start with. Set to false if you want to
- * get back to the whole stack
- */
- $translate.useFallbackLanguage = function (langKey) {
- if (langKey !== undefined && langKey !== null) {
- if (!langKey) {
- startFallbackIteration = 0;
- } else {
- var langKeyPosition = indexOf($fallbackLanguage, langKey);
- if (langKeyPosition > -1) {
- startFallbackIteration = langKeyPosition;
- }
- }
- }
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#proposedLanguage
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Returns the language key of language that is currently loaded asynchronously.
- *
- * @return {string} language key
- */
- $translate.proposedLanguage = function () {
- return $nextLang;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#storage
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Returns registered storage.
- *
- * @return {object} Storage
- */
- $translate.storage = function () {
- return Storage;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#use
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Tells angular-translate which language to use by given language key. This method is
- * used to change language at runtime. It also takes care of storing the language
- * key in a configured store to let your app remember the choosed language.
- *
- * When trying to 'use' a language which isn't available it tries to load it
- * asynchronously with registered loaders.
- *
- * Returns promise object with loaded language file data
- * @example
- * $translate.use("en_US").then(function(data){
- * $scope.text = $translate("HELLO");
- * });
- *
- * @param {string} key Language key
- * @return {string} Language key
- */
- $translate.use = function (key) {
- if (!key) {
- return $uses;
- }
- var deferred = $q.defer();
- $rootScope.$emit('$translateChangeStart', {language: key});
- // Try to get the aliased language key
- var aliasedKey = negotiateLocale(key);
- if (aliasedKey) {
- key = aliasedKey;
- }
- // if there isn't a translation table for the language we've requested,
- // we load it asynchronously
- if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {
- $nextLang = key;
- langPromises[key] = loadAsync(key).then(function (translation) {
- translations(translation.key, translation.table);
- deferred.resolve(translation.key);
- useLanguage(translation.key);
- if ($nextLang === key) {
- $nextLang = undefined;
- }
- return translation;
- }, function (key) {
- if ($nextLang === key) {
- $nextLang = undefined;
- }
- $rootScope.$emit('$translateChangeError', {language: key});
- deferred.reject(key);
- $rootScope.$emit('$translateChangeEnd', {language: key});
- });
- } else {
- deferred.resolve(key);
- useLanguage(key);
- }
- return deferred.promise;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#storageKey
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Returns the key for the storage.
- *
- * @return {string} storage key
- */
- $translate.storageKey = function () {
- return storageKey();
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#isPostCompilingEnabled
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Returns whether post compiling is enabled or not
- *
- * @return {bool} storage key
- */
- $translate.isPostCompilingEnabled = function () {
- return $postCompilingEnabled;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#refresh
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Refreshes a translation table pointed by the given langKey. If langKey is not specified,
- * the module will drop all existent translation tables and load new version of those which
- * are currently in use.
- *
- * Refresh means that the module will drop target translation table and try to load it again.
- *
- * In case there are no loaders registered the refresh() method will throw an Error.
- *
- * If the module is able to refresh translation tables refresh() method will broadcast
- * $translateRefreshStart and $translateRefreshEnd events.
- *
- * @example
- * // this will drop all currently existent translation tables and reload those which are
- * // currently in use
- * $translate.refresh();
- * // this will refresh a translation table for the en_US language
- * $translate.refresh('en_US');
- *
- * @param {string} langKey A language key of the table, which has to be refreshed
- *
- * @return {promise} Promise, which will be resolved in case a translation tables refreshing
- * process is finished successfully, and reject if not.
- */
- $translate.refresh = function (langKey) {
- if (!$loaderFactory) {
- throw new Error('Couldn\'t refresh translation table, no loader registered!');
- }
- var deferred = $q.defer();
- function resolve() {
- deferred.resolve();
- $rootScope.$emit('$translateRefreshEnd', {language: langKey});
- }
- function reject() {
- deferred.reject();
- $rootScope.$emit('$translateRefreshEnd', {language: langKey});
- }
- $rootScope.$emit('$translateRefreshStart', {language: langKey});
- if (!langKey) {
- // if there's no language key specified we refresh ALL THE THINGS!
- var tables = [], loadingKeys = {};
- // reload registered fallback languages
- if ($fallbackLanguage && $fallbackLanguage.length) {
- for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {
- tables.push(loadAsync($fallbackLanguage[i]));
- loadingKeys[$fallbackLanguage[i]] = true;
- }
- }
- // reload currently used language
- if ($uses && !loadingKeys[$uses]) {
- tables.push(loadAsync($uses));
- }
- $q.all(tables).then(function (tableData) {
- angular.forEach(tableData, function (data) {
- if ($translationTable[data.key]) {
- delete $translationTable[data.key];
- }
- translations(data.key, data.table);
- });
- if ($uses) {
- useLanguage($uses);
- }
- resolve();
- });
- } else if ($translationTable[langKey]) {
- loadAsync(langKey).then(function (data) {
- translations(data.key, data.table);
- if (langKey === $uses) {
- useLanguage($uses);
- }
- resolve();
- }, reject);
- } else {
- reject();
- }
- return deferred.promise;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#instant
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Returns a translation instantly from the internal state of loaded translation. All rules
- * regarding the current language, the preferred language of even fallback languages will be
- * used except any promise handling. If a language was not found, an asynchronous loading
- * will be invoked in the background.
- *
- * @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's promise returns an object where
- * each key is the translation id and the value the translation.
- * @param {object} interpolateParams Params
- * @param {string} interpolationId The id of the interpolation to use
- *
- * @return {string} translation
- */
- $translate.instant = function (translationId, interpolateParams, interpolationId) {
- // Detect undefined and null values to shorten the execution and prevent exceptions
- if (translationId === null || angular.isUndefined(translationId)) {
- return translationId;
- }
- // Duck detection: If the first argument is an array, a bunch of translations was requested.
- // The result is an object.
- if (angular.isArray(translationId)) {
- var results = {};
- for (var i = 0, c = translationId.length; i < c; i++) {
- results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId);
- }
- return results;
- }
- // We discarded unacceptable values. So we just need to verify if translationId is empty String
- if (angular.isString(translationId) && translationId.length < 1) {
- return translationId;
- }
- // trim off any whitespace
- if (translationId) {
- translationId = trim.apply(translationId);
- }
- var result, possibleLangKeys = [];
- if ($preferredLanguage) {
- possibleLangKeys.push($preferredLanguage);
- }
- if ($uses) {
- possibleLangKeys.push($uses);
- }
- if ($fallbackLanguage && $fallbackLanguage.length) {
- possibleLangKeys = possibleLangKeys.concat($fallbackLanguage);
- }
- for (var j = 0, d = possibleLangKeys.length; j < d; j++) {
- var possibleLangKey = possibleLangKeys[j];
- if ($translationTable[possibleLangKey]) {
- if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') {
- result = determineTranslationInstant(translationId, interpolateParams, interpolationId);
- } else if ($notFoundIndicatorLeft || $notFoundIndicatorRight) {
- result = applyNotFoundIndicators(translationId);
- }
- }
- if (typeof result !== 'undefined') {
- break;
- }
- }
- if (!result && result !== '') {
- // Return translation of default interpolator if not found anything.
- result = defaultInterpolator.interpolate(translationId, interpolateParams);
- if ($missingTranslationHandlerFactory && !pendingLoader) {
- result = translateByHandler(translationId);
- }
- }
- return result;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#versionInfo
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Returns the current version information for the angular-translate library
- *
- * @return {string} angular-translate version
- */
- $translate.versionInfo = function () {
- return version;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translate#loaderCache
- * @methodOf pascalprecht.translate.$translate
- *
- * @description
- * Returns the defined loaderCache.
- *
- * @return {boolean|string|object} current value of loaderCache
- */
- $translate.loaderCache = function () {
- return loaderCache;
- };
- // internal purpose only
- $translate.directivePriority = function () {
- return directivePriority;
- };
- if ($loaderFactory) {
- // If at least one async loader is defined and there are no
- // (default) translations available we should try to load them.
- if (angular.equals($translationTable, {})) {
- $translate.use($translate.use());
- }
- // Also, if there are any fallback language registered, we start
- // loading them asynchronously as soon as we can.
- if ($fallbackLanguage && $fallbackLanguage.length) {
- var processAsyncResult = function (translation) {
- translations(translation.key, translation.table);
- $rootScope.$emit('$translateChangeEnd', { language: translation.key });
- return translation;
- };
- for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {
- langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]).then(processAsyncResult);
- }
- }
- }
- return $translate;
- }
- ];
- }]);
- /**
- * @ngdoc object
- * @name pascalprecht.translate.$translateDefaultInterpolation
- * @requires $interpolate
- *
- * @description
- * Uses angular's `$interpolate` services to interpolate strings against some values.
- *
- * @return {object} $translateInterpolator Interpolator service
- */
- angular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', ['$interpolate', function ($interpolate) {
- var $translateInterpolator = {},
- $locale,
- $identifier = 'default',
- $sanitizeValueStrategy = null,
- // map of all sanitize strategies
- sanitizeValueStrategies = {
- escaped: function (params) {
- var result = {};
- for (var key in params) {
- if (Object.prototype.hasOwnProperty.call(params, key)) {
- if (angular.isNumber(params[key])) {
- result[key] = params[key];
- } else {
- result[key] = angular.element('<div></div>').text(params[key]).html();
- }
- }
- }
- return result;
- }
- };
- var sanitizeParams = function (params) {
- var result;
- if (angular.isFunction(sanitizeValueStrategies[$sanitizeValueStrategy])) {
- result = sanitizeValueStrategies[$sanitizeValueStrategy](params);
- } else {
- result = params;
- }
- return result;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translateDefaultInterpolation#setLocale
- * @methodOf pascalprecht.translate.$translateDefaultInterpolation
- *
- * @description
- * Sets current locale (this is currently not use in this interpolation).
- *
- * @param {string} locale Language key or locale.
- */
- $translateInterpolator.setLocale = function (locale) {
- $locale = locale;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translateDefaultInterpolation#getInterpolationIdentifier
- * @methodOf pascalprecht.translate.$translateDefaultInterpolation
- *
- * @description
- * Returns an identifier for this interpolation service.
- *
- * @returns {string} $identifier
- */
- $translateInterpolator.getInterpolationIdentifier = function () {
- return $identifier;
- };
- $translateInterpolator.useSanitizeValueStrategy = function (value) {
- $sanitizeValueStrategy = value;
- return this;
- };
- /**
- * @ngdoc function
- * @name pascalprecht.translate.$translateDefaultInterpolation#interpolate
- * @methodOf pascalprecht.translate.$translateDefaultInterpolation
- *
- * @description
- * Interpolates given string agains given interpolate params using angulars
- * `$interpolate` service.
- *
- * @returns {string} interpolated string.
- */
- $translateInterpolator.interpolate = function (string, interpolateParams) {
- if ($sanitizeValueStrategy) {
- interpolateParams = sanitizeParams(interpolateParams);
- }
- return $interpolate(string)(interpolateParams || {});
- };
- return $translateInterpolator;
- }]);
- angular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY');
- angular.module('pascalprecht.translate')
- /**
- * @ngdoc directive
- * @name pascalprecht.translate.directive:translate
- * @requires $compile
- * @requires $filter
- * @requires $interpolate
- * @restrict A
- *
- * @description
- * Translates given translation id either through attribute or DOM content.
- * Internally it uses `translate` filter to translate translation id. It possible to
- * pass an optional `translate-values` object literal as string into translation id.
- *
- * @param {string=} translate Translation id which could be either string or interpolated string.
- * @param {string=} translate-values Values to pass into translation id. Can be passed as object literal string or interpolated object.
- * @param {string=} translate-attr-ATTR translate Translation id and put it into ATTR attribute.
- * @param {string=} translate-default will be used unless translation was successful
- * @param {boolean=} translate-compile (default true if present) defines locally activation of {@link pascalprecht.translate.$translate#usePostCompiling}
- *
- * @example
- <example module="ngView">
- <file name="index.html">
- <div ng-controller="TranslateCtrl">
- <pre translate="TRANSLATION_ID"></pre>
- <pre translate>TRANSLATION_ID</pre>
- <pre translate translate-attr-title="TRANSLATION_ID"></pre>
- <pre translate="{{translationId}}"></pre>
- <pre translate>{{translationId}}</pre>
- <pre translate="WITH_VALUES" translate-values="{value: 5}"></pre>
- <pre translate translate-values="{value: 5}">WITH_VALUES</pre>
- <pre translate="WITH_VALUES" translate-values="{{values}}"></pre>
- <pre translate translate-values="{{values}}">WITH_VALUES</pre>
- <pre translate translate-attr-title="WITH_VALUES" translate-values="{{values}}"></pre>
- </div>
- </file>
- <file name="script.js">
- angular.module('ngView', ['pascalprecht.translate'])
- .config(function ($translateProvider) {
- $translateProvider.translations('en',{
- 'TRANSLATION_ID': 'Hello there!',
- 'WITH_VALUES': 'The following value is dynamic: {{value}}'
- }).preferredLanguage('en');
- });
- angular.module('ngView').controller('TranslateCtrl', function ($scope) {
- $scope.translationId = 'TRANSLATION_ID';
- $scope.values = {
- value: 78
- };
- });
- </file>
- <file name="scenario.js">
- it('should translate', function () {
- inject(function ($rootScope, $compile) {
- $rootScope.translationId = 'TRANSLATION_ID';
- element = $compile('<p translate="TRANSLATION_ID"></p>')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toBe('Hello there!');
- element = $compile('<p translate="{{translationId}}"></p>')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toBe('Hello there!');
- element = $compile('<p translate>TRANSLATION_ID</p>')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toBe('Hello there!');
- element = $compile('<p translate>{{translationId}}</p>')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toBe('Hello there!');
- element = $compile('<p translate translate-attr-title="TRANSLATION_ID"></p>')($rootScope);
- $rootScope.$digest();
- expect(element.attr('title')).toBe('Hello there!');
- });
- });
- </file>
- </example>
- */
- .directive('translate', ['$translate', '$q', '$interpolate', '$compile', '$parse', '$rootScope', function ($translate, $q, $interpolate, $compile, $parse, $rootScope) {
- /**
- * @name trim
- * @private
- *
- * @description
- * trim polyfill
- *
- * @returns {string} The string stripped of whitespace from both ends
- */
- var trim = function() {
- return this.replace(/^\s+|\s+$/g, '');
- };
- return {
- restrict: 'AE',
- scope: true,
- priority: $translate.directivePriority(),
- compile: function (tElement, tAttr) {
- var translateValuesExist = (tAttr.translateValues) ?
- tAttr.translateValues : undefined;
- var translateInterpolation = (tAttr.translateInterpolation) ?
- tAttr.translateInterpolation : undefined;
- var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i);
- var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)',
- watcherRegExp = '^(.*)' + $interpolate.startSymbol() + '(.*)' + $interpolate.endSymbol() + '(.*)';
- return function linkFn(scope, iElement, iAttr) {
- scope.interpolateParams = {};
- scope.preText = '';
- scope.postText = '';
- var translationIds = {};
- // Ensures any change of the attribute "translate" containing the id will
- // be re-stored to the scope's "translationId".
- // If the attribute has no content, the element's text value (white spaces trimmed off) will be used.
- var observeElementTranslation = function (translationId) {
- // Remove any old watcher
- if (angular.isFunction(observeElementTranslation._unwatchOld)) {
- observeElementTranslation._unwatchOld();
- observeElementTranslation._unwatchOld = undefined;
- }
- if (angular.equals(translationId , '') || !angular.isDefined(translationId)) {
- // Resolve translation id by inner html if required
- var interpolateMatches = trim.apply(iElement.text()).match(interpolateRegExp);
- // Interpolate translation id if required
- if (angular.isArray(interpolateMatches)) {
- scope.preText = interpolateMatches[1];
- scope.postText = interpolateMatches[3];
- translationIds.translate = $interpolate(interpolateMatches[2])(scope.$parent);
- var watcherMatches = iElement.text().match(watcherRegExp);
- if (angular.isArray(watcherMatches) && watcherMatches[2] && watcherMatches[2].length) {
- observeElementTranslation._unwatchOld = scope.$watch(watcherMatches[2], function (newValue) {
- translationIds.translate = newValue;
- updateTranslations();
- });
- }
- } else {
- translationIds.translate = iElement.text().replace(/^\s+|\s+$/g,'');
- }
- } else {
- translationIds.translate = translationId;
- }
- updateTranslations();
- };
- var observeAttributeTranslation = function (translateAttr) {
- iAttr.$observe(translateAttr, function (translationId) {
- translationIds[translateAttr] = translationId;
- updateTranslations();
- });
- };
- var firstAttributeChangedEvent = true;
- iAttr.$observe('translate', function (translationId) {
- if (typeof translationId === 'undefined') {
- // case of element "<translate>xyz</translate>"
- observeElementTranslation('');
- } else {
- // case of regular attribute
- if (translationId !== '' || !firstAttributeChangedEvent) {
- translationIds.translate = translationId;
- updateTranslations();
- }
- }
- firstAttributeChangedEvent = false;
- });
- for (var translateAttr in iAttr) {
- if (iAttr.hasOwnProperty(translateAttr) && translateAttr.substr(0, 13) === 'translateAttr') {
- observeAttributeTranslation(translateAttr);
- }
- }
- iAttr.$observe('translateDefault', function (value) {
- scope.defaultText = value;
- });
- if (translateValuesExist) {
- iAttr.$observe('translateValues', function (interpolateParams) {
- if (interpolateParams) {
- scope.$parent.$watch(function () {
- angular.extend(scope.interpolateParams, $parse(interpolateParams)(scope.$parent));
- });
- }
- });
- }
- if (translateValueExist) {
- var observeValueAttribute = function (attrName) {
- iAttr.$observe(attrName, function (value) {
- var attributeName = angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15);
- scope.interpolateParams[attributeName] = value;
- });
- };
- for (var attr in iAttr) {
- if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {
- observeValueAttribute(attr);
- }
- }
- }
- // Master update function
- var updateTranslations = function () {
- for (var key in translationIds) {
- if (translationIds.hasOwnProperty(key)) {
- updateTranslation(key, translationIds[key], scope, scope.interpolateParams, scope.defaultText);
- }
- }
- };
- // Put translation processing function outside loop
- var updateTranslation = function(translateAttr, translationId, scope, interpolateParams, defaultTranslationText) {
- if (translationId) {
- $translate(translationId, interpolateParams, translateInterpolation, defaultTranslationText)
- .then(function (translation) {
- applyTranslation(translation, scope, true, translateAttr);
- }, function (translationId) {
- applyTranslation(translationId, scope, false, translateAttr);
- });
- } else {
- // as an empty string cannot be translated, we can solve this using successful=false
- applyTranslation(translationId, scope, false, translateAttr);
- }
- };
- var applyTranslation = function (value, scope, successful, translateAttr) {
- if (translateAttr === 'translate') {
- // default translate into innerHTML
- if (!successful && typeof scope.defaultText !== 'undefined') {
- value = scope.defaultText;
- }
- iElement.html(scope.preText + value + scope.postText);
- var globallyEnabled = $translate.isPostCompilingEnabled();
- var locallyDefined = typeof tAttr.translateCompile !== 'undefined';
- var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false';
- if ((globallyEnabled && !locallyDefined) || locallyEnabled) {
- $compile(iElement.contents())(scope);
- }
- } else {
- // translate attribute
- if (!successful && typeof scope.defaultText !== 'undefined') {
- value = scope.defaultText;
- }
- var attributeName = iAttr.$attr[translateAttr].substr(15);
- iElement.attr(attributeName, value);
- }
- };
- scope.$watch('interpolateParams', updateTranslations, true);
- // Ensures the text will be refreshed after the current language was changed
- // w/ $translate.use(...)
- var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);
- // ensure translation will be looked up at least one
- if (iElement.text().length) {
- observeElementTranslation('');
- }
- updateTranslations();
- scope.$on('$destroy', unbind);
- };
- }
- };
- }]);
- angular.module('pascalprecht.translate')
- /**
- * @ngdoc directive
- * @name pascalprecht.translate.directive:translateCloak
- * @requires $rootScope
- * @requires $translate
- * @restrict A
- *
- * $description
- * Adds a `translate-cloak` class name to the given element where this directive
- * is applied initially and removes it, once a loader has finished loading.
- *
- * This directive can be used to prevent initial flickering when loading translation
- * data asynchronously.
- *
- * The class name is defined in
- * {@link pascalprecht.translate.$translateProvider#cloakClassName $translate.cloakClassName()}.
- *
- * @param {string=} translate-cloak If a translationId is provided, it will be used for showing
- * or hiding the cloak. Basically it relies on the translation
- * resolve.
- */
- .directive('translateCloak', ['$rootScope', '$translate', function ($rootScope, $translate) {
- return {
- compile: function (tElement) {
- var applyCloak = function () {
- tElement.addClass($translate.cloakClassName());
- },
- removeCloak = function () {
- tElement.removeClass($translate.cloakClassName());
- },
- removeListener = $rootScope.$on('$translateChangeEnd', function () {
- removeCloak();
- removeListener();
- removeListener = null;
- });
- applyCloak();
- return function linkFn(scope, iElement, iAttr) {
- // Register a watcher for the defined translation allowing a fine tuned cloak
- if (iAttr.translateCloak && iAttr.translateCloak.length) {
- iAttr.$observe('translateCloak', function (translationId) {
- $translate(translationId).then(removeCloak, applyCloak);
- });
- }
- };
- }
- };
- }]);
- angular.module('pascalprecht.translate')
- /**
- * @ngdoc filter
- * @name pascalprecht.translate.filter:translate
- * @requires $parse
- * @requires pascalprecht.translate.$translate
- * @function
- *
- * @description
- * Uses `$translate` service to translate contents. Accepts interpolate parameters
- * to pass dynamized values though translation.
- *
- * @param {string} translationId A translation id to be translated.
- * @param {*=} interpolateParams Optional object literal (as hash or string) to pass values into translation.
- *
- * @returns {string} Translated text.
- *
- * @example
- <example module="ngView">
- <file name="index.html">
- <div ng-controller="TranslateCtrl">
- <pre>{{ 'TRANSLATION_ID' | translate }}</pre>
- <pre>{{ translationId | translate }}</pre>
- <pre>{{ 'WITH_VALUES' | translate:'{value: 5}' }}</pre>
- <pre>{{ 'WITH_VALUES' | translate:values }}</pre>
- </div>
- </file>
- <file name="script.js">
- angular.module('ngView', ['pascalprecht.translate'])
- .config(function ($translateProvider) {
- $translateProvider.translations('en', {
- 'TRANSLATION_ID': 'Hello there!',
- 'WITH_VALUES': 'The following value is dynamic: {{value}}'
- });
- $translateProvider.preferredLanguage('en');
- });
- angular.module('ngView').controller('TranslateCtrl', function ($scope) {
- $scope.translationId = 'TRANSLATION_ID';
- $scope.values = {
- value: 78
- };
- });
- </file>
- </example>
- */
- .filter('translate', ['$parse', '$translate', function ($parse, $translate) {
- var translateFilter = function (translationId, interpolateParams, interpolation) {
- if (!angular.isObject(interpolateParams)) {
- interpolateParams = $parse(interpolateParams)(this);
- }
- return $translate.instant(translationId, interpolateParams, interpolation);
- };
- // Since AngularJS 1.3, filters which are not stateless (depending at the scope)
- // have to explicit define this behavior.
- translateFilter.$stateful = true;
- return translateFilter;
- }]);
|