Возврат к другому идентификатору перевода с директивой angular-translate

угловой перевод 2.7.2, AngularJS 1.4.2

У меня есть требование (не спрашивайте...), чтобы для каждого переводимого фрагмента текста на моем сайте на самом деле существовало два перевода-кандидата, один из которых получается путем добавления префикса к translationId.

Примеры переводов:

greeting => "hi"
abc.greeting => "yo"

abc. здесь мой префикс. Если abc.greeting можно перевести, то должен быть показан его перевод, в противном случае можно вернуться к translationId greeting, если он доступен, и если ни один translationId не существует: сдаться, обработать отсутствующий перевод.

Я хочу заключить это поведение в директиву, чтобы мне было удобно использовать его следующим образом:

<p my-translate="greeting"></p>

который производит либо <p>yo</p>, либо <p>hi</p> в зависимости от существования translationIds. Я придумал этот код в своей директиве, которая по сути обертывает $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);
  });
}

Вскоре я понял, что этого решения не хватает по сравнению с директивой angular-translate: она не замечает выбор языка (думаю, мне нужно слушать на $translateChangeSuccess) и не настраивает наблюдателей за изменениями в идентификатор перевода и значения перевода. Выполнение всего этого эффективным образом — это то, что уже делает директива angular-translate: https://stackoverflow.com/a/23866441

Итак, мой вопрос: как я могу расширить или повторно использовать директиву перевода, но с запасным вариантом в отношении идентификаторов перевода? Любые идеи?


person stholzm    schedule 18.08.2015    source источник


Ответы (2)


Наконец-то я нашел способ изменить angular-translate, сохранив при этом возможность использовать его директиву и фильтр. По сути, я заменил $translate своей собственной функцией. $provide позволяет мне украсить $translate, который затем используется другими инструментами angular-translate.

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;
        } ]);
} ]);

Пришлось также скопировать кучу свойств; иначе моя функция translate не работает как замена $translate. Все еще выглядит немного хакерским, но это лучшее решение, которое я мог придумать. По крайней мере, никаких других изменений (или даже собственных директив или фильтров) не потребовалось, только этот блок конфигурации.

person stholzm    schedule 09.09.2015
comment
Привет, @stholzm, я немного опоздал и не уверен на 100%, но не могли бы вы использовать angular.extend(translate, $delegate), чтобы избежать повторного объявления всех свойств после объявления функции перевода? - person DavidTw; 23.05.2017
comment
@DavidTw выглядит более разумно! К сожалению, эта проблема давно решена, и я не могу легко ее проверить. Но спасибо за предложение! Я буду иметь это в виду. - person stholzm; 23.05.2017

Как я понимаю, для существования нужен чек перевода.
Первое, что пришло в голову:

//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;
};

и уже можно использовать с:

$rootScope.$on('$translateChangeSuccess', function(){
  //do something with $scope.isExist(); like:
  $scope.somethingValue = $scope.isExist(somethingValue);
});

Будьте осторожны с данными переводов, он не будет работать с такими данными, как:

abc.greeting => "abc.greeting"
abc.value=> "abc.value"
//but it is unlikely, that You could have tr. like 'abc.Hello';

Я надеюсь, что это поможет вам;
Извините за мой английский;

person user3335966    schedule 18.08.2015
comment
Извините, это звучит довольно неудобно для меня, потому что мне нужно свойство области действия для каждой переводимой строки в моем приложении. Я действительно хочу инкапсулировать резервное поведение в директиве. - person stholzm; 19.08.2015