Đa ngôn ngữ trong AngularJS
Trong thực tế, có nhiều ứng dựng web cần hỗ trợ đa ngôn ngữ. Với AngularJS, có hỗ trợ ngôn ngữ/ vùng lãnh thổ (Internationalization-i18n) và hỗ trợ ngôn ngữ/ khu vực (localization-l10n). Bài viết này giới thiệu cách hỗ trợ i18n và l10n trong một ứng dụng web với AngularJS.
1. Giới thiệu về Internationlization (i18n) và locationlization (l10n)
Internationalization (quốc tế hóa) gọi tắt là i18n (18 là số kí tự còn lại trong chữ khi viết tắt) là sự hỗ trợ phát triển ứng dụng theo cách mà có thể bản địa hóa cho ngôn ngữ và văn hóa một cách dễ dàng. (có thể hiểu từ một chuỗi hoặc ký tự cụ thể tạo thành 1 chuỗi hoặc ký tự chung)
Localization (bản địa hóa) gọi tắt là l10n (10 là số kí tự còn lại trong chữ khi viết tắt) là sự hỗ trợ các ứng dụng có thể thích ứng với văn bản, cho phép người dùng sử dụng được văn bản trong một khu vực quốc gia cụ thể. (có thể hiểu từ một chuỗi hoặc ký tự dùng chung tạo thành nhiều chuỗi hoặc ký tự dùng riêng cho mỗi vùng quốc gia, khu vực)
Hình sau minh họa cho khái niệm i18n và l10n:
Trong hình minh họa ở trên ta thấy form chuẩn chung sẽ gồm PRODUCTNAME và định dạng ngày tháng năm là 2014-12-15. Sự quốc tế hóa thể hiện khi họ sử dụng form tiếng Anh dể chuyển từ product name chuyển thành PRODUCTNAME và Mon, 15 Dec, 2014 chuyển thành 2014-12-15. Sự bản địa hóa thể hiện ở chỗ là từ PRODUCT_NAME ở form chuẩn chung, ta có thể bản địa hóa ra nhiều ngôn ngữ khác nhau ví dụ tiếng Việt, tiếng Anh, tiếng Pháp tương ứng với Tên sản phẩm, Product name, nom du produit. Tương tự đối với định dạng ngày tháng năm từ form chuẩn chung, cũng có thể bản địa ra tương ứng là Thứ 2, 15/12/2014; Mon, 15 Dec, 2014; Lun 12 desceember 2014.
2. i18n, l10n trong AngularJS
AngularJS hỗ trợ i18n, l10n với định dạng date, number và currency filter.
Ngoài ra AngularJS còn hỗ trợ bản địa hóa thông qua ngPluralize.
2.1 Bản địa hóa với phần lõi bằng các gói angular-locale
Tất cả các components localizable Angular phụ thuộc vào bộ quy tắc (locale-specific) được cung cấp bởi service $locale.
$locale là service trong module ng. Nó cung cấp các quy định bản địa hóa cho các Angular components.
id – {string} – locale id formatted as languageId-countryId (e.g. en-us)
Có thể import các thư viện locale như angular-locale-en.js hoặc angular-locale_vi-vn.js. Tham khảo thư viện tại i18n
- Cách cung cấp qui tắc locale trong AngularJS
Cách 1: Dùng bộ quy tắc Pre-bundled Bạn có thể cài gói các tập tin locale mong muốn bằng cách kết hợp các nội dung của tập tin địa phương cụ thể đến phía cuối trong tệp angular.js hoặc angular.min.js
Ví dụ: Để tạo ra một tập tin angular.js có chứa quy tắc nội địa hóa cho miền địa phương ở Đức, bạn có thể làm như sau:
cat angular.js i18n/angular-locale_de-de.js > angular_de-de.js
Khi các ứng dụng có chứa angular_de-de.js mà không phải angular.js , AngularJS được tự động cấu hình sẵn với các quy định nội địa hóa các địa phương ở Đức.
Cách 2: Including a locale script trong trang index.html
<html ng-app>
<head>
….
<script src="angular.js"></script>
<script src="i18n/angular-locale_de-de.js"></script>
….
</head>
</html>
2.2 Bản địa hóa với ngPluralize
ngPluralize là một directive trong module ng để hiển thị các thông báo theo quy định bản địa hóa en-US (với số lượng nhiều hơn một thì sẽ quy định cách hiển thị như thế nào)
Plural categories: Có 2 plural categories mặc định trong Angular với địa phương en-US là "one" và "other".
Cấu hình ngPluralize
Bằng cách cung cấp 2 thuộc tính "count" và "then", có thể có thêm "offset"
Giá trị của "count" có thể là string hoặc expression. Các thuộc tính sau khi mapping giữa pluralize và actual string sẽ được hiển thị.
<ng-pluralize count="personCount"
when="{'0': 'Nobody is viewing.',
'one': '1 person is viewing.',
'other': '{} people are viewing.'}">
</ng-pluralize>
- Cấu hình ngPluralize với offset: các thuộc tính offset cho phép bù đắp 1 số bằng bất kỳ giá trị nào mong muốn.
<ng-pluralize count="personCount" offset=2
when="{'0': 'Nobody is viewing.',
'1': ' is viewing.',
'2': ' and are viewing.',
'one': ', and one other person are viewing.',
'other': ', and {} other people are viewing.'}">
</ng-pluralize>
Ví dụ minh họa:
2.3.Một số lưu ý khi sử dụng i18n trong AngularJS
- Currency symbol
Filter tiền tệ trong Angular cho phép sử dụng các ký hiệu tiền tệ mặc định từ service locale hoặc tự định nghĩa filter tiền tệ riêng. Nếu ứng dụng chỉ sử dụng ở 1 địa phương, tốt nhất là sử dụng kí hiệu mặc định. Nếu như biết sẽ có thêm những người ở nơi khác sử dụng ứng dụng thì nên cung cấp rõ ràng một biểu tượng tiền tệ.
Ví dụ bạn đang viết ứng dụng thể hiện giá của một mặt hàng là 100USD. Ở đây phải sử dụng filter cho tiền tệ. {{100 | currency }}
Nếu ứng dụng bạn đang ở locale en-US nó sẽ hiển thị trên trình duyệt là $100, nếu 1 người nào đó ở Pháp truy cập và xem thì trình duyệt hiển thị 100€. Vấn đề ở đây là $100 khác so với 100€.
Vì thế nếu ta thay đổi {{100 | currency: "USD" }} thì Angular sẽ luôn hiển thị giá tiền là $100 ở bất kì địa phương nào.
- Translation length
Định dạng strings/datetime có thể khác nhau về chiều dài. Ví dụ June 5, 2013 sẽ dịch qua tiếng Tây Ban Nha là 5 de junio de 2013.
Vì vậy khi quốc tế hóa ứng dụng, cần làm thử nghiệm kỹ trước để đảm bảo các giao diện người dùng thể hiện kết quả như mong đợi ngay cả khi kích thước nội dung hiển thị khác nhau.
- Timzone
Filter datetime trong Angular sử dụng các thiết lập múi giờ của trình duyệt. Cùng 1 ứng dụng sẽ hiển thị thông tin thời gian khác nhau tùy thuộc thiết lập múi giờ của máy tính đang chạy ứng dụng. Không thể dùng Javascript hay Angular để hỗ trợ hiển thị ngày với một múi giờ theo quy định của riêng người lập trình.
3. Các kĩ thuật đa ngôn ngữ hóa ứng dụng
3.1 Đa ngôn ngữ hóa giao diện
Thay vì tạo ra nhiều template khác nhau để hiển thị theo từng ngôn ngữ, AngularJS hỗ trợ cách dùng angular-translate, là một module của i18n cho phép dịch và hiển thị chuỗi trên giao diện người dùng bằng cách tạo ra các tệp JSON đại diện cho dữ liệu dịch của mỗi ngôn ngữ.
Sau khi download angular-translate.js, ta nhúng trong HTML để sử dụng.
Cách đặt tên file JSON: "translation_" + locale id + ".json"
Ví dụ: translation–en.json, translation–nb-no.json...
File chứa JSON của English("en"):
{
"COLOR" : "Color",
"HELLO" : "Hello",
"HELLO_WORLD" : " Hello World!"
"NAME" :"My name is Thuy"
}
File chứa JSON của Norwegian - Nauy("nb-no"):
{
"COLOR" : "Farge",
"HELLO" : "Hallo",
"HELLO_WORLD" : "Hallo verden!"
"NAME" : "Mitt navn er Thuy"
}
Tạo translation service:
app.service('translationService', function($resource) {
this.getTranslation = function($scope, language) {
var languageFilePath = 'somepath_' + language + '.json';
$resource(languageFilePath).get(function (data) {
$scope.translation = data;
});
};
};
Controller cần gọi đến translate Service:
app.controller('myController',['$scope', 'translationService',
function ($scope, translationService){
//Run translation if selected language changes
$scope.translate = function(){
translationService.getTranslation($scope, $scope.selectedLanguage);
};
//Init
$scope.selectedLanguage = 'en';
$scope.translate();
}]);
Đưa dữ liệu vào hiển thị trong HTML:
{{translation.HELLO_WORLD}}
Và HTML sẽ hiển thị nội dung với locale id là "en"
3.2 Bản địa hóa ngôn ngữ
Với một ứng dụng web, có thể cần phải bản địa hóa nó sang các ngôn ngữ khác nhau, ta không cần phải sao chép các mã HTML để tạo ra nhiều ngôn ngữ, với AngularJS hỗ trợ angular-l10n để thực hiện điều đó.
Bài viết này giới thiệu về quốc tế hóa và bản địa hóa trong AngularJS cùng với cách áp dụng i18n cũng như l10n để bản địa hóa giao diện, ngôn ngữ. Ngoài ra có những lưu ý khi sử dụng i18n trong AngularJS, bản địa hóa với ngPluralize.