From e82061af0fb382d53fb2e87ea4c22a652135c8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Saquetim?= <1108771+megothss@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:30:03 -0300 Subject: [PATCH] DEV: Added compatibility with the Glimmer Post Menu (#173) --- .../post-menu/toggle-translation-button.gjs | 79 +++++++++++++++++++ .../discourse/components/translated-post.gjs | 60 ++++++++++++++ .../discourse/components/translated-post.js | 9 --- .../extend-for-translate-button.js | 73 ++++++++++++----- .../discourse/services/translator.js | 21 +++++ .../templates/components/translated-post.hbs | 17 ---- .../post-after-cooked/translate.hbs | 1 - config/locales/client.en.yml | 1 + 8 files changed, 216 insertions(+), 45 deletions(-) create mode 100644 assets/javascripts/discourse/components/post-menu/toggle-translation-button.gjs create mode 100644 assets/javascripts/discourse/components/translated-post.gjs delete mode 100644 assets/javascripts/discourse/components/translated-post.js create mode 100644 assets/javascripts/discourse/services/translator.js delete mode 100644 assets/javascripts/discourse/templates/components/translated-post.hbs delete mode 100644 assets/javascripts/discourse/templates/connectors/post-after-cooked/translate.hbs diff --git a/assets/javascripts/discourse/components/post-menu/toggle-translation-button.gjs b/assets/javascripts/discourse/components/post-menu/toggle-translation-button.gjs new file mode 100644 index 0000000..9f41016 --- /dev/null +++ b/assets/javascripts/discourse/components/post-menu/toggle-translation-button.gjs @@ -0,0 +1,79 @@ +import Component from "@glimmer/component"; +import { action } from "@ember/object"; +import { inject as service } from "@ember/service"; +import DButton from "discourse/components/d-button"; +import concatClass from "discourse/helpers/concat-class"; +import { popupAjaxError } from "discourse/lib/ajax-error"; + +export default class ToggleTranslationButton extends Component { + static shouldRender(args) { + return args.post.can_translate; + } + + @service modal; + @service translator; + + get isTranslating() { + return this.args.post.isTranslating; + } + + get isTranslated() { + return this.args.post.isTranslated; + } + + get title() { + if (this.isTranslating) { + return "translator.translating"; + } + + return this.isTranslated + ? "translator.hide_translation" + : "translator.view_translation"; + } + + @action + hideTranslation() { + this.args.post.isTranslated = false; + this.args.post.isTranslating = false; + this.translator.clearPostTranslation(this.args.post); + } + + @action + toggleTranslation() { + return this.args.post.isTranslated + ? this.hideTranslation() + : this.translate(); + } + + @action + async translate() { + const post = this.args.post; + post.isTranslating = true; + + try { + await this.translator.translatePost(post); + post.isTranslated = true; + } catch (error) { + this.translator.clearPostTranslation(this.args.post); + post.isTranslated = false; + popupAjaxError(error); + } finally { + post.isTranslating = false; + } + } + + + + +} diff --git a/assets/javascripts/discourse/components/translated-post.gjs b/assets/javascripts/discourse/components/translated-post.gjs new file mode 100644 index 0000000..f01e8be --- /dev/null +++ b/assets/javascripts/discourse/components/translated-post.gjs @@ -0,0 +1,60 @@ +import Component from "@glimmer/component"; +import { inject as service } from "@ember/service"; +import { htmlSafe } from "@ember/template"; +import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner"; +import i18n from "discourse-common/helpers/i18n"; + +export default class TranslatedPost extends Component { + static shouldRender(args) { + return args.post.isTranslated || args.post.isTranslating; + } + + @service siteSettings; + + get loading() { + return this.post.isTranslating; + } + + get isTranslated() { + return this.post.isTranslated; + } + + get post() { + return this.args.outletArgs.post; + } + + get translatedText() { + return this.post.translatedText; + } + + get translatedTitle() { + return this.post.translatedTitle; + } + + + + + + {{#if this.translatedTitle}} + + {{this.translatedTitle}} + + {{/if}} + + {{i18n + "translator.translated_from" + language=this.post.detectedLang + translator=this.siteSettings.translator + }} + + + {{htmlSafe this.post.translatedText}} + + + + +} diff --git a/assets/javascripts/discourse/components/translated-post.js b/assets/javascripts/discourse/components/translated-post.js deleted file mode 100644 index 941ab5a..0000000 --- a/assets/javascripts/discourse/components/translated-post.js +++ /dev/null @@ -1,9 +0,0 @@ -import Component from "@ember/component"; -import computed from "discourse-common/utils/decorators"; - -export default Component.extend({ - @computed("post.translated_text") - loading(translated_text) { - return translated_text === true ? true : false; - }, -}); diff --git a/assets/javascripts/discourse/initializers/extend-for-translate-button.js b/assets/javascripts/discourse/initializers/extend-for-translate-button.js index 4928295..b8e993a 100644 --- a/assets/javascripts/discourse/initializers/extend-for-translate-button.js +++ b/assets/javascripts/discourse/initializers/extend-for-translate-button.js @@ -1,32 +1,58 @@ +import { tracked } from "@glimmer/tracking"; import { ajax } from "discourse/lib/ajax"; import { popupAjaxError } from "discourse/lib/ajax-error"; import { withPluginApi } from "discourse/lib/plugin-api"; +import { withSilencedDeprecations } from "discourse-common/lib/deprecated"; import I18n from "I18n"; - -function translatePost(post) { - return ajax("/translator/translate", { - type: "POST", - data: { post_id: post.get("id") }, - }).then(function (res) { - post.setProperties({ - translated_text: res.translation, - detected_lang: res.detected_lang, - translated_title: res.title_translation, - }); - }); -} +import ToggleTranslationButton from "../components/post-menu/toggle-translation-button"; +import TranslatedPost from "../components/translated-post"; function initializeTranslation(api) { const siteSettings = api.container.lookup("service:site-settings"); const currentUser = api.getCurrentUser(); - if (!currentUser) { + if (!currentUser || !siteSettings.translator_enabled) { return; } - if (!siteSettings.translator_enabled) { - return; + + customizePostMenu(api); +} + +function customizePostMenu(api, container) { + const transformerRegistered = api.registerValueTransformer( + "post-menu-buttons", + ({ value: dag, context: { firstButtonKey } }) => { + dag.add("translate", ToggleTranslationButton, { before: firstButtonKey }); + } + ); + + if (transformerRegistered) { + // the plugin outlet is not updated when the post instance is modified unless we extend it to add the tracking to + // the new properties + api.modifyClass( + "model:post", + (Superclass) => + class extends Superclass { + @tracked detectedLang; + @tracked isTranslating; + @tracked isTranslated; + @tracked translatedText; + @tracked translatedTitle; + } + ); + + api.renderBeforeWrapperOutlet("post-menu", TranslatedPost); } + const silencedKey = + transformerRegistered && "discourse.post-menu-widget-overrides"; + + withSilencedDeprecations(silencedKey, () => + customizeWidgetPostMenu(api, container) + ); +} + +function customizeWidgetPostMenu(api) { api.includePostAttributes( "can_translate", "translated_text", @@ -34,6 +60,7 @@ function initializeTranslation(api) { "translated_title" ); + const siteSettings = api.container.lookup("service:site-settings"); api.decorateWidget("post-menu:before", (dec) => { if (!dec.state.isTranslated) { return; @@ -74,7 +101,17 @@ function initializeTranslation(api) { const post = this.findAncestorModel(); if (post) { - return translatePost(post) + return ajax("/translator/translate", { + type: "POST", + data: { post_id: post.get("id") }, + }) + .then(function (res) { + post.setProperties({ + translated_text: res.translation, + detected_lang: res.detected_lang, + translated_title: res.title_translation, + }); + }) .catch((error) => { popupAjaxError(error); state.isTranslating = false; @@ -114,6 +151,6 @@ function initializeTranslation(api) { export default { name: "extend-for-translate-button", initialize() { - withPluginApi("0.1", (api) => initializeTranslation(api)); + withPluginApi("1.34.0", (api) => initializeTranslation(api)); }, }; diff --git a/assets/javascripts/discourse/services/translator.js b/assets/javascripts/discourse/services/translator.js new file mode 100644 index 0000000..bcb5ca1 --- /dev/null +++ b/assets/javascripts/discourse/services/translator.js @@ -0,0 +1,21 @@ +import Service from "@ember/service"; +import { ajax } from "discourse/lib/ajax"; + +export default class TranslatorService extends Service { + async translatePost(post) { + const response = await ajax("/translator/translate", { + type: "POST", + data: { post_id: post.id }, + }); + + post.detectedLang = response.detected_lang; + post.translatedText = response.translation; + post.translatedTitle = response.title_translation; + } + + clearPostTranslation(post) { + post.detectedLang = null; + post.translatedText = null; + post.translatedTitle = null; + } +} diff --git a/assets/javascripts/discourse/templates/components/translated-post.hbs b/assets/javascripts/discourse/templates/components/translated-post.hbs deleted file mode 100644 index 6f7d951..0000000 --- a/assets/javascripts/discourse/templates/components/translated-post.hbs +++ /dev/null @@ -1,17 +0,0 @@ -{{#if post.translated_text}} - - - - - - {{i18n - "translator.translated_from" - language=post.detected_lang - translator=siteSettings.translator - }} - - - {{html-safe post.translated_text}} - - -{{/if}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/connectors/post-after-cooked/translate.hbs b/assets/javascripts/discourse/templates/connectors/post-after-cooked/translate.hbs deleted file mode 100644 index 4870ae4..0000000 --- a/assets/javascripts/discourse/templates/connectors/post-after-cooked/translate.hbs +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index bd318ef..f021783 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -9,3 +9,4 @@ en: view_translation: "View translation" hide_translation: "Hide translation" translated_from: "Translated from %{language} by %{translator}" + translating: "Translating"