Reputation: 441
I'm trying to integrate the angular-translate module into my application.
I've gotten an asynchronous loader to work correctly, and it loads my language translations correctly.
The problem I'm running in to, however, is that our backend is based on Struts 1. We have a template that is included in each page load instead of the body content being swapped out like in a single-page application. This template is where we instantiate the angular app with angular.module
and all the dependencies. After instantiation, I set up the translation provider:
myApp.config(['$translateProvider', function($translateProvider){
$translateProvider.useUrlLoader('url/to/my/load/action.do');
$translateProvider.determinePreferredLanguage();
}]);
Because this template is included on each page load, and the angular app is thus instantiated again after each page load, the translation provider is hitting my action on every page load to get the translations.
This wouldn't be a huge load on the backend because I've implemented caching, but the problem is the flashes of untranslated content on every page.
My proposed solution is as follows:
Have a controller that will catch the $translateLoadingEnd
event fired by angular translate and put the translation table into a cookie with some expiration time
myApp.controller('TranslationController', function($scope, $rootScope){
$rootScope.$on('$translateLoadingEnd',function(event) {
// Get the translation table and put it in a cookie
});
});
In the config, I will only set $translateProvider.useUrlLoader('url/to/my/load/action.do');
if the cookie does not exist or it has expired. To do this, I will have to get the cookie by injecting the cookies service into the config with something like the following (how to use cookiesProvider in angular config) and grabbing out the translation table:
var $cookies;
angular.injector(['ngCookies']).invoke(function(_$cookies_) {
$cookies = _$cookies_;
});
My question is if there way to get the translation table for a given language so that I can put it into a cookie. I've dug through the source code for the module a bit, and the only thing that I have found is only a local function and is not exposed for my use.
Any comments and suggestions on my approach to solving this problem are also welcome.
Upvotes: 1
Views: 2830
Reputation: 441
I decided to fix this in a much more elegant way. Instead of using the useUrlLoader
function, I used a custom loader.
$translateProvider.useLoader("translationFactory");
myApp.factory("translationFactory", function($q, $resource, localStorageService) {
var GetTranslationsResource = $resource(baseHref + 'url/to/my/load/actiongetTranslations.do', {}, {});
return function(options) {
var deferred = $q.defer();
var currentTime = new Date().getTime();
var twelveHours = 12 * 60 * 60 * 1000;
var translationStorage = localStorageService.get("translationStorage");
if(translationStorage && translationStorage.expiration + twelveHours > currentTime && translationStorage.translations[options.key]) { // Have local storage, it hasn't been 12 hours yet, and we have translations for this language
setTimeout(function() { // Need a timeout so that the promise returns first
return deferred.resolve(translationStorage.translations[options.key]);
}, 500);
} else {
GetTranslationsResource.get({"lang" : options.key}, function(result) {
switch(result.status){
case 'success':
var newTranslationStorage = {
expiration : currentTime,
translations : {}
};
newTranslationStorage.translations[options.key] = result.data;
localStorageService.set("translationStorage", newTranslationStorage);
return deferred.resolve(result.data);
break;
case 'error': deferred.reject(options.key); break;
case 'logout': hideLoader(); ajaxLogout(); break;
}
}, function(){
return deferred.reject(options.key);
});
}
return deferred.promise;
};
});
Upvotes: 1