Pull to refresh

Локализация с AngularJS

Reading time 5 min
Views 36K
imageДобрый день, уважаемые Хабражители.

AngularJS — отличный Framework для создания ваших сайтов. На Хабре уже достаточно много про него написано, но почему то ни разу не затрагивалась тема локализации приложений. Тем не менее, поддержка локализации в нем есть и сегодня мы попробуем с ней разобраться.

Существует несколько способов локализации и мы рассмотрим несколько из них.

Способ 1. Как в документации


В документе i18n and l10n указано, что Angularjs поддерживает отображение дат, чисел и валют в том виде, в котором их привыкли видеть пользователи соответствующих стран. Это означает, что при создании интернет магазина мы можем один раз написать {{amount | currency}}, подключить необходимую локаль и не думать о том, как будет выглядеть сумма покупки для России и США. AngularJS сам сделает это за вас:

1 234,56 руб — в России
$1,234.56 — в США


Аналогичная ситуация и с датами. Можно написать {{currentDate | date}} и мы увидим:

23 сент. 2014 г. — в России
Sep 23, 2014 — США


Если же необходимо использовать обе валюты на одной странице, то можно временно переопределить обозначение, указав явно единицу измерения {{amount | currency:"USD$"}}.
Пример работы с валютами и датами
<!doctype html>
<html ng-app="testApp">
<head>
  <meta charset="utf-8">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.2/angular.js"></script>
  <!-- Оставьте только одно включение локали -->
  <!-- Локаль США -->
  <!-- <script src="https://code.angularjs.org/1.3.0-rc.2/i18n/angular-locale_en-us.js"></script>-->
  <!-- Русская локаль -->
  <script src="https://code.angularjs.org/1.3.0-rc.2/i18n/angular-locale_ru-ru.js"></script>
  <script>
    angular.module('testApp', [])
      .controller('mainController', ['$scope', function($scope){
        $scope.amount = 1234.56;
        $scope.currentDate = new Date();
    }])
  </script>
</head>
<body ng-controller="mainController">
  <input type="number" ng-model="amount"> <br>
  Стандартное обозначение валюты: <span id="currency-default">{{amount | currency}}</span><br>
  Определяем своё обозначение валюты (USD$): <span>{{amount | currency:"USD$"}}</span><br>
  Текущая дата: <span>{{currentDate | date}}</span>
</body>
</html>

Пример на Plunker.

Для некоторых преобразований текста, разработчики рекомендуют использовать ngPluralize, но для простой локализации приложения это нам не сильно поможет.

Способ 2. Велосипед


Предположим, что у нас есть два файла с переводами, хранящиеся в формате json.
translation_ru.json
{  
    "COLOR" : "Цвет",
    "HELLO" : "Привет",
    "HELLO_HABR" : "Привет Хабрахабр!"
}


translation_en.json
{  
    "COLOR" : "Color",
    "HELLO" : "Hello",
    "HELLO_HABR" : "Hello Habrahabr!"
}


И мы хотим, что бы на странице отображались эти сообщения в зависимости от того, какой язык выберет пользователь. Для этого, создадим приложение myApp.
angularApp.js
var app = angular.module('myApp', ['ngResource']);



И сервис translationService, который будет загружать нам эти файлы.
angularTranslationService.js
app.service('translationService', function($resource) {  

        this.getTranslation = function($scope, language) {
            var languageFilePath = 'translation_' + language + '.json';
            console.log(languageFilePath);
            $resource(languageFilePath).get(function (data) {
                $scope.translation = data;
            });
        };
    });


Так же, создадим контроллер myController, к которому подключим данный сервис:
angularController.js
app.controller('myController',['$scope', 'translationService', 
function ($scope, translationService){  

  //Выполняем перевод, если произошло событие смены языка
  $scope.translate = function(){
       translationService.getTranslation($scope, $scope.selectedLanguage);
   };
   // Инициализация
   $scope.selectedLanguage = 'en';
   $scope.translate();
  
}]);


И само тестовое предоставление index.html, в котором подключаем все скрипты.
Для того, чтобы вывести текст перевода, необходимо описать его следующим образом:

{{translation.HELLO_HABR}}


Прошу обратить внимание, что помимо angular.js мы подключаем еще и angular-resource.js для работы с ресурсами.
index.html
<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.2/angular.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.2/angular-resource.min.js"></script>
  <script src="angularApp.js"></script>
  <script src="angularController.js"></script>
  <script src="angularTranslationService.js"></script>
</head>

<body>
  <div ng-app="myApp" ng-controller="myController">
    <section>
      <h4>Select language for translation:</h4>
      <select ng-change="translate()" ng-model="selectedLanguage">
        <option value="en">English</option>
        <option value="ru">Русский</option>
      </select>
    </section>

    <h4>Выбранный язык: <strong>{{selectedLanguage}}</strong></h4>
    <h4>Перевод слов:</h4>
    <p>
      {{translation.HELLO_HABR}}
    </p>
  </div>
</body>
</html>



Получаем результат:



Рабочий пример вы можете посмотреть здесь.

Способ 3. Правильный


Что же предлагает нам мировая общественность для решения вопроса локализации? Я нашел только два крупных проекта с хорошей документацией. Это Angular-Translate и Angular-Gettext.
Пример использования Angular-Translate
var app = angular.module('at', ['pascalprecht.translate']);

app.config(function ($translateProvider) {
  $translateProvider.translations('en', {
    TITLE: 'Hello',
    FOO: 'This is a paragraph.',
    BUTTON_LANG_EN: 'english',
    BUTTON_LANG_DE: 'german'
  });
  $translateProvider.translations('de', {
    TITLE: 'Hallo',
    FOO: 'Dies ist ein Paragraph.',
    BUTTON_LANG_EN: 'englisch',
    BUTTON_LANG_DE: 'deutsch'
  });
  $translateProvider.preferredLanguage('en');
});

app.controller('Ctrl', function ($scope, $translate) {
  $scope.changeLanguage = function (key) {
    $translate.use(key);
  };
});


Пример использования Angular-Gettext
angular.module("myApp").controller("MyCtrl", function ($scope, gettextCatalog) {
    // Do things with gettextCatalog
});


Лично мне симпатизирует Angular-Gettext. Перевод в нем осуществляется в несколько шагов:

  1. Создаем сайт полностью на одном языке;
  2. Приписываем в html слово translate возле тех строк, которые необходимо перевести;
  3. Используем angular-gettext tools для генерации шаблона «po»;
  4. Переводим на все необходимые нам языки используя Poedit. Хотя лучше — отдать переводить профессионалам;
  5. Подключаем gettext и шаблоны;
  6. Используем.


С Angular-Translate придется писать все переводы в файлах.

Заключение


Сегодня мы изобрели велосипед в учебных целях. Но использовать такой код в реальных проектах нельзя. Использование проработанных библиотек — это хорошо. Какую из них выбрать — решать вам. Каждая заслуживает отдельной статьи и имеет свои особенности. В следующих постах, опишу каждую из них подробнее.

Спасибо за внимание и удачных вам разработок и локализаций!

Ссылки


Файлы поддержки локалей для версии 1.3.0-rc2 Вы можете найти здесь;
1-й пример на Plunker;
2-й пример на Plunker;
Angular-Gettext;
Angular-Translate.
Tags:
Hubs:
+18
Comments 10
Comments Comments 10

Articles