i18next / ng-i18next

translation for AngularJS using i18next
https://github.com/i18next/ng-i18next
MIT License
161 stars 54 forks source link

Language change doens't works in specific case (using i18next-http-backend) #165

Open vituchon opened 2 years ago

vituchon commented 2 years ago

🐛 Bug Report :lady_beetle:

Hi all, how you doing?

To Reproduce

Just run the examples below

index.html

<!doctype html>
<html ng-app="MyApp">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width">
    <title>Testing - ng-i18next</title>

    <script src="../../node_modules/angular/angular.js"></script>
    <script src="../../node_modules/angular-sanitize/angular-sanitize.min.js"></script>
    <script src="../../node_modules/i18next/i18next.js"></script>
    <script src="../../node_modules/i18next-xhr-backend/i18nextXHRBackend.js"></script>
    <script src="../../dist/ng-i18next.js"></script>
    <script src="script.js"></script>

</head>

<body>
    <!-- You can escape HTML here: http://www.htmlescape.net/htmlescape_tool.html -->
    <div ng-controller="MyDirectiveCtrl">
        <p>
            Change language to: <br>
            <a href="#" ng-click="changeLng('dev')">English</a><br>
            <a href="#" ng-click="changeLng('de')">German</a><br>
            <a href="#" ng-click="changeLng('patrick')">Patrick</a><br>
        </p>

    <!-- uncomment this and call to translate(key) eventually will work (perhaps not the first call, that is also kind of undesired behaviour, i expect to work on first call but you have to give them "time")
        <h3> {{ 'both.basicUsage' | i18next }}</h3>
        <p> {{  'hello' | i18next }}</p>
  -->
        <input type="text" ng-init="key = 'both.basicUsage'" ng-model="key"></input><br/>
        <button ng-click="translate(key)">Translate({{key}})</button>
    </div>
</body>
</html>

script.js


var myApp = angular.module('MyApp', ['ngSanitize','jm.i18next']);

if (window.i18next) {
    window.i18next
        .use(i18nextXHRBackend).init({
        debug: true,
        lng: 'dev',
    fallbackLng: "dev",
    supportedLngs: ["dev","de","patrick"],
    ns: "translation",
    interpolation: {
      escapeValue: false
    },
        useCookie: false,
        useLocalStorage: false,
        backend: {
            loadPath: '/examples/locales/{{lng}}/{{ns}}.json' // i prefer to use absolute paths
        },
    }, function (err, t) {
        console.log('resources loaded');
    });
}

myApp.controller('MyDirectiveCtrl', function ($rootScope, $scope, $timeout, $i18next, $filter) {

    'use strict';
    $scope.i18nextReady = false;

    $scope.$on('i18nextLanguageChange', function () {
        console.log('Language has changed!');
        if (!$scope.i18nextReady) {
            $timeout(function () {
                $scope.i18nextReady = true;
            }, 500);
        }
    });

    $scope.changeLng = function (lng) {
        $i18next.changeLanguage(lng);
    };

  $scope.translate = (key) => {
    var msg = $i18next.t(key);
    console.log(msg); // HERE if you don't use i18next filter within the angular HTML template `index.html` then you will see the same message whatever the current language
  }
});

Observed behavior

Expected behavior

Your Environment

Aditional Context

In my ongoing project I'm using angularjs and I start to internationalizating it. First add i18next, then ng-i18next but when I added i18next-http-backend support for using translation files a problem arises. So i submit a ticket into the related proyect http-backend for i18next but after a quick talk with one of their guys and some suspicious things I see debugging your code it might be on your side after all.. i don't know really.

Technical Insight :nerd_face:

I made some debug following the debbuger into the sources and indeed it could be a problem of ng-i18next as I saw that the translations files are correctly loaded (http-backend responsability), but inside the angular service (ng-i18next responsability) the this.translations["auto"] remains with the same values once setup I mean, it doesn't change when you change the language. But things are, quite complex to really understand what is actually happening... i need, more knowledge and more debugging time.

Cheers

Victor.

vituchon commented 2 years ago

Well you know guys, I fix this problem by adding a very specific line on one of your sources.

on ng-i18next/src/translateService.ts if you go to method changeLanguage and the MAGIC LINE (see comment below), this problem is solved.

I18nTranslateService.prototype.changeLanguage = function (lng) {
        var _this = this;
        if (this.options.lng !== lng && this.i18n.language !== lng) {
            this.options.lng = lng;
            this.translations = {}; // THIS IS THE MAGIC LINE
            this.i18n.changeLanguage(lng, function (err, t) {
                _this.$rootScope.$broadcast('i18nextLanguageChange', _this.i18n.language);
            });
        }
    };

I do wonder if this magic line doesn't not breaks other things... at least I'm not seeying that right now.

Cheers

Víctor