i18next / i18next-http-backend

i18next-http-backend is a backend layer for i18next using in Node.js, in the browser and for Deno.
MIT License
453 stars 70 forks source link

Language change doens't works in specific case (using backend) #90

Closed vituchon closed 2 years ago

vituchon commented 2 years ago

🐛 Bug Report :lady_beetle:

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

adrai commented 2 years ago

Sounds like a "problem" of ng-i18next you might ask @anwalkers in the ng-i18next repo... In general the language change seems to work, like in this example (but probably with a different angular lib): https://locize.com/blog/unleash-the-full-power-of-angular-i18next/

vituchon commented 2 years ago

Hi @adrai how are you?

Thanks for your reply. Yeah, I'm afraid that in my ongoing project I wasn't having any problem until i added http-backend support. That is the reason that the ticket is here.

So.. i know this issue has at least 3 main characters: i18next (as the main character), ng-i18next and i18next-http-backend... It is indeed a complex system and the boundaries between these characters aren't clear at all as they are part of an integral solution. It sounds that you have already summon Anwalkers, so let's hope he has something to say about it.

Some 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.

vituchon commented 2 years ago

Well you know guys, i fix this problem by adding a very specific line on the sources of ng-i18next, so now i can actually put all the focus on that proyect, leaving this proyect in peace... just for informing i do this

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);
            });
        }
    };

Perhaps you could notify the buddies at the silbing proyect ng-i18next for this, i have already started a ticket on their proyect that references this ticket.

Cheers

Víctor

adrai commented 2 years ago

ok, so this issue here can be closed, right?

vituchon commented 2 years ago

Sure adrai, but leave the content as it can be valuable for the your silbing proyect ng-i18next

Greetings

Vituchon