From 3ab4141f635ba21fbaeb0fc59a5b9848f811b3dc Mon Sep 17 00:00:00 2001
From: Arnaud Levy <contact@arnaudlevy.com>
Date: Tue, 26 Dec 2023 18:39:16 +0100
Subject: [PATCH] working

---
 .../javascripts/admin/commons/translation.js  | 58 +++++++++++++++++++
 .../admin/translation_controller.rb           |  3 +
 .../i18n/_translate_button.html.erb           | 21 +++++++
 .../meta_description/_form.html.erb           |  2 +
 .../admin/application/summary/_form.html.erb  |  1 +
 .../websites/posts/_form.html.erb             | 22 +++----
 app/views/admin/translation/translate.js.erb  | 13 -----
 config/locales/en.yml                         |  4 +-
 config/locales/fr.yml                         |  4 +-
 config/routes.rb                              |  2 +-
 10 files changed, 100 insertions(+), 30 deletions(-)
 create mode 100644 app/assets/javascripts/admin/commons/translation.js
 create mode 100644 app/views/admin/application/i18n/_translate_button.html.erb
 delete mode 100644 app/views/admin/translation/translate.js.erb

diff --git a/app/assets/javascripts/admin/commons/translation.js b/app/assets/javascripts/admin/commons/translation.js
new file mode 100644
index 000000000..ab91b8767
--- /dev/null
+++ b/app/assets/javascripts/admin/commons/translation.js
@@ -0,0 +1,58 @@
+window.osuny.translation = {
+    init: function () {
+        'use strict';
+        this.component = document.querySelector('#translation-button');
+        this.start = document.querySelector('.js-translation-start');
+        this.loader = document.querySelector('.js-translation-loader');
+        this.done = document.querySelector('.js-translation-done');
+        this.start.addEventListener('click', this.run.bind(this));
+        this.url = this.component.dataset.translationUrl;
+        this.translatableFields = document.querySelectorAll('[data-translatable]');
+    },
+    
+    run: function () {
+        this.start.hidden = true;
+        this.loader.hidden = false;
+        setTimeout(this.translateAllFields.bind(this), 100);
+    },
+
+    translateAllFields: function () {
+        for (var i = 0; i < this.translatableFields.length; i++) {
+            var field = this.translatableFields[i];
+            this.translate(field);
+        }
+        this.loader.hidden = true;
+        this.done.hidden = false;
+    },
+
+    translate: function (field) {
+        var text = field.value, 
+            xhr = new XMLHttpRequest();
+        xhr.open("POST", this.url, false);
+        xhr.setRequestHeader('Content-Type', 'application/json');
+        xhr.onreadystatechange = function () {
+            if (this.readyState != 4) return;
+            if (this.status == 200) {
+                var data = JSON.parse(this.responseText);
+                field.value = data.translatedText;
+            }
+        };
+        xhr.send(JSON.stringify({
+            text: text
+        }));
+    },
+
+    invoke: function () {
+        'use strict';
+        return {
+            init: this.init.bind(this)
+        };
+    }
+}.invoke();
+
+window.addEventListener('DOMContentLoaded', function () {
+    'use strict';
+    if (document.querySelector('#translation-button')) {
+        window.osuny.translation.init();
+    }
+});
diff --git a/app/controllers/admin/translation_controller.rb b/app/controllers/admin/translation_controller.rb
index 5bd966ace..973d82267 100644
--- a/app/controllers/admin/translation_controller.rb
+++ b/app/controllers/admin/translation_controller.rb
@@ -1,9 +1,12 @@
 class Admin::TranslationController < Admin::ApplicationController
+  skip_before_action :verify_authenticity_token
+
   def translate
     @target = translation_params[:target]
     @response = LibreTranslate.translate  translation_params[:text],
                                           source: translation_params[:from],
                                           target: translation_params[:to]
+    render json: @response
   end
 
   protected
diff --git a/app/views/admin/application/i18n/_translate_button.html.erb b/app/views/admin/application/i18n/_translate_button.html.erb
new file mode 100644
index 000000000..03590325e
--- /dev/null
+++ b/app/views/admin/application/i18n/_translate_button.html.erb
@@ -0,0 +1,21 @@
+<% if about.is_a_translation? %>
+  <%
+  path = admin_translate_path from: about.original.language.iso_code, 
+                              to: about.language.iso_code,
+                              lang: nil,
+                              website_id: nil
+  %>
+  <span id="translation-button" data-translation-url="<%= path %>"> 
+    <a class="btn btn-light btn-xs js-translation-start">
+      <%= t('admin.translation.button') %>
+    </a>
+    <span class="spinner-border spinner-border-sm js-translation-loader" role="status" hidden>
+      <span class="sr-only">
+        <%= t('admin.translation.running') %>
+      </span>
+    </span>
+    <span class="js-translation-done small" hidden>
+      <%= t('admin.translation.done') %>
+    </span>
+  </span>
+<% end %>
\ No newline at end of file
diff --git a/app/views/admin/application/meta_description/_form.html.erb b/app/views/admin/application/meta_description/_form.html.erb
index 0deb74c7d..b2fa7057e 100644
--- a/app/views/admin/application/meta_description/_form.html.erb
+++ b/app/views/admin/application/meta_description/_form.html.erb
@@ -3,6 +3,8 @@
               label: t('admin.meta_description.label'),
               hint: t('admin.meta_description.hint'),
               input_html: {
+                data: { translatable: true },
+                rows: 3,
                 value: about.meta_description&.gsub('&amp;', '&')
               } %>
 <% end %>
diff --git a/app/views/admin/application/summary/_form.html.erb b/app/views/admin/application/summary/_form.html.erb
index a81bccd8b..23d1058a5 100644
--- a/app/views/admin/application/summary/_form.html.erb
+++ b/app/views/admin/application/summary/_form.html.erb
@@ -2,5 +2,6 @@
             label: t('admin.summary.label'),
             hint: t('admin.summary.hint'),
             input_html: {
+              data: { translatable: true },
               value: about.summary&.gsub('&amp;', '&')
             } %>
diff --git a/app/views/admin/communication/websites/posts/_form.html.erb b/app/views/admin/communication/websites/posts/_form.html.erb
index 5db38e3d8..1caf9af94 100644
--- a/app/views/admin/communication/websites/posts/_form.html.erb
+++ b/app/views/admin/communication/websites/posts/_form.html.erb
@@ -5,17 +5,7 @@
   <div class="row">
     <div class="col-md-8">
       <%= osuny_panel t('content') do %>
-        <%= link_to 'Traduire', 
-                    admin_translate_path(
-                      text: post.title, 
-                      from: post.original.language.iso_code, 
-                      to: post.language.iso_code,
-                      target: 'communication_website_post_title'
-                    ), 
-                    method: :post, 
-                    class: 'action float-end',
-                    remote: true if post.is_a_translation? %>
-        <%= f.input :title %>
+        <%= f.input :title, input_html: { data: { translatable: true } } %>
         <%= render 'admin/application/summary/form', f: f, about: post %>
         <%= f.input :text, as: :summernote if strip_tags(post.text).present? %>
       <% end %>
@@ -30,9 +20,7 @@
             <% end %>
           </div>
         <% end %>
-        <div class="col-md-6">
-          <%= render 'admin/application/meta_description/form', f: f, about: post %>
-        </div>
+        <%= render 'admin/application/meta_description/form', f: f, about: post %>
       </div>
     </div>
     <div class="col-md-4">
@@ -61,6 +49,12 @@
       <%= render 'admin/application/featured_image/edit', about: @post, f: f %>
     </div>
   </div>
+
+
+  <% content_for :action_bar_left do %>
+    <%= render 'admin/application/i18n/translate_button', about: @post %>
+  <% end %>
+
   <% content_for :action_bar_right do %>
     <%= submit f %>
   <% end %>
diff --git a/app/views/admin/translation/translate.js.erb b/app/views/admin/translation/translate.js.erb
deleted file mode 100644
index 974d6e578..000000000
--- a/app/views/admin/translation/translate.js.erb
+++ /dev/null
@@ -1,13 +0,0 @@
-document.getElementById("<%= @target %>").value = "<%= @response['translatedText'] %>";
-notyf = new Notyf();
-notyf.open({
-    type: 'success',
-    position: {
-        x: 'center',
-        y: 'bottom'
-    },
-    message: "<%= t('admin.translation.done') %>",
-    duration: 9000,
-    ripple: true,
-    dismissible: true
-});
\ No newline at end of file
diff --git a/config/locales/en.yml b/config/locales/en.yml
index a4c4afbd4..4a2aea9d5 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -145,7 +145,9 @@ en:
       label: Summary
       hint: A short text, like a heading for an article. Don't write all the content here, there are blocks for that.
     translation:
-      done: Translation done!
+      button: Translate automatically
+      done: Translation done! Please proof read before you save.
+      running: Currently translating
     users_alerts:
       already_confirmed: "Your account has already been confirmed."
       not_locked_html: '<i>%{model}</i> was not locked.'
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index f53544748..679021523 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -145,7 +145,9 @@ fr:
       label: Résumé
       hint: Un texte court, comme un chapô pour un article. Ne mettez pas tout le contenu ici, pour ça, il y a les blocs !
     translation: 
-      done: Traduction effectuée !
+      button: Traduire automatiquement
+      done: Traduction effectuée ! Merci de relire avant d'enregistrer.
+      running: Traduction en cours
     users_alerts:
       already_confirmed: "Votre compte est déjà confirmé."
       not_locked_html: "<i>%{model}</i> n'était pas verrouillé(e)."
diff --git a/config/routes.rb b/config/routes.rb
index 8c25c18d2..a95647a60 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -23,7 +23,7 @@ Rails.application.routes.draw do
       post 'resend_confirmation_email' => 'users#resend_confirmation_email', on: :member
       patch 'unlock' => 'users#unlock', on: :member
     end
-    post 'translate' => 'translation#translate', as: :translate
+    post 'translate/:from/:to' => 'translation#translate', as: :translate
     put 'theme' => 'application#set_theme', as: :set_theme
     put 'favorite' => 'users#favorite', as: :favorite
     draw 'admin/administration'
-- 
GitLab