angular-translate.js 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. /*!
  2. * angular-translate - v2.4.2 - 2014-10-21
  3. * http://github.com/angular-translate/angular-translate
  4. * Copyright (c) 2014 ; Licensed MIT
  5. */
  6. angular.module('pascalprecht.translate', ['ng']).run([
  7. '$translate',
  8. function ($translate) {
  9. var key = $translate.storageKey(), storage = $translate.storage();
  10. if (storage) {
  11. if (!storage.get(key)) {
  12. if (angular.isString($translate.preferredLanguage())) {
  13. $translate.use($translate.preferredLanguage());
  14. } else {
  15. storage.set(key, $translate.use());
  16. }
  17. } else {
  18. $translate.use(storage.get(key));
  19. }
  20. } else if (angular.isString($translate.preferredLanguage())) {
  21. $translate.use($translate.preferredLanguage());
  22. }
  23. }
  24. ]);
  25. angular.module('pascalprecht.translate').provider('$translate', [
  26. '$STORAGE_KEY',
  27. function ($STORAGE_KEY) {
  28. 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;
  29. var version = '2.4.2';
  30. var getLocale = function () {
  31. var nav = window.navigator;
  32. return ((angular.isArray(nav.languages) ? nav.languages[0] : nav.language || nav.browserLanguage || nav.systemLanguage || nav.userLanguage) || '').split('-').join('_');
  33. };
  34. var indexOf = function (array, searchElement) {
  35. for (var i = 0, len = array.length; i < len; i++) {
  36. if (array[i] === searchElement) {
  37. return i;
  38. }
  39. }
  40. return -1;
  41. };
  42. var trim = function () {
  43. return this.replace(/^\s+|\s+$/g, '');
  44. };
  45. var negotiateLocale = function (preferred) {
  46. var avail = [], locale = angular.lowercase(preferred), i = 0, n = $availableLanguageKeys.length;
  47. for (; i < n; i++) {
  48. avail.push(angular.lowercase($availableLanguageKeys[i]));
  49. }
  50. if (indexOf(avail, locale) > -1) {
  51. return preferred;
  52. }
  53. if ($languageKeyAliases) {
  54. var alias;
  55. for (var langKeyAlias in $languageKeyAliases) {
  56. var hasWildcardKey = false;
  57. var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) && angular.lowercase(langKeyAlias) === angular.lowercase(preferred);
  58. if (langKeyAlias.slice(-1) === '*') {
  59. hasWildcardKey = langKeyAlias.slice(0, -1) === preferred.slice(0, langKeyAlias.length - 1);
  60. }
  61. if (hasExactKey || hasWildcardKey) {
  62. alias = $languageKeyAliases[langKeyAlias];
  63. if (indexOf(avail, angular.lowercase(alias)) > -1) {
  64. return alias;
  65. }
  66. }
  67. }
  68. }
  69. var parts = preferred.split('_');
  70. if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) {
  71. return parts[0];
  72. }
  73. return preferred;
  74. };
  75. var translations = function (langKey, translationTable) {
  76. if (!langKey && !translationTable) {
  77. return $translationTable;
  78. }
  79. if (langKey && !translationTable) {
  80. if (angular.isString(langKey)) {
  81. return $translationTable[langKey];
  82. }
  83. } else {
  84. if (!angular.isObject($translationTable[langKey])) {
  85. $translationTable[langKey] = {};
  86. }
  87. angular.extend($translationTable[langKey], flatObject(translationTable));
  88. }
  89. return this;
  90. };
  91. this.translations = translations;
  92. this.cloakClassName = function (name) {
  93. if (!name) {
  94. return $cloakClassName;
  95. }
  96. $cloakClassName = name;
  97. return this;
  98. };
  99. var flatObject = function (data, path, result, prevKey) {
  100. var key, keyWithPath, keyWithShortPath, val;
  101. if (!path) {
  102. path = [];
  103. }
  104. if (!result) {
  105. result = {};
  106. }
  107. for (key in data) {
  108. if (!Object.prototype.hasOwnProperty.call(data, key)) {
  109. continue;
  110. }
  111. val = data[key];
  112. if (angular.isObject(val)) {
  113. flatObject(val, path.concat(key), result, key);
  114. } else {
  115. keyWithPath = path.length ? '' + path.join(NESTED_OBJECT_DELIMITER) + NESTED_OBJECT_DELIMITER + key : key;
  116. if (path.length && key === prevKey) {
  117. keyWithShortPath = '' + path.join(NESTED_OBJECT_DELIMITER);
  118. result[keyWithShortPath] = '@:' + keyWithPath;
  119. }
  120. result[keyWithPath] = val;
  121. }
  122. }
  123. return result;
  124. };
  125. this.addInterpolation = function (factory) {
  126. $interpolatorFactories.push(factory);
  127. return this;
  128. };
  129. this.useMessageFormatInterpolation = function () {
  130. return this.useInterpolation('$translateMessageFormatInterpolation');
  131. };
  132. this.useInterpolation = function (factory) {
  133. $interpolationFactory = factory;
  134. return this;
  135. };
  136. this.useSanitizeValueStrategy = function (value) {
  137. $interpolationSanitizationStrategy = value;
  138. return this;
  139. };
  140. this.preferredLanguage = function (langKey) {
  141. setupPreferredLanguage(langKey);
  142. return this;
  143. };
  144. var setupPreferredLanguage = function (langKey) {
  145. if (langKey) {
  146. $preferredLanguage = langKey;
  147. }
  148. return $preferredLanguage;
  149. };
  150. this.translationNotFoundIndicator = function (indicator) {
  151. this.translationNotFoundIndicatorLeft(indicator);
  152. this.translationNotFoundIndicatorRight(indicator);
  153. return this;
  154. };
  155. this.translationNotFoundIndicatorLeft = function (indicator) {
  156. if (!indicator) {
  157. return $notFoundIndicatorLeft;
  158. }
  159. $notFoundIndicatorLeft = indicator;
  160. return this;
  161. };
  162. this.translationNotFoundIndicatorRight = function (indicator) {
  163. if (!indicator) {
  164. return $notFoundIndicatorRight;
  165. }
  166. $notFoundIndicatorRight = indicator;
  167. return this;
  168. };
  169. this.fallbackLanguage = function (langKey) {
  170. fallbackStack(langKey);
  171. return this;
  172. };
  173. var fallbackStack = function (langKey) {
  174. if (langKey) {
  175. if (angular.isString(langKey)) {
  176. $fallbackWasString = true;
  177. $fallbackLanguage = [langKey];
  178. } else if (angular.isArray(langKey)) {
  179. $fallbackWasString = false;
  180. $fallbackLanguage = langKey;
  181. }
  182. if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) {
  183. $fallbackLanguage.push($preferredLanguage);
  184. }
  185. return this;
  186. } else {
  187. if ($fallbackWasString) {
  188. return $fallbackLanguage[0];
  189. } else {
  190. return $fallbackLanguage;
  191. }
  192. }
  193. };
  194. this.use = function (langKey) {
  195. if (langKey) {
  196. if (!$translationTable[langKey] && !$loaderFactory) {
  197. throw new Error('$translateProvider couldn\'t find translationTable for langKey: \'' + langKey + '\'');
  198. }
  199. $uses = langKey;
  200. return this;
  201. }
  202. return $uses;
  203. };
  204. var storageKey = function (key) {
  205. if (!key) {
  206. if ($storagePrefix) {
  207. return $storagePrefix + $storageKey;
  208. }
  209. return $storageKey;
  210. }
  211. $storageKey = key;
  212. };
  213. this.storageKey = storageKey;
  214. this.useUrlLoader = function (url, options) {
  215. return this.useLoader('$translateUrlLoader', angular.extend({ url: url }, options));
  216. };
  217. this.useStaticFilesLoader = function (options) {
  218. return this.useLoader('$translateStaticFilesLoader', options);
  219. };
  220. this.useLoader = function (loaderFactory, options) {
  221. $loaderFactory = loaderFactory;
  222. $loaderOptions = options || {};
  223. return this;
  224. };
  225. this.useLocalStorage = function () {
  226. return this.useStorage('$translateLocalStorage');
  227. };
  228. this.useCookieStorage = function () {
  229. return this.useStorage('$translateCookieStorage');
  230. };
  231. this.useStorage = function (storageFactory) {
  232. $storageFactory = storageFactory;
  233. return this;
  234. };
  235. this.storagePrefix = function (prefix) {
  236. if (!prefix) {
  237. return prefix;
  238. }
  239. $storagePrefix = prefix;
  240. return this;
  241. };
  242. this.useMissingTranslationHandlerLog = function () {
  243. return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog');
  244. };
  245. this.useMissingTranslationHandler = function (factory) {
  246. $missingTranslationHandlerFactory = factory;
  247. return this;
  248. };
  249. this.usePostCompiling = function (value) {
  250. $postCompilingEnabled = !!value;
  251. return this;
  252. };
  253. this.determinePreferredLanguage = function (fn) {
  254. var locale = fn && angular.isFunction(fn) ? fn() : getLocale();
  255. if (!$availableLanguageKeys.length) {
  256. $preferredLanguage = locale;
  257. } else {
  258. $preferredLanguage = negotiateLocale(locale);
  259. }
  260. return this;
  261. };
  262. this.registerAvailableLanguageKeys = function (languageKeys, aliases) {
  263. if (languageKeys) {
  264. $availableLanguageKeys = languageKeys;
  265. if (aliases) {
  266. $languageKeyAliases = aliases;
  267. }
  268. return this;
  269. }
  270. return $availableLanguageKeys;
  271. };
  272. this.useLoaderCache = function (cache) {
  273. if (cache === false) {
  274. loaderCache = undefined;
  275. } else if (cache === true) {
  276. loaderCache = true;
  277. } else if (typeof cache === 'undefined') {
  278. loaderCache = '$translationCache';
  279. } else if (cache) {
  280. loaderCache = cache;
  281. }
  282. return this;
  283. };
  284. this.$get = [
  285. '$log',
  286. '$injector',
  287. '$rootScope',
  288. '$q',
  289. function ($log, $injector, $rootScope, $q) {
  290. var Storage, defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'), pendingLoader = false, interpolatorHashMap = {}, langPromises = {}, fallbackIndex, startFallbackIteration;
  291. var $translate = function (translationId, interpolateParams, interpolationId) {
  292. if (angular.isArray(translationId)) {
  293. var translateAll = function (translationIds) {
  294. var results = {};
  295. var promises = [];
  296. var translate = function (translationId) {
  297. var deferred = $q.defer();
  298. var regardless = function (value) {
  299. results[translationId] = value;
  300. deferred.resolve([
  301. translationId,
  302. value
  303. ]);
  304. };
  305. $translate(translationId, interpolateParams, interpolationId).then(regardless, regardless);
  306. return deferred.promise;
  307. };
  308. for (var i = 0, c = translationIds.length; i < c; i++) {
  309. promises.push(translate(translationIds[i]));
  310. }
  311. return $q.all(promises).then(function () {
  312. return results;
  313. });
  314. };
  315. return translateAll(translationId);
  316. }
  317. var deferred = $q.defer();
  318. if (translationId) {
  319. translationId = trim.apply(translationId);
  320. }
  321. var promiseToWaitFor = function () {
  322. var promise = $preferredLanguage ? langPromises[$preferredLanguage] : langPromises[$uses];
  323. fallbackIndex = 0;
  324. if ($storageFactory && !promise) {
  325. var langKey = Storage.get($storageKey);
  326. promise = langPromises[langKey];
  327. if ($fallbackLanguage && $fallbackLanguage.length) {
  328. var index = indexOf($fallbackLanguage, langKey);
  329. fallbackIndex = index === 0 ? 1 : 0;
  330. if (indexOf($fallbackLanguage, $preferredLanguage) < 0) {
  331. $fallbackLanguage.push($preferredLanguage);
  332. }
  333. }
  334. }
  335. return promise;
  336. }();
  337. if (!promiseToWaitFor) {
  338. determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject);
  339. } else {
  340. promiseToWaitFor.then(function () {
  341. determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject);
  342. }, deferred.reject);
  343. }
  344. return deferred.promise;
  345. };
  346. var applyNotFoundIndicators = function (translationId) {
  347. if ($notFoundIndicatorLeft) {
  348. translationId = [
  349. $notFoundIndicatorLeft,
  350. translationId
  351. ].join(' ');
  352. }
  353. if ($notFoundIndicatorRight) {
  354. translationId = [
  355. translationId,
  356. $notFoundIndicatorRight
  357. ].join(' ');
  358. }
  359. return translationId;
  360. };
  361. var useLanguage = function (key) {
  362. $uses = key;
  363. $rootScope.$emit('$translateChangeSuccess', { language: key });
  364. if ($storageFactory) {
  365. Storage.set($translate.storageKey(), $uses);
  366. }
  367. defaultInterpolator.setLocale($uses);
  368. angular.forEach(interpolatorHashMap, function (interpolator, id) {
  369. interpolatorHashMap[id].setLocale($uses);
  370. });
  371. $rootScope.$emit('$translateChangeEnd', { language: key });
  372. };
  373. var loadAsync = function (key) {
  374. if (!key) {
  375. throw 'No language key specified for loading.';
  376. }
  377. var deferred = $q.defer();
  378. $rootScope.$emit('$translateLoadingStart', { language: key });
  379. pendingLoader = true;
  380. var cache = loaderCache;
  381. if (typeof cache === 'string') {
  382. cache = $injector.get(cache);
  383. }
  384. var loaderOptions = angular.extend({}, $loaderOptions, {
  385. key: key,
  386. $http: angular.extend({}, { cache: cache }, $loaderOptions.$http)
  387. });
  388. $injector.get($loaderFactory)(loaderOptions).then(function (data) {
  389. var translationTable = {};
  390. $rootScope.$emit('$translateLoadingSuccess', { language: key });
  391. if (angular.isArray(data)) {
  392. angular.forEach(data, function (table) {
  393. angular.extend(translationTable, flatObject(table));
  394. });
  395. } else {
  396. angular.extend(translationTable, flatObject(data));
  397. }
  398. pendingLoader = false;
  399. deferred.resolve({
  400. key: key,
  401. table: translationTable
  402. });
  403. $rootScope.$emit('$translateLoadingEnd', { language: key });
  404. }, function (key) {
  405. $rootScope.$emit('$translateLoadingError', { language: key });
  406. deferred.reject(key);
  407. $rootScope.$emit('$translateLoadingEnd', { language: key });
  408. });
  409. return deferred.promise;
  410. };
  411. if ($storageFactory) {
  412. Storage = $injector.get($storageFactory);
  413. if (!Storage.get || !Storage.set) {
  414. throw new Error('Couldn\'t use storage \'' + $storageFactory + '\', missing get() or set() method!');
  415. }
  416. }
  417. if (angular.isFunction(defaultInterpolator.useSanitizeValueStrategy)) {
  418. defaultInterpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy);
  419. }
  420. if ($interpolatorFactories.length) {
  421. angular.forEach($interpolatorFactories, function (interpolatorFactory) {
  422. var interpolator = $injector.get(interpolatorFactory);
  423. interpolator.setLocale($preferredLanguage || $uses);
  424. if (angular.isFunction(interpolator.useSanitizeValueStrategy)) {
  425. interpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy);
  426. }
  427. interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;
  428. });
  429. }
  430. var getTranslationTable = function (langKey) {
  431. var deferred = $q.defer();
  432. if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) {
  433. deferred.resolve($translationTable[langKey]);
  434. } else if (langPromises[langKey]) {
  435. langPromises[langKey].then(function (data) {
  436. translations(data.key, data.table);
  437. deferred.resolve(data.table);
  438. }, deferred.reject);
  439. } else {
  440. deferred.reject();
  441. }
  442. return deferred.promise;
  443. };
  444. var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator) {
  445. var deferred = $q.defer();
  446. getTranslationTable(langKey).then(function (translationTable) {
  447. if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) {
  448. Interpolator.setLocale(langKey);
  449. deferred.resolve(Interpolator.interpolate(translationTable[translationId], interpolateParams));
  450. Interpolator.setLocale($uses);
  451. } else {
  452. deferred.reject();
  453. }
  454. }, deferred.reject);
  455. return deferred.promise;
  456. };
  457. var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator) {
  458. var result, translationTable = $translationTable[langKey];
  459. if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) {
  460. Interpolator.setLocale(langKey);
  461. result = Interpolator.interpolate(translationTable[translationId], interpolateParams);
  462. Interpolator.setLocale($uses);
  463. }
  464. return result;
  465. };
  466. var translateByHandler = function (translationId) {
  467. if ($missingTranslationHandlerFactory) {
  468. var resultString = $injector.get($missingTranslationHandlerFactory)(translationId, $uses);
  469. if (resultString !== undefined) {
  470. return resultString;
  471. } else {
  472. return translationId;
  473. }
  474. } else {
  475. return translationId;
  476. }
  477. };
  478. var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) {
  479. var deferred = $q.defer();
  480. if (fallbackLanguageIndex < $fallbackLanguage.length) {
  481. var langKey = $fallbackLanguage[fallbackLanguageIndex];
  482. getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator).then(deferred.resolve, function () {
  483. resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator).then(deferred.resolve);
  484. });
  485. } else {
  486. deferred.resolve(translateByHandler(translationId));
  487. }
  488. return deferred.promise;
  489. };
  490. var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) {
  491. var result;
  492. if (fallbackLanguageIndex < $fallbackLanguage.length) {
  493. var langKey = $fallbackLanguage[fallbackLanguageIndex];
  494. result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator);
  495. if (!result) {
  496. result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);
  497. }
  498. }
  499. return result;
  500. };
  501. var fallbackTranslation = function (translationId, interpolateParams, Interpolator) {
  502. return resolveForFallbackLanguage(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator);
  503. };
  504. var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator) {
  505. return resolveForFallbackLanguageInstant(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator);
  506. };
  507. var determineTranslation = function (translationId, interpolateParams, interpolationId) {
  508. var deferred = $q.defer();
  509. var table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator;
  510. if (table && Object.prototype.hasOwnProperty.call(table, translationId)) {
  511. var translation = table[translationId];
  512. if (translation.substr(0, 2) === '@:') {
  513. $translate(translation.substr(2), interpolateParams, interpolationId).then(deferred.resolve, deferred.reject);
  514. } else {
  515. deferred.resolve(Interpolator.interpolate(translation, interpolateParams));
  516. }
  517. } else {
  518. var missingTranslationHandlerTranslation;
  519. if ($missingTranslationHandlerFactory && !pendingLoader) {
  520. missingTranslationHandlerTranslation = translateByHandler(translationId);
  521. }
  522. if ($uses && $fallbackLanguage && $fallbackLanguage.length) {
  523. fallbackTranslation(translationId, interpolateParams, Interpolator).then(function (translation) {
  524. deferred.resolve(translation);
  525. }, function (_translationId) {
  526. deferred.reject(applyNotFoundIndicators(_translationId));
  527. });
  528. } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
  529. deferred.resolve(missingTranslationHandlerTranslation);
  530. } else {
  531. deferred.reject(applyNotFoundIndicators(translationId));
  532. }
  533. }
  534. return deferred.promise;
  535. };
  536. var determineTranslationInstant = function (translationId, interpolateParams, interpolationId) {
  537. var result, table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator;
  538. if (table && Object.prototype.hasOwnProperty.call(table, translationId)) {
  539. var translation = table[translationId];
  540. if (translation.substr(0, 2) === '@:') {
  541. result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId);
  542. } else {
  543. result = Interpolator.interpolate(translation, interpolateParams);
  544. }
  545. } else {
  546. var missingTranslationHandlerTranslation;
  547. if ($missingTranslationHandlerFactory && !pendingLoader) {
  548. missingTranslationHandlerTranslation = translateByHandler(translationId);
  549. }
  550. if ($uses && $fallbackLanguage && $fallbackLanguage.length) {
  551. fallbackIndex = 0;
  552. result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator);
  553. } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
  554. result = missingTranslationHandlerTranslation;
  555. } else {
  556. result = applyNotFoundIndicators(translationId);
  557. }
  558. }
  559. return result;
  560. };
  561. $translate.preferredLanguage = function (langKey) {
  562. if (langKey) {
  563. setupPreferredLanguage(langKey);
  564. }
  565. return $preferredLanguage;
  566. };
  567. $translate.cloakClassName = function () {
  568. return $cloakClassName;
  569. };
  570. $translate.fallbackLanguage = function (langKey) {
  571. if (langKey !== undefined && langKey !== null) {
  572. fallbackStack(langKey);
  573. if ($loaderFactory) {
  574. if ($fallbackLanguage && $fallbackLanguage.length) {
  575. for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {
  576. if (!langPromises[$fallbackLanguage[i]]) {
  577. langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]);
  578. }
  579. }
  580. }
  581. }
  582. $translate.use($translate.use());
  583. }
  584. if ($fallbackWasString) {
  585. return $fallbackLanguage[0];
  586. } else {
  587. return $fallbackLanguage;
  588. }
  589. };
  590. $translate.useFallbackLanguage = function (langKey) {
  591. if (langKey !== undefined && langKey !== null) {
  592. if (!langKey) {
  593. startFallbackIteration = 0;
  594. } else {
  595. var langKeyPosition = indexOf($fallbackLanguage, langKey);
  596. if (langKeyPosition > -1) {
  597. startFallbackIteration = langKeyPosition;
  598. }
  599. }
  600. }
  601. };
  602. $translate.proposedLanguage = function () {
  603. return $nextLang;
  604. };
  605. $translate.storage = function () {
  606. return Storage;
  607. };
  608. $translate.use = function (key) {
  609. if (!key) {
  610. return $uses;
  611. }
  612. var deferred = $q.defer();
  613. $rootScope.$emit('$translateChangeStart', { language: key });
  614. var aliasedKey = negotiateLocale(key);
  615. if (aliasedKey) {
  616. key = aliasedKey;
  617. }
  618. if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {
  619. $nextLang = key;
  620. langPromises[key] = loadAsync(key).then(function (translation) {
  621. translations(translation.key, translation.table);
  622. deferred.resolve(translation.key);
  623. useLanguage(translation.key);
  624. if ($nextLang === key) {
  625. $nextLang = undefined;
  626. }
  627. }, function (key) {
  628. if ($nextLang === key) {
  629. $nextLang = undefined;
  630. }
  631. $rootScope.$emit('$translateChangeError', { language: key });
  632. deferred.reject(key);
  633. $rootScope.$emit('$translateChangeEnd', { language: key });
  634. });
  635. } else {
  636. deferred.resolve(key);
  637. useLanguage(key);
  638. }
  639. return deferred.promise;
  640. };
  641. $translate.storageKey = function () {
  642. return storageKey();
  643. };
  644. $translate.isPostCompilingEnabled = function () {
  645. return $postCompilingEnabled;
  646. };
  647. $translate.refresh = function (langKey) {
  648. if (!$loaderFactory) {
  649. throw new Error('Couldn\'t refresh translation table, no loader registered!');
  650. }
  651. var deferred = $q.defer();
  652. function resolve() {
  653. deferred.resolve();
  654. $rootScope.$emit('$translateRefreshEnd', { language: langKey });
  655. }
  656. function reject() {
  657. deferred.reject();
  658. $rootScope.$emit('$translateRefreshEnd', { language: langKey });
  659. }
  660. $rootScope.$emit('$translateRefreshStart', { language: langKey });
  661. if (!langKey) {
  662. var tables = [], loadingKeys = {};
  663. if ($fallbackLanguage && $fallbackLanguage.length) {
  664. for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {
  665. tables.push(loadAsync($fallbackLanguage[i]));
  666. loadingKeys[$fallbackLanguage[i]] = true;
  667. }
  668. }
  669. if ($uses && !loadingKeys[$uses]) {
  670. tables.push(loadAsync($uses));
  671. }
  672. $q.all(tables).then(function (tableData) {
  673. angular.forEach(tableData, function (data) {
  674. if ($translationTable[data.key]) {
  675. delete $translationTable[data.key];
  676. }
  677. translations(data.key, data.table);
  678. });
  679. if ($uses) {
  680. useLanguage($uses);
  681. }
  682. resolve();
  683. });
  684. } else if ($translationTable[langKey]) {
  685. loadAsync(langKey).then(function (data) {
  686. translations(data.key, data.table);
  687. if (langKey === $uses) {
  688. useLanguage($uses);
  689. }
  690. resolve();
  691. }, reject);
  692. } else {
  693. reject();
  694. }
  695. return deferred.promise;
  696. };
  697. $translate.instant = function (translationId, interpolateParams, interpolationId) {
  698. if (translationId === null || angular.isUndefined(translationId)) {
  699. return translationId;
  700. }
  701. if (angular.isArray(translationId)) {
  702. var results = {};
  703. for (var i = 0, c = translationId.length; i < c; i++) {
  704. results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId);
  705. }
  706. return results;
  707. }
  708. if (angular.isString(translationId) && translationId.length < 1) {
  709. return translationId;
  710. }
  711. if (translationId) {
  712. translationId = trim.apply(translationId);
  713. }
  714. var result, possibleLangKeys = [];
  715. if ($preferredLanguage) {
  716. possibleLangKeys.push($preferredLanguage);
  717. }
  718. if ($uses) {
  719. possibleLangKeys.push($uses);
  720. }
  721. if ($fallbackLanguage && $fallbackLanguage.length) {
  722. possibleLangKeys = possibleLangKeys.concat($fallbackLanguage);
  723. }
  724. for (var j = 0, d = possibleLangKeys.length; j < d; j++) {
  725. var possibleLangKey = possibleLangKeys[j];
  726. if ($translationTable[possibleLangKey]) {
  727. if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') {
  728. result = determineTranslationInstant(translationId, interpolateParams, interpolationId);
  729. }
  730. }
  731. if (typeof result !== 'undefined') {
  732. break;
  733. }
  734. }
  735. if (!result && result !== '') {
  736. result = defaultInterpolator.interpolate(translationId, interpolateParams);
  737. if ($missingTranslationHandlerFactory && !pendingLoader) {
  738. result = translateByHandler(translationId);
  739. }
  740. }
  741. return result;
  742. };
  743. $translate.versionInfo = function () {
  744. return version;
  745. };
  746. $translate.loaderCache = function () {
  747. return loaderCache;
  748. };
  749. if ($loaderFactory) {
  750. if (angular.equals($translationTable, {})) {
  751. $translate.use($translate.use());
  752. }
  753. if ($fallbackLanguage && $fallbackLanguage.length) {
  754. var processAsyncResult = function (translation) {
  755. translations(translation.key, translation.table);
  756. $rootScope.$emit('$translateChangeEnd', { language: translation.key });
  757. };
  758. for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {
  759. langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]).then(processAsyncResult);
  760. }
  761. }
  762. }
  763. return $translate;
  764. }
  765. ];
  766. }
  767. ]);
  768. angular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', [
  769. '$interpolate',
  770. function ($interpolate) {
  771. var $translateInterpolator = {}, $locale, $identifier = 'default', $sanitizeValueStrategy = null, sanitizeValueStrategies = {
  772. escaped: function (params) {
  773. var result = {};
  774. for (var key in params) {
  775. if (Object.prototype.hasOwnProperty.call(params, key)) {
  776. result[key] = angular.element('<div></div>').text(params[key]).html();
  777. }
  778. }
  779. return result;
  780. }
  781. };
  782. var sanitizeParams = function (params) {
  783. var result;
  784. if (angular.isFunction(sanitizeValueStrategies[$sanitizeValueStrategy])) {
  785. result = sanitizeValueStrategies[$sanitizeValueStrategy](params);
  786. } else {
  787. result = params;
  788. }
  789. return result;
  790. };
  791. $translateInterpolator.setLocale = function (locale) {
  792. $locale = locale;
  793. };
  794. $translateInterpolator.getInterpolationIdentifier = function () {
  795. return $identifier;
  796. };
  797. $translateInterpolator.useSanitizeValueStrategy = function (value) {
  798. $sanitizeValueStrategy = value;
  799. return this;
  800. };
  801. $translateInterpolator.interpolate = function (string, interpolateParams) {
  802. if ($sanitizeValueStrategy) {
  803. interpolateParams = sanitizeParams(interpolateParams);
  804. }
  805. return $interpolate(string)(interpolateParams || {});
  806. };
  807. return $translateInterpolator;
  808. }
  809. ]);
  810. angular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY');
  811. angular.module('pascalprecht.translate').directive('translate', [
  812. '$translate',
  813. '$q',
  814. '$interpolate',
  815. '$compile',
  816. '$parse',
  817. '$rootScope',
  818. function ($translate, $q, $interpolate, $compile, $parse, $rootScope) {
  819. return {
  820. restrict: 'AE',
  821. scope: true,
  822. compile: function (tElement, tAttr) {
  823. var translateValuesExist = tAttr.translateValues ? tAttr.translateValues : undefined;
  824. var translateInterpolation = tAttr.translateInterpolation ? tAttr.translateInterpolation : undefined;
  825. var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i);
  826. var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)';
  827. return function linkFn(scope, iElement, iAttr) {
  828. scope.interpolateParams = {};
  829. scope.preText = '';
  830. scope.postText = '';
  831. iAttr.$observe('translate', function (translationId) {
  832. if (angular.equals(translationId, '') || !angular.isDefined(translationId)) {
  833. var interpolateMatches = iElement.text().match(interpolateRegExp);
  834. if (angular.isArray(interpolateMatches)) {
  835. scope.preText = interpolateMatches[1];
  836. scope.postText = interpolateMatches[3];
  837. scope.translationId = $interpolate(interpolateMatches[2])(scope.$parent);
  838. } else {
  839. scope.translationId = iElement.text().replace(/^\s+|\s+$/g, '');
  840. }
  841. } else {
  842. scope.translationId = translationId;
  843. }
  844. });
  845. iAttr.$observe('translateDefault', function (value) {
  846. scope.defaultText = value;
  847. });
  848. if (translateValuesExist) {
  849. iAttr.$observe('translateValues', function (interpolateParams) {
  850. if (interpolateParams) {
  851. scope.$parent.$watch(function () {
  852. angular.extend(scope.interpolateParams, $parse(interpolateParams)(scope.$parent));
  853. });
  854. }
  855. });
  856. }
  857. if (translateValueExist) {
  858. var fn = function (attrName) {
  859. iAttr.$observe(attrName, function (value) {
  860. scope.interpolateParams[angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15)] = value;
  861. });
  862. };
  863. for (var attr in iAttr) {
  864. if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {
  865. fn(attr);
  866. }
  867. }
  868. }
  869. var applyElementContent = function (value, scope, successful) {
  870. if (!successful && typeof scope.defaultText !== 'undefined') {
  871. value = scope.defaultText;
  872. }
  873. iElement.html(scope.preText + value + scope.postText);
  874. var globallyEnabled = $translate.isPostCompilingEnabled();
  875. var locallyDefined = typeof tAttr.translateCompile !== 'undefined';
  876. var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false';
  877. if (globallyEnabled && !locallyDefined || locallyEnabled) {
  878. $compile(iElement.contents())(scope);
  879. }
  880. };
  881. var updateTranslationFn = function () {
  882. if (!translateValuesExist && !translateValueExist) {
  883. return function () {
  884. var unwatch = scope.$watch('translationId', function (value) {
  885. if (scope.translationId && value) {
  886. $translate(value, {}, translateInterpolation).then(function (translation) {
  887. applyElementContent(translation, scope, true);
  888. unwatch();
  889. }, function (translationId) {
  890. applyElementContent(translationId, scope, false);
  891. unwatch();
  892. });
  893. }
  894. }, true);
  895. };
  896. } else {
  897. return function () {
  898. var updateTranslations = function () {
  899. if (scope.translationId && scope.interpolateParams) {
  900. $translate(scope.translationId, scope.interpolateParams, translateInterpolation).then(function (translation) {
  901. applyElementContent(translation, scope, true);
  902. }, function (translationId) {
  903. applyElementContent(translationId, scope, false);
  904. });
  905. }
  906. };
  907. scope.$watch('interpolateParams', updateTranslations, true);
  908. scope.$watch('translationId', updateTranslations);
  909. };
  910. }
  911. }();
  912. var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslationFn);
  913. updateTranslationFn();
  914. scope.$on('$destroy', unbind);
  915. };
  916. }
  917. };
  918. }
  919. ]);
  920. angular.module('pascalprecht.translate').directive('translateCloak', [
  921. '$rootScope',
  922. '$translate',
  923. function ($rootScope, $translate) {
  924. return {
  925. compile: function (tElement) {
  926. var applyCloak = function () {
  927. tElement.addClass($translate.cloakClassName());
  928. }, removeCloak = function () {
  929. tElement.removeClass($translate.cloakClassName());
  930. }, removeListener = $rootScope.$on('$translateChangeEnd', function () {
  931. removeCloak();
  932. removeListener();
  933. removeListener = null;
  934. });
  935. applyCloak();
  936. return function linkFn(scope, iElement, iAttr) {
  937. if (iAttr.translateCloak && iAttr.translateCloak.length) {
  938. iAttr.$observe('translateCloak', function (translationId) {
  939. $translate(translationId).then(removeCloak, applyCloak);
  940. });
  941. }
  942. };
  943. }
  944. };
  945. }
  946. ]);
  947. angular.module('pascalprecht.translate').filter('translate', [
  948. '$parse',
  949. '$translate',
  950. function ($parse, $translate) {
  951. var translateFilter = function (translationId, interpolateParams, interpolation) {
  952. if (!angular.isObject(interpolateParams)) {
  953. interpolateParams = $parse(interpolateParams)(this);
  954. }
  955. return $translate.instant(translationId, interpolateParams, interpolation);
  956. };
  957. translateFilter.$stateful = true;
  958. return translateFilter;
  959. }
  960. ]);