angular-translate-rails-tf 2.7.2 → 2.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/vendor/assets/javascripts/angular-translate.js +1879 -1073
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a8c289c878691e9ef070eb726514e852b9163e9
|
4
|
+
data.tar.gz: f53d2649e6fd7410a1d947a9eeb50c7787166a76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a8de09ea84acde418bd28adb4fe5bdfa09800e3fef41f4bda455b00423f9a3db6757c550c2fa5ba174c9eff7c6d95758d6813be105369a6e352fc31f8656059
|
7
|
+
data.tar.gz: aa1f105aaf921c2a6211b8a431f6fa58d6715d6f6595d4bc3a18e20f2f345466ee3e54beaa4bff14ffea6a73955cb7a3d24b3899f3d5c86ae0dcb4bd7dded07c
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/*!
|
2
|
-
* angular-translate - v2.
|
3
|
-
*
|
4
|
-
* Copyright (c)
|
2
|
+
* angular-translate - v2.15.2 - 2017-06-22
|
3
|
+
*
|
4
|
+
* Copyright (c) 2017 The angular-translate team, Pascal Precht; Licensed MIT
|
5
5
|
*/
|
6
6
|
(function (root, factory) {
|
7
7
|
if (typeof define === 'function' && define.amd) {
|
@@ -9,7 +9,7 @@
|
|
9
9
|
define([], function () {
|
10
10
|
return (factory());
|
11
11
|
});
|
12
|
-
} else if (typeof
|
12
|
+
} else if (typeof module === 'object' && module.exports) {
|
13
13
|
// Node. Does not work with strict CommonJS, but
|
14
14
|
// only CommonJS-like environments that support module.exports,
|
15
15
|
// like Node.
|
@@ -26,6 +26,14 @@
|
|
26
26
|
* @description
|
27
27
|
* The main module which holds everything together.
|
28
28
|
*/
|
29
|
+
runTranslate.$inject = ['$translate'];
|
30
|
+
$translate.$inject = ['$STORAGE_KEY', '$windowProvider', '$translateSanitizationProvider', 'pascalprechtTranslateOverrider'];
|
31
|
+
$translateDefaultInterpolation.$inject = ['$interpolate', '$translateSanitization'];
|
32
|
+
translateDirective.$inject = ['$translate', '$interpolate', '$compile', '$parse', '$rootScope'];
|
33
|
+
translateAttrDirective.$inject = ['$translate', '$rootScope'];
|
34
|
+
translateCloakDirective.$inject = ['$translate', '$rootScope'];
|
35
|
+
translateFilterFactory.$inject = ['$parse', '$translate'];
|
36
|
+
$translationCache.$inject = ['$cacheFactory'];
|
29
37
|
angular.module('pascalprecht.translate', ['ng'])
|
30
38
|
.run(runTranslate);
|
31
39
|
|
@@ -59,7 +67,6 @@ function runTranslate($translate) {
|
|
59
67
|
$translate.use($translate.preferredLanguage());
|
60
68
|
}
|
61
69
|
}
|
62
|
-
runTranslate.$inject = ['$translate'];
|
63
70
|
|
64
71
|
runTranslate.displayName = 'runTranslate';
|
65
72
|
|
@@ -78,6 +85,7 @@ function $translateSanitizationProvider () {
|
|
78
85
|
'use strict';
|
79
86
|
|
80
87
|
var $sanitize,
|
88
|
+
$sce,
|
81
89
|
currentStrategy = null, // TODO change to either 'sanitize', 'escape' or ['sanitize', 'escapeParameters'] in 3.0.
|
82
90
|
hasConfiguredStrategy = false,
|
83
91
|
hasShownNoStrategyConfiguredWarning = false,
|
@@ -114,29 +122,46 @@ function $translateSanitizationProvider () {
|
|
114
122
|
*/
|
115
123
|
|
116
124
|
strategies = {
|
117
|
-
sanitize: function (value, mode) {
|
125
|
+
sanitize: function (value, mode/*, context*/) {
|
118
126
|
if (mode === 'text') {
|
119
127
|
value = htmlSanitizeValue(value);
|
120
128
|
}
|
121
129
|
return value;
|
122
130
|
},
|
123
|
-
escape: function (value, mode) {
|
131
|
+
escape: function (value, mode/*, context*/) {
|
124
132
|
if (mode === 'text') {
|
125
133
|
value = htmlEscapeValue(value);
|
126
134
|
}
|
127
135
|
return value;
|
128
136
|
},
|
129
|
-
sanitizeParameters: function (value, mode) {
|
137
|
+
sanitizeParameters: function (value, mode/*, context*/) {
|
130
138
|
if (mode === 'params') {
|
131
139
|
value = mapInterpolationParameters(value, htmlSanitizeValue);
|
132
140
|
}
|
133
141
|
return value;
|
134
142
|
},
|
135
|
-
escapeParameters: function (value, mode) {
|
143
|
+
escapeParameters: function (value, mode/*, context*/) {
|
136
144
|
if (mode === 'params') {
|
137
145
|
value = mapInterpolationParameters(value, htmlEscapeValue);
|
138
146
|
}
|
139
147
|
return value;
|
148
|
+
},
|
149
|
+
sce: function (value, mode, context) {
|
150
|
+
if (mode === 'text') {
|
151
|
+
value = htmlTrustValue(value);
|
152
|
+
} else if (mode === 'params') {
|
153
|
+
if (context !== 'filter') {
|
154
|
+
// do html escape in filter context #1101
|
155
|
+
value = mapInterpolationParameters(value, htmlEscapeValue);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
return value;
|
159
|
+
},
|
160
|
+
sceParameters: function (value, mode/*, context*/) {
|
161
|
+
if (mode === 'params') {
|
162
|
+
value = mapInterpolationParameters(value, htmlTrustValue);
|
163
|
+
}
|
164
|
+
return value;
|
140
165
|
}
|
141
166
|
};
|
142
167
|
// Support legacy strategy name 'escaped' for backwards compatibility.
|
@@ -205,12 +230,24 @@ function $translateSanitizationProvider () {
|
|
205
230
|
*/
|
206
231
|
this.$get = ['$injector', '$log', function ($injector, $log) {
|
207
232
|
|
208
|
-
var
|
233
|
+
var cachedStrategyMap = {};
|
234
|
+
|
235
|
+
var applyStrategies = function (value, mode, context, selectedStrategies) {
|
209
236
|
angular.forEach(selectedStrategies, function (selectedStrategy) {
|
210
237
|
if (angular.isFunction(selectedStrategy)) {
|
211
|
-
value = selectedStrategy(value, mode);
|
238
|
+
value = selectedStrategy(value, mode, context);
|
212
239
|
} else if (angular.isFunction(strategies[selectedStrategy])) {
|
213
|
-
value = strategies[selectedStrategy](value, mode);
|
240
|
+
value = strategies[selectedStrategy](value, mode, context);
|
241
|
+
} else if (angular.isString(strategies[selectedStrategy])) {
|
242
|
+
if (!cachedStrategyMap[strategies[selectedStrategy]]) {
|
243
|
+
try {
|
244
|
+
cachedStrategyMap[strategies[selectedStrategy]] = $injector.get(strategies[selectedStrategy]);
|
245
|
+
} catch (e) {
|
246
|
+
cachedStrategyMap[strategies[selectedStrategy]] = function() {};
|
247
|
+
throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \'' + selectedStrategy + '\'');
|
248
|
+
}
|
249
|
+
}
|
250
|
+
value = cachedStrategyMap[strategies[selectedStrategy]](value, mode, context);
|
214
251
|
} else {
|
215
252
|
throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \'' + selectedStrategy + '\'');
|
216
253
|
}
|
@@ -229,6 +266,9 @@ function $translateSanitizationProvider () {
|
|
229
266
|
if ($injector.has('$sanitize')) {
|
230
267
|
$sanitize = $injector.get('$sanitize');
|
231
268
|
}
|
269
|
+
if ($injector.has('$sce')) {
|
270
|
+
$sce = $injector.get('$sce');
|
271
|
+
}
|
232
272
|
|
233
273
|
return {
|
234
274
|
/**
|
@@ -258,14 +298,15 @@ function $translateSanitizationProvider () {
|
|
258
298
|
* @param {string|object} value The value which should be sanitized.
|
259
299
|
* @param {string} mode The current sanitization mode, either 'params' or 'text'.
|
260
300
|
* @param {string|StrategyFunction|array} [strategy] Optional custom strategy which should be used instead of the currently selected strategy.
|
301
|
+
* @param {string} [context] The context of this call: filter, service. Default is service
|
261
302
|
* @returns {string|object} sanitized value
|
262
303
|
*/
|
263
|
-
sanitize: function (value, mode, strategy) {
|
304
|
+
sanitize: function (value, mode, strategy, context) {
|
264
305
|
if (!currentStrategy) {
|
265
306
|
showNoStrategyConfiguredWarning();
|
266
307
|
}
|
267
308
|
|
268
|
-
if (
|
309
|
+
if (!strategy && strategy !== null) {
|
269
310
|
strategy = currentStrategy;
|
270
311
|
}
|
271
312
|
|
@@ -273,8 +314,12 @@ function $translateSanitizationProvider () {
|
|
273
314
|
return value;
|
274
315
|
}
|
275
316
|
|
317
|
+
if (!context) {
|
318
|
+
context = 'service';
|
319
|
+
}
|
320
|
+
|
276
321
|
var selectedStrategies = angular.isArray(strategy) ? strategy : [strategy];
|
277
|
-
return applyStrategies(value, mode, selectedStrategies);
|
322
|
+
return applyStrategies(value, mode, context, selectedStrategies);
|
278
323
|
}
|
279
324
|
};
|
280
325
|
}];
|
@@ -292,19 +337,48 @@ function $translateSanitizationProvider () {
|
|
292
337
|
return $sanitize(value);
|
293
338
|
};
|
294
339
|
|
295
|
-
var
|
296
|
-
if (
|
340
|
+
var htmlTrustValue = function (value) {
|
341
|
+
if (!$sce) {
|
342
|
+
throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sce service.');
|
343
|
+
}
|
344
|
+
return $sce.trustAsHtml(value);
|
345
|
+
};
|
346
|
+
|
347
|
+
var mapInterpolationParameters = function (value, iteratee, stack) {
|
348
|
+
if (angular.isDate(value)) {
|
349
|
+
return value;
|
350
|
+
} else if (angular.isObject(value)) {
|
297
351
|
var result = angular.isArray(value) ? [] : {};
|
298
352
|
|
353
|
+
if (!stack) {
|
354
|
+
stack = [];
|
355
|
+
} else {
|
356
|
+
if (stack.indexOf(value) > -1) {
|
357
|
+
throw new Error('pascalprecht.translate.$translateSanitization: Error cannot interpolate parameter due recursive object');
|
358
|
+
}
|
359
|
+
}
|
360
|
+
|
361
|
+
stack.push(value);
|
299
362
|
angular.forEach(value, function (propertyValue, propertyKey) {
|
300
|
-
|
363
|
+
|
364
|
+
/* Skipping function properties. */
|
365
|
+
if (angular.isFunction(propertyValue)) {
|
366
|
+
return;
|
367
|
+
}
|
368
|
+
|
369
|
+
result[propertyKey] = mapInterpolationParameters(propertyValue, iteratee, stack);
|
301
370
|
});
|
371
|
+
stack.splice(-1, 1); // remove last
|
302
372
|
|
303
373
|
return result;
|
304
374
|
} else if (angular.isNumber(value)) {
|
305
375
|
return value;
|
306
|
-
} else {
|
376
|
+
} else if (value === true || value === false) {
|
377
|
+
return value;
|
378
|
+
} else if (!angular.isUndefined(value) && value !== null) {
|
307
379
|
return iteratee(value);
|
380
|
+
} else {
|
381
|
+
return value;
|
308
382
|
}
|
309
383
|
};
|
310
384
|
}
|
@@ -319,56 +393,64 @@ function $translateSanitizationProvider () {
|
|
319
393
|
*
|
320
394
|
*/
|
321
395
|
angular.module('pascalprecht.translate')
|
322
|
-
.constant('pascalprechtTranslateOverrider', {})
|
323
|
-
.provider('$translate', $translate);
|
396
|
+
.constant('pascalprechtTranslateOverrider', {})
|
397
|
+
.provider('$translate', $translate);
|
324
398
|
|
325
399
|
function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvider, pascalprechtTranslateOverrider) {
|
326
400
|
|
327
401
|
'use strict';
|
328
402
|
|
329
403
|
var $translationTable = {},
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
404
|
+
$preferredLanguage,
|
405
|
+
$availableLanguageKeys = [],
|
406
|
+
$languageKeyAliases,
|
407
|
+
$fallbackLanguage,
|
408
|
+
$fallbackWasString,
|
409
|
+
$uses,
|
410
|
+
$nextLang,
|
411
|
+
$storageFactory,
|
412
|
+
$storageKey = $STORAGE_KEY,
|
413
|
+
$storagePrefix,
|
414
|
+
$missingTranslationHandlerFactory,
|
415
|
+
$interpolationFactory,
|
416
|
+
$interpolatorFactories = [],
|
417
|
+
$loaderFactory,
|
418
|
+
$cloakClassName = 'translate-cloak',
|
419
|
+
$loaderOptions,
|
420
|
+
$notFoundIndicatorLeft,
|
421
|
+
$notFoundIndicatorRight,
|
422
|
+
$postCompilingEnabled = false,
|
423
|
+
$forceAsyncReloadEnabled = false,
|
424
|
+
$nestedObjectDelimeter = '.',
|
425
|
+
$isReady = false,
|
426
|
+
$keepContent = false,
|
427
|
+
loaderCache,
|
428
|
+
directivePriority = 0,
|
429
|
+
statefulFilter = true,
|
430
|
+
postProcessFn,
|
431
|
+
uniformLanguageTagResolver = 'default',
|
432
|
+
languageTagResolver = {
|
433
|
+
'default' : function (tag) {
|
434
|
+
return (tag || '').split('-').join('_');
|
435
|
+
},
|
436
|
+
java : function (tag) {
|
437
|
+
var temp = (tag || '').split('-').join('_');
|
438
|
+
var parts = temp.split('_');
|
439
|
+
return parts.length > 1 ? (parts[0].toLowerCase() + '_' + parts[1].toUpperCase()) : temp;
|
440
|
+
},
|
441
|
+
bcp47 : function (tag) {
|
442
|
+
var temp = (tag || '').split('_').join('-');
|
443
|
+
var parts = temp.split('-');
|
444
|
+
return parts.length > 1 ? (parts[0].toLowerCase() + '-' + parts[1].toUpperCase()) : temp;
|
445
|
+
},
|
446
|
+
'iso639-1' : function (tag) {
|
447
|
+
var temp = (tag || '').split('_').join('-');
|
448
|
+
var parts = temp.split('-');
|
449
|
+
return parts[0].toLowerCase();
|
450
|
+
}
|
451
|
+
};
|
370
452
|
|
371
|
-
var version = '2.
|
453
|
+
var version = '2.15.2';
|
372
454
|
|
373
455
|
// tries to determine the browsers language
|
374
456
|
var getFirstBrowserLanguage = function () {
|
@@ -379,9 +461,9 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
379
461
|
}
|
380
462
|
|
381
463
|
var nav = $windowProvider.$get().navigator,
|
382
|
-
|
383
|
-
|
384
|
-
|
464
|
+
browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],
|
465
|
+
i,
|
466
|
+
language;
|
385
467
|
|
386
468
|
// support for HTML 5.1 "navigator.languages"
|
387
469
|
if (angular.isArray(nav.languages)) {
|
@@ -427,7 +509,7 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
427
509
|
*
|
428
510
|
* @returns {int} Index of search element.
|
429
511
|
*/
|
430
|
-
var indexOf = function(array, searchElement) {
|
512
|
+
var indexOf = function (array, searchElement) {
|
431
513
|
for (var i = 0, len = array.length; i < len; i++) {
|
432
514
|
if (array[i] === searchElement) {
|
433
515
|
return i;
|
@@ -445,21 +527,25 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
445
527
|
*
|
446
528
|
* @returns {string} The string stripped of whitespace from both ends
|
447
529
|
*/
|
448
|
-
var trim = function() {
|
530
|
+
var trim = function () {
|
449
531
|
return this.toString().replace(/^\s+|\s+$/g, '');
|
450
532
|
};
|
451
533
|
|
452
534
|
var negotiateLocale = function (preferred) {
|
535
|
+
if (!preferred) {
|
536
|
+
return;
|
537
|
+
}
|
453
538
|
|
454
539
|
var avail = [],
|
455
|
-
|
456
|
-
|
457
|
-
|
540
|
+
locale = angular.lowercase(preferred),
|
541
|
+
i = 0,
|
542
|
+
n = $availableLanguageKeys.length;
|
458
543
|
|
459
544
|
for (; i < n; i++) {
|
460
545
|
avail.push(angular.lowercase($availableLanguageKeys[i]));
|
461
546
|
}
|
462
547
|
|
548
|
+
// Check for an exact match in our list of available keys
|
463
549
|
if (indexOf(avail, locale) > -1) {
|
464
550
|
return preferred;
|
465
551
|
}
|
@@ -467,32 +553,33 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
467
553
|
if ($languageKeyAliases) {
|
468
554
|
var alias;
|
469
555
|
for (var langKeyAlias in $languageKeyAliases) {
|
470
|
-
|
471
|
-
|
472
|
-
|
556
|
+
if ($languageKeyAliases.hasOwnProperty(langKeyAlias)) {
|
557
|
+
var hasWildcardKey = false;
|
558
|
+
var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) &&
|
559
|
+
angular.lowercase(langKeyAlias) === angular.lowercase(preferred);
|
473
560
|
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
561
|
+
if (langKeyAlias.slice(-1) === '*') {
|
562
|
+
hasWildcardKey = langKeyAlias.slice(0, -1) === preferred.slice(0, langKeyAlias.length - 1);
|
563
|
+
}
|
564
|
+
if (hasExactKey || hasWildcardKey) {
|
565
|
+
alias = $languageKeyAliases[langKeyAlias];
|
566
|
+
if (indexOf(avail, angular.lowercase(alias)) > -1) {
|
567
|
+
return alias;
|
568
|
+
}
|
481
569
|
}
|
482
570
|
}
|
483
571
|
}
|
484
572
|
}
|
485
573
|
|
486
|
-
|
487
|
-
|
574
|
+
// Check for a language code without region
|
575
|
+
var parts = preferred.split('_');
|
488
576
|
|
489
|
-
|
490
|
-
|
491
|
-
}
|
577
|
+
if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) {
|
578
|
+
return parts[0];
|
492
579
|
}
|
493
580
|
|
494
|
-
// If everything fails,
|
495
|
-
return
|
581
|
+
// If everything fails, return undefined.
|
582
|
+
return;
|
496
583
|
};
|
497
584
|
|
498
585
|
/**
|
@@ -527,7 +614,7 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
527
614
|
* registered with no language key. Invoking it with a language key returns the
|
528
615
|
* related translation table.
|
529
616
|
*
|
530
|
-
* @param {string}
|
617
|
+
* @param {string} langKey A language key.
|
531
618
|
* @param {object} translationTable A plain old JavaScript object that represents a translation table.
|
532
619
|
*
|
533
620
|
*/
|
@@ -572,6 +659,26 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
572
659
|
return this;
|
573
660
|
};
|
574
661
|
|
662
|
+
/**
|
663
|
+
* @ngdoc function
|
664
|
+
* @name pascalprecht.translate.$translateProvider#nestedObjectDelimeter
|
665
|
+
* @methodOf pascalprecht.translate.$translateProvider
|
666
|
+
*
|
667
|
+
* @description
|
668
|
+
*
|
669
|
+
* Let's you change the delimiter for namespaced translations.
|
670
|
+
* Default delimiter is `.`.
|
671
|
+
*
|
672
|
+
* @param {string} delimiter namespace separator
|
673
|
+
*/
|
674
|
+
this.nestedObjectDelimeter = function (delimiter) {
|
675
|
+
if (!delimiter) {
|
676
|
+
return $nestedObjectDelimeter;
|
677
|
+
}
|
678
|
+
$nestedObjectDelimeter = delimiter;
|
679
|
+
return this;
|
680
|
+
};
|
681
|
+
|
575
682
|
/**
|
576
683
|
* @name flatObject
|
577
684
|
* @private
|
@@ -597,10 +704,10 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
597
704
|
if (angular.isObject(val)) {
|
598
705
|
flatObject(val, path.concat(key), result, key);
|
599
706
|
} else {
|
600
|
-
keyWithPath = path.length ? ('' + path.join(
|
601
|
-
if(path.length && key === prevKey){
|
707
|
+
keyWithPath = path.length ? ('' + path.join($nestedObjectDelimeter) + $nestedObjectDelimeter + key) : key;
|
708
|
+
if (path.length && key === prevKey) {
|
602
709
|
// Create shortcut path (foo.bar == foo.bar.bar)
|
603
|
-
keyWithShortPath = '' + path.join(
|
710
|
+
keyWithShortPath = '' + path.join($nestedObjectDelimeter);
|
604
711
|
// Link it to original path
|
605
712
|
result[keyWithShortPath] = '@:' + keyWithPath;
|
606
713
|
}
|
@@ -671,7 +778,7 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
671
778
|
return this;
|
672
779
|
};
|
673
780
|
|
674
|
-
|
781
|
+
/**
|
675
782
|
* @ngdoc function
|
676
783
|
* @name pascalprecht.translate.$translateProvider#preferredLanguage
|
677
784
|
* @methodOf pascalprecht.translate.$translateProvider
|
@@ -682,12 +789,13 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
682
789
|
* only that it says which language to **prefer**.
|
683
790
|
*
|
684
791
|
* @param {string} langKey A language key.
|
685
|
-
*
|
686
792
|
*/
|
687
|
-
this.preferredLanguage = function(langKey) {
|
688
|
-
|
689
|
-
|
690
|
-
|
793
|
+
this.preferredLanguage = function (langKey) {
|
794
|
+
if (langKey) {
|
795
|
+
setupPreferredLanguage(langKey);
|
796
|
+
return this;
|
797
|
+
}
|
798
|
+
return $preferredLanguage;
|
691
799
|
};
|
692
800
|
var setupPreferredLanguage = function (langKey) {
|
693
801
|
if (langKey) {
|
@@ -780,12 +888,12 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
780
888
|
if (langKey) {
|
781
889
|
if (angular.isString(langKey)) {
|
782
890
|
$fallbackWasString = true;
|
783
|
-
$fallbackLanguage = [
|
891
|
+
$fallbackLanguage = [langKey];
|
784
892
|
} else if (angular.isArray(langKey)) {
|
785
893
|
$fallbackWasString = false;
|
786
894
|
$fallbackLanguage = langKey;
|
787
895
|
}
|
788
|
-
if (angular.isString($preferredLanguage)
|
896
|
+
if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) {
|
789
897
|
$fallbackLanguage.push($preferredLanguage);
|
790
898
|
}
|
791
899
|
|
@@ -825,7 +933,21 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
825
933
|
return $uses;
|
826
934
|
};
|
827
935
|
|
828
|
-
|
936
|
+
/**
|
937
|
+
* @ngdoc function
|
938
|
+
* @name pascalprecht.translate.$translateProvider#resolveClientLocale
|
939
|
+
* @methodOf pascalprecht.translate.$translateProvider
|
940
|
+
*
|
941
|
+
* @description
|
942
|
+
* This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.
|
943
|
+
*
|
944
|
+
* @returns {string} the current client/browser language key
|
945
|
+
*/
|
946
|
+
this.resolveClientLocale = function () {
|
947
|
+
return getLocale();
|
948
|
+
};
|
949
|
+
|
950
|
+
/**
|
829
951
|
* @ngdoc function
|
830
952
|
* @name pascalprecht.translate.$translateProvider#storageKey
|
831
953
|
* @methodOf pascalprecht.translate.$translateProvider
|
@@ -835,7 +957,7 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
835
957
|
*
|
836
958
|
* @param {string} key A key for the storage.
|
837
959
|
*/
|
838
|
-
var storageKey = function(key) {
|
960
|
+
var storageKey = function (key) {
|
839
961
|
if (!key) {
|
840
962
|
if ($storagePrefix) {
|
841
963
|
return $storagePrefix + $storageKey;
|
@@ -860,7 +982,7 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
860
982
|
* @param {Object=} options Optional configuration object
|
861
983
|
*/
|
862
984
|
this.useUrlLoader = function (url, options) {
|
863
|
-
return this.useLoader('$translateUrlLoader', angular.extend({
|
985
|
+
return this.useLoader('$translateUrlLoader', angular.extend({url : url}, options));
|
864
986
|
};
|
865
987
|
|
866
988
|
/**
|
@@ -1091,7 +1213,7 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
1091
1213
|
options = {};
|
1092
1214
|
} else if (angular.isString(options)) {
|
1093
1215
|
options = {
|
1094
|
-
standard: options
|
1216
|
+
standard : options
|
1095
1217
|
};
|
1096
1218
|
}
|
1097
1219
|
|
@@ -1126,7 +1248,7 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
1126
1248
|
if (!$availableLanguageKeys.length) {
|
1127
1249
|
$preferredLanguage = locale;
|
1128
1250
|
} else {
|
1129
|
-
$preferredLanguage = negotiateLocale(locale);
|
1251
|
+
$preferredLanguage = negotiateLocale(locale) || locale;
|
1130
1252
|
}
|
1131
1253
|
|
1132
1254
|
return this;
|
@@ -1166,7 +1288,7 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
1166
1288
|
*
|
1167
1289
|
* @description
|
1168
1290
|
* Registers a cache for internal $http based loaders.
|
1169
|
-
* {@link pascalprecht.translate.$
|
1291
|
+
* {@link pascalprecht.translate.$translationCache $translationCache}.
|
1170
1292
|
* When false the cache will be disabled (default). When true or undefined
|
1171
1293
|
* the cache will be a default (see $cacheFactory). When an object it will
|
1172
1294
|
* be treat as a cache object itself: the usage is $http({cache: cache})
|
@@ -1237,6 +1359,48 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
1237
1359
|
}
|
1238
1360
|
};
|
1239
1361
|
|
1362
|
+
/**
|
1363
|
+
* @ngdoc function
|
1364
|
+
* @name pascalprecht.translate.$translateProvider#postProcess
|
1365
|
+
* @methodOf pascalprecht.translate.$translateProvider
|
1366
|
+
*
|
1367
|
+
* @description
|
1368
|
+
* The post processor will be intercept right after the translation result. It can modify the result.
|
1369
|
+
*
|
1370
|
+
* @param {object} fn Function or service name (string) to be called after the translation value has been set / resolved. The function itself will enrich every value being processed and then continue the normal resolver process
|
1371
|
+
*/
|
1372
|
+
this.postProcess = function (fn) {
|
1373
|
+
if (fn) {
|
1374
|
+
postProcessFn = fn;
|
1375
|
+
} else {
|
1376
|
+
postProcessFn = undefined;
|
1377
|
+
}
|
1378
|
+
return this;
|
1379
|
+
};
|
1380
|
+
|
1381
|
+
/**
|
1382
|
+
* @ngdoc function
|
1383
|
+
* @name pascalprecht.translate.$translateProvider#keepContent
|
1384
|
+
* @methodOf pascalprecht.translate.$translateProvider
|
1385
|
+
*
|
1386
|
+
* @description
|
1387
|
+
* If keepContent is set to true than translate directive will always use innerHTML
|
1388
|
+
* as a default translation
|
1389
|
+
*
|
1390
|
+
* Example:
|
1391
|
+
* <pre>
|
1392
|
+
* app.config(function ($translateProvider) {
|
1393
|
+
* $translateProvider.keepContent(true);
|
1394
|
+
* });
|
1395
|
+
* </pre>
|
1396
|
+
*
|
1397
|
+
* @param {boolean} value - valid values are true or false
|
1398
|
+
*/
|
1399
|
+
this.keepContent = function (value) {
|
1400
|
+
$keepContent = !(!value);
|
1401
|
+
return this;
|
1402
|
+
};
|
1403
|
+
|
1240
1404
|
/**
|
1241
1405
|
* @ngdoc object
|
1242
1406
|
* @name pascalprecht.translate.$translate
|
@@ -1261,1069 +1425,1344 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
|
|
1261
1425
|
* is the translation id and the value the translation.
|
1262
1426
|
* @param {object=} interpolateParams An object hash for dynamic values
|
1263
1427
|
* @param {string} interpolationId The id of the interpolation to use
|
1428
|
+
* @param {string} defaultTranslationText the optional default translation text that is written as
|
1429
|
+
* as default text in case it is not found in any configured language
|
1430
|
+
* @param {string} forceLanguage A language to be used instead of the current language
|
1264
1431
|
* @returns {object} promise
|
1265
1432
|
*/
|
1266
|
-
this.$get = [
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1433
|
+
this.$get = ['$log', '$injector', '$rootScope', '$q', function ($log, $injector, $rootScope, $q) {
|
1434
|
+
|
1435
|
+
var Storage,
|
1436
|
+
defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'),
|
1437
|
+
pendingLoader = false,
|
1438
|
+
interpolatorHashMap = {},
|
1439
|
+
langPromises = {},
|
1440
|
+
fallbackIndex,
|
1441
|
+
startFallbackIteration;
|
1442
|
+
|
1443
|
+
var $translate = function (translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage) {
|
1444
|
+
if (!$uses && $preferredLanguage) {
|
1445
|
+
$uses = $preferredLanguage;
|
1446
|
+
}
|
1447
|
+
var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses
|
1448
|
+
(negotiateLocale(forceLanguage) || forceLanguage) : $uses;
|
1449
|
+
|
1450
|
+
// Check forceLanguage is present
|
1451
|
+
if (forceLanguage) {
|
1452
|
+
loadTranslationsIfMissing(forceLanguage);
|
1453
|
+
}
|
1454
|
+
|
1455
|
+
// Duck detection: If the first argument is an array, a bunch of translations was requested.
|
1456
|
+
// The result is an object.
|
1457
|
+
if (angular.isArray(translationId)) {
|
1458
|
+
// Inspired by Q.allSettled by Kris Kowal
|
1459
|
+
// https://github.com/kriskowal/q/blob/b0fa72980717dc202ffc3cbf03b936e10ebbb9d7/q.js#L1553-1563
|
1460
|
+
// This transforms all promises regardless resolved or rejected
|
1461
|
+
var translateAll = function (translationIds) {
|
1462
|
+
var results = {}; // storing the actual results
|
1463
|
+
var promises = []; // promises to wait for
|
1464
|
+
// Wraps the promise a) being always resolved and b) storing the link id->value
|
1465
|
+
var translate = function (translationId) {
|
1466
|
+
var deferred = $q.defer();
|
1467
|
+
var regardless = function (value) {
|
1468
|
+
results[translationId] = value;
|
1469
|
+
deferred.resolve([translationId, value]);
|
1302
1470
|
};
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
// wait for all (including storing to results)
|
1307
|
-
return $q.all(promises).then(function () {
|
1308
|
-
// return the results
|
1309
|
-
return results;
|
1310
|
-
});
|
1471
|
+
// we don't care whether the promise was resolved or rejected; just store the values
|
1472
|
+
$translate(translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage).then(regardless, regardless);
|
1473
|
+
return deferred.promise;
|
1311
1474
|
};
|
1312
|
-
|
1313
|
-
|
1475
|
+
for (var i = 0, c = translationIds.length; i < c; i++) {
|
1476
|
+
promises.push(translate(translationIds[i]));
|
1477
|
+
}
|
1478
|
+
// wait for all (including storing to results)
|
1479
|
+
return $q.all(promises).then(function () {
|
1480
|
+
// return the results
|
1481
|
+
return results;
|
1482
|
+
});
|
1483
|
+
};
|
1484
|
+
return translateAll(translationId);
|
1485
|
+
}
|
1314
1486
|
|
1315
|
-
|
1487
|
+
var deferred = $q.defer();
|
1316
1488
|
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1489
|
+
// trim off any whitespace
|
1490
|
+
if (translationId) {
|
1491
|
+
translationId = trim.apply(translationId);
|
1492
|
+
}
|
1321
1493
|
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1494
|
+
var promiseToWaitFor = (function () {
|
1495
|
+
var promise = $preferredLanguage ?
|
1496
|
+
langPromises[$preferredLanguage] :
|
1497
|
+
langPromises[uses];
|
1326
1498
|
|
1327
|
-
|
1499
|
+
fallbackIndex = 0;
|
1328
1500
|
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
}
|
1501
|
+
if ($storageFactory && !promise) {
|
1502
|
+
// looks like there's no pending promise for $preferredLanguage or
|
1503
|
+
// $uses. Maybe there's one pending for a language that comes from
|
1504
|
+
// storage.
|
1505
|
+
var langKey = Storage.get($storageKey);
|
1506
|
+
promise = langPromises[langKey];
|
1507
|
+
|
1508
|
+
if ($fallbackLanguage && $fallbackLanguage.length) {
|
1509
|
+
var index = indexOf($fallbackLanguage, langKey);
|
1510
|
+
// maybe the language from storage is also defined as fallback language
|
1511
|
+
// we increase the fallback language index to not search in that language
|
1512
|
+
// as fallback, since it's probably the first used language
|
1513
|
+
// in that case the index starts after the first element
|
1514
|
+
fallbackIndex = (index === 0) ? 1 : 0;
|
1515
|
+
|
1516
|
+
// but we can make sure to ALWAYS fallback to preferred language at least
|
1517
|
+
if (indexOf($fallbackLanguage, $preferredLanguage) < 0) {
|
1518
|
+
$fallbackLanguage.push($preferredLanguage);
|
1348
1519
|
}
|
1349
1520
|
}
|
1350
|
-
return promise;
|
1351
|
-
}());
|
1352
|
-
|
1353
|
-
if (!promiseToWaitFor) {
|
1354
|
-
// no promise to wait for? okay. Then there's no loader registered
|
1355
|
-
// nor is a one pending for language that comes from storage.
|
1356
|
-
// We can just translate.
|
1357
|
-
determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText).then(deferred.resolve, deferred.reject);
|
1358
|
-
} else {
|
1359
|
-
var promiseResolved = function () {
|
1360
|
-
determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText).then(deferred.resolve, deferred.reject);
|
1361
|
-
};
|
1362
|
-
promiseResolved.displayName = 'promiseResolved';
|
1363
|
-
|
1364
|
-
promiseToWaitFor['finally'](promiseResolved, deferred.reject);
|
1365
1521
|
}
|
1366
|
-
return
|
1367
|
-
};
|
1522
|
+
return promise;
|
1523
|
+
}());
|
1524
|
+
|
1525
|
+
if (!promiseToWaitFor) {
|
1526
|
+
// no promise to wait for? okay. Then there's no loader registered
|
1527
|
+
// nor is a one pending for language that comes from storage.
|
1528
|
+
// We can just translate.
|
1529
|
+
determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject);
|
1530
|
+
} else {
|
1531
|
+
var promiseResolved = function () {
|
1532
|
+
// $uses may have changed while waiting
|
1533
|
+
if (!forceLanguage) {
|
1534
|
+
uses = $uses;
|
1535
|
+
}
|
1536
|
+
determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses).then(deferred.resolve, deferred.reject);
|
1537
|
+
};
|
1538
|
+
promiseResolved.displayName = 'promiseResolved';
|
1368
1539
|
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
* @description
|
1374
|
-
* Applies not fount indicators to given translation id, if needed.
|
1375
|
-
* This function gets only executed, if a translation id doesn't exist,
|
1376
|
-
* which is why a translation id is expected as argument.
|
1377
|
-
*
|
1378
|
-
* @param {string} translationId Translation id.
|
1379
|
-
* @returns {string} Same as given translation id but applied with not found
|
1380
|
-
* indicators.
|
1381
|
-
*/
|
1382
|
-
var applyNotFoundIndicators = function (translationId) {
|
1383
|
-
// applying notFoundIndicators
|
1384
|
-
if ($notFoundIndicatorLeft) {
|
1385
|
-
translationId = [$notFoundIndicatorLeft, translationId].join(' ');
|
1386
|
-
}
|
1387
|
-
if ($notFoundIndicatorRight) {
|
1388
|
-
translationId = [translationId, $notFoundIndicatorRight].join(' ');
|
1389
|
-
}
|
1390
|
-
return translationId;
|
1391
|
-
};
|
1540
|
+
promiseToWaitFor['finally'](promiseResolved)['catch'](angular.noop); // we don't care about errors here, already handled
|
1541
|
+
}
|
1542
|
+
return deferred.promise;
|
1543
|
+
};
|
1392
1544
|
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1545
|
+
/**
|
1546
|
+
* @name applyNotFoundIndicators
|
1547
|
+
* @private
|
1548
|
+
*
|
1549
|
+
* @description
|
1550
|
+
* Applies not fount indicators to given translation id, if needed.
|
1551
|
+
* This function gets only executed, if a translation id doesn't exist,
|
1552
|
+
* which is why a translation id is expected as argument.
|
1553
|
+
*
|
1554
|
+
* @param {string} translationId Translation id.
|
1555
|
+
* @returns {string} Same as given translation id but applied with not found
|
1556
|
+
* indicators.
|
1557
|
+
*/
|
1558
|
+
var applyNotFoundIndicators = function (translationId) {
|
1559
|
+
// applying notFoundIndicators
|
1560
|
+
if ($notFoundIndicatorLeft) {
|
1561
|
+
translationId = [$notFoundIndicatorLeft, translationId].join(' ');
|
1562
|
+
}
|
1563
|
+
if ($notFoundIndicatorRight) {
|
1564
|
+
translationId = [translationId, $notFoundIndicatorRight].join(' ');
|
1565
|
+
}
|
1566
|
+
return translationId;
|
1567
|
+
};
|
1407
1568
|
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1569
|
+
/**
|
1570
|
+
* @name useLanguage
|
1571
|
+
* @private
|
1572
|
+
*
|
1573
|
+
* @description
|
1574
|
+
* Makes actual use of a language by setting a given language key as used
|
1575
|
+
* language and informs registered interpolators to also use the given
|
1576
|
+
* key as locale.
|
1577
|
+
*
|
1578
|
+
* @param {string} key Locale key.
|
1579
|
+
*/
|
1580
|
+
var useLanguage = function (key) {
|
1581
|
+
$uses = key;
|
1582
|
+
|
1583
|
+
// make sure to store new language key before triggering success event
|
1584
|
+
if ($storageFactory) {
|
1585
|
+
Storage.put($translate.storageKey(), $uses);
|
1586
|
+
}
|
1413
1587
|
|
1414
|
-
|
1415
|
-
interpolatorHashMap[id].setLocale($uses);
|
1416
|
-
};
|
1417
|
-
eachInterpolator.displayName = 'eachInterpolatorLocaleSetter';
|
1588
|
+
$rootScope.$emit('$translateChangeSuccess', {language : key});
|
1418
1589
|
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1590
|
+
// inform default interpolator
|
1591
|
+
defaultInterpolator.setLocale($uses);
|
1592
|
+
|
1593
|
+
var eachInterpolator = function (interpolator, id) {
|
1594
|
+
interpolatorHashMap[id].setLocale($uses);
|
1422
1595
|
};
|
1596
|
+
eachInterpolator.displayName = 'eachInterpolatorLocaleSetter';
|
1423
1597
|
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
* @description
|
1429
|
-
* Kicks of registered async loader using `$injector` and applies existing
|
1430
|
-
* loader options. When resolved, it updates translation tables accordingly
|
1431
|
-
* or rejects with given language key.
|
1432
|
-
*
|
1433
|
-
* @param {string} key Language key.
|
1434
|
-
* @return {Promise} A promise.
|
1435
|
-
*/
|
1436
|
-
var loadAsync = function (key) {
|
1437
|
-
if (!key) {
|
1438
|
-
throw 'No language key specified for loading.';
|
1439
|
-
}
|
1598
|
+
// inform all others too!
|
1599
|
+
angular.forEach(interpolatorHashMap, eachInterpolator);
|
1600
|
+
$rootScope.$emit('$translateChangeEnd', {language : key});
|
1601
|
+
};
|
1440
1602
|
|
1441
|
-
|
1603
|
+
/**
|
1604
|
+
* @name loadAsync
|
1605
|
+
* @private
|
1606
|
+
*
|
1607
|
+
* @description
|
1608
|
+
* Kicks off registered async loader using `$injector` and applies existing
|
1609
|
+
* loader options. When resolved, it updates translation tables accordingly
|
1610
|
+
* or rejects with given language key.
|
1611
|
+
*
|
1612
|
+
* @param {string} key Language key.
|
1613
|
+
* @return {Promise} A promise.
|
1614
|
+
*/
|
1615
|
+
var loadAsync = function (key) {
|
1616
|
+
if (!key) {
|
1617
|
+
throw 'No language key specified for loading.';
|
1618
|
+
}
|
1442
1619
|
|
1443
|
-
|
1444
|
-
pendingLoader = true;
|
1620
|
+
var deferred = $q.defer();
|
1445
1621
|
|
1446
|
-
|
1447
|
-
|
1448
|
-
// getting on-demand instance of loader
|
1449
|
-
cache = $injector.get(cache);
|
1450
|
-
}
|
1622
|
+
$rootScope.$emit('$translateLoadingStart', {language : key});
|
1623
|
+
pendingLoader = true;
|
1451
1624
|
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
});
|
1625
|
+
var cache = loaderCache;
|
1626
|
+
if (typeof(cache) === 'string') {
|
1627
|
+
// getting on-demand instance of loader
|
1628
|
+
cache = $injector.get(cache);
|
1629
|
+
}
|
1458
1630
|
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1631
|
+
var loaderOptions = angular.extend({}, $loaderOptions, {
|
1632
|
+
key : key,
|
1633
|
+
$http : angular.extend({}, {
|
1634
|
+
cache : cache
|
1635
|
+
}, $loaderOptions.$http)
|
1636
|
+
});
|
1462
1637
|
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
pendingLoader = false;
|
1471
|
-
deferred.resolve({
|
1472
|
-
key: key,
|
1473
|
-
table: translationTable
|
1638
|
+
var onLoaderSuccess = function (data) {
|
1639
|
+
var translationTable = {};
|
1640
|
+
$rootScope.$emit('$translateLoadingSuccess', {language : key});
|
1641
|
+
|
1642
|
+
if (angular.isArray(data)) {
|
1643
|
+
angular.forEach(data, function (table) {
|
1644
|
+
angular.extend(translationTable, flatObject(table));
|
1474
1645
|
});
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1646
|
+
} else {
|
1647
|
+
angular.extend(translationTable, flatObject(data));
|
1648
|
+
}
|
1649
|
+
pendingLoader = false;
|
1650
|
+
deferred.resolve({
|
1651
|
+
key : key,
|
1652
|
+
table : translationTable
|
1653
|
+
});
|
1654
|
+
$rootScope.$emit('$translateLoadingEnd', {language : key});
|
1655
|
+
};
|
1656
|
+
onLoaderSuccess.displayName = 'onLoaderSuccess';
|
1478
1657
|
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1658
|
+
var onLoaderError = function (key) {
|
1659
|
+
$rootScope.$emit('$translateLoadingError', {language : key});
|
1660
|
+
deferred.reject(key);
|
1661
|
+
$rootScope.$emit('$translateLoadingEnd', {language : key});
|
1662
|
+
};
|
1663
|
+
onLoaderError.displayName = 'onLoaderError';
|
1485
1664
|
|
1486
|
-
|
1487
|
-
|
1665
|
+
$injector.get($loaderFactory)(loaderOptions)
|
1666
|
+
.then(onLoaderSuccess, onLoaderError);
|
1488
1667
|
|
1489
|
-
|
1490
|
-
|
1668
|
+
return deferred.promise;
|
1669
|
+
};
|
1491
1670
|
|
1492
|
-
|
1493
|
-
|
1671
|
+
if ($storageFactory) {
|
1672
|
+
Storage = $injector.get($storageFactory);
|
1494
1673
|
|
1495
|
-
|
1496
|
-
|
1497
|
-
}
|
1674
|
+
if (!Storage.get || !Storage.put) {
|
1675
|
+
throw new Error('Couldn\'t use storage \'' + $storageFactory + '\', missing get() or put() method!');
|
1498
1676
|
}
|
1677
|
+
}
|
1499
1678
|
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1679
|
+
// if we have additional interpolations that were added via
|
1680
|
+
// $translateProvider.addInterpolation(), we have to map'em
|
1681
|
+
if ($interpolatorFactories.length) {
|
1682
|
+
var eachInterpolationFactory = function (interpolatorFactory) {
|
1683
|
+
var interpolator = $injector.get(interpolatorFactory);
|
1684
|
+
// setting initial locale for each interpolation service
|
1685
|
+
interpolator.setLocale($preferredLanguage || $uses);
|
1686
|
+
// make'em recognizable through id
|
1687
|
+
interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;
|
1688
|
+
};
|
1689
|
+
eachInterpolationFactory.displayName = 'interpolationFactoryAdder';
|
1690
|
+
|
1691
|
+
angular.forEach($interpolatorFactories, eachInterpolationFactory);
|
1692
|
+
}
|
1511
1693
|
|
1512
|
-
|
1694
|
+
/**
|
1695
|
+
* @name getTranslationTable
|
1696
|
+
* @private
|
1697
|
+
*
|
1698
|
+
* @description
|
1699
|
+
* Returns a promise that resolves to the translation table
|
1700
|
+
* or is rejected if an error occurred.
|
1701
|
+
*
|
1702
|
+
* @param langKey
|
1703
|
+
* @returns {Q.promise}
|
1704
|
+
*/
|
1705
|
+
var getTranslationTable = function (langKey) {
|
1706
|
+
var deferred = $q.defer();
|
1707
|
+
if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) {
|
1708
|
+
deferred.resolve($translationTable[langKey]);
|
1709
|
+
} else if (langPromises[langKey]) {
|
1710
|
+
var onResolve = function (data) {
|
1711
|
+
translations(data.key, data.table);
|
1712
|
+
deferred.resolve(data.table);
|
1713
|
+
};
|
1714
|
+
onResolve.displayName = 'translationTableResolver';
|
1715
|
+
langPromises[langKey].then(onResolve, deferred.reject);
|
1716
|
+
} else {
|
1717
|
+
deferred.reject();
|
1513
1718
|
}
|
1719
|
+
return deferred.promise;
|
1720
|
+
};
|
1514
1721
|
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1722
|
+
/**
|
1723
|
+
* @name getFallbackTranslation
|
1724
|
+
* @private
|
1725
|
+
*
|
1726
|
+
* @description
|
1727
|
+
* Returns a promise that will resolve to the translation
|
1728
|
+
* or be rejected if no translation was found for the language.
|
1729
|
+
* This function is currently only used for fallback language translation.
|
1730
|
+
*
|
1731
|
+
* @param langKey The language to translate to.
|
1732
|
+
* @param translationId
|
1733
|
+
* @param interpolateParams
|
1734
|
+
* @param Interpolator
|
1735
|
+
* @param sanitizeStrategy
|
1736
|
+
* @returns {Q.promise}
|
1737
|
+
*/
|
1738
|
+
var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {
|
1739
|
+
var deferred = $q.defer();
|
1740
|
+
|
1741
|
+
var onResolve = function (translationTable) {
|
1742
|
+
if (Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {
|
1743
|
+
Interpolator.setLocale(langKey);
|
1744
|
+
var translation = translationTable[translationId];
|
1745
|
+
if (translation.substr(0, 2) === '@:') {
|
1746
|
+
getFallbackTranslation(langKey, translation.substr(2), interpolateParams, Interpolator, sanitizeStrategy)
|
1747
|
+
.then(deferred.resolve, deferred.reject);
|
1748
|
+
} else {
|
1749
|
+
var interpolatedValue = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'service', sanitizeStrategy, translationId);
|
1750
|
+
interpolatedValue = applyPostProcessing(translationId, translationTable[translationId], interpolatedValue, interpolateParams, langKey);
|
1751
|
+
|
1752
|
+
deferred.resolve(interpolatedValue);
|
1753
|
+
|
1754
|
+
}
|
1755
|
+
Interpolator.setLocale($uses);
|
1537
1756
|
} else {
|
1538
1757
|
deferred.reject();
|
1539
1758
|
}
|
1540
|
-
return deferred.promise;
|
1541
1759
|
};
|
1760
|
+
onResolve.displayName = 'fallbackTranslationResolver';
|
1542
1761
|
|
1543
|
-
|
1544
|
-
* @name getFallbackTranslation
|
1545
|
-
* @private
|
1546
|
-
*
|
1547
|
-
* @description
|
1548
|
-
* Returns a promise that will resolve to the translation
|
1549
|
-
* or be rejected if no translation was found for the language.
|
1550
|
-
* This function is currently only used for fallback language translation.
|
1551
|
-
*
|
1552
|
-
* @param langKey The language to translate to.
|
1553
|
-
* @param translationId
|
1554
|
-
* @param interpolateParams
|
1555
|
-
* @param Interpolator
|
1556
|
-
* @returns {Q.promise}
|
1557
|
-
*/
|
1558
|
-
var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator) {
|
1559
|
-
var deferred = $q.defer();
|
1560
|
-
|
1561
|
-
var onResolve = function (translationTable) {
|
1562
|
-
if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) {
|
1563
|
-
Interpolator.setLocale(langKey);
|
1564
|
-
var translation = translationTable[translationId];
|
1565
|
-
if (translation.substr(0, 2) === '@:') {
|
1566
|
-
getFallbackTranslation(langKey, translation.substr(2), interpolateParams, Interpolator)
|
1567
|
-
.then(deferred.resolve, deferred.reject);
|
1568
|
-
} else {
|
1569
|
-
deferred.resolve(Interpolator.interpolate(translationTable[translationId], interpolateParams));
|
1570
|
-
}
|
1571
|
-
Interpolator.setLocale($uses);
|
1572
|
-
} else {
|
1573
|
-
deferred.reject();
|
1574
|
-
}
|
1575
|
-
};
|
1576
|
-
onResolve.displayName = 'fallbackTranslationResolver';
|
1577
|
-
|
1578
|
-
getTranslationTable(langKey).then(onResolve, deferred.reject);
|
1762
|
+
getTranslationTable(langKey).then(onResolve, deferred.reject);
|
1579
1763
|
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
/**
|
1584
|
-
* @name getFallbackTranslationInstant
|
1585
|
-
* @private
|
1586
|
-
*
|
1587
|
-
* @description
|
1588
|
-
* Returns a translation
|
1589
|
-
* This function is currently only used for fallback language translation.
|
1590
|
-
*
|
1591
|
-
* @param langKey The language to translate to.
|
1592
|
-
* @param translationId
|
1593
|
-
* @param interpolateParams
|
1594
|
-
* @param Interpolator
|
1595
|
-
* @returns {string} translation
|
1596
|
-
*/
|
1597
|
-
var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator) {
|
1598
|
-
var result, translationTable = $translationTable[langKey];
|
1764
|
+
return deferred.promise;
|
1765
|
+
};
|
1599
1766
|
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1767
|
+
/**
|
1768
|
+
* @name getFallbackTranslationInstant
|
1769
|
+
* @private
|
1770
|
+
*
|
1771
|
+
* @description
|
1772
|
+
* Returns a translation
|
1773
|
+
* This function is currently only used for fallback language translation.
|
1774
|
+
*
|
1775
|
+
* @param langKey The language to translate to.
|
1776
|
+
* @param translationId
|
1777
|
+
* @param interpolateParams
|
1778
|
+
* @param Interpolator
|
1779
|
+
* @param sanitizeStrategy sanitize strategy override
|
1780
|
+
*
|
1781
|
+
* @returns {string} translation
|
1782
|
+
*/
|
1783
|
+
var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {
|
1784
|
+
var result, translationTable = $translationTable[langKey];
|
1785
|
+
|
1786
|
+
if (translationTable && Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {
|
1787
|
+
Interpolator.setLocale(langKey);
|
1788
|
+
result = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'filter', sanitizeStrategy, translationId);
|
1789
|
+
result = applyPostProcessing(translationId, translationTable[translationId], result, interpolateParams, langKey, sanitizeStrategy);
|
1790
|
+
// workaround for TrustedValueHolderType
|
1791
|
+
if (!angular.isString(result) && angular.isFunction(result.$$unwrapTrustedValue)) {
|
1792
|
+
var result2 = result.$$unwrapTrustedValue();
|
1793
|
+
if (result2.substr(0, 2) === '@:') {
|
1794
|
+
return getFallbackTranslationInstant(langKey, result2.substr(2), interpolateParams, Interpolator, sanitizeStrategy);
|
1605
1795
|
}
|
1606
|
-
|
1796
|
+
} else if (result.substr(0, 2) === '@:') {
|
1797
|
+
return getFallbackTranslationInstant(langKey, result.substr(2), interpolateParams, Interpolator, sanitizeStrategy);
|
1607
1798
|
}
|
1799
|
+
Interpolator.setLocale($uses);
|
1800
|
+
}
|
1608
1801
|
|
1609
|
-
|
1610
|
-
|
1802
|
+
return result;
|
1803
|
+
};
|
1611
1804
|
|
1612
1805
|
|
1613
|
-
|
1614
|
-
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1806
|
+
/**
|
1807
|
+
* @name translateByHandler
|
1808
|
+
* @private
|
1809
|
+
*
|
1810
|
+
* Translate by missing translation handler.
|
1811
|
+
*
|
1812
|
+
* @param translationId
|
1813
|
+
* @param interpolateParams
|
1814
|
+
* @param defaultTranslationText
|
1815
|
+
* @param sanitizeStrategy sanitize strategy override
|
1816
|
+
*
|
1817
|
+
* @returns translation created by $missingTranslationHandler or translationId is $missingTranslationHandler is
|
1818
|
+
* absent
|
1819
|
+
*/
|
1820
|
+
var translateByHandler = function (translationId, interpolateParams, defaultTranslationText, sanitizeStrategy) {
|
1821
|
+
// If we have a handler factory - we might also call it here to determine if it provides
|
1822
|
+
// a default text for a translationid that can't be found anywhere in our tables
|
1823
|
+
if ($missingTranslationHandlerFactory) {
|
1824
|
+
return $injector.get($missingTranslationHandlerFactory)(translationId, $uses, interpolateParams, defaultTranslationText, sanitizeStrategy);
|
1825
|
+
} else {
|
1826
|
+
return translationId;
|
1827
|
+
}
|
1828
|
+
};
|
1829
|
+
|
1830
|
+
/**
|
1831
|
+
* @name resolveForFallbackLanguage
|
1832
|
+
* @private
|
1833
|
+
*
|
1834
|
+
* Recursive helper function for fallbackTranslation that will sequentially look
|
1835
|
+
* for a translation in the fallbackLanguages starting with fallbackLanguageIndex.
|
1836
|
+
*
|
1837
|
+
* @param fallbackLanguageIndex
|
1838
|
+
* @param translationId
|
1839
|
+
* @param interpolateParams
|
1840
|
+
* @param Interpolator
|
1841
|
+
* @param defaultTranslationText
|
1842
|
+
* @param sanitizeStrategy
|
1843
|
+
* @returns {Q.promise} Promise that will resolve to the translation.
|
1844
|
+
*/
|
1845
|
+
var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {
|
1846
|
+
var deferred = $q.defer();
|
1847
|
+
|
1848
|
+
if (fallbackLanguageIndex < $fallbackLanguage.length) {
|
1849
|
+
var langKey = $fallbackLanguage[fallbackLanguageIndex];
|
1850
|
+
getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy).then(
|
1851
|
+
function (data) {
|
1852
|
+
deferred.resolve(data);
|
1853
|
+
},
|
1854
|
+
function () {
|
1855
|
+
// Look in the next fallback language for a translation.
|
1856
|
+
// It delays the resolving by passing another promise to resolve.
|
1857
|
+
return resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy).then(deferred.resolve, deferred.reject);
|
1632
1858
|
}
|
1859
|
+
);
|
1860
|
+
} else {
|
1861
|
+
// No translation found in any fallback language
|
1862
|
+
// if a default translation text is set in the directive, then return this as a result
|
1863
|
+
if (defaultTranslationText) {
|
1864
|
+
deferred.resolve(defaultTranslationText);
|
1633
1865
|
} else {
|
1634
|
-
|
1635
|
-
}
|
1636
|
-
};
|
1866
|
+
var missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);
|
1637
1867
|
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
* Recursive helper function for fallbackTranslation that will sequentially look
|
1643
|
-
* for a translation in the fallbackLanguages starting with fallbackLanguageIndex.
|
1644
|
-
*
|
1645
|
-
* @param fallbackLanguageIndex
|
1646
|
-
* @param translationId
|
1647
|
-
* @param interpolateParams
|
1648
|
-
* @param Interpolator
|
1649
|
-
* @returns {Q.promise} Promise that will resolve to the translation.
|
1650
|
-
*/
|
1651
|
-
var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, defaultTranslationText) {
|
1652
|
-
var deferred = $q.defer();
|
1653
|
-
|
1654
|
-
if (fallbackLanguageIndex < $fallbackLanguage.length) {
|
1655
|
-
var langKey = $fallbackLanguage[fallbackLanguageIndex];
|
1656
|
-
getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator).then(
|
1657
|
-
deferred.resolve,
|
1658
|
-
function () {
|
1659
|
-
// Look in the next fallback language for a translation.
|
1660
|
-
// It delays the resolving by passing another promise to resolve.
|
1661
|
-
resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator, defaultTranslationText).then(deferred.resolve);
|
1662
|
-
}
|
1663
|
-
);
|
1664
|
-
} else {
|
1665
|
-
// No translation found in any fallback language
|
1666
|
-
// if a default translation text is set in the directive, then return this as a result
|
1667
|
-
if (defaultTranslationText) {
|
1668
|
-
deferred.resolve(defaultTranslationText);
|
1868
|
+
// if no default translation is set and an error handler is defined, send it to the handler
|
1869
|
+
// and then return the result if it isn't undefined
|
1870
|
+
if ($missingTranslationHandlerFactory && missingTranslationHandlerTranslation) {
|
1871
|
+
deferred.resolve(missingTranslationHandlerTranslation);
|
1669
1872
|
} else {
|
1670
|
-
|
1671
|
-
// and then return the result
|
1672
|
-
deferred.resolve(translateByHandler(translationId, interpolateParams));
|
1873
|
+
deferred.reject(applyNotFoundIndicators(translationId));
|
1673
1874
|
}
|
1674
1875
|
}
|
1675
|
-
|
1676
|
-
|
1876
|
+
}
|
1877
|
+
return deferred.promise;
|
1878
|
+
};
|
1677
1879
|
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1880
|
+
/**
|
1881
|
+
* @name resolveForFallbackLanguageInstant
|
1882
|
+
* @private
|
1883
|
+
*
|
1884
|
+
* Recursive helper function for fallbackTranslation that will sequentially look
|
1885
|
+
* for a translation in the fallbackLanguages starting with fallbackLanguageIndex.
|
1886
|
+
*
|
1887
|
+
* @param fallbackLanguageIndex
|
1888
|
+
* @param translationId
|
1889
|
+
* @param interpolateParams
|
1890
|
+
* @param Interpolator
|
1891
|
+
* @param sanitizeStrategy
|
1892
|
+
* @returns {string} translation
|
1893
|
+
*/
|
1894
|
+
var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, sanitizeStrategy) {
|
1895
|
+
var result;
|
1896
|
+
|
1897
|
+
if (fallbackLanguageIndex < $fallbackLanguage.length) {
|
1898
|
+
var langKey = $fallbackLanguage[fallbackLanguageIndex];
|
1899
|
+
result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy);
|
1900
|
+
if (!result && result !== '') {
|
1901
|
+
result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);
|
1700
1902
|
}
|
1701
|
-
|
1702
|
-
|
1903
|
+
}
|
1904
|
+
return result;
|
1905
|
+
};
|
1703
1906
|
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1907
|
+
/**
|
1908
|
+
* Translates with the usage of the fallback languages.
|
1909
|
+
*
|
1910
|
+
* @param translationId
|
1911
|
+
* @param interpolateParams
|
1912
|
+
* @param Interpolator
|
1913
|
+
* @param defaultTranslationText
|
1914
|
+
* @param sanitizeStrategy
|
1915
|
+
* @returns {Q.promise} Promise, that resolves to the translation.
|
1916
|
+
*/
|
1917
|
+
var fallbackTranslation = function (translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {
|
1918
|
+
// Start with the fallbackLanguage with index 0
|
1919
|
+
return resolveForFallbackLanguage((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy);
|
1920
|
+
};
|
1716
1921
|
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1922
|
+
/**
|
1923
|
+
* Translates with the usage of the fallback languages.
|
1924
|
+
*
|
1925
|
+
* @param translationId
|
1926
|
+
* @param interpolateParams
|
1927
|
+
* @param Interpolator
|
1928
|
+
* @param sanitizeStrategy
|
1929
|
+
* @returns {String} translation
|
1930
|
+
*/
|
1931
|
+
var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator, sanitizeStrategy) {
|
1932
|
+
// Start with the fallbackLanguage with index 0
|
1933
|
+
return resolveForFallbackLanguageInstant((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, sanitizeStrategy);
|
1934
|
+
};
|
1729
1935
|
|
1730
|
-
|
1936
|
+
var determineTranslation = function (translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy) {
|
1731
1937
|
|
1732
|
-
|
1938
|
+
var deferred = $q.defer();
|
1733
1939
|
|
1734
|
-
|
1735
|
-
|
1940
|
+
var table = uses ? $translationTable[uses] : $translationTable,
|
1941
|
+
Interpolator = (interpolationId) ? interpolatorHashMap[interpolationId] : defaultInterpolator;
|
1736
1942
|
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1943
|
+
// if the translation id exists, we can just interpolate it
|
1944
|
+
if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {
|
1945
|
+
var translation = table[translationId];
|
1740
1946
|
|
1741
|
-
|
1742
|
-
|
1947
|
+
// If using link, rerun $translate with linked translationId and return it
|
1948
|
+
if (translation.substr(0, 2) === '@:') {
|
1743
1949
|
|
1744
|
-
|
1745
|
-
|
1950
|
+
$translate(translation.substr(2), interpolateParams, interpolationId, defaultTranslationText, uses)
|
1951
|
+
.then(deferred.resolve, deferred.reject);
|
1952
|
+
} else {
|
1953
|
+
//
|
1954
|
+
var resolvedTranslation = Interpolator.interpolate(translation, interpolateParams, 'service', sanitizeStrategy, translationId);
|
1955
|
+
resolvedTranslation = applyPostProcessing(translationId, translation, resolvedTranslation, interpolateParams, uses);
|
1956
|
+
deferred.resolve(resolvedTranslation);
|
1957
|
+
}
|
1958
|
+
} else {
|
1959
|
+
var missingTranslationHandlerTranslation;
|
1960
|
+
// for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise
|
1961
|
+
if ($missingTranslationHandlerFactory && !pendingLoader) {
|
1962
|
+
missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);
|
1963
|
+
}
|
1964
|
+
|
1965
|
+
// since we couldn't translate the inital requested translation id,
|
1966
|
+
// we try it now with one or more fallback languages, if fallback language(s) is
|
1967
|
+
// configured.
|
1968
|
+
if (uses && $fallbackLanguage && $fallbackLanguage.length) {
|
1969
|
+
fallbackTranslation(translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy)
|
1970
|
+
.then(function (translation) {
|
1971
|
+
deferred.resolve(translation);
|
1972
|
+
}, function (_translationId) {
|
1973
|
+
deferred.reject(applyNotFoundIndicators(_translationId));
|
1974
|
+
});
|
1975
|
+
} else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
|
1976
|
+
// looks like the requested translation id doesn't exists.
|
1977
|
+
// Now, if there is a registered handler for missing translations and no
|
1978
|
+
// asyncLoader is pending, we execute the handler
|
1979
|
+
if (defaultTranslationText) {
|
1980
|
+
deferred.resolve(defaultTranslationText);
|
1746
1981
|
} else {
|
1747
|
-
deferred.resolve(
|
1982
|
+
deferred.resolve(missingTranslationHandlerTranslation);
|
1748
1983
|
}
|
1749
1984
|
} else {
|
1750
|
-
|
1751
|
-
|
1752
|
-
if ($missingTranslationHandlerFactory && !pendingLoader) {
|
1753
|
-
missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams);
|
1754
|
-
}
|
1755
|
-
|
1756
|
-
// since we couldn't translate the inital requested translation id,
|
1757
|
-
// we try it now with one or more fallback languages, if fallback language(s) is
|
1758
|
-
// configured.
|
1759
|
-
if ($uses && $fallbackLanguage && $fallbackLanguage.length) {
|
1760
|
-
fallbackTranslation(translationId, interpolateParams, Interpolator, defaultTranslationText)
|
1761
|
-
.then(function (translation) {
|
1762
|
-
deferred.resolve(translation);
|
1763
|
-
}, function (_translationId) {
|
1764
|
-
deferred.reject(applyNotFoundIndicators(_translationId));
|
1765
|
-
});
|
1766
|
-
} else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
|
1767
|
-
// looks like the requested translation id doesn't exists.
|
1768
|
-
// Now, if there is a registered handler for missing translations and no
|
1769
|
-
// asyncLoader is pending, we execute the handler
|
1770
|
-
if (defaultTranslationText) {
|
1771
|
-
deferred.resolve(defaultTranslationText);
|
1772
|
-
} else {
|
1773
|
-
deferred.resolve(missingTranslationHandlerTranslation);
|
1774
|
-
}
|
1985
|
+
if (defaultTranslationText) {
|
1986
|
+
deferred.resolve(defaultTranslationText);
|
1775
1987
|
} else {
|
1776
|
-
|
1777
|
-
deferred.resolve(defaultTranslationText);
|
1778
|
-
} else {
|
1779
|
-
deferred.reject(applyNotFoundIndicators(translationId));
|
1780
|
-
}
|
1988
|
+
deferred.reject(applyNotFoundIndicators(translationId));
|
1781
1989
|
}
|
1782
1990
|
}
|
1783
|
-
|
1784
|
-
|
1991
|
+
}
|
1992
|
+
return deferred.promise;
|
1993
|
+
};
|
1785
1994
|
|
1786
|
-
|
1995
|
+
var determineTranslationInstant = function (translationId, interpolateParams, interpolationId, uses, sanitizeStrategy) {
|
1787
1996
|
|
1788
|
-
|
1789
|
-
|
1997
|
+
var result, table = uses ? $translationTable[uses] : $translationTable,
|
1998
|
+
Interpolator = defaultInterpolator;
|
1790
1999
|
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
2000
|
+
// if the interpolation id exists use custom interpolator
|
2001
|
+
if (interpolatorHashMap && Object.prototype.hasOwnProperty.call(interpolatorHashMap, interpolationId)) {
|
2002
|
+
Interpolator = interpolatorHashMap[interpolationId];
|
2003
|
+
}
|
1795
2004
|
|
1796
|
-
|
1797
|
-
|
1798
|
-
|
2005
|
+
// if the translation id exists, we can just interpolate it
|
2006
|
+
if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {
|
2007
|
+
var translation = table[translationId];
|
1799
2008
|
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
1803
|
-
} else {
|
1804
|
-
result = Interpolator.interpolate(translation, interpolateParams);
|
1805
|
-
}
|
2009
|
+
// If using link, rerun $translate with linked translationId and return it
|
2010
|
+
if (translation.substr(0, 2) === '@:') {
|
2011
|
+
result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId, uses, sanitizeStrategy);
|
1806
2012
|
} else {
|
1807
|
-
|
1808
|
-
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
2013
|
+
result = Interpolator.interpolate(translation, interpolateParams, 'filter', sanitizeStrategy, translationId);
|
2014
|
+
result = applyPostProcessing(translationId, translation, result, interpolateParams, uses, sanitizeStrategy);
|
2015
|
+
}
|
2016
|
+
} else {
|
2017
|
+
var missingTranslationHandlerTranslation;
|
2018
|
+
// for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise
|
2019
|
+
if ($missingTranslationHandlerFactory && !pendingLoader) {
|
2020
|
+
missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);
|
2021
|
+
}
|
1812
2022
|
|
1813
|
-
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
1817
|
-
|
1818
|
-
|
1819
|
-
|
1820
|
-
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1824
|
-
|
1825
|
-
|
1826
|
-
}
|
2023
|
+
// since we couldn't translate the inital requested translation id,
|
2024
|
+
// we try it now with one or more fallback languages, if fallback language(s) is
|
2025
|
+
// configured.
|
2026
|
+
if (uses && $fallbackLanguage && $fallbackLanguage.length) {
|
2027
|
+
fallbackIndex = 0;
|
2028
|
+
result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator, sanitizeStrategy);
|
2029
|
+
} else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
|
2030
|
+
// looks like the requested translation id doesn't exists.
|
2031
|
+
// Now, if there is a registered handler for missing translations and no
|
2032
|
+
// asyncLoader is pending, we execute the handler
|
2033
|
+
result = missingTranslationHandlerTranslation;
|
2034
|
+
} else {
|
2035
|
+
result = applyNotFoundIndicators(translationId);
|
1827
2036
|
}
|
2037
|
+
}
|
1828
2038
|
|
1829
|
-
|
1830
|
-
|
2039
|
+
return result;
|
2040
|
+
};
|
1831
2041
|
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
2042
|
+
var clearNextLangAndPromise = function (key) {
|
2043
|
+
if ($nextLang === key) {
|
2044
|
+
$nextLang = undefined;
|
2045
|
+
}
|
2046
|
+
langPromises[key] = undefined;
|
2047
|
+
};
|
1838
2048
|
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
* @param {string} langKey language String or Array to be used as preferredLanguage (changing at runtime)
|
1848
|
-
*
|
1849
|
-
* @return {string} preferred language key
|
1850
|
-
*/
|
1851
|
-
$translate.preferredLanguage = function (langKey) {
|
1852
|
-
if(langKey) {
|
1853
|
-
setupPreferredLanguage(langKey);
|
2049
|
+
var applyPostProcessing = function (translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy) {
|
2050
|
+
var fn = postProcessFn;
|
2051
|
+
|
2052
|
+
if (fn) {
|
2053
|
+
|
2054
|
+
if (typeof(fn) === 'string') {
|
2055
|
+
// getting on-demand instance
|
2056
|
+
fn = $injector.get(fn);
|
1854
2057
|
}
|
1855
|
-
|
1856
|
-
|
2058
|
+
if (fn) {
|
2059
|
+
return fn(translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy);
|
2060
|
+
}
|
2061
|
+
}
|
1857
2062
|
|
1858
|
-
|
1859
|
-
|
1860
|
-
* @name pascalprecht.translate.$translate#cloakClassName
|
1861
|
-
* @methodOf pascalprecht.translate.$translate
|
1862
|
-
*
|
1863
|
-
* @description
|
1864
|
-
* Returns the configured class name for `translate-cloak` directive.
|
1865
|
-
*
|
1866
|
-
* @return {string} cloakClassName
|
1867
|
-
*/
|
1868
|
-
$translate.cloakClassName = function () {
|
1869
|
-
return $cloakClassName;
|
1870
|
-
};
|
2063
|
+
return resolvedTranslation;
|
2064
|
+
};
|
1871
2065
|
|
1872
|
-
|
1873
|
-
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
1882
|
-
|
1883
|
-
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
1890
|
-
|
1891
|
-
|
1892
|
-
|
1893
|
-
|
1894
|
-
|
1895
|
-
|
2066
|
+
var loadTranslationsIfMissing = function (key) {
|
2067
|
+
if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {
|
2068
|
+
langPromises[key] = loadAsync(key).then(function (translation) {
|
2069
|
+
translations(translation.key, translation.table);
|
2070
|
+
return translation;
|
2071
|
+
});
|
2072
|
+
}
|
2073
|
+
};
|
2074
|
+
|
2075
|
+
/**
|
2076
|
+
* @ngdoc function
|
2077
|
+
* @name pascalprecht.translate.$translate#preferredLanguage
|
2078
|
+
* @methodOf pascalprecht.translate.$translate
|
2079
|
+
*
|
2080
|
+
* @description
|
2081
|
+
* Returns the language key for the preferred language.
|
2082
|
+
*
|
2083
|
+
* @param {string} langKey language String or Array to be used as preferredLanguage (changing at runtime)
|
2084
|
+
*
|
2085
|
+
* @return {string} preferred language key
|
2086
|
+
*/
|
2087
|
+
$translate.preferredLanguage = function (langKey) {
|
2088
|
+
if (langKey) {
|
2089
|
+
setupPreferredLanguage(langKey);
|
2090
|
+
}
|
2091
|
+
return $preferredLanguage;
|
2092
|
+
};
|
2093
|
+
|
2094
|
+
/**
|
2095
|
+
* @ngdoc function
|
2096
|
+
* @name pascalprecht.translate.$translate#cloakClassName
|
2097
|
+
* @methodOf pascalprecht.translate.$translate
|
2098
|
+
*
|
2099
|
+
* @description
|
2100
|
+
* Returns the configured class name for `translate-cloak` directive.
|
2101
|
+
*
|
2102
|
+
* @return {string} cloakClassName
|
2103
|
+
*/
|
2104
|
+
$translate.cloakClassName = function () {
|
2105
|
+
return $cloakClassName;
|
2106
|
+
};
|
2107
|
+
|
2108
|
+
/**
|
2109
|
+
* @ngdoc function
|
2110
|
+
* @name pascalprecht.translate.$translate#nestedObjectDelimeter
|
2111
|
+
* @methodOf pascalprecht.translate.$translate
|
2112
|
+
*
|
2113
|
+
* @description
|
2114
|
+
* Returns the configured delimiter for nested namespaces.
|
2115
|
+
*
|
2116
|
+
* @return {string} nestedObjectDelimeter
|
2117
|
+
*/
|
2118
|
+
$translate.nestedObjectDelimeter = function () {
|
2119
|
+
return $nestedObjectDelimeter;
|
2120
|
+
};
|
2121
|
+
|
2122
|
+
/**
|
2123
|
+
* @ngdoc function
|
2124
|
+
* @name pascalprecht.translate.$translate#fallbackLanguage
|
2125
|
+
* @methodOf pascalprecht.translate.$translate
|
2126
|
+
*
|
2127
|
+
* @description
|
2128
|
+
* Returns the language key for the fallback languages or sets a new fallback stack.
|
2129
|
+
*
|
2130
|
+
* @param {string=} langKey language String or Array of fallback languages to be used (to change stack at runtime)
|
2131
|
+
*
|
2132
|
+
* @return {string||array} fallback language key
|
2133
|
+
*/
|
2134
|
+
$translate.fallbackLanguage = function (langKey) {
|
2135
|
+
if (langKey !== undefined && langKey !== null) {
|
2136
|
+
fallbackStack(langKey);
|
2137
|
+
|
2138
|
+
// as we might have an async loader initiated and a new translation language might have been defined
|
2139
|
+
// we need to add the promise to the stack also. So - iterate.
|
2140
|
+
if ($loaderFactory) {
|
2141
|
+
if ($fallbackLanguage && $fallbackLanguage.length) {
|
2142
|
+
for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {
|
2143
|
+
if (!langPromises[$fallbackLanguage[i]]) {
|
2144
|
+
langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]);
|
1896
2145
|
}
|
1897
2146
|
}
|
1898
2147
|
}
|
1899
|
-
$translate.use($translate.use());
|
1900
|
-
}
|
1901
|
-
if ($fallbackWasString) {
|
1902
|
-
return $fallbackLanguage[0];
|
1903
|
-
} else {
|
1904
|
-
return $fallbackLanguage;
|
1905
2148
|
}
|
2149
|
+
$translate.use($translate.use());
|
2150
|
+
}
|
2151
|
+
if ($fallbackWasString) {
|
2152
|
+
return $fallbackLanguage[0];
|
2153
|
+
} else {
|
2154
|
+
return $fallbackLanguage;
|
2155
|
+
}
|
1906
2156
|
|
1907
|
-
|
2157
|
+
};
|
1908
2158
|
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
1912
|
-
|
1913
|
-
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
1917
|
-
|
1918
|
-
|
1919
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
1928
|
-
|
1929
|
-
}
|
2159
|
+
/**
|
2160
|
+
* @ngdoc function
|
2161
|
+
* @name pascalprecht.translate.$translate#useFallbackLanguage
|
2162
|
+
* @methodOf pascalprecht.translate.$translate
|
2163
|
+
*
|
2164
|
+
* @description
|
2165
|
+
* Sets the first key of the fallback language stack to be used for translation.
|
2166
|
+
* Therefore all languages in the fallback array BEFORE this key will be skipped!
|
2167
|
+
*
|
2168
|
+
* @param {string=} langKey Contains the langKey the iteration shall start with. Set to false if you want to
|
2169
|
+
* get back to the whole stack
|
2170
|
+
*/
|
2171
|
+
$translate.useFallbackLanguage = function (langKey) {
|
2172
|
+
if (langKey !== undefined && langKey !== null) {
|
2173
|
+
if (!langKey) {
|
2174
|
+
startFallbackIteration = 0;
|
2175
|
+
} else {
|
2176
|
+
var langKeyPosition = indexOf($fallbackLanguage, langKey);
|
2177
|
+
if (langKeyPosition > -1) {
|
2178
|
+
startFallbackIteration = langKeyPosition;
|
1930
2179
|
}
|
1931
|
-
|
1932
2180
|
}
|
1933
2181
|
|
1934
|
-
}
|
2182
|
+
}
|
1935
2183
|
|
1936
|
-
|
1937
|
-
* @ngdoc function
|
1938
|
-
* @name pascalprecht.translate.$translate#proposedLanguage
|
1939
|
-
* @methodOf pascalprecht.translate.$translate
|
1940
|
-
*
|
1941
|
-
* @description
|
1942
|
-
* Returns the language key of language that is currently loaded asynchronously.
|
1943
|
-
*
|
1944
|
-
* @return {string} language key
|
1945
|
-
*/
|
1946
|
-
$translate.proposedLanguage = function () {
|
1947
|
-
return $nextLang;
|
1948
|
-
};
|
2184
|
+
};
|
1949
2185
|
|
1950
|
-
|
1951
|
-
|
1952
|
-
|
1953
|
-
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
1961
|
-
|
1962
|
-
|
2186
|
+
/**
|
2187
|
+
* @ngdoc function
|
2188
|
+
* @name pascalprecht.translate.$translate#proposedLanguage
|
2189
|
+
* @methodOf pascalprecht.translate.$translate
|
2190
|
+
*
|
2191
|
+
* @description
|
2192
|
+
* Returns the language key of language that is currently loaded asynchronously.
|
2193
|
+
*
|
2194
|
+
* @return {string} language key
|
2195
|
+
*/
|
2196
|
+
$translate.proposedLanguage = function () {
|
2197
|
+
return $nextLang;
|
2198
|
+
};
|
1963
2199
|
|
1964
|
-
|
1965
|
-
|
1966
|
-
|
1967
|
-
|
1968
|
-
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
2200
|
+
/**
|
2201
|
+
* @ngdoc function
|
2202
|
+
* @name pascalprecht.translate.$translate#storage
|
2203
|
+
* @methodOf pascalprecht.translate.$translate
|
2204
|
+
*
|
2205
|
+
* @description
|
2206
|
+
* Returns registered storage.
|
2207
|
+
*
|
2208
|
+
* @return {object} Storage
|
2209
|
+
*/
|
2210
|
+
$translate.storage = function () {
|
2211
|
+
return Storage;
|
2212
|
+
};
|
2213
|
+
|
2214
|
+
/**
|
2215
|
+
* @ngdoc function
|
2216
|
+
* @name pascalprecht.translate.$translate#negotiateLocale
|
2217
|
+
* @methodOf pascalprecht.translate.$translate
|
2218
|
+
*
|
2219
|
+
* @description
|
2220
|
+
* Returns a language key based on available languages and language aliases. If a
|
2221
|
+
* language key cannot be resolved, returns undefined.
|
2222
|
+
*
|
2223
|
+
* If no or a falsy key is given, returns undefined.
|
2224
|
+
*
|
2225
|
+
* @param {string} [key] Language key
|
2226
|
+
* @return {string|undefined} Language key or undefined if no language key is found.
|
2227
|
+
*/
|
2228
|
+
$translate.negotiateLocale = negotiateLocale;
|
2229
|
+
|
2230
|
+
/**
|
2231
|
+
* @ngdoc function
|
2232
|
+
* @name pascalprecht.translate.$translate#use
|
2233
|
+
* @methodOf pascalprecht.translate.$translate
|
2234
|
+
*
|
2235
|
+
* @description
|
2236
|
+
* Tells angular-translate which language to use by given language key. This method is
|
2237
|
+
* used to change language at runtime. It also takes care of storing the language
|
2238
|
+
* key in a configured store to let your app remember the choosed language.
|
2239
|
+
*
|
2240
|
+
* When trying to 'use' a language which isn't available it tries to load it
|
2241
|
+
* asynchronously with registered loaders.
|
2242
|
+
*
|
2243
|
+
* Returns promise object with loaded language file data or string of the currently used language.
|
2244
|
+
*
|
2245
|
+
* If no or a falsy key is given it returns the currently used language key.
|
2246
|
+
* The returned string will be ```undefined``` if setting up $translate hasn't finished.
|
2247
|
+
* @example
|
2248
|
+
* $translate.use("en_US").then(function(data){
|
1980
2249
|
* $scope.text = $translate("HELLO");
|
1981
2250
|
* });
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
1990
|
-
|
1991
|
-
var deferred = $q.defer();
|
2251
|
+
*
|
2252
|
+
* @param {string} [key] Language key
|
2253
|
+
* @return {object|string} Promise with loaded language data or the language key if a falsy param was given.
|
2254
|
+
*/
|
2255
|
+
$translate.use = function (key) {
|
2256
|
+
if (!key) {
|
2257
|
+
return $uses;
|
2258
|
+
}
|
1992
2259
|
|
1993
|
-
|
2260
|
+
var deferred = $q.defer();
|
2261
|
+
deferred.promise.then(null, angular.noop); // AJS "Possibly unhandled rejection"
|
1994
2262
|
|
1995
|
-
|
1996
|
-
var aliasedKey = negotiateLocale(key);
|
1997
|
-
if (aliasedKey) {
|
1998
|
-
key = aliasedKey;
|
1999
|
-
}
|
2263
|
+
$rootScope.$emit('$translateChangeStart', {language : key});
|
2000
2264
|
|
2001
|
-
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
2007
|
-
deferred.resolve(translation.key);
|
2008
|
-
useLanguage(translation.key);
|
2009
|
-
return translation;
|
2010
|
-
}, function (key) {
|
2011
|
-
$rootScope.$emit('$translateChangeError', {language: key});
|
2012
|
-
deferred.reject(key);
|
2013
|
-
$rootScope.$emit('$translateChangeEnd', {language: key});
|
2014
|
-
return $q.reject(key);
|
2015
|
-
});
|
2016
|
-
langPromises[key]['finally'](function () {
|
2017
|
-
clearNextLangAndPromise(key);
|
2018
|
-
});
|
2019
|
-
} else if ($nextLang === key && langPromises[key]) {
|
2020
|
-
// we are already loading this asynchronously
|
2021
|
-
// resolve our new deferred when the old langPromise is resolved
|
2022
|
-
langPromises[key].then(function (translation) {
|
2023
|
-
deferred.resolve(translation.key);
|
2024
|
-
return translation;
|
2025
|
-
}, function (key) {
|
2026
|
-
deferred.reject(key);
|
2027
|
-
return $q.reject(key);
|
2028
|
-
});
|
2029
|
-
} else {
|
2030
|
-
deferred.resolve(key);
|
2031
|
-
useLanguage(key);
|
2032
|
-
}
|
2265
|
+
// Try to get the aliased language key
|
2266
|
+
var aliasedKey = negotiateLocale(key);
|
2267
|
+
// Ensure only registered language keys will be loaded
|
2268
|
+
if ($availableLanguageKeys.length > 0 && !aliasedKey) {
|
2269
|
+
return $q.reject(key);
|
2270
|
+
}
|
2033
2271
|
|
2034
|
-
|
2035
|
-
|
2272
|
+
if (aliasedKey) {
|
2273
|
+
key = aliasedKey;
|
2274
|
+
}
|
2036
2275
|
|
2037
|
-
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
2048
|
-
|
2049
|
-
|
2276
|
+
// if there isn't a translation table for the language we've requested,
|
2277
|
+
// we load it asynchronously
|
2278
|
+
$nextLang = key;
|
2279
|
+
if (($forceAsyncReloadEnabled || !$translationTable[key]) && $loaderFactory && !langPromises[key]) {
|
2280
|
+
langPromises[key] = loadAsync(key).then(function (translation) {
|
2281
|
+
translations(translation.key, translation.table);
|
2282
|
+
deferred.resolve(translation.key);
|
2283
|
+
if ($nextLang === key) {
|
2284
|
+
useLanguage(translation.key);
|
2285
|
+
}
|
2286
|
+
return translation;
|
2287
|
+
}, function (key) {
|
2288
|
+
$rootScope.$emit('$translateChangeError', {language : key});
|
2289
|
+
deferred.reject(key);
|
2290
|
+
$rootScope.$emit('$translateChangeEnd', {language : key});
|
2291
|
+
return $q.reject(key);
|
2292
|
+
});
|
2293
|
+
langPromises[key]['finally'](function () {
|
2294
|
+
clearNextLangAndPromise(key);
|
2295
|
+
})['catch'](angular.noop); // we don't care about errors (clearing)
|
2296
|
+
} else if (langPromises[key]) {
|
2297
|
+
// we are already loading this asynchronously
|
2298
|
+
// resolve our new deferred when the old langPromise is resolved
|
2299
|
+
langPromises[key].then(function (translation) {
|
2300
|
+
if ($nextLang === translation.key) {
|
2301
|
+
useLanguage(translation.key);
|
2302
|
+
}
|
2303
|
+
deferred.resolve(translation.key);
|
2304
|
+
return translation;
|
2305
|
+
}, function (key) {
|
2306
|
+
// find first available fallback language if that request has failed
|
2307
|
+
if (!$uses && $fallbackLanguage && $fallbackLanguage.length > 0 && $fallbackLanguage[0] !== key) {
|
2308
|
+
return $translate.use($fallbackLanguage[0]).then(deferred.resolve, deferred.reject);
|
2309
|
+
} else {
|
2310
|
+
return deferred.reject(key);
|
2311
|
+
}
|
2312
|
+
});
|
2313
|
+
} else {
|
2314
|
+
deferred.resolve(key);
|
2315
|
+
useLanguage(key);
|
2316
|
+
}
|
2050
2317
|
|
2051
|
-
|
2052
|
-
|
2053
|
-
* @name pascalprecht.translate.$translate#isPostCompilingEnabled
|
2054
|
-
* @methodOf pascalprecht.translate.$translate
|
2055
|
-
*
|
2056
|
-
* @description
|
2057
|
-
* Returns whether post compiling is enabled or not
|
2058
|
-
*
|
2059
|
-
* @return {bool} storage key
|
2060
|
-
*/
|
2061
|
-
$translate.isPostCompilingEnabled = function () {
|
2062
|
-
return $postCompilingEnabled;
|
2063
|
-
};
|
2318
|
+
return deferred.promise;
|
2319
|
+
};
|
2064
2320
|
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
|
2071
|
-
|
2072
|
-
|
2073
|
-
|
2074
|
-
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2321
|
+
/**
|
2322
|
+
* @ngdoc function
|
2323
|
+
* @name pascalprecht.translate.$translate#resolveClientLocale
|
2324
|
+
* @methodOf pascalprecht.translate.$translate
|
2325
|
+
*
|
2326
|
+
* @description
|
2327
|
+
* This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.
|
2328
|
+
*
|
2329
|
+
* @returns {string} the current client/browser language key
|
2330
|
+
*/
|
2331
|
+
$translate.resolveClientLocale = function () {
|
2332
|
+
return getLocale();
|
2333
|
+
};
|
2078
2334
|
|
2079
|
-
|
2080
|
-
|
2081
|
-
|
2082
|
-
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
*
|
2093
|
-
* If the module is able to refresh translation tables refresh() method will broadcast
|
2094
|
-
* $translateRefreshStart and $translateRefreshEnd events.
|
2095
|
-
*
|
2096
|
-
* @example
|
2097
|
-
* // this will drop all currently existent translation tables and reload those which are
|
2098
|
-
* // currently in use
|
2099
|
-
* $translate.refresh();
|
2100
|
-
* // this will refresh a translation table for the en_US language
|
2101
|
-
* $translate.refresh('en_US');
|
2102
|
-
*
|
2103
|
-
* @param {string} langKey A language key of the table, which has to be refreshed
|
2104
|
-
*
|
2105
|
-
* @return {promise} Promise, which will be resolved in case a translation tables refreshing
|
2106
|
-
* process is finished successfully, and reject if not.
|
2107
|
-
*/
|
2108
|
-
$translate.refresh = function (langKey) {
|
2109
|
-
if (!$loaderFactory) {
|
2110
|
-
throw new Error('Couldn\'t refresh translation table, no loader registered!');
|
2111
|
-
}
|
2335
|
+
/**
|
2336
|
+
* @ngdoc function
|
2337
|
+
* @name pascalprecht.translate.$translate#storageKey
|
2338
|
+
* @methodOf pascalprecht.translate.$translate
|
2339
|
+
*
|
2340
|
+
* @description
|
2341
|
+
* Returns the key for the storage.
|
2342
|
+
*
|
2343
|
+
* @return {string} storage key
|
2344
|
+
*/
|
2345
|
+
$translate.storageKey = function () {
|
2346
|
+
return storageKey();
|
2347
|
+
};
|
2112
2348
|
|
2113
|
-
|
2349
|
+
/**
|
2350
|
+
* @ngdoc function
|
2351
|
+
* @name pascalprecht.translate.$translate#isPostCompilingEnabled
|
2352
|
+
* @methodOf pascalprecht.translate.$translate
|
2353
|
+
*
|
2354
|
+
* @description
|
2355
|
+
* Returns whether post compiling is enabled or not
|
2356
|
+
*
|
2357
|
+
* @return {bool} storage key
|
2358
|
+
*/
|
2359
|
+
$translate.isPostCompilingEnabled = function () {
|
2360
|
+
return $postCompilingEnabled;
|
2361
|
+
};
|
2114
2362
|
|
2115
|
-
|
2116
|
-
|
2117
|
-
|
2118
|
-
|
2363
|
+
/**
|
2364
|
+
* @ngdoc function
|
2365
|
+
* @name pascalprecht.translate.$translate#isForceAsyncReloadEnabled
|
2366
|
+
* @methodOf pascalprecht.translate.$translate
|
2367
|
+
*
|
2368
|
+
* @description
|
2369
|
+
* Returns whether force async reload is enabled or not
|
2370
|
+
*
|
2371
|
+
* @return {boolean} forceAsyncReload value
|
2372
|
+
*/
|
2373
|
+
$translate.isForceAsyncReloadEnabled = function () {
|
2374
|
+
return $forceAsyncReloadEnabled;
|
2375
|
+
};
|
2119
2376
|
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2377
|
+
/**
|
2378
|
+
* @ngdoc function
|
2379
|
+
* @name pascalprecht.translate.$translate#isKeepContent
|
2380
|
+
* @methodOf pascalprecht.translate.$translate
|
2381
|
+
*
|
2382
|
+
* @description
|
2383
|
+
* Returns whether keepContent or not
|
2384
|
+
*
|
2385
|
+
* @return {boolean} keepContent value
|
2386
|
+
*/
|
2387
|
+
$translate.isKeepContent = function () {
|
2388
|
+
return $keepContent;
|
2389
|
+
};
|
2124
2390
|
|
2125
|
-
|
2391
|
+
/**
|
2392
|
+
* @ngdoc function
|
2393
|
+
* @name pascalprecht.translate.$translate#refresh
|
2394
|
+
* @methodOf pascalprecht.translate.$translate
|
2395
|
+
*
|
2396
|
+
* @description
|
2397
|
+
* Refreshes a translation table pointed by the given langKey. If langKey is not specified,
|
2398
|
+
* the module will drop all existent translation tables and load new version of those which
|
2399
|
+
* are currently in use.
|
2400
|
+
*
|
2401
|
+
* Refresh means that the module will drop target translation table and try to load it again.
|
2402
|
+
*
|
2403
|
+
* In case there are no loaders registered the refresh() method will throw an Error.
|
2404
|
+
*
|
2405
|
+
* If the module is able to refresh translation tables refresh() method will broadcast
|
2406
|
+
* $translateRefreshStart and $translateRefreshEnd events.
|
2407
|
+
*
|
2408
|
+
* @example
|
2409
|
+
* // this will drop all currently existent translation tables and reload those which are
|
2410
|
+
* // currently in use
|
2411
|
+
* $translate.refresh();
|
2412
|
+
* // this will refresh a translation table for the en_US language
|
2413
|
+
* $translate.refresh('en_US');
|
2414
|
+
*
|
2415
|
+
* @param {string} langKey A language key of the table, which has to be refreshed
|
2416
|
+
*
|
2417
|
+
* @return {promise} Promise, which will be resolved in case a translation tables refreshing
|
2418
|
+
* process is finished successfully, and reject if not.
|
2419
|
+
*/
|
2420
|
+
$translate.refresh = function (langKey) {
|
2421
|
+
if (!$loaderFactory) {
|
2422
|
+
throw new Error('Couldn\'t refresh translation table, no loader registered!');
|
2423
|
+
}
|
2126
2424
|
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2425
|
+
$rootScope.$emit('$translateRefreshStart', {language : langKey});
|
2426
|
+
|
2427
|
+
var deferred = $q.defer(), updatedLanguages = {};
|
2428
|
+
|
2429
|
+
//private helper
|
2430
|
+
function loadNewData(languageKey) {
|
2431
|
+
var promise = loadAsync(languageKey);
|
2432
|
+
//update the load promise cache for this language
|
2433
|
+
langPromises[languageKey] = promise;
|
2434
|
+
//register a data handler for the promise
|
2435
|
+
promise.then(function (data) {
|
2436
|
+
//clear the cache for this language
|
2437
|
+
$translationTable[languageKey] = {};
|
2438
|
+
//add the new data for this language
|
2439
|
+
translations(languageKey, data.table);
|
2440
|
+
//track that we updated this language
|
2441
|
+
updatedLanguages[languageKey] = true;
|
2442
|
+
},
|
2443
|
+
//handle rejection to appease the $q validation
|
2444
|
+
angular.noop);
|
2445
|
+
return promise;
|
2446
|
+
}
|
2130
2447
|
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
|
2135
|
-
|
2448
|
+
//set up post-processing
|
2449
|
+
deferred.promise.then(
|
2450
|
+
function () {
|
2451
|
+
for (var key in $translationTable) {
|
2452
|
+
if ($translationTable.hasOwnProperty(key)) {
|
2453
|
+
//delete cache entries that were not updated
|
2454
|
+
if (!(key in updatedLanguages)) {
|
2455
|
+
delete $translationTable[key];
|
2456
|
+
}
|
2136
2457
|
}
|
2137
2458
|
}
|
2138
|
-
|
2139
|
-
|
2140
|
-
if ($uses && !loadingKeys[$uses]) {
|
2141
|
-
tables.push(loadAsync($uses));
|
2459
|
+
if ($uses) {
|
2460
|
+
useLanguage($uses);
|
2142
2461
|
}
|
2462
|
+
},
|
2463
|
+
//handle rejection to appease the $q validation
|
2464
|
+
angular.noop
|
2465
|
+
)['finally'](
|
2466
|
+
function () {
|
2467
|
+
$rootScope.$emit('$translateRefreshEnd', {language : langKey});
|
2468
|
+
}
|
2469
|
+
);
|
2143
2470
|
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2147
|
-
|
2148
|
-
|
2149
|
-
|
2150
|
-
|
2151
|
-
}
|
2152
|
-
resolve();
|
2153
|
-
};
|
2154
|
-
allTranslationsLoaded.displayName = 'refreshPostProcessor';
|
2471
|
+
if (!langKey) {
|
2472
|
+
// if there's no language key specified we refresh ALL THE THINGS!
|
2473
|
+
var languagesToReload = $fallbackLanguage && $fallbackLanguage.slice() || [];
|
2474
|
+
if ($uses && languagesToReload.indexOf($uses) === -1) {
|
2475
|
+
languagesToReload.push($uses);
|
2476
|
+
}
|
2477
|
+
$q.all(languagesToReload.map(loadNewData)).then(deferred.resolve, deferred.reject);
|
2155
2478
|
|
2156
|
-
|
2479
|
+
} else if ($translationTable[langKey]) {
|
2480
|
+
//just refresh the specified language cache
|
2481
|
+
loadNewData(langKey).then(deferred.resolve, deferred.reject);
|
2157
2482
|
|
2158
|
-
|
2483
|
+
} else {
|
2484
|
+
deferred.reject();
|
2485
|
+
}
|
2159
2486
|
|
2160
|
-
|
2161
|
-
|
2162
|
-
if (langKey === $uses) {
|
2163
|
-
useLanguage($uses);
|
2164
|
-
}
|
2165
|
-
resolve();
|
2166
|
-
};
|
2167
|
-
oneTranslationsLoaded.displayName = 'refreshPostProcessor';
|
2487
|
+
return deferred.promise;
|
2488
|
+
};
|
2168
2489
|
|
2169
|
-
|
2490
|
+
/**
|
2491
|
+
* @ngdoc function
|
2492
|
+
* @name pascalprecht.translate.$translate#instant
|
2493
|
+
* @methodOf pascalprecht.translate.$translate
|
2494
|
+
*
|
2495
|
+
* @description
|
2496
|
+
* Returns a translation instantly from the internal state of loaded translation. All rules
|
2497
|
+
* regarding the current language, the preferred language of even fallback languages will be
|
2498
|
+
* used except any promise handling. If a language was not found, an asynchronous loading
|
2499
|
+
* will be invoked in the background.
|
2500
|
+
*
|
2501
|
+
* @param {string|array} translationId A token which represents a translation id
|
2502
|
+
* This can be optionally an array of translation ids which
|
2503
|
+
* results that the function's promise returns an object where
|
2504
|
+
* each key is the translation id and the value the translation.
|
2505
|
+
* @param {object} interpolateParams Params
|
2506
|
+
* @param {string} interpolationId The id of the interpolation to use
|
2507
|
+
* @param {string} forceLanguage A language to be used instead of the current language
|
2508
|
+
* @param {string} sanitizeStrategy force sanitize strategy for this call instead of using the configured one
|
2509
|
+
*
|
2510
|
+
* @return {string|object} translation
|
2511
|
+
*/
|
2512
|
+
$translate.instant = function (translationId, interpolateParams, interpolationId, forceLanguage, sanitizeStrategy) {
|
2513
|
+
|
2514
|
+
// we don't want to re-negotiate $uses
|
2515
|
+
var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses
|
2516
|
+
(negotiateLocale(forceLanguage) || forceLanguage) : $uses;
|
2517
|
+
|
2518
|
+
// Detect undefined and null values to shorten the execution and prevent exceptions
|
2519
|
+
if (translationId === null || angular.isUndefined(translationId)) {
|
2520
|
+
return translationId;
|
2521
|
+
}
|
2170
2522
|
|
2171
|
-
|
2172
|
-
|
2523
|
+
// Check forceLanguage is present
|
2524
|
+
if (forceLanguage) {
|
2525
|
+
loadTranslationsIfMissing(forceLanguage);
|
2526
|
+
}
|
2527
|
+
|
2528
|
+
// Duck detection: If the first argument is an array, a bunch of translations was requested.
|
2529
|
+
// The result is an object.
|
2530
|
+
if (angular.isArray(translationId)) {
|
2531
|
+
var results = {};
|
2532
|
+
for (var i = 0, c = translationId.length; i < c; i++) {
|
2533
|
+
results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId, forceLanguage, sanitizeStrategy);
|
2173
2534
|
}
|
2174
|
-
return
|
2175
|
-
}
|
2535
|
+
return results;
|
2536
|
+
}
|
2176
2537
|
|
2177
|
-
|
2178
|
-
|
2179
|
-
|
2180
|
-
|
2181
|
-
*
|
2182
|
-
* @description
|
2183
|
-
* Returns a translation instantly from the internal state of loaded translation. All rules
|
2184
|
-
* regarding the current language, the preferred language of even fallback languages will be
|
2185
|
-
* used except any promise handling. If a language was not found, an asynchronous loading
|
2186
|
-
* will be invoked in the background.
|
2187
|
-
*
|
2188
|
-
* @param {string|array} translationId A token which represents a translation id
|
2189
|
-
* This can be optionally an array of translation ids which
|
2190
|
-
* results that the function's promise returns an object where
|
2191
|
-
* each key is the translation id and the value the translation.
|
2192
|
-
* @param {object} interpolateParams Params
|
2193
|
-
* @param {string} interpolationId The id of the interpolation to use
|
2194
|
-
*
|
2195
|
-
* @return {string|object} translation
|
2196
|
-
*/
|
2197
|
-
$translate.instant = function (translationId, interpolateParams, interpolationId) {
|
2538
|
+
// We discarded unacceptable values. So we just need to verify if translationId is empty String
|
2539
|
+
if (angular.isString(translationId) && translationId.length < 1) {
|
2540
|
+
return translationId;
|
2541
|
+
}
|
2198
2542
|
|
2199
|
-
|
2200
|
-
|
2201
|
-
|
2202
|
-
|
2543
|
+
// trim off any whitespace
|
2544
|
+
if (translationId) {
|
2545
|
+
translationId = trim.apply(translationId);
|
2546
|
+
}
|
2203
2547
|
|
2204
|
-
|
2205
|
-
|
2206
|
-
|
2207
|
-
|
2208
|
-
|
2209
|
-
|
2548
|
+
var result, possibleLangKeys = [];
|
2549
|
+
if ($preferredLanguage) {
|
2550
|
+
possibleLangKeys.push($preferredLanguage);
|
2551
|
+
}
|
2552
|
+
if (uses) {
|
2553
|
+
possibleLangKeys.push(uses);
|
2554
|
+
}
|
2555
|
+
if ($fallbackLanguage && $fallbackLanguage.length) {
|
2556
|
+
possibleLangKeys = possibleLangKeys.concat($fallbackLanguage);
|
2557
|
+
}
|
2558
|
+
for (var j = 0, d = possibleLangKeys.length; j < d; j++) {
|
2559
|
+
var possibleLangKey = possibleLangKeys[j];
|
2560
|
+
if ($translationTable[possibleLangKey]) {
|
2561
|
+
if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') {
|
2562
|
+
result = determineTranslationInstant(translationId, interpolateParams, interpolationId, uses, sanitizeStrategy);
|
2210
2563
|
}
|
2211
|
-
return results;
|
2212
2564
|
}
|
2213
|
-
|
2214
|
-
|
2215
|
-
if (angular.isString(translationId) && translationId.length < 1) {
|
2216
|
-
return translationId;
|
2565
|
+
if (typeof result !== 'undefined') {
|
2566
|
+
break;
|
2217
2567
|
}
|
2568
|
+
}
|
2218
2569
|
|
2219
|
-
|
2220
|
-
if (
|
2221
|
-
|
2222
|
-
}
|
2570
|
+
if (!result && result !== '') {
|
2571
|
+
if ($notFoundIndicatorLeft || $notFoundIndicatorRight) {
|
2572
|
+
result = applyNotFoundIndicators(translationId);
|
2573
|
+
} else {
|
2574
|
+
// Return translation of default interpolator if not found anything.
|
2575
|
+
result = defaultInterpolator.interpolate(translationId, interpolateParams, 'filter', sanitizeStrategy);
|
2223
2576
|
|
2224
|
-
|
2225
|
-
|
2226
|
-
|
2227
|
-
|
2228
|
-
|
2229
|
-
|
2230
|
-
}
|
2231
|
-
if ($fallbackLanguage && $fallbackLanguage.length) {
|
2232
|
-
possibleLangKeys = possibleLangKeys.concat($fallbackLanguage);
|
2233
|
-
}
|
2234
|
-
for (var j = 0, d = possibleLangKeys.length; j < d; j++) {
|
2235
|
-
var possibleLangKey = possibleLangKeys[j];
|
2236
|
-
if ($translationTable[possibleLangKey]) {
|
2237
|
-
if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') {
|
2238
|
-
result = determineTranslationInstant(translationId, interpolateParams, interpolationId);
|
2239
|
-
} else if ($notFoundIndicatorLeft || $notFoundIndicatorRight) {
|
2240
|
-
result = applyNotFoundIndicators(translationId);
|
2241
|
-
}
|
2242
|
-
}
|
2243
|
-
if (typeof result !== 'undefined') {
|
2244
|
-
break;
|
2577
|
+
// looks like the requested translation id doesn't exists.
|
2578
|
+
// Now, if there is a registered handler for missing translations and no
|
2579
|
+
// asyncLoader is pending, we execute the handler
|
2580
|
+
var missingTranslationHandlerTranslation;
|
2581
|
+
if ($missingTranslationHandlerFactory && !pendingLoader) {
|
2582
|
+
missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);
|
2245
2583
|
}
|
2246
|
-
}
|
2247
2584
|
|
2248
|
-
|
2249
|
-
|
2250
|
-
result = defaultInterpolator.interpolate(translationId, interpolateParams);
|
2251
|
-
if ($missingTranslationHandlerFactory && !pendingLoader) {
|
2252
|
-
result = translateByHandler(translationId, interpolateParams);
|
2585
|
+
if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {
|
2586
|
+
result = missingTranslationHandlerTranslation;
|
2253
2587
|
}
|
2254
2588
|
}
|
2589
|
+
}
|
2255
2590
|
|
2256
|
-
|
2257
|
-
|
2591
|
+
return result;
|
2592
|
+
};
|
2258
2593
|
|
2259
|
-
|
2260
|
-
|
2261
|
-
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
2269
|
-
|
2270
|
-
|
2271
|
-
|
2594
|
+
/**
|
2595
|
+
* @ngdoc function
|
2596
|
+
* @name pascalprecht.translate.$translate#versionInfo
|
2597
|
+
* @methodOf pascalprecht.translate.$translate
|
2598
|
+
*
|
2599
|
+
* @description
|
2600
|
+
* Returns the current version information for the angular-translate library
|
2601
|
+
*
|
2602
|
+
* @return {string} angular-translate version
|
2603
|
+
*/
|
2604
|
+
$translate.versionInfo = function () {
|
2605
|
+
return version;
|
2606
|
+
};
|
2607
|
+
|
2608
|
+
/**
|
2609
|
+
* @ngdoc function
|
2610
|
+
* @name pascalprecht.translate.$translate#loaderCache
|
2611
|
+
* @methodOf pascalprecht.translate.$translate
|
2612
|
+
*
|
2613
|
+
* @description
|
2614
|
+
* Returns the defined loaderCache.
|
2615
|
+
*
|
2616
|
+
* @return {boolean|string|object} current value of loaderCache
|
2617
|
+
*/
|
2618
|
+
$translate.loaderCache = function () {
|
2619
|
+
return loaderCache;
|
2620
|
+
};
|
2621
|
+
|
2622
|
+
// internal purpose only
|
2623
|
+
$translate.directivePriority = function () {
|
2624
|
+
return directivePriority;
|
2625
|
+
};
|
2626
|
+
|
2627
|
+
// internal purpose only
|
2628
|
+
$translate.statefulFilter = function () {
|
2629
|
+
return statefulFilter;
|
2630
|
+
};
|
2272
2631
|
|
2273
|
-
|
2274
|
-
|
2275
|
-
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
|
2285
|
-
|
2632
|
+
/**
|
2633
|
+
* @ngdoc function
|
2634
|
+
* @name pascalprecht.translate.$translate#isReady
|
2635
|
+
* @methodOf pascalprecht.translate.$translate
|
2636
|
+
*
|
2637
|
+
* @description
|
2638
|
+
* Returns whether the service is "ready" to translate (i.e. loading 1st language).
|
2639
|
+
*
|
2640
|
+
* See also {@link pascalprecht.translate.$translate#methods_onReady onReady()}.
|
2641
|
+
*
|
2642
|
+
* @return {boolean} current value of ready
|
2643
|
+
*/
|
2644
|
+
$translate.isReady = function () {
|
2645
|
+
return $isReady;
|
2646
|
+
};
|
2286
2647
|
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2648
|
+
var $onReadyDeferred = $q.defer();
|
2649
|
+
$onReadyDeferred.promise.then(function () {
|
2650
|
+
$isReady = true;
|
2651
|
+
});
|
2291
2652
|
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2295
|
-
|
2653
|
+
/**
|
2654
|
+
* @ngdoc function
|
2655
|
+
* @name pascalprecht.translate.$translate#onReady
|
2656
|
+
* @methodOf pascalprecht.translate.$translate
|
2657
|
+
*
|
2658
|
+
* @description
|
2659
|
+
* Calls the function provided or resolved the returned promise after the service is "ready" to translate (i.e. loading 1st language).
|
2660
|
+
*
|
2661
|
+
* See also {@link pascalprecht.translate.$translate#methods_isReady isReady()}.
|
2662
|
+
*
|
2663
|
+
* @param {Function=} fn Function to invoke when service is ready
|
2664
|
+
* @return {object} Promise resolved when service is ready
|
2665
|
+
*/
|
2666
|
+
$translate.onReady = function (fn) {
|
2667
|
+
var deferred = $q.defer();
|
2668
|
+
if (angular.isFunction(fn)) {
|
2669
|
+
deferred.promise.then(fn);
|
2670
|
+
}
|
2671
|
+
if ($isReady) {
|
2672
|
+
deferred.resolve();
|
2673
|
+
} else {
|
2674
|
+
$onReadyDeferred.promise.then(deferred.resolve);
|
2675
|
+
}
|
2676
|
+
return deferred.promise;
|
2677
|
+
};
|
2678
|
+
|
2679
|
+
/**
|
2680
|
+
* @ngdoc function
|
2681
|
+
* @name pascalprecht.translate.$translate#getAvailableLanguageKeys
|
2682
|
+
* @methodOf pascalprecht.translate.$translate
|
2683
|
+
*
|
2684
|
+
* @description
|
2685
|
+
* This function simply returns the registered language keys being defined before in the config phase
|
2686
|
+
* With this, an application can use the array to provide a language selection dropdown or similar
|
2687
|
+
* without any additional effort
|
2688
|
+
*
|
2689
|
+
* @returns {object} returns the list of possibly registered language keys and mapping or null if not defined
|
2690
|
+
*/
|
2691
|
+
$translate.getAvailableLanguageKeys = function () {
|
2692
|
+
if ($availableLanguageKeys.length > 0) {
|
2693
|
+
return $availableLanguageKeys;
|
2694
|
+
}
|
2695
|
+
return null;
|
2696
|
+
};
|
2697
|
+
|
2698
|
+
/**
|
2699
|
+
* @ngdoc function
|
2700
|
+
* @name pascalprecht.translate.$translate#getTranslationTable
|
2701
|
+
* @methodOf pascalprecht.translate.$translate
|
2702
|
+
*
|
2703
|
+
* @description
|
2704
|
+
* Returns translation table by the given language key.
|
2705
|
+
*
|
2706
|
+
* Unless a language is provided it returns a translation table of the current one.
|
2707
|
+
* Note: If translation dictionary is currently downloading or in progress
|
2708
|
+
* it will return null.
|
2709
|
+
*
|
2710
|
+
* @param {string} langKey A token which represents a translation id
|
2711
|
+
*
|
2712
|
+
* @return {object} a copy of angular-translate $translationTable
|
2713
|
+
*/
|
2714
|
+
$translate.getTranslationTable = function (langKey) {
|
2715
|
+
langKey = langKey || $translate.use();
|
2716
|
+
if (langKey && $translationTable[langKey]) {
|
2717
|
+
return angular.copy($translationTable[langKey]);
|
2718
|
+
}
|
2719
|
+
return null;
|
2720
|
+
};
|
2721
|
+
|
2722
|
+
// Whenever $translateReady is being fired, this will ensure the state of $isReady
|
2723
|
+
var globalOnReadyListener = $rootScope.$on('$translateReady', function () {
|
2724
|
+
$onReadyDeferred.resolve();
|
2725
|
+
globalOnReadyListener(); // one time only
|
2726
|
+
globalOnReadyListener = null;
|
2727
|
+
});
|
2728
|
+
var globalOnChangeListener = $rootScope.$on('$translateChangeEnd', function () {
|
2729
|
+
$onReadyDeferred.resolve();
|
2730
|
+
globalOnChangeListener(); // one time only
|
2731
|
+
globalOnChangeListener = null;
|
2732
|
+
});
|
2296
2733
|
|
2297
|
-
|
2734
|
+
if ($loaderFactory) {
|
2298
2735
|
|
2299
|
-
|
2300
|
-
|
2301
|
-
|
2736
|
+
// If at least one async loader is defined and there are no
|
2737
|
+
// (default) translations available we should try to load them.
|
2738
|
+
if (angular.equals($translationTable, {})) {
|
2739
|
+
if ($translate.use()) {
|
2302
2740
|
$translate.use($translate.use());
|
2303
2741
|
}
|
2742
|
+
}
|
2304
2743
|
|
2305
|
-
|
2306
|
-
|
2307
|
-
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2315
|
-
|
2316
|
-
|
2317
|
-
}
|
2744
|
+
// Also, if there are any fallback language registered, we start
|
2745
|
+
// loading them asynchronously as soon as we can.
|
2746
|
+
if ($fallbackLanguage && $fallbackLanguage.length) {
|
2747
|
+
var processAsyncResult = function (translation) {
|
2748
|
+
translations(translation.key, translation.table);
|
2749
|
+
$rootScope.$emit('$translateChangeEnd', {language : translation.key});
|
2750
|
+
return translation;
|
2751
|
+
};
|
2752
|
+
for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {
|
2753
|
+
var fallbackLanguageId = $fallbackLanguage[i];
|
2754
|
+
if ($forceAsyncReloadEnabled || !$translationTable[fallbackLanguageId]) {
|
2755
|
+
langPromises[fallbackLanguageId] = loadAsync(fallbackLanguageId).then(processAsyncResult);
|
2318
2756
|
}
|
2319
2757
|
}
|
2320
2758
|
}
|
2321
|
-
|
2322
|
-
|
2759
|
+
} else {
|
2760
|
+
$rootScope.$emit('$translateReady', {language : $translate.use()});
|
2323
2761
|
}
|
2324
|
-
|
2762
|
+
|
2763
|
+
return $translate;
|
2764
|
+
}];
|
2325
2765
|
}
|
2326
|
-
$translate.$inject = ['$STORAGE_KEY', '$windowProvider', '$translateSanitizationProvider', 'pascalprechtTranslateOverrider'];
|
2327
2766
|
|
2328
2767
|
$translate.displayName = 'displayName';
|
2329
2768
|
|
@@ -2395,24 +2834,41 @@ function $translateDefaultInterpolation ($interpolate, $translateSanitization) {
|
|
2395
2834
|
* @methodOf pascalprecht.translate.$translateDefaultInterpolation
|
2396
2835
|
*
|
2397
2836
|
* @description
|
2398
|
-
* Interpolates given
|
2837
|
+
* Interpolates given value agains given interpolate params using angulars
|
2399
2838
|
* `$interpolate` service.
|
2400
2839
|
*
|
2401
|
-
*
|
2840
|
+
* Since AngularJS 1.5, `value` must not be a string but can be anything input.
|
2841
|
+
*
|
2842
|
+
* @param {string} value translation
|
2843
|
+
* @param {object} interpolationParams interpolation params
|
2844
|
+
* @param {string} context current context (filter, directive, service)
|
2845
|
+
* @param {string} sanitizeStrategy sanitize strategy
|
2846
|
+
* @param {string} translationId current translationId
|
2847
|
+
*
|
2848
|
+
* @returns {string} interpolated string
|
2402
2849
|
*/
|
2403
|
-
$translateInterpolator.interpolate = function (
|
2850
|
+
$translateInterpolator.interpolate = function (value, interpolationParams, context, sanitizeStrategy, translationId) { // jshint ignore:line
|
2404
2851
|
interpolationParams = interpolationParams || {};
|
2405
|
-
interpolationParams = $translateSanitization.sanitize(interpolationParams, 'params');
|
2406
|
-
|
2407
|
-
var interpolatedText
|
2408
|
-
|
2852
|
+
interpolationParams = $translateSanitization.sanitize(interpolationParams, 'params', sanitizeStrategy, context);
|
2853
|
+
|
2854
|
+
var interpolatedText;
|
2855
|
+
if (angular.isNumber(value)) {
|
2856
|
+
// numbers are safe
|
2857
|
+
interpolatedText = '' + value;
|
2858
|
+
} else if (angular.isString(value)) {
|
2859
|
+
// strings must be interpolated (that's the job here)
|
2860
|
+
interpolatedText = $interpolate(value)(interpolationParams);
|
2861
|
+
interpolatedText = $translateSanitization.sanitize(interpolatedText, 'text', sanitizeStrategy, context);
|
2862
|
+
} else {
|
2863
|
+
// neither a number or a string, cant interpolate => empty string
|
2864
|
+
interpolatedText = '';
|
2865
|
+
}
|
2409
2866
|
|
2410
2867
|
return interpolatedText;
|
2411
2868
|
};
|
2412
2869
|
|
2413
2870
|
return $translateInterpolator;
|
2414
2871
|
}
|
2415
|
-
$translateDefaultInterpolation.$inject = ['$interpolate', '$translateSanitization'];
|
2416
2872
|
|
2417
2873
|
$translateDefaultInterpolation.displayName = '$translateDefaultInterpolation';
|
2418
2874
|
|
@@ -2422,14 +2878,15 @@ angular.module('pascalprecht.translate')
|
|
2422
2878
|
/**
|
2423
2879
|
* @ngdoc directive
|
2424
2880
|
* @name pascalprecht.translate.directive:translate
|
2425
|
-
* @requires $
|
2426
|
-
* @requires $
|
2427
|
-
* @requires $
|
2428
|
-
* @
|
2881
|
+
* @requires $interpolate,
|
2882
|
+
* @requires $compile,
|
2883
|
+
* @requires $parse,
|
2884
|
+
* @requires $rootScope
|
2885
|
+
* @restrict AE
|
2429
2886
|
*
|
2430
2887
|
* @description
|
2431
2888
|
* Translates given translation id either through attribute or DOM content.
|
2432
|
-
* Internally it uses
|
2889
|
+
* Internally it uses $translate service to translate the translation id. It possible to
|
2433
2890
|
* pass an optional `translate-values` object literal as string into translation id.
|
2434
2891
|
*
|
2435
2892
|
* @param {string=} translate Translation id which could be either string or interpolated string.
|
@@ -2437,6 +2894,7 @@ angular.module('pascalprecht.translate')
|
|
2437
2894
|
* @param {string=} translate-attr-ATTR translate Translation id and put it into ATTR attribute.
|
2438
2895
|
* @param {string=} translate-default will be used unless translation was successful
|
2439
2896
|
* @param {boolean=} translate-compile (default true if present) defines locally activation of {@link pascalprecht.translate.$translateProvider#methods_usePostCompiling}
|
2897
|
+
* @param {boolean=} translate-keep-content (default true if present) defines that in case a KEY could not be translated, that the existing content is left in the innerHTML}
|
2440
2898
|
*
|
2441
2899
|
* @example
|
2442
2900
|
<example module="ngView">
|
@@ -2453,6 +2911,7 @@ angular.module('pascalprecht.translate')
|
|
2453
2911
|
<pre translate="WITH_VALUES" translate-values="{{values}}"></pre>
|
2454
2912
|
<pre translate translate-values="{{values}}">WITH_VALUES</pre>
|
2455
2913
|
<pre translate translate-attr-title="WITH_VALUES" translate-values="{{values}}"></pre>
|
2914
|
+
<pre translate="WITH_CAMEL_CASE_KEY" translate-value-camel-case-key="Hi"></pre>
|
2456
2915
|
|
2457
2916
|
</div>
|
2458
2917
|
</file>
|
@@ -2463,7 +2922,8 @@ angular.module('pascalprecht.translate')
|
|
2463
2922
|
|
2464
2923
|
$translateProvider.translations('en',{
|
2465
2924
|
'TRANSLATION_ID': 'Hello there!',
|
2466
|
-
'WITH_VALUES': 'The following value is dynamic: {{value}}'
|
2925
|
+
'WITH_VALUES': 'The following value is dynamic: {{value}}',
|
2926
|
+
'WITH_CAMEL_CASE_KEY': 'The interpolation key is camel cased: {{camelCaseKey}}'
|
2467
2927
|
}).preferredLanguage('en');
|
2468
2928
|
|
2469
2929
|
});
|
@@ -2500,13 +2960,17 @@ angular.module('pascalprecht.translate')
|
|
2500
2960
|
element = $compile('<p translate translate-attr-title="TRANSLATION_ID"></p>')($rootScope);
|
2501
2961
|
$rootScope.$digest();
|
2502
2962
|
expect(element.attr('title')).toBe('Hello there!');
|
2963
|
+
|
2964
|
+
element = $compile('<p translate="WITH_CAMEL_CASE_KEY" translate-value-camel-case-key="Hello"></p>')($rootScope);
|
2965
|
+
$rootScope.$digest();
|
2966
|
+
expect(element.text()).toBe('The interpolation key is camel cased: Hello');
|
2503
2967
|
});
|
2504
2968
|
});
|
2505
2969
|
</file>
|
2506
2970
|
</example>
|
2507
2971
|
*/
|
2508
2972
|
.directive('translate', translateDirective);
|
2509
|
-
function translateDirective($translate, $
|
2973
|
+
function translateDirective($translate, $interpolate, $compile, $parse, $rootScope) {
|
2510
2974
|
|
2511
2975
|
'use strict';
|
2512
2976
|
|
@@ -2545,6 +3009,7 @@ function translateDirective($translate, $q, $interpolate, $compile, $parse, $roo
|
|
2545
3009
|
scope.interpolateParams = {};
|
2546
3010
|
scope.preText = '';
|
2547
3011
|
scope.postText = '';
|
3012
|
+
scope.translateNamespace = getTranslateNamespace(scope);
|
2548
3013
|
var translationIds = {};
|
2549
3014
|
|
2550
3015
|
var initInterpolationParams = function (interpolateParams, iAttr, tAttr) {
|
@@ -2575,14 +3040,16 @@ function translateDirective($translate, $q, $interpolate, $compile, $parse, $roo
|
|
2575
3040
|
}
|
2576
3041
|
|
2577
3042
|
if (angular.equals(translationId , '') || !angular.isDefined(translationId)) {
|
3043
|
+
var iElementText = trim.apply(iElement.text());
|
3044
|
+
|
2578
3045
|
// Resolve translation id by inner html if required
|
2579
|
-
var interpolateMatches =
|
3046
|
+
var interpolateMatches = iElementText.match(interpolateRegExp);
|
2580
3047
|
// Interpolate translation id if required
|
2581
3048
|
if (angular.isArray(interpolateMatches)) {
|
2582
3049
|
scope.preText = interpolateMatches[1];
|
2583
3050
|
scope.postText = interpolateMatches[3];
|
2584
3051
|
translationIds.translate = $interpolate(interpolateMatches[2])(scope.$parent);
|
2585
|
-
var watcherMatches =
|
3052
|
+
var watcherMatches = iElementText.match(watcherRegExp);
|
2586
3053
|
if (angular.isArray(watcherMatches) && watcherMatches[2] && watcherMatches[2].length) {
|
2587
3054
|
observeElementTranslation._unwatchOld = scope.$watch(watcherMatches[2], function (newValue) {
|
2588
3055
|
translationIds.translate = newValue;
|
@@ -2590,7 +3057,8 @@ function translateDirective($translate, $q, $interpolate, $compile, $parse, $roo
|
|
2590
3057
|
});
|
2591
3058
|
}
|
2592
3059
|
} else {
|
2593
|
-
|
3060
|
+
// do not assigne the translation id if it is empty.
|
3061
|
+
translationIds.translate = !iElementText ? undefined : iElementText;
|
2594
3062
|
}
|
2595
3063
|
} else {
|
2596
3064
|
translationIds.translate = translationId;
|
@@ -2624,13 +3092,14 @@ function translateDirective($translate, $q, $interpolate, $compile, $parse, $roo
|
|
2624
3092
|
});
|
2625
3093
|
|
2626
3094
|
for (var translateAttr in iAttr) {
|
2627
|
-
if (iAttr.hasOwnProperty(translateAttr) && translateAttr.substr(0, 13) === 'translateAttr') {
|
3095
|
+
if (iAttr.hasOwnProperty(translateAttr) && translateAttr.substr(0, 13) === 'translateAttr' && translateAttr.length > 13) {
|
2628
3096
|
observeAttributeTranslation(translateAttr);
|
2629
3097
|
}
|
2630
3098
|
}
|
2631
3099
|
|
2632
3100
|
iAttr.$observe('translateDefault', function (value) {
|
2633
3101
|
scope.defaultText = value;
|
3102
|
+
updateTranslations();
|
2634
3103
|
});
|
2635
3104
|
|
2636
3105
|
if (translateValuesExist) {
|
@@ -2660,17 +3129,21 @@ function translateDirective($translate, $q, $interpolate, $compile, $parse, $roo
|
|
2660
3129
|
// Master update function
|
2661
3130
|
var updateTranslations = function () {
|
2662
3131
|
for (var key in translationIds) {
|
2663
|
-
|
2664
3132
|
if (translationIds.hasOwnProperty(key) && translationIds[key] !== undefined) {
|
2665
|
-
updateTranslation(key, translationIds[key], scope, scope.interpolateParams, scope.defaultText);
|
3133
|
+
updateTranslation(key, translationIds[key], scope, scope.interpolateParams, scope.defaultText, scope.translateNamespace);
|
2666
3134
|
}
|
2667
3135
|
}
|
2668
3136
|
};
|
2669
3137
|
|
2670
3138
|
// Put translation processing function outside loop
|
2671
|
-
var updateTranslation = function(translateAttr, translationId, scope, interpolateParams, defaultTranslationText) {
|
3139
|
+
var updateTranslation = function(translateAttr, translationId, scope, interpolateParams, defaultTranslationText, translateNamespace) {
|
2672
3140
|
if (translationId) {
|
2673
|
-
|
3141
|
+
// if translation id starts with '.' and translateNamespace given, prepend namespace
|
3142
|
+
if (translateNamespace && translationId.charAt(0) === '.') {
|
3143
|
+
translationId = translateNamespace + translationId;
|
3144
|
+
}
|
3145
|
+
|
3146
|
+
$translate(translationId, interpolateParams, translateInterpolation, defaultTranslationText, scope.translateLanguage)
|
2674
3147
|
.then(function (translation) {
|
2675
3148
|
applyTranslation(translation, scope, true, translateAttr);
|
2676
3149
|
}, function (translationId) {
|
@@ -2683,12 +3156,16 @@ function translateDirective($translate, $q, $interpolate, $compile, $parse, $roo
|
|
2683
3156
|
};
|
2684
3157
|
|
2685
3158
|
var applyTranslation = function (value, scope, successful, translateAttr) {
|
3159
|
+
if (!successful) {
|
3160
|
+
if (typeof scope.defaultText !== 'undefined') {
|
3161
|
+
value = scope.defaultText;
|
3162
|
+
}
|
3163
|
+
}
|
2686
3164
|
if (translateAttr === 'translate') {
|
2687
3165
|
// default translate into innerHTML
|
2688
|
-
if (!successful && typeof
|
2689
|
-
value
|
3166
|
+
if (successful || (!successful && !$translate.isKeepContent() && typeof iAttr.translateKeepContent === 'undefined')) {
|
3167
|
+
iElement.empty().append(scope.preText + value + scope.postText);
|
2690
3168
|
}
|
2691
|
-
iElement.html(scope.preText + value + scope.postText);
|
2692
3169
|
var globallyEnabled = $translate.isPostCompilingEnabled();
|
2693
3170
|
var locallyDefined = typeof tAttr.translateCompile !== 'undefined';
|
2694
3171
|
var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false';
|
@@ -2697,9 +3174,6 @@ function translateDirective($translate, $q, $interpolate, $compile, $parse, $roo
|
|
2697
3174
|
}
|
2698
3175
|
} else {
|
2699
3176
|
// translate attribute
|
2700
|
-
if (!successful && typeof scope.defaultText !== 'undefined') {
|
2701
|
-
value = scope.defaultText;
|
2702
|
-
}
|
2703
3177
|
var attributeName = iAttr.$attr[translateAttr];
|
2704
3178
|
if (attributeName.substr(0, 5) === 'data-') {
|
2705
3179
|
// ensure html5 data prefix is stripped
|
@@ -2714,6 +3188,9 @@ function translateDirective($translate, $q, $interpolate, $compile, $parse, $roo
|
|
2714
3188
|
scope.$watch('interpolateParams', updateTranslations, true);
|
2715
3189
|
}
|
2716
3190
|
|
3191
|
+
// Replaced watcher on translateLanguage with event listener
|
3192
|
+
scope.$on('translateLanguageChanged', updateTranslations);
|
3193
|
+
|
2717
3194
|
// Ensures the text will be refreshed after the current language was changed
|
2718
3195
|
// w/ $translate.use(...)
|
2719
3196
|
var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);
|
@@ -2735,15 +3212,179 @@ function translateDirective($translate, $q, $interpolate, $compile, $parse, $roo
|
|
2735
3212
|
}
|
2736
3213
|
};
|
2737
3214
|
}
|
2738
|
-
|
3215
|
+
|
3216
|
+
/**
|
3217
|
+
* Returns the scope's namespace.
|
3218
|
+
* @private
|
3219
|
+
* @param scope
|
3220
|
+
* @returns {string}
|
3221
|
+
*/
|
3222
|
+
function getTranslateNamespace(scope) {
|
3223
|
+
'use strict';
|
3224
|
+
if (scope.translateNamespace) {
|
3225
|
+
return scope.translateNamespace;
|
3226
|
+
}
|
3227
|
+
if (scope.$parent) {
|
3228
|
+
return getTranslateNamespace(scope.$parent);
|
3229
|
+
}
|
3230
|
+
}
|
2739
3231
|
|
2740
3232
|
translateDirective.displayName = 'translateDirective';
|
2741
3233
|
|
3234
|
+
angular.module('pascalprecht.translate')
|
3235
|
+
/**
|
3236
|
+
* @ngdoc directive
|
3237
|
+
* @name pascalprecht.translate.directive:translate-attr
|
3238
|
+
* @restrict A
|
3239
|
+
*
|
3240
|
+
* @description
|
3241
|
+
* Translates attributes like translate-attr-ATTR, but with an object like ng-class.
|
3242
|
+
* Internally it uses `translate` service to translate translation id. It possible to
|
3243
|
+
* pass an optional `translate-values` object literal as string into translation id.
|
3244
|
+
*
|
3245
|
+
* @param {string=} translate-attr Object literal mapping attributes to translation ids.
|
3246
|
+
* @param {string=} translate-values Values to pass into the translation ids. Can be passed as object literal string.
|
3247
|
+
*
|
3248
|
+
* @example
|
3249
|
+
<example module="ngView">
|
3250
|
+
<file name="index.html">
|
3251
|
+
<div ng-controller="TranslateCtrl">
|
3252
|
+
|
3253
|
+
<input translate-attr="{ placeholder: translationId, title: 'WITH_VALUES' }" translate-values="{value: 5}" />
|
3254
|
+
|
3255
|
+
</div>
|
3256
|
+
</file>
|
3257
|
+
<file name="script.js">
|
3258
|
+
angular.module('ngView', ['pascalprecht.translate'])
|
3259
|
+
|
3260
|
+
.config(function ($translateProvider) {
|
3261
|
+
|
3262
|
+
$translateProvider.translations('en',{
|
3263
|
+
'TRANSLATION_ID': 'Hello there!',
|
3264
|
+
'WITH_VALUES': 'The following value is dynamic: {{value}}',
|
3265
|
+
}).preferredLanguage('en');
|
3266
|
+
|
3267
|
+
});
|
3268
|
+
|
3269
|
+
angular.module('ngView').controller('TranslateCtrl', function ($scope) {
|
3270
|
+
$scope.translationId = 'TRANSLATION_ID';
|
3271
|
+
|
3272
|
+
$scope.values = {
|
3273
|
+
value: 78
|
3274
|
+
};
|
3275
|
+
});
|
3276
|
+
</file>
|
3277
|
+
<file name="scenario.js">
|
3278
|
+
it('should translate', function () {
|
3279
|
+
inject(function ($rootScope, $compile) {
|
3280
|
+
$rootScope.translationId = 'TRANSLATION_ID';
|
3281
|
+
|
3282
|
+
element = $compile('<input translate-attr="{ placeholder: translationId, title: 'WITH_VALUES' }" translate-values="{ value: 5 }" />')($rootScope);
|
3283
|
+
$rootScope.$digest();
|
3284
|
+
expect(element.attr('placeholder)).toBe('Hello there!');
|
3285
|
+
expect(element.attr('title)).toBe('The following value is dynamic: 5');
|
3286
|
+
});
|
3287
|
+
});
|
3288
|
+
</file>
|
3289
|
+
</example>
|
3290
|
+
*/
|
3291
|
+
.directive('translateAttr', translateAttrDirective);
|
3292
|
+
function translateAttrDirective($translate, $rootScope) {
|
3293
|
+
|
3294
|
+
'use strict';
|
3295
|
+
|
3296
|
+
return {
|
3297
|
+
restrict: 'A',
|
3298
|
+
priority: $translate.directivePriority(),
|
3299
|
+
link: function linkFn(scope, element, attr) {
|
3300
|
+
|
3301
|
+
var translateAttr,
|
3302
|
+
translateValues,
|
3303
|
+
previousAttributes = {};
|
3304
|
+
|
3305
|
+
// Main update translations function
|
3306
|
+
var updateTranslations = function () {
|
3307
|
+
angular.forEach(translateAttr, function (translationId, attributeName) {
|
3308
|
+
if (!translationId) {
|
3309
|
+
return;
|
3310
|
+
}
|
3311
|
+
previousAttributes[attributeName] = true;
|
3312
|
+
|
3313
|
+
// if translation id starts with '.' and translateNamespace given, prepend namespace
|
3314
|
+
if (scope.translateNamespace && translationId.charAt(0) === '.') {
|
3315
|
+
translationId = scope.translateNamespace + translationId;
|
3316
|
+
}
|
3317
|
+
$translate(translationId, translateValues, attr.translateInterpolation, undefined, scope.translateLanguage)
|
3318
|
+
.then(function (translation) {
|
3319
|
+
element.attr(attributeName, translation);
|
3320
|
+
}, function (translationId) {
|
3321
|
+
element.attr(attributeName, translationId);
|
3322
|
+
});
|
3323
|
+
});
|
3324
|
+
|
3325
|
+
// Removing unused attributes that were previously used
|
3326
|
+
angular.forEach(previousAttributes, function (flag, attributeName) {
|
3327
|
+
if (!translateAttr[attributeName]) {
|
3328
|
+
element.removeAttr(attributeName);
|
3329
|
+
delete previousAttributes[attributeName];
|
3330
|
+
}
|
3331
|
+
});
|
3332
|
+
};
|
3333
|
+
|
3334
|
+
// Watch for attribute changes
|
3335
|
+
watchAttribute(
|
3336
|
+
scope,
|
3337
|
+
attr.translateAttr,
|
3338
|
+
function (newValue) { translateAttr = newValue; },
|
3339
|
+
updateTranslations
|
3340
|
+
);
|
3341
|
+
// Watch for value changes
|
3342
|
+
watchAttribute(
|
3343
|
+
scope,
|
3344
|
+
attr.translateValues,
|
3345
|
+
function (newValue) { translateValues = newValue; },
|
3346
|
+
updateTranslations
|
3347
|
+
);
|
3348
|
+
|
3349
|
+
if (attr.translateValues) {
|
3350
|
+
scope.$watch(attr.translateValues, updateTranslations, true);
|
3351
|
+
}
|
3352
|
+
|
3353
|
+
// Replaced watcher on translateLanguage with event listener
|
3354
|
+
scope.$on('translateLanguageChanged', updateTranslations);
|
3355
|
+
|
3356
|
+
// Ensures the text will be refreshed after the current language was changed
|
3357
|
+
// w/ $translate.use(...)
|
3358
|
+
var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);
|
3359
|
+
|
3360
|
+
updateTranslations();
|
3361
|
+
scope.$on('$destroy', unbind);
|
3362
|
+
}
|
3363
|
+
};
|
3364
|
+
}
|
3365
|
+
|
3366
|
+
function watchAttribute(scope, attribute, valueCallback, changeCallback) {
|
3367
|
+
'use strict';
|
3368
|
+
if (!attribute) {
|
3369
|
+
return;
|
3370
|
+
}
|
3371
|
+
if (attribute.substr(0, 2) === '::') {
|
3372
|
+
attribute = attribute.substr(2);
|
3373
|
+
} else {
|
3374
|
+
scope.$watch(attribute, function(newValue) {
|
3375
|
+
valueCallback(newValue);
|
3376
|
+
changeCallback();
|
3377
|
+
}, true);
|
3378
|
+
}
|
3379
|
+
valueCallback(scope.$eval(attribute));
|
3380
|
+
}
|
3381
|
+
|
3382
|
+
translateAttrDirective.displayName = 'translateAttrDirective';
|
3383
|
+
|
2742
3384
|
angular.module('pascalprecht.translate')
|
2743
3385
|
/**
|
2744
3386
|
* @ngdoc directive
|
2745
3387
|
* @name pascalprecht.translate.directive:translateCloak
|
2746
|
-
* @requires $rootScope
|
2747
3388
|
* @requires $translate
|
2748
3389
|
* @restrict A
|
2749
3390
|
*
|
@@ -2763,40 +3404,205 @@ angular.module('pascalprecht.translate')
|
|
2763
3404
|
*/
|
2764
3405
|
.directive('translateCloak', translateCloakDirective);
|
2765
3406
|
|
2766
|
-
function translateCloakDirective($
|
3407
|
+
function translateCloakDirective($translate, $rootScope) {
|
2767
3408
|
|
2768
3409
|
'use strict';
|
2769
3410
|
|
2770
3411
|
return {
|
2771
|
-
compile: function (tElement) {
|
2772
|
-
var applyCloak = function () {
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
removeCloak();
|
2780
|
-
removeListener();
|
2781
|
-
removeListener = null;
|
2782
|
-
});
|
2783
|
-
applyCloak();
|
3412
|
+
compile : function (tElement) {
|
3413
|
+
var applyCloak = function (element) {
|
3414
|
+
element.addClass($translate.cloakClassName());
|
3415
|
+
},
|
3416
|
+
removeCloak = function (element) {
|
3417
|
+
element.removeClass($translate.cloakClassName());
|
3418
|
+
};
|
3419
|
+
applyCloak(tElement);
|
2784
3420
|
|
2785
3421
|
return function linkFn(scope, iElement, iAttr) {
|
2786
|
-
//
|
3422
|
+
//Create bound functions that incorporate the active DOM element.
|
3423
|
+
var iRemoveCloak = removeCloak.bind(this, iElement), iApplyCloak = applyCloak.bind(this, iElement);
|
2787
3424
|
if (iAttr.translateCloak && iAttr.translateCloak.length) {
|
3425
|
+
// Register a watcher for the defined translation allowing a fine tuned cloak
|
2788
3426
|
iAttr.$observe('translateCloak', function (translationId) {
|
2789
|
-
$translate(translationId).then(
|
3427
|
+
$translate(translationId).then(iRemoveCloak, iApplyCloak);
|
2790
3428
|
});
|
3429
|
+
$rootScope.$on('$translateChangeSuccess', function () {
|
3430
|
+
$translate(iAttr.translateCloak).then(iRemoveCloak, iApplyCloak);
|
3431
|
+
});
|
3432
|
+
} else {
|
3433
|
+
$translate.onReady(iRemoveCloak);
|
2791
3434
|
}
|
2792
3435
|
};
|
2793
3436
|
}
|
2794
3437
|
};
|
2795
3438
|
}
|
2796
|
-
translateCloakDirective.$inject = ['$rootScope', '$translate'];
|
2797
3439
|
|
2798
3440
|
translateCloakDirective.displayName = 'translateCloakDirective';
|
2799
3441
|
|
3442
|
+
angular.module('pascalprecht.translate')
|
3443
|
+
/**
|
3444
|
+
* @ngdoc directive
|
3445
|
+
* @name pascalprecht.translate.directive:translateNamespace
|
3446
|
+
* @restrict A
|
3447
|
+
*
|
3448
|
+
* @description
|
3449
|
+
* Translates given translation id either through attribute or DOM content.
|
3450
|
+
* Internally it uses `translate` filter to translate translation id. It possible to
|
3451
|
+
* pass an optional `translate-values` object literal as string into translation id.
|
3452
|
+
*
|
3453
|
+
* @param {string=} translate namespace name which could be either string or interpolated string.
|
3454
|
+
*
|
3455
|
+
* @example
|
3456
|
+
<example module="ngView">
|
3457
|
+
<file name="index.html">
|
3458
|
+
<div translate-namespace="CONTENT">
|
3459
|
+
|
3460
|
+
<div>
|
3461
|
+
<h1 translate>.HEADERS.TITLE</h1>
|
3462
|
+
<h1 translate>.HEADERS.WELCOME</h1>
|
3463
|
+
</div>
|
3464
|
+
|
3465
|
+
<div translate-namespace=".HEADERS">
|
3466
|
+
<h1 translate>.TITLE</h1>
|
3467
|
+
<h1 translate>.WELCOME</h1>
|
3468
|
+
</div>
|
3469
|
+
|
3470
|
+
</div>
|
3471
|
+
</file>
|
3472
|
+
<file name="script.js">
|
3473
|
+
angular.module('ngView', ['pascalprecht.translate'])
|
3474
|
+
|
3475
|
+
.config(function ($translateProvider) {
|
3476
|
+
|
3477
|
+
$translateProvider.translations('en',{
|
3478
|
+
'TRANSLATION_ID': 'Hello there!',
|
3479
|
+
'CONTENT': {
|
3480
|
+
'HEADERS': {
|
3481
|
+
TITLE: 'Title'
|
3482
|
+
}
|
3483
|
+
},
|
3484
|
+
'CONTENT.HEADERS.WELCOME': 'Welcome'
|
3485
|
+
}).preferredLanguage('en');
|
3486
|
+
|
3487
|
+
});
|
3488
|
+
|
3489
|
+
</file>
|
3490
|
+
</example>
|
3491
|
+
*/
|
3492
|
+
.directive('translateNamespace', translateNamespaceDirective);
|
3493
|
+
|
3494
|
+
function translateNamespaceDirective() {
|
3495
|
+
|
3496
|
+
'use strict';
|
3497
|
+
|
3498
|
+
return {
|
3499
|
+
restrict: 'A',
|
3500
|
+
scope: true,
|
3501
|
+
compile: function () {
|
3502
|
+
return {
|
3503
|
+
pre: function (scope, iElement, iAttrs) {
|
3504
|
+
scope.translateNamespace = getTranslateNamespace(scope);
|
3505
|
+
|
3506
|
+
if (scope.translateNamespace && iAttrs.translateNamespace.charAt(0) === '.') {
|
3507
|
+
scope.translateNamespace += iAttrs.translateNamespace;
|
3508
|
+
} else {
|
3509
|
+
scope.translateNamespace = iAttrs.translateNamespace;
|
3510
|
+
}
|
3511
|
+
}
|
3512
|
+
};
|
3513
|
+
}
|
3514
|
+
};
|
3515
|
+
}
|
3516
|
+
|
3517
|
+
/**
|
3518
|
+
* Returns the scope's namespace.
|
3519
|
+
* @private
|
3520
|
+
* @param scope
|
3521
|
+
* @returns {string}
|
3522
|
+
*/
|
3523
|
+
function getTranslateNamespace(scope) {
|
3524
|
+
'use strict';
|
3525
|
+
if (scope.translateNamespace) {
|
3526
|
+
return scope.translateNamespace;
|
3527
|
+
}
|
3528
|
+
if (scope.$parent) {
|
3529
|
+
return getTranslateNamespace(scope.$parent);
|
3530
|
+
}
|
3531
|
+
}
|
3532
|
+
|
3533
|
+
translateNamespaceDirective.displayName = 'translateNamespaceDirective';
|
3534
|
+
|
3535
|
+
angular.module('pascalprecht.translate')
|
3536
|
+
/**
|
3537
|
+
* @ngdoc directive
|
3538
|
+
* @name pascalprecht.translate.directive:translateLanguage
|
3539
|
+
* @restrict A
|
3540
|
+
*
|
3541
|
+
* @description
|
3542
|
+
* Forces the language to the directives in the underlying scope.
|
3543
|
+
*
|
3544
|
+
* @param {string=} translate language that will be negotiated.
|
3545
|
+
*
|
3546
|
+
* @example
|
3547
|
+
<example module="ngView">
|
3548
|
+
<file name="index.html">
|
3549
|
+
<div>
|
3550
|
+
|
3551
|
+
<div>
|
3552
|
+
<h1 translate>HELLO</h1>
|
3553
|
+
</div>
|
3554
|
+
|
3555
|
+
<div translate-language="de">
|
3556
|
+
<h1 translate>HELLO</h1>
|
3557
|
+
</div>
|
3558
|
+
|
3559
|
+
</div>
|
3560
|
+
</file>
|
3561
|
+
<file name="script.js">
|
3562
|
+
angular.module('ngView', ['pascalprecht.translate'])
|
3563
|
+
|
3564
|
+
.config(function ($translateProvider) {
|
3565
|
+
|
3566
|
+
$translateProvider
|
3567
|
+
.translations('en',{
|
3568
|
+
'HELLO': 'Hello world!'
|
3569
|
+
})
|
3570
|
+
.translations('de',{
|
3571
|
+
'HELLO': 'Hallo Welt!'
|
3572
|
+
})
|
3573
|
+
.preferredLanguage('en');
|
3574
|
+
|
3575
|
+
});
|
3576
|
+
|
3577
|
+
</file>
|
3578
|
+
</example>
|
3579
|
+
*/
|
3580
|
+
.directive('translateLanguage', translateLanguageDirective);
|
3581
|
+
|
3582
|
+
function translateLanguageDirective() {
|
3583
|
+
|
3584
|
+
'use strict';
|
3585
|
+
|
3586
|
+
return {
|
3587
|
+
restrict: 'A',
|
3588
|
+
scope: true,
|
3589
|
+
compile: function () {
|
3590
|
+
return function linkFn(scope, iElement, iAttrs) {
|
3591
|
+
|
3592
|
+
iAttrs.$observe('translateLanguage', function (newTranslateLanguage) {
|
3593
|
+
scope.translateLanguage = newTranslateLanguage;
|
3594
|
+
});
|
3595
|
+
|
3596
|
+
scope.$watch('translateLanguage', function(){
|
3597
|
+
scope.$broadcast('translateLanguageChanged');
|
3598
|
+
});
|
3599
|
+
};
|
3600
|
+
}
|
3601
|
+
};
|
3602
|
+
}
|
3603
|
+
|
3604
|
+
translateLanguageDirective.displayName = 'translateLanguageDirective';
|
3605
|
+
|
2800
3606
|
angular.module('pascalprecht.translate')
|
2801
3607
|
/**
|
2802
3608
|
* @ngdoc filter
|
@@ -2855,13 +3661,15 @@ function translateFilterFactory($parse, $translate) {
|
|
2855
3661
|
|
2856
3662
|
'use strict';
|
2857
3663
|
|
2858
|
-
var translateFilter = function (translationId, interpolateParams, interpolation) {
|
2859
|
-
|
3664
|
+
var translateFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {
|
2860
3665
|
if (!angular.isObject(interpolateParams)) {
|
2861
|
-
|
3666
|
+
var ctx = this || {
|
3667
|
+
'__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'
|
3668
|
+
};
|
3669
|
+
interpolateParams = $parse(interpolateParams)(ctx);
|
2862
3670
|
}
|
2863
3671
|
|
2864
|
-
return $translate.instant(translationId, interpolateParams, interpolation);
|
3672
|
+
return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);
|
2865
3673
|
};
|
2866
3674
|
|
2867
3675
|
if ($translate.statefulFilter()) {
|
@@ -2870,7 +3678,6 @@ function translateFilterFactory($parse, $translate) {
|
|
2870
3678
|
|
2871
3679
|
return translateFilter;
|
2872
3680
|
}
|
2873
|
-
translateFilterFactory.$inject = ['$parse', '$translate'];
|
2874
3681
|
|
2875
3682
|
translateFilterFactory.displayName = 'translateFilterFactory';
|
2876
3683
|
|
@@ -2896,7 +3703,6 @@ function $translationCache($cacheFactory) {
|
|
2896
3703
|
|
2897
3704
|
return $cacheFactory('translations');
|
2898
3705
|
}
|
2899
|
-
$translationCache.$inject = ['$cacheFactory'];
|
2900
3706
|
|
2901
3707
|
$translationCache.displayName = '$translationCache';
|
2902
3708
|
return 'pascalprecht.translate';
|