[AngularJS] i18n Directive


Client side gettext-like Internationalization (i18n) via AngularJS Directives. This is an alternative to solution in [1].

Demo

Source code:

index.html | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!doctype html>
<html ng-app="demoI18nDirective">
<head>
  <meta charset="utf-8">
  <title>AngularJS i18n Directive Demo</title>
</head>
<body>

<div>
  <button ng-click="i18nLocale = 'en'">English</button>
  <button ng-click="i18nLocale = 'zh_TW'">傳統中文</button>
  <button ng-click="i18nLocale = 'vi_VN'">Tiếng Việt</button>
</div>
<br>
<div>
  <span i18n str="Home">Home</span>
  <br>
  <span i18n str="Canon">Canon</span>
</div>

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script src="ngGettextData.js"></script>
<script src="ngI18nDirective.js"></script>
<script src="app.js"></script>
</body>
</html>
app.js | repository | view raw
1
2
3
4
5
6
7
8
'use strict';


angular.module('demoI18nDirective', ['i18nDirective', "gettextData"]).
  run(['$rootScope', function($rootScope) {
    // default locale is English
    $rootScope.i18nLocale = "en";
  }]);
ngI18nDirective.js | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
'use strict';


angular.module('i18nDirective', ['gettextData']).
  directive('i18n', ['i18nserv', '$rootScope', function(i18nserv, $rootScope) {
    /**
     * wrap the string to be translated in ELEMENT
     * with attribute 'i18n', 'str', and 'locale'(optional)
     * example: <ELEMENT i18n str='Home'>Home</ELEMENT>
     *      or  <ELEMENT i18n locale={{locale}} str='Home'>Home</ELEMENT>
     */
    return {
      restrict: 'A',
      link: function(scope, elm, attrs) {
        // if "locale" attribute exists, use it
        attrs.$observe('locale', function() {
          var trText = i18nserv.gettext(attrs.str, attrs.locale);
          elm.html(trText);
        });

        // if there is no "locale" attribute, use $rootScope.i18nLocale
        if (angular.isUndefined(attrs.locale)) {
          $rootScope.$watch('i18nLocale', function() {
            var trText = i18nserv.gettext(attrs.str, $rootScope.i18nLocale);
            elm.html(trText);
          });
        }
      }
    };
  }]).

  factory('i18nserv', ['gettextData', function(gettextData) {
  // service: for translating texts according to locale

    var i18nStr = gettextData.all;

    function gettext(value, locale) {
      if (i18nStr.hasOwnProperty(locale)) {
        if (i18nStr[locale].hasOwnProperty(value)) {
          if (i18nStr[locale][value] !== '' &&
              i18nStr[locale][value] !== null)
            return i18nStr[locale][value];
        }
      }
      return value;
    }

    return { gettext: gettext };
  }]);
ngGettextData.js | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
angular.module('gettextData', []).
  factory('gettextData', [function() {
    var data = {
      "zh_TW": {
        "Home": "首頁",
        "Canon": "經典"
      },
      "vi_VN": {
        "Home": "Trang chính",
        "Canon": "Kinh điển"
      }
    }
    var serviceInstance = { all: data };
    return serviceInstance;
  }]);

Tested on: Chromium Version 50.0.2661.102 Ubuntu 16.04 (64-bit), AngularJS 1.5.5.


References:

[1][AngularJS] gettext-like i18n Solution
[2][Golang] gettext Function on Frontend (Browser) by GopherJS