From c95e0e402d35abe88dfb51e5381d7901e877ab8c Mon Sep 17 00:00:00 2001
From: Ludovic DANIEL <ludovic.daniel@smile.fr>
Date: Wed, 9 Aug 2023 16:18:23 +0200
Subject: [PATCH 1/3] Adding internationalization capabilities + initialized
 with English and French

---
 src/dvwebloader.html  |  8 +++---
 src/js/fileupload2.js | 57 ++++++++++++++++++++++++++-----------------
 src/js/lang.js        | 45 ++++++++++++++++++++++++++++++++++
 3 files changed, 84 insertions(+), 26 deletions(-)
 create mode 100644 src/js/lang.js

diff --git a/src/dvwebloader.html b/src/dvwebloader.html
index fa2cee3..bfded93 100644
--- a/src/dvwebloader.html
+++ b/src/dvwebloader.html
@@ -5,15 +5,15 @@
         <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
         <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core.js"></script>
         <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/md5.js"></script>
-        <script src="js/fileupload2.js"></script>
+        <script type="module" src="js/fileupload2.js"></script>
     </head>
     <body>
-        <div id='help'><a href='https://github.com/gdcc/dvwebloader/wiki' target='_blank'>Help/Tutorial</a></div>
-        <div id="top"><label for='files' class='button'>Select  a Directory<input type="file" id="files" name="files[]" multiple webkitdirectory style="display:none"/></label>
+        <div id='help'><a href='https://github.com/gdcc/dvwebloader/wiki' target='_blank'><span id="help-tutorial-text">Help/Tutorial</span></a></div>
+        <div id="top"><label for='files' class='button'><span id="select-dir-text">Select  a Directory</span><input type="file" id="files" name="files[]" multiple webkitdirectory style="display:none"/></label>
             <div id='messages'></div>
         </div>
         <div id="filelist"></div>
-        <div id="credit"><a href='https://github.com/gdcc/dvwebloader' target='_blank'>DVWebloader v0.2</a>, development sponsored by UiT/DataverseNO</div>
+        <div id="credit"><a href='https://github.com/gdcc/dvwebloader' target='_blank'>DVWebloader v0.2</a><span id="sponsor-text">, development sponsored by UiT/DataverseNO</span></div>
         <script>
             var input = document.getElementById('files');
 
diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js
index 63cb9ee..22b07dc 100644
--- a/src/js/fileupload2.js
+++ b/src/js/fileupload2.js
@@ -1,3 +1,5 @@
+import getLocalizedString from './lang.js';
+
 var fileList = [];
 var rawFileMap = {};
 var toRegisterFileList = [];
@@ -42,6 +44,7 @@ var apiKey;
 var existingFiles;
 var convertedFileNameMap;
 var queryParams;
+var dvLocale;
 
 $(document).ready(function () {
     queryParams = new URLSearchParams(window.location.search.substring(1));
@@ -51,8 +54,11 @@ $(document).ready(function () {
     console.log('PID: ' + datasetPid);
     apiKey = queryParams.get("key");
     console.log(apiKey);
+    dvLocale = queryParams.get("dvLocale");
+    console.log('locale: ' + dvLocale);
     directUploadEnabled = true;
-    addMessage('info', 'Getting Dataset Information...');
+    initTranslation();
+    addMessage('info', 'msgGettingDatasetInfo');
     retrieveDatasetInfo();
     var input = document.getElementById('files');
     input.onchange = function (e) {
@@ -69,24 +75,31 @@ $(document).ready(function () {
         console.log('exists: ' + numExists);
         console.log('rawFileMap len: ' + totalFiles);
         if (totalFiles === numExists) {
-            addMessage('info', 'All files already exist in dataset. There\'s nothing to upload.');
+            addMessage('info', 'msgFilesAlreadyExist');
         } else
         if (numExists !== 0 && totalFiles > numExists) {
-            addMessage('info', 'Some files already exist in dataset. Only checked files will be uploaded.');
+            addMessage('info', 'msgUploadOnlyCheckedFiles');
         }
         $('label.button').hide();
     };
 });
-function addMessage(type, text) {
-    $('#messages').html('').append($('<div/>').addClass(type).text(text));
+function initTranslation() {
+    initSpanTxt('select-dir-text', 'selectDir');
+    initSpanTxt('help-tutorial-text', 'helpTutorial');
+    initSpanTxt('sponsor-text', 'sponsor');
+}
+function initSpanTxt(htmlId, key) {
+    $('#'+htmlId).text(getLocalizedString(dvLocale, key));
+}
+function addMessage(type, key) {
+    $('#messages').html('').append($('<div/>').addClass(type).text(getLocalizedString(dvLocale, key)));
 }
 async function populatePageMetadata(data) {
     var mdFields = data.metadataBlocks.citation.fields;
     var title = "";
     var authors = "";
-    datasetUrl = data.storageIdentifier;
-    datasetUrl = siteUrl + '/dataset.xhtml?persistentId=' + datasetPid;
-    version = queryParams.get("datasetversion");
+    var datasetUrl = siteUrl + '/dataset.xhtml?persistentId=' + datasetPid;
+    var version = queryParams.get("datasetversion");
     if (version === ":draft") {
         version = "DRAFT";
     }
@@ -106,7 +119,7 @@ async function populatePageMetadata(data) {
             }
         }
     }
-    let mdDiv = $('<div/>').append($('<h1/>').text("Uploading to ").append($('<a/>').prop("href", datasetUrl).prop('target', '_blank').text(title)));
+    let mdDiv = $('<div/>').append($('<h1/>').text(getLocalizedString(dvLocale, 'uploadingTo')).append($('<a/>').prop("href", datasetUrl).prop('target', '_blank').text(title)));
     $('#top').prepend(mdDiv);
 }
 
@@ -149,7 +162,7 @@ async function retrieveDatasetInfo() {
                 }
             }
             $('#files').prop('disabled', false);
-            addMessage('info', 'Ready. Click Select a Directory. Review the selected files. Start Uploads. (Note - selection dialog will not show files, but they will be shown afterwards on the page.) ');
+            addMessage('info', 'msgReadyToStart');
         },
         error: function (jqXHR, textStatus, errorThrown) {
             console.log('Failure: ' + jqXHR.status);
@@ -576,7 +589,7 @@ function queueFileForDirectUpload(file) {
     //startUploads();
     if (send) {
         if ($('#upload').length === 0) {
-            $('<button/>').prop('id', 'upload').text('Start Uploads').addClass('button').click(startUploads).appendTo($('#top'));
+            $('<button/>').prop('id', 'upload').text(getLocalizedString(dvLocale, 'startUpload')).addClass('button').click(startUploads).appendTo($('#top'));
         }
     }
     let fileBlock = $('#filelist>.ui-fileupload-files');
@@ -602,12 +615,12 @@ function toggleUpload() {
     if ($('.ui-fileupload-row').children('input:checked').length !== 0) {
         console.log('yes');
         if ($('#upload').length === 0) {
-            $('<button/>').prop('id', 'upload').text('Start Uploads').addClass('button').click(startUploads).insertBefore($('#messages'));
-            addMessage('info', 'Checked files will be uploaded.');
+            $('<button/>').prop('id', 'upload').text(getLocalizedString(dvLocale, 'startUpload')).addClass('button').click(startUploads).insertBefore($('#messages'));
+            addMessage('info', 'msgStartUpload');
         }
     } else {
         $('#upload').remove();
-        addMessage('info', 'No files to upload. Check some files, or refresh to start over.');
+        addMessage('info', 'msgNoFile');
     }
 }
 
@@ -634,7 +647,7 @@ async function uploadFileDirectly(urls, storageId, filesize) {
     if (directUploadEnabled) {
         var upload = null;
         //As long as we have the right file size, we're OK
-        for (i = 0; i < fileList.length; i++) {
+        for (let i = 0; i < fileList.length; i++) {
             if (fileList[i].file.size === filesize) {
                 upload = fileList.splice(i, 1)[0];
                 break;
@@ -654,7 +667,7 @@ async function uploadFileDirectly(urls, storageId, filesize) {
 
 function removeErrors() {
     var errors = document.getElementsByClassName("ui-fileupload-error");
-    for (i = errors.length - 1; i >= 0; i--) {
+    for (let i = errors.length - 1; i >= 0; i--) {
         errors[i].parentNode.removeChild(errors[i]);
     }
 }
@@ -668,7 +681,7 @@ function uploadStarted() {
     //Find the upload table body
     var files = $('.ui-fileupload-files .ui-fileupload-row');
     //Add an id attribute to each entry so we can later match errors with the right entry
-    for (i = 0; i < files.length; i++) {
+    for (let i = 0; i < files.length; i++) {
         files[i].setAttribute('upid', curId);
         curId = curId + 1;
     }
@@ -677,7 +690,7 @@ function uploadStarted() {
     var callback = function (mutations) {
         //Add an id attribute to all new entries
         mutations.forEach(function (mutation) {
-            for (i = 0; i < mutation.addedNodes.length; i++) {
+            for (let i = 0; i < mutation.addedNodes.length; i++) {
                 mutation.addedNodes[i].setAttribute('upid', curId);
                 curId = curId + 1;
             }
@@ -716,7 +729,7 @@ async function directUploadFinished() {
             if (total === numDone) {
                 //   $('button[id$="AllUploadsFinished"]').trigger('click');
                 console.log("All files in S3");
-                addMessage('info', 'Uploads to S3 complete. Now registering all files with the dataset. This may take some time for large numbers of files.');
+                addMessage('info', 'msgUploadCompleteRegistering');
                 let body = [];
                 for (let i = 0; i < toRegisterFileList.length; i++) {
                     let fup = toRegisterFileList[i];
@@ -754,7 +767,7 @@ async function directUploadFinished() {
                     processData: false,
                     success: function (body, statusText, jqXHR) {
                         console.log("All files sent to " + siteUrl + '/dataset.xhtml?persistentId=doi:' + datasetPid + '&version=DRAFT');
-                        addMessage('success', 'Upload complete, all files in dataset. Close this window and refresh your dataset page to see the uploaded files.');
+                        addMessage('success', 'msgUploadComplete');
                     },
                     error: function (jqXHR, textStatus, errorThrown) {
                         console.log('Failure: ' + jqXHR.status);
@@ -771,7 +784,7 @@ async function directUploadFinished() {
         } else {
             if ((inProgress < 4) && (inProgress < inList)) {
                 filesInProgress = filesInProgress + 1;
-                for (i = 0; i < fileList.length; i++) {
+                for (let i = 0; i < fileList.length; i++) {
                     if (fileList[i].state === UploadState.QUEUED) {
                         fileList[i].startRequestForDirectUploadUrl();
                         break;
@@ -844,7 +857,7 @@ async function uploadFailure(jqXHR, upid, filename) {
     var textnode = document.createTextNode("Upload unsuccessful (" + status + ": " + statusText + ").");
     node.appendChild(textnode);
     //Add the error message to the correct row
-    for (i = 0; i < rows.length; i++) {
+    for (let i = 0; i < rows.length; i++) {
         if (rows[i].getAttribute('upid') === id) {
             //Remove any existing error message/only show last error (have seen two error 0 from one network disconnect)
             var err = rows[i].getElementsByClassName('ui-fileupload-error');
diff --git a/src/js/lang.js b/src/js/lang.js
new file mode 100644
index 0000000..1cc6c1f
--- /dev/null
+++ b/src/js/lang.js
@@ -0,0 +1,45 @@
+const defaultLocale = 'en';
+const translations = {
+    en: {
+        selectDir: "Select  a Directory",
+        helpTutorial: "Help/Tutorial",
+        sponsor: ", development sponsored by UiT/DataverseNO",
+        startUpload: "Start Uploads",
+        uploadingTo: "Uploading to ",
+        msgGettingDatasetInfo: "Getting Dataset Information...",
+        msgFilesAlreadyExist: "All files already exist in dataset. There's nothing to upload.",
+        msgUploadOnlyCheckedFiles: "Some files already exist in dataset. Only checked files will be uploaded.",
+        msgReadyToStart: "Ready. Click Select a Directory. Review the selected files. Start Uploads. (Note - selection dialog will not show files, but they will be shown afterwards on the page.) ",
+        msgStartUpload: "Checked files will be uploaded.",
+        msgNoFile: "No files to upload. Check some files, or refresh to start over.",
+        msgUploadCompleteRegistering: "Uploads to S3 complete. Now registering all files with the dataset. This may take some time for large numbers of files.",
+        msgUploadComplete: "Upload complete, all files in dataset. Close this window and refresh your dataset page to see the uploaded files.",
+    },
+    fr: {
+        selectDir: "Sélectionner un répertoire",
+        helpTutorial: "Aide/Tutoriel",
+        sponsor: ", développement sponsorisé par UiT/DataverseNO",
+        startUpload: "Démarrer les envois",
+        uploadingTo: "Envoi vers ",
+        msgGettingDatasetInfo: "Récupération des informations du jeu de données...",
+        msgFilesAlreadyExist: "Tous les fichiers existent déjà dans le jeu de données. Il n'y a rien à envoyer.",
+        msgUploadOnlyCheckedFiles: "Certains fichiers existent déjà dans le jeu de données. Seuls les fichiers cochés seront envoyés.",
+        msgReadyToStart: "Prêt. Cliquez sur Sélectionner un répertoire. Passez en revue les fichiers sélectionnés. Démarrez les envois. (Remarque : la boîte de dialogue de sélection ne montrera pas les fichiers, mais ils seront affichés ensuite sur la page.) ",
+        msgStartUpload: "Les fichiers cochés seront envoyés.",
+        msgNoFile: "Aucun fichier à envoyer. Cochez certains fichiers ou rafraîchissez la page pour recommencer.",
+        msgUploadCompleteRegistering: "Envois vers S3 terminés. Enregistrement de tous les fichiers en cours dans le jeu de données. Cela peut prendre du temps pour un grand nombre de fichiers.",
+        msgUploadComplete: "Envoi terminé, tous les fichiers sont dans le jeu de données. Fermez cette fenêtre et rafraîchissez la page de votre jeu de données pour voir les fichiers envoyés.",
+    },
+};
+
+export default function getLocalizedString(locale, key) {
+    if(!locale || !translations[locale]) {
+        locale = defaultLocale;
+        console.log('getLocalizedString - locale empty or unknown, using defaultLocale: '+defaultLocale)
+    }
+    if (translations[locale] && translations[locale][key]) {
+        return translations[locale][key];
+    }
+    console.log('getLocalizedString - transalation not found with locale: '+locale+' and key:'+key);
+    return key;
+}
\ No newline at end of file

From ca1cee633cf5b13fd0d296bfb6ce241169b4bb22 Mon Sep 17 00:00:00 2001
From: Ludovic DANIEL <ludovic.daniel@smile.fr>
Date: Wed, 9 Aug 2023 17:17:26 +0200
Subject: [PATCH 2/3] Fixed issues after merge

---
 src/dvwebloader.html  | 2 +-
 src/js/fileupload2.js | 9 ++++++---
 src/js/lang.js        | 2 ++
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/dvwebloader.html b/src/dvwebloader.html
index dff3c50..21e7169 100644
--- a/src/dvwebloader.html
+++ b/src/dvwebloader.html
@@ -11,7 +11,7 @@
         <main>
             <div>
                 <img id='logo' alt='Site Logo'>
-                <h1>Folder Upload</h1>
+                <h1><span id="title-text">Folder Upload</span></h1>
                 <div id='help'>
                     <a href='https://github.com/gdcc/dvwebloader/wiki' target='_blank'><span id="help-tutorial-text">Help/Tutorial</span></a>
                 </div>
diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js
index cc1723d..f984da2 100644
--- a/src/js/fileupload2.js
+++ b/src/js/fileupload2.js
@@ -1,3 +1,5 @@
+import getLocalizedString from './lang.js';
+
 var fileList = [];
 var rawFileMap = {};
 var toRegisterFileList = [];
@@ -174,6 +176,7 @@ function addIconAndLogo(siteUrl) {
 
 }
 function initTranslation() {
+    initSpanTxt('title-text', 'title');
     initSpanTxt('select-dir-text', 'selectDir');
     initSpanTxt('help-tutorial-text', 'helpTutorial');
     initSpanTxt('sponsor-text', 'sponsor');
@@ -289,7 +292,7 @@ function setupDirectUpload(enabled) {
         var config = { childList: true };
         var callback = function(mutations) {
             mutations.forEach(function(mutation) {
-                for (i = 0; i < mutation.addedNodes.length; i++) {
+                for (let i = 0; i < mutation.addedNodes.length; i++) {
                     //Add a listener on any replacement file 'select' widget
                     if (mutation.addedNodes[i].id === 'datasetForm:fileUpload_input') {
                         fileInput = mutation.addedNodes[i];
@@ -851,7 +854,7 @@ async function directUploadFinished() {
                     processData: false,
                     success: function(body, statusText, jqXHR) {
                         console.log("All files sent to " + siteUrl + '/dataset.xhtml?persistentId=doi:' + datasetPid + '&version=DRAFT');
-                        addMessage('success', 'Upload complete, all files in dataset. Close this window and refresh your dataset page to see the uploaded files.');
+                        addMessage('success', 'msgUploadComplete');
                     },
                     error: function(jqXHR, textStatus, errorThrown) {
                         console.log('Failure: ' + jqXHR.status);
@@ -868,7 +871,7 @@ async function directUploadFinished() {
         } else {
             if ((inProgress < 4) && (inProgress < inList)) {
                 filesInProgress = filesInProgress + 1;
-                for (i = 0; i < fileList.length; i++) {
+                for (let i = 0; i < fileList.length; i++) {
                     if (fileList[i].state === UploadState.QUEUED) {
                         fileList[i].startRequestForDirectUploadUrl();
                         break;
diff --git a/src/js/lang.js b/src/js/lang.js
index 1cc6c1f..39a3d9b 100644
--- a/src/js/lang.js
+++ b/src/js/lang.js
@@ -1,6 +1,7 @@
 const defaultLocale = 'en';
 const translations = {
     en: {
+        title: "Folder Upload",
         selectDir: "Select  a Directory",
         helpTutorial: "Help/Tutorial",
         sponsor: ", development sponsored by UiT/DataverseNO",
@@ -16,6 +17,7 @@ const translations = {
         msgUploadComplete: "Upload complete, all files in dataset. Close this window and refresh your dataset page to see the uploaded files.",
     },
     fr: {
+        title: "Envoi d'un dossier",
         selectDir: "Sélectionner un répertoire",
         helpTutorial: "Aide/Tutoriel",
         sponsor: ", développement sponsorisé par UiT/DataverseNO",

From 01ad117c5c31c1339e6381320c9f447f9b58b11f Mon Sep 17 00:00:00 2001
From: Ludovic DANIEL <ludovic.daniel@smile.fr>
Date: Wed, 9 Aug 2023 17:21:52 +0200
Subject: [PATCH 3/3] Fixed a space in texts

---
 src/dvwebloader.html | 2 +-
 src/js/lang.js       | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/dvwebloader.html b/src/dvwebloader.html
index 21e7169..3dfe7b0 100644
--- a/src/dvwebloader.html
+++ b/src/dvwebloader.html
@@ -19,7 +19,7 @@ <h1><span id="title-text">Folder Upload</span></h1>
             <hr class='solid'>
             
             <div id="top">
-                <label for='files' class='button'><span id="select-dir-text">Select  a Directory</span><input type="file" id="files" name="files[]" multiple webkitdirectory style="display: none" /></label>
+                <label for='files' class='button'><span id="select-dir-text">Select a Directory</span><input type="file" id="files" name="files[]" multiple webkitdirectory style="display: none" /></label>
                 <div id='messages'></div>
             </div>
             <div id="filelist"></div>
diff --git a/src/js/lang.js b/src/js/lang.js
index 39a3d9b..c6ea7ba 100644
--- a/src/js/lang.js
+++ b/src/js/lang.js
@@ -2,7 +2,7 @@ const defaultLocale = 'en';
 const translations = {
     en: {
         title: "Folder Upload",
-        selectDir: "Select  a Directory",
+        selectDir: "Select a Directory",
         helpTutorial: "Help/Tutorial",
         sponsor: ", development sponsored by UiT/DataverseNO",
         startUpload: "Start Uploads",