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

Commit

Permalink
fix(partial loader): add check for added/removed part while refreshing
Browse files Browse the repository at this point in the history
While the partial loader is refreshing all parts (implictiy invoked by
a language change), any additional part will be missed and added again.

Fixes #1781
  • Loading branch information
knalli committed Dec 21, 2017
1 parent 6c3b63e commit 3520418
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 2 deletions.
28 changes: 26 additions & 2 deletions src/service/loader-partial.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ function $translatePartialLoader() {
*
* @throws {TypeError}
*/
this.$get = ['$rootScope', '$injector', '$q', '$http',
function ($rootScope, $injector, $q, $http) {
this.$get = ['$rootScope', '$injector', '$q', '$http', '$log',
function ($rootScope, $injector, $q, $http, $log) {

/**
* @ngdoc event
Expand Down Expand Up @@ -344,15 +344,39 @@ function $translatePartialLoader() {
part.urlTemplate = part.urlTemplate || options.urlTemplate;
});

// workaround for #1781
var structureHasBeenChangedWhileLoading = false;
var dirtyCheckEventCloser = $rootScope.$on('$translatePartialLoaderStructureChanged', function () {
structureHasBeenChangedWhileLoading = true;
});

return $q.all(loaders)
.then(function () {
dirtyCheckEventCloser();
if (structureHasBeenChangedWhileLoading) {
if (!options.__retries) {
// the part structure has been changed while loading (the origin ones)
// this can happen if an addPart/removePart has been invoked right after a $translate.use(lang)
// TODO maybe we can optimize this with the actual list of missing parts
options.__retries = (options.__retries || 0) + 1;
return service(options);
} else {
// the part structure has been changed again while loading (retried one)
// because this could an infinite loop, this will not load another one again
$log.warn('The partial loader has detected a multiple structure change (with addPort/removePart) ' +
'while loading translations. You should consider using promises of $translate.use(lang) and ' +
'$translate.refresh(). Also parts should be added/removed right before an explicit refresh ' +
'if possible.');
}
}
var table = {};
prioritizedParts = getPrioritizedParts();
angular.forEach(prioritizedParts, function (part) {
deepExtend(table, part.tables[options.key]);
});
return table;
}, function () {
dirtyCheckEventCloser();
return $q.reject(options.key);
});
};
Expand Down
76 changes: 76 additions & 0 deletions test/unit/service/translate.partialLoader.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* jshint camelcase: false, quotmark: false, unused: false */
/* global inject: false */
'use strict';

describe('pascalprecht.translate', function () {

beforeEach(module('ngMockE2EAsync'));

beforeEach(module('pascalprecht.translate', function ($translateProvider, $translatePartialLoaderProvider) {
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate : '/locales/{part}-{lang}.json'
});
$translatePartialLoaderProvider.addPart('part1');
$translateProvider.use('en');
}));

module(function ($provide) {
//Randomly delay $http response to simulate real-world scenario.
$provide.decorator('$httpBackend', function ($delegate) {
var proxy = function (method, url, data, callback, headers) {
var interceptor = function () {
var _this = this,
_arguments = arguments,
_timeout = Math.floor((Math.random() * 50) + 1);
console.log('setting timeout to', _timeout);
setTimeout(function () {
callback.apply(_this, _arguments);
}, _timeout);
};
return $delegate.call(this, method, url, data, interceptor, headers);
};
for (var key in $delegate) {
proxy[key] = $delegate[key];
}
return proxy;
});
});

describe('using partial-loader', function () {

it('and one part right before $translate.use(…)', inject(function ($translatePartialLoader, $httpBackend, $translate, $timeout) {

$httpBackend.whenGET('/locales/part1-en.json').respond(200, '{"key1":"value1","key2":"value2","key3":"value3","key4":"value4"}');

$translate(['key1', 'key2', 'key3'])
.then(function (translations) {
expect(translations.key1).toEqual('value1');
expect(translations.key2).toEqual('value2');
expect(translations.key3).toEqual('value3');
console.log(translations);
});

$timeout.flush();

}));

// #1781
it('additional part right after $translate.use(…)', inject(function ($translatePartialLoader, $httpBackend, $translate, $timeout) {

$translatePartialLoader.addPart('part2');

$httpBackend.whenGET('/locales/part1-en.json').respond(200, '{"key1":"value1","key2":"value2","key3":"value3","key4":"value4"}');
$httpBackend.whenGET('/locales/part2-en.json').respond(200, '{"key2" : "overridenby2","key4":"overridenby2"}');

$translate(['key1', 'key2', 'key3'])
.then(function (translations) {
expect(translations.key1).toEqual('value1');
expect(translations.key2).toEqual('overridenby2');
expect(translations.key3).toEqual('value3');
});

$timeout.flush();

}));
});
});

0 comments on commit 3520418

Please sign in to comment.