Exploring AngularJS and the Power of i18next

After researching i18n plugins for Angular, I decided to use the i18next library instead of reinventing the wheel. To implement this, I created a directive named i18n that simply calls the i18n library:

define(['app', 'jquery', 'i18n'], function(app, $, i18n) {'use strict';
    app.directive('i18n', function() {
        return function($scope, elm, attrs) {
            attrs.$observe('i18n', function(value) {
                if ($.fn.i18n) {// for some reason, it isn't loaded quickly enough and first directives process fails
                    $(elm).i18n();
                }
            });
        };
    });
});

On my page, users can easily change the language:

<a ng-repeat="l in languages"> <img ng-src="images/{{l.id}}.png" title="{{l.label}}" ng-click="setLanguage(l.id)" /> </a>

In the main controller defined on the html tag:

define(['app', 'i18n', 'jquery'], function(app, i18n, $) {'use strict';

    return app.controller('BuilderController', ['$scope', '$location',
    function BuilderController($scope, $location) {

        /* Listen for url changes */
        $scope.$watch(function() {
            return $location.path();
        }, function() {
            $scope.setLanguage(($location.search()).lang || 'en');
        });

        /* Language options */
        $scope.languages = [{
            id : "en",
            label : "English"
        }, {
            id : "fr",
            label : "Français"
        }];

        $scope.$watch('language', function() {
            $location.search('lang', $scope.language);
            i18n.init({
                resGetPath : 'i18n/__lng__/__ns__.json',
                lng : $scope.language,
                getAsync : false,
                sendMissing : true,
                fallbackLng : 'en',
                debug : true
            });
            $(document).i18n();
        });

        $scope.setLanguage = function(id) {
            $scope.language = id;
        };

    }]);
});

The workflow involves a watcher on the language to initialize the i18n object with the new locale and update all DOM elements using the i18n jQuery extension. While this approach works effectively, I am aware that manipulating the DOM inside a controller is not recommended. However, as nothing untoward occurs in the end, I have not yet found a better solution.

Ideally, I would like Angular to re-compile all DOM elements, parsing all directives to update labels. Unfortunately, I haven't been able to figure out how to achieve this. I tried using $scope.$apply(), but it didn't work because it was already in digest at that point. I also experimented with the Scope.onReady plugin without any significant improvement.

Coming from a novice perspective in Angular development, I find it challenging to grasp the intricacies of how everything functions seamlessly.

Answer №1

In my opinion, it is advisable to avoid relying on jQuery when working with i18next. You can easily use i18next without jQuery by utilizing

window.i18n.t("YourStringToTranslate")
. ;)

Furthermore, there is no need to utilize $(document).i18n(); as you can create your own directive. I have developed a straightforward directive for Angular for this purpose.

If interested, you can find the directive here: https://gist.github.com/bugwelle/5239617

You can see that using jQuery is not necessary and it is recommended to initialize i18next within your directive instead of the controller.

To implement it, simply add the attribute ng-i18next="" to the desired element. Provide your options to $rootScope.i18nextOptions anywhere in your code (e.g., in the controller) and the translation will update automatically for all elements.

I have modified the code to integrate with my directive.

define(['app', 'i18n', 'jquery'], function(app, i18n, $) {

  'use strict';

  return app.controller('BuilderController', ['$rootScope', '$scope', '$location',
    function BuilderController($rootScope, $scope, $location) {

      /* Monitor URL changes */
      $scope.$watch(function() {
          return $location.path();
      }, function() {
          $scope.setLanguage(($location.search()).lang || 'en');
      });

      /* Language settings */
      $scope.languages = [{
          id : "en",
          label : "English"
      }, {
          id : "fr",
          label : "Français"
      }];

      // Updated section
      $scope.$watch('language', function() {
        $location.search('lang', $scope.language);
        $rootScope.i18nextOptions = {
            resGetPath : 'i18n/__lng__/__ns__.json',
            lng : $scope.language,
            getAsync : false,
            sendMissing : true,
            fallbackLng : 'en',
            debug : true
        };
      });

      $scope.setLanguage = function(id) {
          $scope.language = id;
      };

  }]);
});

Remember to include the directive as a dependency in your app and ensure to use the i18next version without AMD+jQuery. For more information, refer to the gist provided. ;)


An i18next module for angular is now accessible on GitHub at: https://github.com/i18next/ng-i18next

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to modify a record using the 'findById' method and save() function while utilizing promises

I am in the process of developing a cinema application using Node.js and MongoDB with Mongoose. One specific requirement I have is to update the 'Show' model when a user places an order. The task involves adding the latest seats that were ordere ...

Creating numerous bar graphs for each specific date

I have a dataset containing dates and corresponding information for each element. Despite trying various approaches, I am unable to create a barchart. Every solution I've attempted has been unsuccessful thus far. The dataset is structured as follows ...

What steps can I take to guarantee that a directive's link function is executed prior to a controller?

Our application features a view that is loaded through a basic route setup. $routeProvider .when('/', { template: require('./views/main.tpl.html'), controller: 'mainCtrl' }) .otherwise({ re ...

How can you update the codebase in PHP with WinSCP? Is there a way to refresh the server automatically after sending a file using

function upload(blobOrFile) { var xhr = new XMLHttpRequest(); xhr.open('POST', './upload.php', true); xhr.onload = function(e) {}; // Monitor the upload progress. var progressBar = document.querySelector('progress'); ...

What is the best way to request an API from a different project within the same solution without explicitly specifying the URL?

I am currently working on two separate projects - one for my front-end Angular code, and another for a Web API. One challenge I am encountering is making calls to the API from my front-end project. Most Web API tutorials demonstrate using relative URLs th ...

Issue with AngularJs Autocomplete: this.source is not being recognized as a function

Below is the HTML code snippet for an autocomplete textbox feature: <body ng-controller="HomeController" ng-init="init()"> <div class="col-xs-4 search-bar-position" > <form role="search" > <div c ...

Using Jquery to send json data to a webserver via Ajax (API)

Currently, I am attempting to use AJAX to post data to a JSON file (API) on a server. As part of this process, I have implemented dragging functionality for two Kineticjs shapes on the stage. Upon stopping the drag action, my goal is to save the updated x ...

Gather information from a line of Javascript using Python's scraping capabilities

Is there a way to extract JSON data from a Javascript line using Python? AH4RSearch.listingsJSON = $.parseJSON('{"properties":[{"Price":3695,"PriceFormatted":"3,695","Street":"9251 E Bajada Road&q ...

Using the innerHTML property to place an Img tag within a div element

I'm facing an issue with including multiple tags within a div using innerHTML. To better illustrate my problem, here's an example: var y = "jack.jpg"; var x = "Jack"; var f = "Hello world!"; document.getElementById("maindDiv").innerHTML += "< ...

angularsjs state provider with multiple parameters

I am struggling to create a state provider that can handle multiple parameters. Is it possible to capture them as an object or array, or do I have to capture them as a string and then separate them? For example, this is my current provider: .state(' ...

Creating a search-enabled multi-select feature in a Tabulator.js column

Currently, I am working on a project involving Tabulator.js and attempting to incorporate a column with a multi-select feature that includes a search option. My approach has been to utilize the Select2 library, but I have run into some challenges. Here is ...

Fill in a URL using the information provided in the boxes and navigate to the website

My colleagues and I access the following link multiple times a day, clicking through several pages to reach this specific URL: http://eharita.mamak.bel.tr/imararsiv/test.aspx?f_ada=36391&f_parsel=4 I am looking to create an HTML page with two input b ...

Tips for incorporating VueJS 2 global components within single file components

As I attempt to utilize a globally registered component (using Vue.component) within a single file component, I consistently encounter the following warning: vue.common.js:2611[Vue warn]: Unknown custom element: <my-component> - did you register the ...

Enable Axios to automatically include cookies in its requests

When sending requests from the client to my Express.js server using Axios, I am facing an issue with accessing cookies. Although I set a cookie on the client side, I cannot read that cookie from all Axios requests without manually adding them to each requ ...

Is my JavaScript coding accurate?

I'm working on extracting JSON data from my Rest API to display in my application. I'm wondering if the function renderUserState is being called, as the rest of my code seems to be functioning correctly. function testSubmit() { var card = ge ...

What is the method to retrieve the return value from this ajax request?

Here's a code snippet: var information = { ObtainInfo : function() { var url = 'http://www.bungie.net/api/reach/reachapijson.svc/game/info/'+storage.get('apikey'); $.ajax({ url: url, su ...

Passing JSON information through PatternLab

Incorporating an atomic pattern and passing data from a JSON array is my goal. Below are the code snippets and JSON file. anchor-link.mustache <a href="{{ url }}" class="{{ class }}">{{ label }}</a> footer-nav.mustache <ul class="menu ve ...

The 8 x 8 grid I am constructing is functional, however, the issue lies in the fact that the first line only begins with a single # symbol

I am attempting to create an 8 x 8 grid. It's coming together, but the issue is that the first line only starts with one # sign. function print(msg) { console.log(msg); return msg; } let result = ""; for(let i=1; i<=8; i++) { result += ...

Troubleshooting issues with sending POST requests in node.js

I've been attempting to initiate a post request, but for some reason, it's not going through. Strangely, I'm not seeing any output in the console log of my browser. My node server.js is up and running on x.x.x.x:8000. I've connected it ...

Utilizing JavaScript regex to remove substrings that contain parentheses

I am working with a string variable named myString that includes some unwanted content towards the end: var myString = 'The sentence is good up to here foo (bar1 bar2)'; var toBeRemoved = 'foo (bar1 bar2)'; I am looking for the best w ...