Skip to content
This repository has been archived by the owner on Jan 29, 2024. It is now read-only.

Commit

Permalink
feat(service): introduce post processing for translations
Browse files Browse the repository at this point in the history
This allows intercepting the result of the effective translation result.

```js
// via function
$translateProvider.postProcess(function (translationId, translation, resolvedTranslation, interpolateParams, uses) {
  return '<span class="highlight" lang="' + uses + '">' + resolvedTranslation + '</span>';
});

// or via service reference
app.service('$myPostProcessFunction', function() {
  return function (translationId, translation, resolvedTranslation) {
    return 'Value: ' + resolvedTranslation;
  };
})
$translateProvider.postProcess('$myPostProcessFunction');
```
  • Loading branch information
tspaeth authored and knalli committed Mar 5, 2016
1 parent 3988af0 commit f0c4874
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 3 deletions.
71 changes: 71 additions & 0 deletions demo/ex14_async_loader_with_postProcessor.htm
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html ng-app='app'>

<head>
<meta charset="utf-8">
<title translate="load.predefined.TITLE">lazy load files together with postProcessor</title>
<style>body { text-align: center; }</style>
</head>

<body ng-controller="ctrl">

<p>
<a href="#" ng-click="setLang('en_US')">English</a>
|
<a href="#" ng-click="setLang('ru_RU')">Русский</a>
</p>

<h1 translate>load.predefined.HEADER</h1>
<h2 translate>load.predefined.SUBHEADER</h2>
<h3 translate>load.static.ONLY_RU</h3>
<script src="../bower_components/angular/angular.js"></script>
<script src="../bower_components/angular-cookies/angular-cookies.js"></script>
<script src="../src/translate.js"></script>
<script src="../src/service/default-interpolation.js"></script>
<script src="../src/service/sanitization.js"></script>
<script src="../src/service/loader-static-files.js"></script>
<script src="../src/service/storage-key.js"></script>
<script src="../src/service/storage-cookie.js"></script>
<script src="../src/service/translate.js"></script>
<script src="../src/directive/translate.js"></script>
<script src="../src/filter/translate.js"></script>
<script>
angular.module('app', ['pascalprecht.translate', 'ngCookies'])

.config(['$translateProvider', function($translateProvider) {

// Register a loader for the static files
// So, the module will search missing translation tables under the specified urls.
// Those urls are [prefix][langKey][suffix].
$translateProvider.useStaticFilesLoader({
prefix: 'l10n/',
suffix: '.json'
});

// Tell the module what language to use by default
$translateProvider.preferredLanguage('en_US');
$translateProvider.fallbackLanguage('ru_RU');

// Tell the module to store the language in the cookies
$translateProvider.useCookieStorage();

// Tell the module to postprocess the translations in success cases
$translateProvider.postProcess(function (translationId, translation, interpolatedTranslation, params, lang) {
return '<span style="color: #cccccc">' + translationId + '(' + lang + '):</span> ' +
(interpolatedTranslation ? interpolatedTranslation : translation);
});

}])

.controller('ctrl', ['$scope', '$translate', function($scope, $translate) {

$scope.setLang = function(langKey) {
// You can change the language during runtime
$translate.use(langKey);
};

}]);
</script>

</body>
</html>
52 changes: 49 additions & 3 deletions src/service/translate.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
loaderCache,
directivePriority = 0,
statefulFilter = true,
postProcessFn,
uniformLanguageTagResolver = 'default',
languageTagResolver = {
'default': function (tag) {
Expand Down Expand Up @@ -951,6 +952,25 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
}
};

/**
* @ngdoc function
* @name pascalprecht.translate.$translateProvider#postProcess
* @methodOf pascalprecht.translate.$translateProvider
*
* @description
* The post processor will be intercept right after the translation result. It can modify the result.
*
* @param {object} fn Function or service name (string) to be called after the translation value has been set / resolved. The function itself will enrich every value being processed and then continue the normal resolver process
*/
this.postProcess = function (fn) {
if (fn) {
postProcessFn = fn;
} else {
postProcessFn = undefined;
}
return this;
};

/**
* @ngdoc object
* @name pascalprecht.translate.$translate
Expand Down Expand Up @@ -1291,7 +1311,11 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
getFallbackTranslation(langKey, translation.substr(2), interpolateParams, Interpolator)
.then(deferred.resolve, deferred.reject);
} else {
deferred.resolve(Interpolator.interpolate(translationTable[translationId], interpolateParams));
var interpolatedValue = Interpolator.interpolate(translationTable[translationId], interpolateParams);
interpolatedValue = applyPostProcessing(translationId, translationTable[translationId], interpolatedValue, interpolateParams, langKey);

deferred.resolve(interpolatedValue);

}
Interpolator.setLocale($uses);
} else {
Expand Down Expand Up @@ -1379,7 +1403,9 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
if (fallbackLanguageIndex < $fallbackLanguage.length) {
var langKey = $fallbackLanguage[fallbackLanguageIndex];
getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator).then(
deferred.resolve,
function (data) {
deferred.resolve(data);
},
function () {
// Look in the next fallback language for a translation.
// It delays the resolving by passing another promise to resolve.
Expand Down Expand Up @@ -1469,7 +1495,10 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
$translate(translation.substr(2), interpolateParams, interpolationId, defaultTranslationText, uses)
.then(deferred.resolve, deferred.reject);
} else {
deferred.resolve(Interpolator.interpolate(translation, interpolateParams));
//
var resolvedTranslation = Interpolator.interpolate(translation, interpolateParams);
resolvedTranslation = applyPostProcessing(translationId, translation, resolvedTranslation, interpolateParams, uses);
deferred.resolve(resolvedTranslation);
}
} else {
var missingTranslationHandlerTranslation;
Expand Down Expand Up @@ -1561,6 +1590,23 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
langPromises[key] = undefined;
};

var applyPostProcessing = function (translationId, translation, resolvedTranslation, interpolateParams, uses) {
var fn = postProcessFn;

if (fn) {

if (typeof(fn) === 'string') {
// getting on-demand instance
fn = $injector.get(fn);
}
if (fn) {
return fn(translationId, translation, resolvedTranslation, interpolateParams, uses);
}
}

return resolvedTranslation;
};

/**
* @ngdoc function
* @name pascalprecht.translate.$translate#preferredLanguage
Expand Down
71 changes: 71 additions & 0 deletions test/unit/service/translate.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2668,4 +2668,75 @@ describe('pascalprecht.translate', function () {

});

describe('$translate#postprocess() with an enabled fallback language', function () {

describe('single post processDemo', function () {

beforeEach(module('pascalprecht.translate', function ($translateProvider) {
$translateProvider
//.translations('de_DE', translationMock)
.translations('de_DE', {'ONLY_GERMAN' : 'DE_TRANS', 'BOTH' : 'BOTH_DE'})
.translations('en_EN', {'TRANSLATION__ID' : 'bazinga', 'BOTH' : 'BOTH_EN'})
.preferredLanguage('de_DE')
.fallbackLanguage('en_EN')
.postProcess(function (translationId, translation, interpolatedTranslation, params, lang) {
return translationId + ',' + lang + ',' + (interpolatedTranslation ? interpolatedTranslation : translation);
});
}));

var $translate, $q, $rootScope;

beforeEach(inject(function (_$translate_, _$q_, _$rootScope_) {
$translate = _$translate_;
$q = _$q_;
$rootScope = _$rootScope_;
}));

it('should return a formatted postprocessed string on fallback language', function () {
var deferred = $q.defer(),
promise = deferred.promise,
value;

promise.then(function (translation) {
value = translation;
});
$translate('TRANSLATION__ID').then(function (translation) {
deferred.resolve(translation);
});

$rootScope.$digest();
expect(value).toEqual('TRANSLATION__ID,en_EN,bazinga');
});
it('should return a formatted postprocessed string on preferred language', function () {
var deferred = $q.defer(),
promise = deferred.promise,
value;

promise.then(function (translation) {
value = translation;
});
$translate('ONLY_GERMAN').then(function (translation) {
deferred.resolve(translation);
});

$rootScope.$digest();
expect(value).toEqual('ONLY_GERMAN,de_DE,DE_TRANS');
});
it('should return a formatted postprocessed string on preferred language', function () {
var deferred = $q.defer(),
promise = deferred.promise,
value;

promise.then(function (translation) {
value = translation;
});
$translate('BOTH').then(function (translation) {
deferred.resolve(translation);
});

$rootScope.$digest();
expect(value).toEqual('BOTH,de_DE,BOTH_DE');
});
});
});
});

0 comments on commit f0c4874

Please sign in to comment.