i18next/ng-i18next

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

vituchon opened this issue Β· 1 comments

πŸ› Bug Report 🐞

Hi all, how you doing?

  • Based on 18next-http-backend's site examples I made a simple app that consists on a single screen that allows a user to select a language (that triggers a language change) and a input to place the key to translate with a button to invoke a translation and view on the console the translation result's for the entered key using the current language.
  • It turns to work ONLY if I use the i18next filter within an angular HTML template. I will leavy snippets, I guess you will be able to run on your enviorments.
    • I can provide a video if you want or if you need
    • You may see the comments within the HTML and JS snippets for further context.

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

  • Translations results doesn't change

Expected behavior

  • Translations results do change

Your Environment

  • os: Ubuntu 20.04.4 LTS, 20.04, focal
  • runtime version: Chrome version: 101.0.4951.54 (Official Build) (64-bit)
  • i18next version: ng-i18next - Version 1.0.7 - 2022-05-09

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 πŸ€“

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.

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