[javascript] 컨트롤러에서 각도 변환에 대한 올바른 사용

AngularJS 응용 프로그램에서 i18n에 대해 angular-translate 를 사용 하고 있습니다.

모든 애플리케이션보기에는 전용 컨트롤러가 있습니다. 아래 컨트롤러에서 페이지 제목으로 표시 할 값을 설정했습니다.

암호

HTML

<h1>{{ pageTitle }}</h1>

자바 스크립트

.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'; , 번역 작품은 처음부터 완벽. 문제는 항상 번역을 사용하고 싶지 않다는 것입니다 (예 : 두 번째 컨트롤러의 경우 원시 문자열을 전달하고 싶습니다).

질문

알려진 문제 / 제한 사항입니까? 이 문제를 어떻게 해결할 수 있습니까?



답변

편집 : 더 나은 솔루션을 위해 PascalPrecht (angular-translate의 저자)의 답변을 참조하십시오.


로드의 비동기 특성으로 인해 문제가 발생합니다. 를 사용 {{ pageTitle | translate }}하면 Angular가 표현식을 볼 것입니다. 현지화 데이터가로드되면 표현식의 값이 변경되고 화면이 업데이트됩니다.

따라서 직접 할 수 있습니다.

.controller('FirstPageCtrl', ['$scope', '$filter', function ($scope, $filter) {
    $scope.$watch(
        function() { return $filter('translate')('HELLO_WORLD'); },
        function(newval) { $scope.pageTitle = newval; }
    );
});

그러나 이것은 모든 다이제스트주기에서 관찰 된 표현식을 실행합니다. 이는 차선책이며 눈에 띄는 성능 저하를 유발할 수도 있고 그렇지 않을 수도 있습니다. 어쨌든 Angular가하는 일이므로 그렇게 나쁠 수는 없습니다.


답변

권장 : 컨트롤러에서 번역하지 말고보기에서 번역하세요.

컨트롤러를 번역 로직에서 자유롭게 유지하고 다음과 같이 뷰 내에서 직접 문자열을 번역하는 것이 좋습니다.

<h1>{{ 'TITLE.HELLO_WORLD' | translate }}</h1>

제공된 서비스 이용

Angular Translate는 $translate컨트롤러에서 사용할 수 있는 서비스를 제공합니다 .

$translate서비스 사용의 예 는 다음과 같습니다.

.controller('TranslateMe', ['$scope', '$translate', function ($scope, $translate) {
    $translate('PAGE.TITLE')
        .then(function (translatedValue) {
            $scope.pageTitle = translatedValue;
        });
});

번역 서비스에는 다음을 사용하여 promise를 처리 할 필요없이 문자열을 직접 번역하는 방법도 있습니다 $translate.instant().

.controller('TranslateMe', ['$scope', '$translate', function ($scope, $translate) {
    $scope.pageTitle = $translate.instant('TITLE.DASHBOARD'); // Assuming TITLE.DASHBOARD is defined
});

using의 단점 $translate.instant()은 비동기로로드하는 경우 언어 파일이 아직로드되지 않는다는 것입니다.

제공된 필터 사용

이런 식으로 promise를 처리 할 필요가 없기 때문에 이것이 제가 선호하는 방법입니다. 필터의 출력은 범위 변수로 직접 설정할 수 있습니다.

.controller('TranslateMe', ['$scope', '$filter', function ($scope, $filter) {
    var $translate = $filter('translate');

    $scope.pageTitle = $translate('TITLE.DASHBOARD'); // Assuming TITLE.DASHBOARD is defined
});

제공된 지시문 사용

@PascalPrecht는이 멋진 라이브러리의 제작자이므로 그의 조언 (아래 답변 참조) 과 함께 이동하여 매우 지능적인 번역을 처리하는 것처럼 보이는 지침을 사용하는 것이 좋습니다 .

이 지시문은 비동기 실행을 처리하며 번역에 동적 값이없는 경우 범위에서 번역 ID를 관찰 할 수있을만큼 영리합니다.


답변

사실, 대신에 이러한 항목에 대해 translate 지시문을 사용해야합니다.

<h1 translate="{{pageTitle}}"></h1>

이 지시문은 비동기 실행을 처리하며 번역에 동적 값이없는 경우 범위에서 번역 ID를 관찰 할 수있을만큼 영리합니다.

이 주위에 방법이 없습니다 당신이 정말 그러나, 에있는 사용 $translate컨트롤러의 서비스, 당신은에 전화를 포장해야 $translateChangeSuccess사용하여 이벤트 $rootScope와 함께 $translate.instant()다음과 같습니다 :

.controller('foo', function ($rootScope, $scope, $translate) {
  $rootScope.$on('$translateChangeSuccess', function () {
    $scope.pageTitle = $translate.instant('PAGE.TITLE');
  });
})

그렇다면 왜 $rootScope그렇지 $scope않습니까? 그 이유 는 전체 범위 계층 구조를 통해 브로드 캐스트 할 필요가 없기 때문에 angular-translate의 이벤트가 $emited on $rootScope이 아닌 $broadcasted on $scope이기 때문입니다.

$translate.instant()비동기가 $translate()아닌가? 때 $translateChangeSuccess이벤트가 시작되고, 따라서 우리가 사용할 수 있으며, 필요한 변환 데이터가 더 비동기 실행 (예 : 비동기 로더 실행을 위해) 발생되지 않도록 확실한 $translate.instant()동기 인 단지 번역을 사용할 수 있다고 가정합니다.

버전 2.8.0 이후에는 $translate.onReady()번역이 준비되는 즉시 해결되는 promise를 반환하는 도 있습니다 . 변경 로그를 참조하십시오 .


답변

컨트롤러에서 번역을하려면 $translate서비스를 사용할 수 있습니다 .

$translate(['COMMON.SI', 'COMMON.NO']).then(function (translations) {
    vm.si = translations['COMMON.SI'];
    vm.no = translations['COMMON.NO'];
});

이 명령문은 컨트롤러 활성화에 대한 번역 만 수행하지만 언어의 런타임 변경을 감지하지 않습니다. 이 동작을 달성하기 위해 $rootScope이벤트를 수신 $translateChangeSuccess하고 동일한 번역을 수행 할 수 있습니다.

    $rootScope.$on('$translateChangeSuccess', function () {
        $translate(['COMMON.SI', 'COMMON.NO']).then(function (translations) {
            vm.si = translations['COMMON.SI'];
            vm.no = translations['COMMON.NO'];
        });
    });

물론, $translate서비스를 메서드에 캡슐화 하고 컨트롤러와 $translateChangeSucess리스너 에서 호출 할 수 있습니다.


답변

무슨 일이 일어나고 있는지 Angular-translate가 이벤트 기반 시스템으로 표현식을 감시하고 있으며 다른 바인딩 또는 양방향 바인딩의 경우와 마찬가지로 데이터가 검색되고 값이 변경되면 이벤트가 발생합니다. 분명히 번역을 위해 작동하지 않습니다. 물론 페이지의 다른 동적 데이터와 달리 번역 데이터는 사용자에게 즉시 표시되어야합니다. 페이지가로드 된 후에는 튀어 나올 수 없습니다.

이 문제를 성공적으로 디버깅 할 수 있더라도 더 큰 문제는 관련된 개발 작업이 거대하다는 것입니다. 개발자는 사이트의 모든 문자열을 수동으로 추출하여 .json 파일에 넣고 문자열 코드 (이 경우 ‘pageTitle’)로 수동으로 참조해야합니다. 대부분의 상업 사이트에는 이런 일이 발생해야하는 수천 개의 문자열이 있습니다. 그리고 그것은 시작에 불과합니다. 이제 일부 텍스트의 기본 텍스트가 변경 될 때 번역을 동기화 상태로 유지하는 시스템, 번역 파일을 다양한 번역자에게 보내고, 빌드에 다시 통합하고, 번역자가 볼 수 있도록 사이트를 재배포하는 시스템이 필요합니다. 상황에 따른 변화, 그리고 계속해서.

또한 이것은 ‘바인딩’, 이벤트 기반 시스템이므로 페이지의 모든 단일 문자열에 대해 이벤트가 발생합니다. 이는 페이지를 변환하는 속도가 느릴뿐만 아니라 페이지의 모든 작업을 느리게 할 수 있습니다. 많은 이벤트를 추가하기 시작하면

어쨌든 후 처리 번역 플랫폼을 사용하는 것이 더 의미가 있습니다. 예를 들어, GlobalizeIt을 사용하면 번역가는 사이트의 페이지로 이동하여 해당 언어 페이지에서 직접 텍스트를 편집 할 수 있습니다. https://www.globalizeit.com/HowItWorks . 프로그래밍이 필요하지 않습니다 (프로그래밍 방식으로 확장 할 수 있지만) Angular : https://www.globalizeit.com/Translate/Angular 와 쉽게 통합 되며 페이지 변환이 한 번에 이루어지며 항상 다음과 같이 번역 된 텍스트를 표시합니다. 페이지의 초기 렌더링.

전체 공개 : 저는 공동 설립자입니다. 🙂


답변