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

Commit

Permalink
feat(translateService): informs interpolator when locale has changed
Browse files Browse the repository at this point in the history
- this commit also teaches interpolators to temporarly use fallback language
if needed
  • Loading branch information
0x-r4bbit committed Jul 19, 2013
1 parent bf3dbbb commit e59b141
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 20 deletions.
83 changes: 64 additions & 19 deletions src/translate.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,18 @@ angular.module('pascalprecht.translate').provider('$translate', ['$STORAGE_KEY',
this.useInterpolation('$translateMessageFormatInterpolation');
};

/**
* @ngdoc function
* @name pascalprecht.translate.$translateProvider#useInterpolation
* @methodOf pascalprecht.translate.$translateProvider
*
* @description
* Tells angular-translate which interpolation style to use as default, application-wide.
* Simply pass a factory/service name. The interpolation service has to implement
* the correct interface.
*
* @param {string} factory Interpolation service name.
*/
this.useInterpolation = function (factory) {
$interpolationFactory = factory;
};
Expand Down Expand Up @@ -506,14 +518,24 @@ angular.module('pascalprecht.translate').provider('$translate', ['$STORAGE_KEY',
function ($log, $injector, $rootScope, $q) {

var Storage,
interpolateFn = $injector.get($interpolationFactory || '$translateDefaultInterpolation').interpolate,
defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation');
pendingLoader = false,
interpolatorHashMap = {};

if ($storageFactory) {
Storage = $injector.get($storageFactory);

if (!Storage.get || !Storage.set) {
throw new Error('Couldn\'t use storage \'' + $storageFactory + '\', missing get() or set() method!');
}
}

// if we have additional interpolations that were added via
// $translateProvider.addInterpolation(), we have to map'em
if ($interpolatorFactories.length) {
if ($interpolatorFactories.length > 0) {

angular.forEach($interpolatorFactories, function (interpolatorFactory) {

var interpolator = $injector.get(interpolatorFactory);
// setting initial locale for each interpolation service
interpolator.setLocale($preferredLanguage || $uses);
Expand All @@ -522,35 +544,44 @@ angular.module('pascalprecht.translate').provider('$translate', ['$STORAGE_KEY',
});
}

if ($storageFactory) {
Storage = $injector.get($storageFactory);

if (!Storage.get || !Storage.set) {
throw new Error('Couldn\'t use storage \'' + $storageFactory + '\', missing get() or set() method!');
}
}

var $translate = function (translationId, interpolateParams, interpolationId) {

// determine translation table and current Interpolator
var table = $uses ? $translationTable[$uses] : $translationTable,
interpolate = (interpolationId) ? interpolatorHashMap[interpolationId].interpolate : interpolateFn;

Interpolator = (interpolationId) ? interpolatorHashMap[interpolationId] : defaultInterpolator;

// if the translation id exists, we can just interpolate it
if (table && table.hasOwnProperty(translationId)) {
return interpolate(table[translationId], interpolateParams);
return Interpolator.interpolate(table[translationId], interpolateParams);
}

// looks like the requested translation id doesn't exists.
// Now, if there is a registered handler for missing translations and no
// asyncLoader is pending, we execute the handler
if ($missingTranslationHandlerFactory && !pendingLoader) {
$injector.get($missingTranslationHandlerFactory)(translationId, $uses);
}

// since we couldn't translate the inital requested translation id,
// we try it now with a fallback language, if a fallback language is
// configured.
if ($uses && $fallbackLanguage && $uses !== $fallbackLanguage){

var translation = $translationTable[$fallbackLanguage][translationId];

// check if a translation for the fallback language exists
if (translation) {
return interpolate(translation, interpolateParams);
var returnVal;
// temporarly letting Interpolator know we're using fallback language now.
Interpolator.setLocale($fallbackLanguage);
returnVal = Interpolator.interpolate(translation, interpolateParams);
// after we've interpolated the translation, we reset Interpolator to proper locale.
Interpolator.setLocale($uses);
return returnVal;
}
}

if ($missingTranslationHandlerFactory && !pendingLoader) {
$injector.get($missingTranslationHandlerFactory)(translationId, $uses);
}


// applying notFoundIndicators
if ($notFoundIndicatorLeft) {
translationId = [$notFoundIndicatorLeft, translationId].join(' ');
}
Expand Down Expand Up @@ -653,6 +684,13 @@ angular.module('pascalprecht.translate').provider('$translate', ['$STORAGE_KEY',
Storage.set($translate.storageKey(), $uses);
}

// inform default interpolator
defaultInterpolator.setLocale($uses);
// inform all others to!
angular.forEach(interpolatorHashMap, function (interpolator, id) {
interpolatorHashMap[id].setLocale($uses);
});

pendingLoader = false;
$rootScope.$broadcast('translationChangeSuccess');
deferred.resolve($uses);
Expand All @@ -670,6 +708,13 @@ angular.module('pascalprecht.translate').provider('$translate', ['$STORAGE_KEY',
Storage.set($translate.storageKey(), $uses);
}

// inform default interpolator
defaultInterpolator.setLocale($uses);
// inform all others to!
angular.forEach(interpolatorHashMap, function (interpolator, id) {
interpolatorHashMap[id].setLocale($uses);
});

deferred.resolve($uses);
$rootScope.$broadcast('translationChangeSuccess');
return deferred.promise;
Expand Down
49 changes: 48 additions & 1 deletion test/unit/translateServiceSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,33 @@ describe('pascalprecht.translate', function () {

describe('interpolations', function () {

/*ddescribe('incorrect interpolation service given', function () {
var $translate;
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide) {
$provide.factory('incorrectInterpolationService', function () {
return {};
});
$translateProvider.translations('en', {
FOO: 'FOO'
});
$translateProvider.useInterpolation('incorrectInterpolationService');
$translateProvider.preferredLanguage('en');
}));
beforeEach(inject(function (_$translate_) {
$translate = _$translate_;
}));
it('should throw an error when interpolation service interface isn\'t implemented', function () {
expect(function () {
$translate('FOO');
}).toThrow("Couldn\'t interpolate! Interpolation service doesn\'t implement the correct interface!");
});
});*/

describe('addInterpolation', function () {

var $translate;
Expand All @@ -670,7 +697,11 @@ describe('pascalprecht.translate', function () {

// defining the actual interpolate function
translateInterpolator.interpolate = function (string, interpolateParams) {
return 'custom interpolation';
if ($locale == 'de') {
return 'foo';
} else {
return 'custom interpolation';
}
};

return translateInterpolator;
Expand All @@ -684,8 +715,13 @@ describe('pascalprecht.translate', function () {
'FOO': 'Some text'
});

$translateProvider.translations('de', {
'FOO': 'Irgendwas',
'BAR': 'yupp'
});
// set default language
$translateProvider.preferredLanguage('en');
$translateProvider.fallbackLanguage('de');
}));

beforeEach(inject(function (_$translate_) {
Expand All @@ -699,6 +735,17 @@ describe('pascalprecht.translate', function () {
it('should use custom interpolation', function () {
expect($translate('FOO', {}, 'custom')).toEqual('custom interpolation');
});

it('should inform custom interpolation when language has been changed', function () {
expect($translate('FOO', {}, 'custom')).toEqual('custom interpolation');
$translate.uses('de');
expect($translate('FOO', {}, 'custom')).toEqual('foo');
});

it('should use fallback language, if configured', function () {
expect($translate('BAR', {}, 'custom')).toEqual('foo');
expect($translate('FOO', {}, 'custom')).toEqual('custom interpolation');
});
});

describe('addInterpolation messageformat', function () {
Expand Down

0 comments on commit e59b141

Please sign in to comment.