Я использую angular-translate для i18n в приложении AngularJS.
Для каждого представления приложения есть выделенный контроллер. В контроллерах ниже я установил значение, которое будет отображаться в качестве заголовка страницы.
Код
HTML
<h1>{{ pageTitle }}</h1>
JavaScript
.controller('FirstPageCtrl', ['$scope', '$filter', function ($scope, $filter) {
$scope.pageTitle = $filter('translate')('HELLO_WORLD');
}])
.controller('SecondPageCtrl', ['$scope', '$filter', function ($scope, $filter) {
$scope.pageTitle = 'Second page title';
}])
Я загружаю файлы перевода, используя расширение angular-translate-loader-url .
проблема
При начальной загрузке страницы вместо перевода для этого ключа отображается ключ перевода. Перевод есть Hello, World!
, но я смотрю HELLO_WORLD
.
Второй раз захожу на страницу, все хорошо, отображается переведенная версия.
Я предполагаю, что проблема связана с тем, что, возможно, файл перевода еще не загружен, когда контроллер присваивает значение $scope.pageTitle
.
замечание
При использовании <h1>{{ pageTitle | translate }}</h1>
и $scope.pageTitle = 'HELLO_WORLD';
перевод работает идеально с первого раза. Проблема в том, что я не всегда хочу использовать переводы (например, для второго контроллера я просто хочу передать необработанную строку).
Вопрос
Это известная проблема / ограничение? Как это можно решить?
источник
$scope.$watch
является излишним, поскольку Angular Translate предлагает службу для использования в контроллерах. Смотрите мой ответ ниже.$translate.instant()
предлагает то же самое, что и услуга. Кроме этого, обратите внимание на ответ Паскаля.Рекомендуется: не переводите в контроллере, переводите в вашем представлении
Я бы рекомендовал освободить ваш контроллер от логики перевода и переводить ваши строки прямо внутри вашего представления следующим образом:
Воспользовавшись предоставленной услугой
Angular Translate предоставляет
$translate
сервис, который вы можете использовать в своих контроллерах.Примером использования
$translate
услуги может быть:Служба перевода также имеет метод прямого перевода строк без необходимости обрабатывать обещание, используя
$translate.instant()
:Обратной стороной использования
$translate.instant()
может быть то, что языковой файл еще не загружен, если вы загружаете его асинхронно.Использование предоставленного фильтра
Это мой предпочтительный способ, поскольку мне не нужно обрабатывать обещания таким образом. Выходные данные фильтра могут быть напрямую установлены в переменную области действия.
Использование предоставленной директивы
Поскольку @PascalPrecht является создателем этой замечательной библиотеки, я бы порекомендовал последовать его совету (см. Его ответ ниже) и использовать предоставленную директиву, которая, кажется, очень умно обрабатывает переводы.
источник
Собственно, вместо этого вам следует использовать директиву translate.
Директива заботится об асинхронном выполнении, а также достаточно умен, чтобы не отслеживать идентификаторы перевода в области видимости, если перевод не имеет динамических значений.
Однако, если нет никакого пути и вам действительно нужно использовать
$translate
службу в контроллере, вы должны заключить вызов в$translateChangeSuccess
событие, используя$rootScope
в сочетании с$translate.instant()
таким:Так почему бы
$rootScope
и нет$scope
? Причина этого в том, что в угловых перевод'S события$emit
эд на$rootScope
чем -$broadcast
е изд на$scope
потому , что мы не должны вещания по всей иерархии областей видимости.Почему,
$translate.instant()
а не просто асинхронный$translate()
? Когда$translateChangeSuccess
событие запускается, очевидно, что необходимые данные перевода есть и асинхронное выполнение не происходит (например, выполнение асинхронного загрузчика), поэтому мы можем просто использовать то,$translate.instant()
что является синхронным, и просто предполагает, что переводы доступны.Начиная с версии 2.8.0 есть также
$translate.onReady()
обещание, которое выполняется, как только переводы готовы. См. Журнал изменений .источник
{{::'HELLO_WORLD | translate}}'
.Чтобы сделать перевод в контроллере, вы можете использовать
$translate
сервис:Этот оператор выполняет перевод только при активации контроллера, но не обнаруживает изменения языка во время выполнения. Чтобы добиться такого поведения, вы можете прослушать
$rootScope
событие:$translateChangeSuccess
и сделать там такой же перевод:Конечно, вы можете инкапсулировать
$translate
сервис в метод и вызывать его в контроллере и в$translateChangeSucess
слушателе.источник
Происходит то, что Angular-translate наблюдает за выражением с помощью системы, основанной на событиях, и, как и в любом другом случае привязки или двусторонней привязки, событие запускается, когда данные извлекаются, и значение изменяется, что явно не работает на перевод. Данные перевода, в отличие от других динамических данных на странице, должны, конечно, сразу же отображаться для пользователя. Он не может появиться после загрузки страницы.
Даже если вы можете успешно отладить эту проблему, более серьезная проблема заключается в том, что требуется огромная работа по разработке. Разработчик должен вручную извлечь каждую строку на сайте, поместить ее в файл .json, вручную указать на нее код строки (например, pageTitle в данном случае). На большинстве коммерческих сайтов есть тысячи строк, для которых это необходимо. И это только начало. Теперь вам нужна система синхронизации переводов при изменении основного текста в некоторых из них, система для отправки файлов перевода различным переводчикам, их повторной интеграции в сборку, повторного развертывания сайта, чтобы переводчики могли видеть их изменения в контексте, и так далее.
Кроме того, поскольку это «привязка», система, основанная на событиях, событие запускается для каждой отдельной строки на странице, что не только является более медленным способом преобразования страницы, но может замедлить все действия на странице, если вы начнете добавлять к нему большое количество событий.
Во всяком случае, использование платформы для постобработки переводов имеет для меня больше смысла. Например, используя GlobalizeIt, переводчик может просто перейти на страницу сайта и начать редактировать текст прямо на странице для своего языка, и все: https://www.globalizeit.com/HowItWorks . Не требует программирования (хотя его можно расширять программно), он легко интегрируется с Angular: https://www.globalizeit.com/Translate/Angular , преобразование страницы происходит за один раз, и он всегда отображает переведенный текст с начальный рендер страницы.
Полное раскрытие: я соучредитель :)
источник