Reputation: 3455
angular-translate 2.7.2, AngularJS 1.4.2
I have the requirement (don't ask...) that for every translatable snippet of text on my site, there are actually two candidate translations of which one is derived by adding a prefix to the translationId.
Example translations:
greeting => "hi"
abc.greeting => "yo"
abc.
is my prefix here. If abc.greeting
can be translated, then its translation should be shown, otherwise fall back to the translationId greeting
if available, and if neither translationId exists: give up, handle the missing translation.
I want to wrap this behavior into a directive so that I can still use conveniently it like this:
<p my-translate="greeting"></p>
which produces either <p>yo</p>
or <p>hi</p>
depending on the existance of translationIds. I came up with this code in my directive that essentially wraps $translate
:
function translateWithFallback(translationId, translationValues, element, prefix) {
function successHandler(translation) {
element.html(translation);
}
function failureHandler(translationId) {
element.html("???" + translationId + "???");
}
var prefixedTranslationId = prefix + translationId;
$translate(prefixedTranslationId, translationValues).then(successHandler, function() {
$translate(translationId, translationValues).then(successHandler, failureHandler);
});
}
Soon I realized that this solution is lacking compared to the angular-translate directive: It does not notice language selection (I guess I'd need to listen on $translateChangeSuccess
) and does not set up watchers for changes to translationId and translationValues. Doing all that and in an efficient manner is what the angular-translate directive already does: https://stackoverflow.com/a/23866441
So my question is: how can I extend or reuse the translate directive but with a fallback regarding translationIds? Any ideas?
Upvotes: 1
Views: 683
Reputation: 3455
I finally found a way to modify angular-translate while still being able to use its directive and filter. In essence, I replaced $translate
with my own function. $provide
allows me to decorate $translate
, which then is used by angular-translate's other tools.
module.config([ "$provide", function($provide) {
$provide.decorator('$translate', [ "$delegate", function($delegate) {
function translate(translationId, tValues, iId, dTText, myPrefix) {
// fallback logic which makes use of $delegate
}
translate.preferredLanguage = $delegate.preferredLanguage;
translate.cloakClassName = $delegate.cloakClassName;
translate.fallbackLanguage = $delegate.fallbackLanguage;
translate.useFallbackLanguage = $delegate.useFallbackLanguage;
translate.proposedLanguage = $delegate.proposedLanguage;
translate.storage = $delegate.storage;
translate.use = $delegate.use;
translate.storageKey = $delegate.storageKey;
translate.isPostCompilingEnabled = $delegate.isPostCompilingEnabled;
translate.isForceAsyncReloadEnabled = $delegate.isForceAsyncReloadEnabled;
translate.refresh = $delegate.refresh;
translate.instant = $delegate.instant;
translate.versionInfo = $delegate.versionInfo;
translate.loaderCache = $delegate.loaderCache;
translate.directivePriority = $delegate.directivePriority;
translate.statefulFilter = $delegate.statefulFilter;
return translate;
} ]);
} ]);
Had to copy a bunch of properties, too; otherwise my translate
function does not work as a replacement for $translate
. Still looks kind of hacky, but that is the best solution I could come up with. At least no other changes (or even own directives or filters) were necessary, just this config block.
Upvotes: 1
Reputation: 2745
As I understand, You need check translation to exist.
The first thing that came to mind:
//it's return translate with prefix, if exist
//and translate without prefix or original value;
$scope.isExist = function(value){
//value = 'greeting';
var tr1 = $filter('translate')(value);
var tr2 = $filter('translate')('abc.' + value);
return tr2 !== 'abc.' + value ? tr2 : tr1;
};
and it is already possible to use with:
$rootScope.$on('$translateChangeSuccess', function(){
//do something with $scope.isExist(); like:
$scope.somethingValue = $scope.isExist(somethingValue);
});
Be careful with translations data, it will not work with data like:
abc.greeting => "abc.greeting"
abc.value=> "abc.value"
//but it is unlikely, that You could have tr. like 'abc.Hello';
I hope this will help you;
Sorry for my English;
Upvotes: 0