discourse-translator/assets/javascripts/discourse/initializers/extend-for-translate-button.js
Natalie Tay 4a2faf9a99
DEV: Use backend plugin api instead of frontend apis to override translation values (#210)
In https://github.com/discourse/discourse-translator/pull/205, we returned translated values using existing JS apis. While this was convenient, it does not allow us to modify crawler views such as ...

https://github.com/discourse/discourse/blob/main/app/views/topics/show.html.erb 

... when we want to serve translated pages.

This commit makes use of https://github.com/discourse/discourse/pull/31261 to override the values.
2025-02-14 12:05:56 +08:00

170 lines
4.6 KiB
JavaScript

import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { withSilencedDeprecations } from "discourse/lib/deprecated";
import { withPluginApi } from "discourse/lib/plugin-api";
import { i18n } from "discourse-i18n";
import LanguageSwitcher from "../components/language-switcher";
import ToggleTranslationButton from "../components/post-menu/toggle-translation-button";
import ShowOriginalContent from "../components/show-original-content";
import TranslatedPost from "../components/translated-post";
function initializeTranslation(api) {
const siteSettings = api.container.lookup("service:site-settings");
if (!siteSettings.translator_enabled) {
return;
}
const currentUser = api.getCurrentUser();
if (!currentUser && siteSettings.experimental_anon_language_switcher) {
api.headerIcons.add(
"discourse-translator_language-switcher",
LanguageSwitcher,
{ before: ["search"] }
);
}
if (
siteSettings.experimental_topic_translation &&
(currentUser || siteSettings.experimental_anon_language_switcher)
) {
api.renderInOutlet("topic-navigation", ShowOriginalContent);
}
if (!siteSettings.experimental_topic_translation) {
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 register the new properties as
// tracked
api.addTrackedPostProperties(
"detectedLang",
"isTranslating",
"isTranslated",
"translatedText",
"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;
}
if (dec.state.isTranslating) {
return dec.h("div.spinner.small");
}
const language = dec.attrs.detected_lang;
const translator = siteSettings.translator;
let titleElements = [];
if (dec.attrs.translated_title) {
titleElements = [
dec.h("div.topic-attribution", dec.attrs.translated_title),
];
}
return dec.h("div.post-translation", [
dec.h("hr"),
...titleElements,
dec.h(
"div.post-attribution",
i18n("translator.translated_from", { language, translator })
),
dec.cooked(dec.attrs.translated_text),
]);
});
api.attachWidgetAction("post-menu", "translate", function () {
const state = this.state;
state.isTranslated = true;
state.isTranslating = true;
this.scheduleRerender();
const post = this.findAncestorModel();
if (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;
state.isTranslated = false;
})
.finally(() => (state.isTranslating = false));
}
});
api.attachWidgetAction("post-menu", "hideTranslation", function () {
this.state.isTranslated = false;
const post = this.findAncestorModel();
if (post) {
post.set("translated_text", "");
}
});
api.addPostMenuButton("translate", (attrs, state) => {
if (!attrs.can_translate) {
return;
}
const [action, title] = !state.isTranslated
? ["translate", "translator.view_translation"]
: ["hideTranslation", "translator.hide_translation"];
return {
action,
title,
icon: "globe",
position: "first",
className: state.isTranslated ? "translated" : null,
};
});
}
export default {
name: "extend-for-translate-button",
initialize() {
withPluginApi("1.39.2", (api) => initializeTranslation(api));
},
};