Używam translacji kątowej dla i18n w aplikacji AngularJS.
Dla każdego widoku aplikacji jest dedykowany kontroler. W kontrolerach poniżej ustawiłem wartość, która ma być wyświetlana jako tytuł strony.
Kod
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';
}])
Ładuję pliki tłumaczeń za pomocą rozszerzenia angular-translate-loader-url .
Problem
Przy początkowym ładowaniu strony klucz tłumaczenia jest wyświetlany zamiast tłumaczenia tego klucza. Tłumaczenie jest Hello, World!
, ale widzę HELLO_WORLD
.
Za drugim razem, gdy wchodzę na stronę, wszystko jest w porządku i wyświetla się przetłumaczona wersja.
Zakładam, że problem polega na tym, że być może plik tłumaczenia nie jest jeszcze ładowany, gdy kontroler przypisuje wartość $scope.pageTitle
.
Uwaga
Podczas korzystania z <h1>{{ pageTitle | translate }}</h1>
i $scope.pageTitle = 'HELLO_WORLD';
tłumaczenie działa idealnie od pierwszego razu. Problem polega na tym, że nie zawsze chcę używać tłumaczeń (np. Dla drugiego kontrolera chcę tylko przekazać nieprzetworzony ciąg znaków).
Pytanie
Czy to znany problem / ograniczenie? Jak można to rozwiązać?
źródło
$scope.$watch
jest raczej przesadą, ponieważ Angular Translate oferuje usługę do użycia w kontrolerach. Zobacz moją odpowiedź poniżej.$translate.instant()
oferuje to samo, co usługa. Poza tym proszę zwróć uwagę na odpowiedź Pascala.Zalecane: nie tłumacz w kontrolerze, tłumacz w swoim widoku
Zalecałbym, aby twój kontroler był wolny od logiki tłumaczenia i tłumaczył ciągi bezpośrednio w widoku w następujący sposób:
Korzystanie ze świadczonej usługi
Angular Translate zapewnia
$translate
usługę, z której możesz korzystać w swoich Kontrolerach.Przykładowym wykorzystaniem
$translate
usługi może być:Usługa tłumaczenia ma również metodę bezpośredniego tłumaczenia ciągów znaków bez konieczności obsługi obietnicy, używając
$translate.instant()
:Wadą używania
$translate.instant()
może być to, że plik językowy nie jest jeszcze załadowany, jeśli ładujesz go asynchronicznie.Korzystanie z dostarczonego filtra
To mój ulubiony sposób, ponieważ nie muszę w ten sposób obsługiwać obietnic. Dane wyjściowe filtru można bezpośrednio ustawić na zmienną zakresu.
Korzystanie z podanej dyrektywy
Ponieważ @PascalPrecht jest twórcą tej niesamowitej biblioteki, polecam skorzystać z jego rady (patrz jego odpowiedź poniżej) i skorzystać z dostarczonej dyrektywy, która wydaje się obsługiwać tłumaczenia bardzo inteligentnie.
źródło
Właściwie do takich rzeczy powinieneś użyć dyrektywy translate.
Dyrektywa zajmuje się wykonywaniem asynchronicznym i jest również wystarczająco sprytna, aby odsłuchać identyfikatory translacji w zakresie, jeśli tłumaczenie nie ma wartości dynamicznych.
Jeśli jednak nie ma sposobu, a ty naprawdę musisz użyć
$translate
usługi w kontrolerze, powinieneś zawinąć wywołanie w$translateChangeSuccess
zdarzeniu, używając$rootScope
w połączeniu z$translate.instant()
następującymi:Więc dlaczego
$rootScope
i nie$scope
? Powodem tego jest to, że w kanciasty-translate wydarzeń są$emit
ed na$rootScope
zamiast$broadcast
ed na$scope
ponieważ nie musimy nadawać przez całą hierarchią zakres.Dlaczego
$translate.instant()
i nie tylko asynchronicznie$translate()
? Kiedy$translateChangeSuccess
zdarzenie jest uruchamiane, jest pewne, że potrzebne są dane translacji i nie ma wykonania asynchronicznego wykonania (na przykład asynchroniczne wykonanie programu ładującego), dlatego możemy po prostu użyć tego,$translate.instant()
który jest synchroniczny i po prostu zakłada, że tłumaczenia są dostępne.Od wersji 2.8.0 istnieje również
$translate.onReady()
, który zwraca obietnicę, która jest rozpatrywana, gdy tylko tłumaczenia są gotowe. Zobacz dziennik zmian .źródło
{{::'HELLO_WORLD | translate}}'
.Aby dokonać tłumaczenia w kontrolerze możesz skorzystać z
$translate
usługi:Ta instrukcja tłumaczy tylko podczas aktywacji kontrolera, ale nie wykrywa zmiany języka w czasie wykonywania. Aby osiągnąć takie zachowanie, możesz posłuchać
$rootScope
zdarzenia:$translateChangeSuccess
i tam wykonać to samo tłumaczenie:Oczywiście możesz hermetyzować
$translate
usługę w metodzie i wywołać ją w kontrolerze i$translateChangeSucess
odbiorniku.źródło
Dzieje się tak, że Angular-translate obserwuje wyrażenie za pomocą systemu opartego na zdarzeniach i tak jak w każdym innym przypadku wiązania lub wiązania dwukierunkowego, zdarzenie jest wyzwalane, gdy dane są pobierane, a wartość zmienia się, co oczywiście nie działa w przypadku tłumaczenia. Dane tłumaczenia, w przeciwieństwie do innych dynamicznych danych na stronie, muszą oczywiście natychmiast pojawić się użytkownikowi. Nie może pojawić się po załadowaniu strony.
Nawet jeśli uda Ci się pomyślnie debugować ten problem, większym problemem jest to, że praca programistyczna jest ogromna. Programista musi ręcznie wyodrębnić każdy ciąg w witrynie, umieścić go w pliku .json, ręcznie odwołać się do niego za pomocą kodu ciągu (tj. W tym przypadku „pageTitle”). Większość witryn komercyjnych ma tysiące ciągów, w przypadku których musi to nastąpić. A to dopiero początek. Potrzebujesz teraz systemu utrzymywania synchronizacji tłumaczeń, gdy tekst będący podstawą zmiany w niektórych z nich, systemu wysyłania plików tłumaczeń do różnych tłumaczy, ponownego włączania ich do kompilacji, ponownego wdrażania witryny, aby tłumacze mogli zobaczyć ich zmiany w kontekście i tak dalej.
Ponadto, ponieważ jest to „wiążący” system oparty na zdarzeniach, zdarzenie jest wywoływane dla każdego pojedynczego ciągu znaków na stronie, co nie tylko jest wolniejszym sposobem transformacji strony, ale może spowolnić wszystkie działania na stronie, jeśli zaczniesz dodawać do niego dużą liczbę wydarzeń.
W każdym razie korzystanie z platformy tłumaczeniowej do przetwarzania końcowego ma dla mnie większy sens. Korzystając na przykład z GlobalizeIt, tłumacz może po prostu przejść do strony w witrynie i rozpocząć edycję tekstu bezpośrednio na stronie w swoim języku i to wszystko: https://www.globalizeit.com/HowItWorks . Nie jest potrzebne programowanie (choć może być programowo rozszerzalne), łatwo integruje się z Angular: https://www.globalizeit.com/Translate/Angular , transformacja strony odbywa się za jednym razem i zawsze wyświetla przetłumaczony tekst z początkowe renderowanie strony.
Pełne ujawnienie: jestem współzałożycielem :)
źródło