From f6b07623951a1df09212d8ae9f7406af82062e24 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Thu, 25 Jan 2024 19:41:07 +0100 Subject: [PATCH 01/13] =?UTF-8?q?=F0=9F=90=9E=20default=20translation=20ap?= =?UTF-8?q?pears=20when=20switching=20language=20for=20the=20first=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parent issue: https://github.com/sequentech/common-ui/pull/375 --- app.js | 30 +++++++- avBooth/booth-directive/booth-directive.js | 80 ++++++++++++++-------- 2 files changed, 80 insertions(+), 30 deletions(-) diff --git a/app.js b/app.js index f89b5b46..e4aab056 100755 --- a/app.js +++ b/app.js @@ -61,7 +61,35 @@ angular cookieName: 'lang', detectLngQS: 'lang', lngWhitelist: ['en', 'es', 'gl', 'ca'], - resGetPath: '/booth/locales/__lng__.json', + ns: {namespaces: ['override', 'locales'], defaultNs: 'override'}, + fallbackNS: 'locales', + resGetPath: '/booth/__ns__/__lng__.json', + customLoad: function (lngValue, nsValue, options, loadComplete) { + if (nsValue === 'locales') { + var url = '/booth/' + nsValue + '/' + lngValue + '.json'; + var req = new XMLHttpRequest(); + // Configure it: GET-request for the URL /your/api/endpoint + req.open('GET', url, true); + req.onload = function() { + if (req.status >= 200 && req.status < 300) { + var data = JSON.parse(req.responseText); + var error = null; + loadComplete(/*err*/ null, data); + } else { + loadComplete(/*err*/ "Error loading locale at url=" + url, null); + } + }; + req.send(""); + } else if (nsValue === 'override') { + if (window.i18nOverride) { + loadComplete(/*err*/ null, window.i18nOverride[lngValue]); + } else { + loadComplete(/*err*/ "Error loading overrides, not found", null); + } + } else { + console.log("unhandled customLoad case for i18next"); + } + }, defaultLoadingValue: '' // ng-i18next option, *NOT* directly supported by i18next }, ConfigServiceProvider.i18nextInitOptions diff --git a/avBooth/booth-directive/booth-directive.js b/avBooth/booth-directive/booth-directive.js index 4868f25c..57b28376 100644 --- a/avBooth/booth-directive/booth-directive.js +++ b/avBooth/booth-directive/booth-directive.js @@ -71,36 +71,58 @@ angular.module('avBooth') // This is used to enable custom css overriding scope.allowCustomElectionThemeCss = ConfigService.allowCustomElectionThemeCss; + scope.alreadyReloaded = null; - function reloadTranslations(force, ms) { - setTimeout( - function () { - var election = ( - scope.state === stateEnum.electionChooserScreen - ) ? scope.parentElection : scope.election; - - // reset $window.i18nOverride - var overrides = ( - election && - election.presentation && - election.presentation.i18n_override - ) ? election.presentation.i18n_override : null; - - var languagesConf = ( - election && - election.presentation && - election.presentation.i18n_languages_conf - ) ? election.presentation.i18n_languages_conf : null; - - $i18next.options.useLocalStorage = true; - I18nOverride( - /* overrides = */ overrides, - /* force = */ force, - /* languagesConf = */ languagesConf - ); - }, - ms || 0 - ); + function reloadTranslations(force) { + function reloadInner() { + var election = ( + scope.state === stateEnum.electionChooserScreen + ) ? scope.parentElection : scope.election; + + if (scope.alreadyReloaded === election.id) { + $i18next.reInit(); + return; + } else { + scope.alreadyReloaded = election.id; + } + + // reset $window.i18nOverride + var overrides = ( + election && + election.presentation && + election.presentation.i18n_override + ) ? election.presentation.i18n_override : null; + + var languagesConf = ( + election && + election.presentation && + election.presentation.i18n_languages_conf + ) ? election.presentation.i18n_languages_conf : null; + + $i18next.options.useLocalStorage = true; + I18nOverride( + /* overrides = */ overrides, + /* force = */ force, + /* languagesConf = */ languagesConf + ); + } + function timeoutWrap() { + console.log("timeoutWrap"); + var election = ( + scope.state === stateEnum.electionChooserScreen + ) ? scope.parentElection : scope.election; + + if (election && scope.alreadyReloaded === election.id) { + return; + } + if (!election) { + console.log("timeoutWrap: delaying.."); + setTimeout(timeoutWrap, 200); + } else { + reloadInner(); + } + } + timeoutWrap(); } function updateWidth() { From b6750e59e96cab2258a2ca7dcbd9c470c83fde12 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Fri, 26 Jan 2024 09:19:36 +0100 Subject: [PATCH 02/13] WIP --- app.js | 65 +++++++++++++--------- avBooth/booth-directive/booth-directive.js | 28 +++++++++- 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/app.js b/app.js index e4aab056..f4945bff 100755 --- a/app.js +++ b/app.js @@ -52,6 +52,17 @@ angular // note that we do not send the language: by default, it will try the language // supported by the web browser $("#no-js").hide(); + var loading = {}; + window.i18nOriginal = {}; + + function getExtended(data, lngValue) { + var override = {}; + if (window.i18nOverride && lngValue in window.i18nOverride) { + var baseOverride = window.i18nOverride[lngValue]; + override = angular.copy(baseOverride); + } + return angular.merge({}, data, override); + } $i18nextProvider.options = _.extend( { @@ -61,34 +72,38 @@ angular cookieName: 'lang', detectLngQS: 'lang', lngWhitelist: ['en', 'es', 'gl', 'ca'], - ns: {namespaces: ['override', 'locales'], defaultNs: 'override'}, - fallbackNS: 'locales', - resGetPath: '/booth/__ns__/__lng__.json', customLoad: function (lngValue, nsValue, options, loadComplete) { - if (nsValue === 'locales') { - var url = '/booth/' + nsValue + '/' + lngValue + '.json'; - var req = new XMLHttpRequest(); - // Configure it: GET-request for the URL /your/api/endpoint - req.open('GET', url, true); - req.onload = function() { - if (req.status >= 200 && req.status < 300) { - var data = JSON.parse(req.responseText); - var error = null; - loadComplete(/*err*/ null, data); - } else { - loadComplete(/*err*/ "Error loading locale at url=" + url, null); - } - }; - req.send(""); - } else if (nsValue === 'override') { - if (window.i18nOverride) { - loadComplete(/*err*/ null, window.i18nOverride[lngValue]); + var url = '/booth/locales/' + lngValue + '.json'; + if (window.i18nOriginal && lngValue in window.i18nOriginal) { + console.log("customLoad: RET ORIGINAL EXTENDED lng=" + lngValue); + // if we already loaded the original, then we don't reload it. + // Otherwise the language selector goes crazy + return; + } + if (lngValue in loading) { + console.log("customLoad: already loading lng=" + lngValue); + loadComplete(/*err*/ "customLoad: already loading lng=" + lngValue, null); + return; + } + loading[lngValue] = true; + var req = new XMLHttpRequest(); + // Configure it: GET-request for the URL /your/api/endpoint + req.open('GET', url, true); + req.onload = function() { + console.log("customLoad: complete lng=" + lngValue + ", req.status=" + req.status); + if (req.status >= 200 && req.status < 300) { + var data = JSON.parse(req.responseText); + window.i18nOriginal[lngValue] = angular.copy(data); + var extended = getExtended(window.i18nOriginal[lngValue], lngValue); + console.log("customLoad: complete lng=" + lngValue + " DONE"); + loadComplete(/*err*/ null, extended); } else { - loadComplete(/*err*/ "Error loading overrides, not found", null); + console.log("customLoad: complete lng=" + lngValue + " ERROR"); + loadComplete(/*err*/ "Error loading locale at url=" + url, null); } - } else { - console.log("unhandled customLoad case for i18next"); - } + }; + console.log("customLoad: sending GET url=" + url); + req.send(""); }, defaultLoadingValue: '' // ng-i18next option, *NOT* directly supported by i18next }, diff --git a/avBooth/booth-directive/booth-directive.js b/avBooth/booth-directive/booth-directive.js index 57b28376..3781b2a1 100644 --- a/avBooth/booth-directive/booth-directive.js +++ b/avBooth/booth-directive/booth-directive.js @@ -111,16 +111,38 @@ angular.module('avBooth') var election = ( scope.state === stateEnum.electionChooserScreen ) ? scope.parentElection : scope.election; + $i18next.options.useLocalStorage = true; if (election && scope.alreadyReloaded === election.id) { return; } if (!election) { - console.log("timeoutWrap: delaying.."); + console.log("timeoutWrap: delaying for election.."); setTimeout(timeoutWrap, 200); - } else { - reloadInner(); + return; + } + var languagesConf = ( + election && + election.presentation && + election.presentation.i18n_languages_conf + ) ? election.presentation.i18n_languages_conf : null; + + var languageNotFound = false; + if (languagesConf && languagesConf.available_languages) { + _.each(languagesConf.available_languages, function (langCode) { + if (!window.i18nOriginal || !(langCode in window.i18nOriginal)) { + console.log("bundle not found for lang=" + langCode); + window.i18n.preload([langCode]); + languageNotFound = true; + } + }); + } + if (languageNotFound) { + console.log("timeoutWrap: delaying for bundle.."); + setTimeout(timeoutWrap, 200); + return; } + reloadInner(); } timeoutWrap(); } From a7d966688ed3ce196c97d3192d7e444bb72ebf5d Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Wed, 7 Feb 2024 09:59:05 +0100 Subject: [PATCH 03/13] trying to adapt to new i18next --- app.js | 54 ++---------- avBooth/booth-directive/booth-directive.js | 97 +++++++--------------- package.json | 1 - 3 files changed, 37 insertions(+), 115 deletions(-) diff --git a/app.js b/app.js index f4945bff..3c118632 100755 --- a/app.js +++ b/app.js @@ -52,58 +52,22 @@ angular // note that we do not send the language: by default, it will try the language // supported by the web browser $("#no-js").hide(); - var loading = {}; - window.i18nOriginal = {}; - - function getExtended(data, lngValue) { - var override = {}; - if (window.i18nOverride && lngValue in window.i18nOverride) { - var baseOverride = window.i18nOverride[lngValue]; - override = angular.copy(baseOverride); - } - return angular.merge({}, data, override); - } - $i18nextProvider.options = _.extend( { + debug: true, useCookie: true, + // Preload is needed because the language selector shows an item for + // each element in lngWhitelist, and the translation for each language + // is contained at each language i18n file, so we either preload it + // or it wouldn't work. + preload: ConfigServiceProvider.i18nextInitOptions.lngWhitelist || [], useLocalStorage: false, fallbackLng: 'en', cookieName: 'lang', detectLngQS: 'lang', - lngWhitelist: ['en', 'es', 'gl', 'ca'], - customLoad: function (lngValue, nsValue, options, loadComplete) { - var url = '/booth/locales/' + lngValue + '.json'; - if (window.i18nOriginal && lngValue in window.i18nOriginal) { - console.log("customLoad: RET ORIGINAL EXTENDED lng=" + lngValue); - // if we already loaded the original, then we don't reload it. - // Otherwise the language selector goes crazy - return; - } - if (lngValue in loading) { - console.log("customLoad: already loading lng=" + lngValue); - loadComplete(/*err*/ "customLoad: already loading lng=" + lngValue, null); - return; - } - loading[lngValue] = true; - var req = new XMLHttpRequest(); - // Configure it: GET-request for the URL /your/api/endpoint - req.open('GET', url, true); - req.onload = function() { - console.log("customLoad: complete lng=" + lngValue + ", req.status=" + req.status); - if (req.status >= 200 && req.status < 300) { - var data = JSON.parse(req.responseText); - window.i18nOriginal[lngValue] = angular.copy(data); - var extended = getExtended(window.i18nOriginal[lngValue], lngValue); - console.log("customLoad: complete lng=" + lngValue + " DONE"); - loadComplete(/*err*/ null, extended); - } else { - console.log("customLoad: complete lng=" + lngValue + " ERROR"); - loadComplete(/*err*/ "Error loading locale at url=" + url, null); - } - }; - console.log("customLoad: sending GET url=" + url); - req.send(""); + lngWhitelist: ['en', 'es'], + backend: { + loadPath: '/locales/__lng__.json', }, defaultLoadingValue: '' // ng-i18next option, *NOT* directly supported by i18next }, diff --git a/avBooth/booth-directive/booth-directive.js b/avBooth/booth-directive/booth-directive.js index 3781b2a1..b1edbe66 100644 --- a/avBooth/booth-directive/booth-directive.js +++ b/avBooth/booth-directive/booth-directive.js @@ -74,77 +74,36 @@ angular.module('avBooth') scope.alreadyReloaded = null; function reloadTranslations(force) { - function reloadInner() { - var election = ( - scope.state === stateEnum.electionChooserScreen - ) ? scope.parentElection : scope.election; - - if (scope.alreadyReloaded === election.id) { - $i18next.reInit(); - return; - } else { - scope.alreadyReloaded = election.id; - } + var election = ( + scope.state === stateEnum.electionChooserScreen + ) ? scope.parentElection : scope.election; - // reset $window.i18nOverride - var overrides = ( - election && - election.presentation && - election.presentation.i18n_override - ) ? election.presentation.i18n_override : null; - - var languagesConf = ( - election && - election.presentation && - election.presentation.i18n_languages_conf - ) ? election.presentation.i18n_languages_conf : null; - - $i18next.options.useLocalStorage = true; - I18nOverride( - /* overrides = */ overrides, - /* force = */ force, - /* languagesConf = */ languagesConf - ); - } - function timeoutWrap() { - console.log("timeoutWrap"); - var election = ( - scope.state === stateEnum.electionChooserScreen - ) ? scope.parentElection : scope.election; - $i18next.options.useLocalStorage = true; - - if (election && scope.alreadyReloaded === election.id) { - return; - } - if (!election) { - console.log("timeoutWrap: delaying for election.."); - setTimeout(timeoutWrap, 200); - return; - } - var languagesConf = ( - election && - election.presentation && - election.presentation.i18n_languages_conf - ) ? election.presentation.i18n_languages_conf : null; - - var languageNotFound = false; - if (languagesConf && languagesConf.available_languages) { - _.each(languagesConf.available_languages, function (langCode) { - if (!window.i18nOriginal || !(langCode in window.i18nOriginal)) { - console.log("bundle not found for lang=" + langCode); - window.i18n.preload([langCode]); - languageNotFound = true; - } - }); - } - if (languageNotFound) { - console.log("timeoutWrap: delaying for bundle.."); - setTimeout(timeoutWrap, 200); - return; - } - reloadInner(); + if (scope.alreadyReloaded === election.id) { + $i18next.reInit(); + return; + } else { + scope.alreadyReloaded = election.id; } - timeoutWrap(); + + // reset $window.i18nOverride + var overrides = ( + election && + election.presentation && + election.presentation.i18n_override + ) ? election.presentation.i18n_override : null; + + var languagesConf = ( + election && + election.presentation && + election.presentation.i18n_languages_conf + ) ? election.presentation.i18n_languages_conf : null; + + $i18next.options.useLocalStorage = true; + I18nOverride( + /* overrides = */ overrides, + /* force = */ force, + /* languagesConf = */ languagesConf + ); } function updateWidth() { diff --git a/package.json b/package.json index c01519fd..9a4e0005 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "dependencies": { "common-ui": "https://github.com/sequentech/common-ui.git#10.1.0", "angular-aria": "^1.8.2", - "common-ui": "https://github.com/sequentech/common-ui.git#10.1.0", "pdfmake": "^0.1.65", "qrcode-generator": "^1.4.4" }, From 17c319e63666678f3a88bc098a9ef3e55112ad9c Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Wed, 7 Feb 2024 11:39:49 +0100 Subject: [PATCH 04/13] WIP --- Gruntfile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index df36b51f..51e5ff4e 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -325,7 +325,6 @@ module.exports = function (grunt) { main: { files: { 'temp/app.js':['temp/app.js'], - 'temp/lib.js': ['temp/lib.js'], 'temp/libnocompat.js': ['temp/libnocompat.js'], } } From ac97146387bafca000a912b00bf95d18b1e5d496 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Wed, 7 Feb 2024 11:52:00 +0100 Subject: [PATCH 05/13] WIP --- avBooth/booth-directive/booth-directive.js | 73 +++++++++++++--------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/avBooth/booth-directive/booth-directive.js b/avBooth/booth-directive/booth-directive.js index b1edbe66..0fef05d1 100644 --- a/avBooth/booth-directive/booth-directive.js +++ b/avBooth/booth-directive/booth-directive.js @@ -74,36 +74,53 @@ angular.module('avBooth') scope.alreadyReloaded = null; function reloadTranslations(force) { - var election = ( - scope.state === stateEnum.electionChooserScreen - ) ? scope.parentElection : scope.election; + function reloadInner() { + var election = ( + scope.state === stateEnum.electionChooserScreen + ) ? scope.parentElection : scope.election; - if (scope.alreadyReloaded === election.id) { - $i18next.reInit(); - return; - } else { - scope.alreadyReloaded = election.id; - } + if (scope.alreadyReloaded === election.id) { + $i18next.reInit(); + return; + } else { + scope.alreadyReloaded = election.id; + } - // reset $window.i18nOverride - var overrides = ( - election && - election.presentation && - election.presentation.i18n_override - ) ? election.presentation.i18n_override : null; - - var languagesConf = ( - election && - election.presentation && - election.presentation.i18n_languages_conf - ) ? election.presentation.i18n_languages_conf : null; - - $i18next.options.useLocalStorage = true; - I18nOverride( - /* overrides = */ overrides, - /* force = */ force, - /* languagesConf = */ languagesConf - ); + // reset $window.i18nOverride + var overrides = ( + election && + election.presentation && + election.presentation.i18n_override + ) ? election.presentation.i18n_override : null; + + var languagesConf = ( + election && + election.presentation && + election.presentation.i18n_languages_conf + ) ? election.presentation.i18n_languages_conf : null; + + I18nOverride( + /* overrides = */ overrides, + /* force = */ force, + /* languagesConf = */ languagesConf + ); + } + function timeoutWrap() { + console.log("timeoutWrap"); + var election = ( + scope.state === stateEnum.electionChooserScreen + ) ? scope.parentElection : scope.election; + if (election && scope.alreadyReloaded === election.id) { + return; + } + if (!election) { + console.log("timeoutWrap: delaying for election.."); + setTimeout(timeoutWrap, 200); + return; + } + reloadInner(); + } + timeoutWrap(); } function updateWidth() { From 64259f05012b5dc32d510ee2f3d9e29c65d4da83 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Wed, 7 Feb 2024 16:48:31 +0100 Subject: [PATCH 06/13] WIP --- app.js | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/app.js b/app.js index 3c118632..f3309f31 100755 --- a/app.js +++ b/app.js @@ -52,27 +52,30 @@ angular // note that we do not send the language: by default, it will try the language // supported by the web browser $("#no-js").hide(); - $i18nextProvider.options = _.extend( - { - debug: true, - useCookie: true, - // Preload is needed because the language selector shows an item for - // each element in lngWhitelist, and the translation for each language - // is contained at each language i18n file, so we either preload it - // or it wouldn't work. - preload: ConfigServiceProvider.i18nextInitOptions.lngWhitelist || [], - useLocalStorage: false, - fallbackLng: 'en', - cookieName: 'lang', - detectLngQS: 'lang', - lngWhitelist: ['en', 'es'], - backend: { - loadPath: '/locales/__lng__.json', + window.i18next + .use(window.i18nextHttpBackend) + .init(_.extend( + { + debug: true, + load: 'languageOnly', + useCookie: true, + // Preload is needed because the language selector shows an item for + // each element in lngWhitelist, and the translation for each language + // is contained at each language i18n file, so we either preload it + // or it wouldn't work. + preload: ConfigServiceProvider.i18nextInitOptions.lngWhitelist || [], + useLocalStorage: false, + fallbackLng: 'en', + cookieName: 'lang', + detectLngQS: 'lang', + lngWhitelist: ['en', 'es'], + backend: { + loadPath: '/locales/{{lng}}.json', + }, + defaultLoadingValue: '' // ng-i18next option, *NOT* directly supported by i18next }, - defaultLoadingValue: '' // ng-i18next option, *NOT* directly supported by i18next - }, - ConfigServiceProvider.i18nextInitOptions - ); + ConfigServiceProvider.i18nextInitOptions + )); // Prevent site translation if configured if (ConfigServiceProvider.preventSiteTranslation) { From 0a2e4f95b2aa873981ac02316dda133c90ee52e4 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Wed, 7 Feb 2024 16:55:01 +0100 Subject: [PATCH 07/13] WIP --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index f3309f31..93f22363 100755 --- a/app.js +++ b/app.js @@ -70,7 +70,7 @@ angular detectLngQS: 'lang', lngWhitelist: ['en', 'es'], backend: { - loadPath: '/locales/{{lng}}.json', + loadPath: '/booth/locales/{{lng}}.json', }, defaultLoadingValue: '' // ng-i18next option, *NOT* directly supported by i18next }, From 7e392317abeb661b4f9f48ae921e56fad67fd988 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Wed, 7 Feb 2024 17:34:18 +0100 Subject: [PATCH 08/13] WIP --- app.js | 12 +++++++++++- avBooth/booth-directive/booth-directive.js | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 93f22363..57aea8a8 100755 --- a/app.js +++ b/app.js @@ -69,8 +69,12 @@ angular cookieName: 'lang', detectLngQS: 'lang', lngWhitelist: ['en', 'es'], + interpolation: { + prefix: '__', + suffix: '__', + }, backend: { - loadPath: '/booth/locales/{{lng}}.json', + loadPath: '/booth/locales/__lng__.json', }, defaultLoadingValue: '' // ng-i18next option, *NOT* directly supported by i18next }, @@ -177,6 +181,12 @@ angular.module('voting-booth').run(function($http, $rootScope, ConfigService, $w this.$apply(fn); } }; + $rootScope.$on( + 'i18nextLanguageChange', + function () { + $rootScope.safeApply(); + } + ); $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) { diff --git a/avBooth/booth-directive/booth-directive.js b/avBooth/booth-directive/booth-directive.js index 0fef05d1..e5f9c634 100644 --- a/avBooth/booth-directive/booth-directive.js +++ b/avBooth/booth-directive/booth-directive.js @@ -80,7 +80,8 @@ angular.module('avBooth') ) ? scope.parentElection : scope.election; if (scope.alreadyReloaded === election.id) { - $i18next.reInit(); + console.log("calling $i18next.changeLanguage($i18next.options.lng);"); + $i18next.changeLanguage($i18next.options.lng); return; } else { scope.alreadyReloaded = election.id; From 667efb7ae5fcd90b196c23b74a2ff45bccfd5cc6 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Wed, 7 Feb 2024 17:55:30 +0100 Subject: [PATCH 09/13] WIP --- app.js | 1 + avBooth/booth-directive/booth-directive.js | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 57aea8a8..6537ec7a 100755 --- a/app.js +++ b/app.js @@ -184,6 +184,7 @@ angular.module('voting-booth').run(function($http, $rootScope, ConfigService, $w $rootScope.$on( 'i18nextLanguageChange', function () { + console.log("i18nextLanguageChange: lang-change, calling safeApply()"); $rootScope.safeApply(); } ); diff --git a/avBooth/booth-directive/booth-directive.js b/avBooth/booth-directive/booth-directive.js index e5f9c634..774fdd08 100644 --- a/avBooth/booth-directive/booth-directive.js +++ b/avBooth/booth-directive/booth-directive.js @@ -22,6 +22,7 @@ angular.module('avBooth') $cookies, $http, $i18next, + $rootScope, $timeout, $window, Authmethod, @@ -80,8 +81,8 @@ angular.module('avBooth') ) ? scope.parentElection : scope.election; if (scope.alreadyReloaded === election.id) { - console.log("calling $i18next.changeLanguage($i18next.options.lng);"); - $i18next.changeLanguage($i18next.options.lng); + console.log("booth-directive: broadcast i18nextLanguageChange"); + $rootScope.$broadcast('i18nextLanguageChange', $i18next.options.lng); return; } else { scope.alreadyReloaded = election.id; From 5591cf64d39528273c21202519c21d8a9c4ecb7f Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Thu, 8 Feb 2024 09:53:34 +0100 Subject: [PATCH 10/13] adding custom backend for overrides --- app.js | 66 +++++++++++++++++++++- avBooth/booth-directive/booth-directive.js | 2 +- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 6537ec7a..f63c9ca7 100755 --- a/app.js +++ b/app.js @@ -49,11 +49,39 @@ angular .config( function ($i18nextProvider, ConfigServiceProvider) { + function expandObject(obj) + { + var result = {}; + // Helper function to handle the recursion + function assignValue(ref, keys, value) { + var key = keys.shift(); // Get the current key part + if (keys.length === 0) { + // If no more keys, assign the value directly + ref[key] = value; + } else { + // Prepare the next level sub-object if necessary + if (!ref[key]) { + ref[key] = {}; + } + // Recurse with the next level of the key and the corresponding sub-object + assignValue(ref[key], keys, value); + } + } + // Iterate over each property in the input object + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + var keys = prop.split('.'); // Split the property by dots into parts + assignValue(result, keys, obj[prop]); // Use the helper to assign the value in the result object + } + } + return result; + } + // note that we do not send the language: by default, it will try the language // supported by the web browser $("#no-js").hide(); window.i18next - .use(window.i18nextHttpBackend) + .use(window.i18nextChainedBackend) .init(_.extend( { debug: true, @@ -73,8 +101,42 @@ angular prefix: '__', suffix: '__', }, + // Define the backends to use in the chain backend: { - loadPath: '/booth/locales/__lng__.json', + backends: [ + { + type: 'backend', + /* use services and options */ + init: function(services, backendOptions, i18nextOptions) {}, + /* return resources */ + read: function(language, namespace, callback) + { + if ( + window.i18nOverride && + typeof window.i18nOverride === 'object' && + window.i18nOverride[language] && + typeof window.i18nOverride[language] === 'object' + ) { + var override = expandObject(window.i18nOverride[language]); + callback(null, override); + } else { + // not found + callback(true, null); + } + }, + /* save the missing translation */ + create: function(languages, namespace, key, fallbackValue) {} + }, + window.i18nextHttpBackend, // Primary backend + ], + backendOptions: [ + // Configuration for custom backend + {}, + // Configuration for http backend + { + loadPath: '/booth/locales/__lng__.json', + }, + ] }, defaultLoadingValue: '' // ng-i18next option, *NOT* directly supported by i18next }, diff --git a/avBooth/booth-directive/booth-directive.js b/avBooth/booth-directive/booth-directive.js index 774fdd08..356be7bf 100644 --- a/avBooth/booth-directive/booth-directive.js +++ b/avBooth/booth-directive/booth-directive.js @@ -88,7 +88,7 @@ angular.module('avBooth') scope.alreadyReloaded = election.id; } - // reset $window.i18nOverride + // should we reset $window.i18nOverride? var overrides = ( election && election.presentation && From 520531079b6a08e754b7b74cccf7a941c378a053 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Thu, 8 Feb 2024 11:02:37 +0100 Subject: [PATCH 11/13] WIP --- avBooth/booth-directive/booth-directive.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/avBooth/booth-directive/booth-directive.js b/avBooth/booth-directive/booth-directive.js index 356be7bf..e9c4e198 100644 --- a/avBooth/booth-directive/booth-directive.js +++ b/avBooth/booth-directive/booth-directive.js @@ -120,7 +120,8 @@ angular.module('avBooth') setTimeout(timeoutWrap, 200); return; } - reloadInner(); + // call reloadInner only after i18next initialization + $window.i18next.on('initialized', reloadInner); } timeoutWrap(); } From 9bcea779853eb7b41a4254e5966fdefd019455fe Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Thu, 8 Feb 2024 11:52:00 +0100 Subject: [PATCH 12/13] WIP --- avBooth/booth-directive/booth-directive.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/avBooth/booth-directive/booth-directive.js b/avBooth/booth-directive/booth-directive.js index e9c4e198..d856e348 100644 --- a/avBooth/booth-directive/booth-directive.js +++ b/avBooth/booth-directive/booth-directive.js @@ -121,7 +121,11 @@ angular.module('avBooth') return; } // call reloadInner only after i18next initialization - $window.i18next.on('initialized', reloadInner); + if ($window.i18next.isInitialized) { + reloadInner(); + } else { + $window.i18next.on('initialized', reloadInner); + } } timeoutWrap(); } From 1b55d87428f7387f139fd783cccbe3edd98bcac2 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Thu, 8 Feb 2024 12:46:51 +0100 Subject: [PATCH 13/13] WIP --- avBooth/booth-directive/booth-directive.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/avBooth/booth-directive/booth-directive.js b/avBooth/booth-directive/booth-directive.js index d856e348..478a91bb 100644 --- a/avBooth/booth-directive/booth-directive.js +++ b/avBooth/booth-directive/booth-directive.js @@ -21,7 +21,6 @@ angular.module('avBooth') $modal, $cookies, $http, - $i18next, $rootScope, $timeout, $window, @@ -82,7 +81,7 @@ angular.module('avBooth') if (scope.alreadyReloaded === election.id) { console.log("booth-directive: broadcast i18nextLanguageChange"); - $rootScope.$broadcast('i18nextLanguageChange', $i18next.options.lng); + $rootScope.$broadcast('i18nextLanguageChange', $window.i18next.resolvedLanguage); return; } else { scope.alreadyReloaded = election.id;