Skip to content

Commit

Permalink
DEV: Added compatibility with the Glimmer Post Menu (#173)
Browse files Browse the repository at this point in the history
  • Loading branch information
megothss authored Nov 14, 2024
1 parent f10d55c commit e82061a
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -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;
}
}

<template>
<DButton
class={{concatClass
"post-action-menu__translate"
(if this.isTranslated "translated")
}}
...attributes
@action={{this.toggleTranslation}}
@disabled={{this.isTranslating}}
@icon="globe"
@label={{if @showLabel this.title}}
@title={{this.title}}
/>
</template>
}
60 changes: 60 additions & 0 deletions assets/javascripts/discourse/components/translated-post.gjs
Original file line number Diff line number Diff line change
@@ -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;
}

<template>
<div class="post-translation">
<ConditionalLoadingSpinner
class="post-translation"
@condition={{this.loading}}
@size="small"
>
<hr />
{{#if this.translatedTitle}}
<div class="topic-attribution">
{{this.translatedTitle}}
</div>
{{/if}}
<div class="post-attribution">
{{i18n
"translator.translated_from"
language=this.post.detectedLang
translator=this.siteSettings.translator
}}
</div>
<div class="cooked">
{{htmlSafe this.post.translatedText}}
</div>
</ConditionalLoadingSpinner>
</div>
</template>
}
9 changes: 0 additions & 9 deletions assets/javascripts/discourse/components/translated-post.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,39 +1,66 @@
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",
"detected_lang",
"translated_title"
);

const siteSettings = api.container.lookup("service:site-settings");
api.decorateWidget("post-menu:before", (dec) => {
if (!dec.state.isTranslated) {
return;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
},
};
21 changes: 21 additions & 0 deletions assets/javascripts/discourse/services/translator.js
Original file line number Diff line number Diff line change
@@ -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;
}
}

This file was deleted.

This file was deleted.

1 change: 1 addition & 0 deletions config/locales/client.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ en:
view_translation: "View translation"
hide_translation: "Hide translation"
translated_from: "Translated from %{language} by %{translator}"
translating: "Translating"

0 comments on commit e82061a

Please sign in to comment.