Skip to content

Commit

Permalink
🐞 default translation appears when switching language for the first t…
Browse files Browse the repository at this point in the history
…ime (#423)

Parent issue: sequentech/common-ui#375
  • Loading branch information
edulix authored Feb 8, 2024
1 parent 8a7dbfc commit 09d3a80
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 46 deletions.
1 change: 0 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
}
}
Expand Down
111 changes: 97 additions & 14 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,99 @@ 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();

$i18nextProvider.options = _.extend(
{
useCookie: true,
useLocalStorage: false,
fallbackLng: 'en',
cookieName: 'lang',
detectLngQS: 'lang',
lngWhitelist: ['en', 'es', 'gl', 'ca'],
resGetPath: '/booth/locales/__lng__.json',
defaultLoadingValue: '' // ng-i18next option, *NOT* directly supported by i18next
},
ConfigServiceProvider.i18nextInitOptions
);
window.i18next
.use(window.i18nextChainedBackend)
.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'],
interpolation: {
prefix: '__',
suffix: '__',
},
// Define the backends to use in the chain
backend: {
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
},
ConfigServiceProvider.i18nextInitOptions
));

// Prevent site translation if configured
if (ConfigServiceProvider.preventSiteTranslation) {
Expand Down Expand Up @@ -167,6 +243,13 @@ angular.module('voting-booth').run(function($http, $rootScope, ConfigService, $w
this.$apply(fn);
}
};
$rootScope.$on(
'i18nextLanguageChange',
function () {
console.log("i18nextLanguageChange: lang-change, calling safeApply()");
$rootScope.safeApply();
}
);

$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams) {
Expand Down
86 changes: 56 additions & 30 deletions avBooth/booth-directive/booth-directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ angular.module('avBooth')
$modal,
$cookies,
$http,
$i18next,
$rootScope,
$timeout,
$window,
Authmethod,
Expand Down Expand Up @@ -71,36 +71,62 @@ 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) {
console.log("booth-directive: broadcast i18nextLanguageChange");
$rootScope.$broadcast('i18nextLanguageChange', $window.i18next.resolvedLanguage);
return;
} else {
scope.alreadyReloaded = election.id;
}

// should we 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;
}
// call reloadInner only after i18next initialization
if ($window.i18next.isInitialized) {
reloadInner();
} else {
$window.i18next.on('initialized', reloadInner);
}
}
timeoutWrap();
}

function updateWidth() {
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down

0 comments on commit 09d3a80

Please sign in to comment.