Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default class ToggleTranslationButton extends Component {

@service modal;
@service translator;
@service siteSettings;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to use this in showButton maybe? It's not used elsewhere in this file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I had originally done some implementation in this file but removed it. Thanks!


get isTranslating() {
return this.args.post.isTranslating;
Expand All @@ -21,6 +22,10 @@ export default class ToggleTranslationButton extends Component {
return this.args.post.isTranslated;
}

get showButton() {
return this.args.post.can_translate;
}

get title() {
if (this.isTranslating) {
return "translator.translating";
Expand Down Expand Up @@ -63,17 +68,19 @@ export default class ToggleTranslationButton extends Component {
}

<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}}
/>
{{#if this.showButton}}
<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}}
/>
{{/if}}
</template>
}
34 changes: 20 additions & 14 deletions assets/javascripts/discourse/components/translated-post.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,35 @@ export default class TranslatedPost extends Component {
return this.post.translatedTitle;
}

get showTranslation() {
return !this.siteSettings.experimental_topic_translation;
}

<template>
<div class="post-translation">
<ConditionalLoadingSpinner
class="post-translation"
@condition={{this.loading}}
@size="small"
>
<hr />
{{#if this.translatedTitle}}
<div class="topic-attribution">
{{this.translatedTitle}}
{{#if this.showTranslation}}
<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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certainly a succinct setting name! :D I thought this was a mistake, I know you didn't add this and it's too late now anyway, but translator_provider or something would be better, it doesn't look like an actual setting ATM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will likely rename the setting together with the "inline" thing we talked about.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing, thank you!

}}
</div>
<div class="cooked">
{{htmlSafe this.post.translatedText}}
</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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ function initializeTranslation(api) {
api.renderInOutlet("topic-navigation", ShowOriginalContent);
}

if (!siteSettings.experimental_topic_translation) {
customizePostMenu(api);
}
customizePostMenu(api);
}

function customizePostMenu(api, container) {
Expand Down
16 changes: 15 additions & 1 deletion assets/javascripts/discourse/services/translator.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import Service from "@ember/service";
import Service, { service } from "@ember/service";
import { ajax } from "discourse/lib/ajax";

export default class TranslatorService extends Service {
@service siteSettings;
@service appEvents;
@service documentTitle;

async translatePost(post) {
const response = await ajax("/translator/translate", {
type: "POST",
Expand All @@ -11,6 +15,16 @@ export default class TranslatorService extends Service {
post.detectedLang = response.detected_lang;
post.translatedText = response.translation;
post.translatedTitle = response.title_translation;
if (this.siteSettings.experimental_topic_translation) {
if (post.post_number === 1) {
post.topic.set("fancy_title", response.title_translation);
this.appEvents.trigger("header:update-topic", post.topic);
this.documentTitle.setTitle(response.title_translation);
}
post.set("cooked", response.translation);
post.set("can_translate", false);
this.appEvents.trigger("post-stream:refresh", { id: post.id });
}
}

clearPostTranslation(post) {
Expand Down
51 changes: 51 additions & 0 deletions test/javascripts/integration/toggle-translation-button-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";

module("Integration | Component | toggle-translation-button", function (hooks) {
setupRenderingTest(hooks);

test("doesn't render when post cannot be translated", async function (assert) {
this.set("post", { can_translate: false });

await render(hbs`
<PostMenu::ToggleTranslationButton @post={{this.post}} />
`);

assert.dom("button").doesNotExist();
});

test("renders translation button with correct states", async function (assert) {
const post = {
can_translate: true,
isTranslated: false,
isTranslating: false,
};

this.set("post", post);

await render(hbs`
<PostMenu::ToggleTranslationButton @post={{this.post}} @showLabel={{true}} />
`);

assert.dom("button").exists();
assert.dom("button").hasText("View translation");
assert.dom("button").doesNotHaveClass("translated");

post.isTranslating = true;
await render(hbs`
<PostMenu::ToggleTranslationButton @post={{this.post}} @showLabel={{true}} />
`);
assert.dom("button").hasAttribute("disabled");
assert.dom("button").hasText("Translating");

post.isTranslating = false;
post.isTranslated = true;
await render(hbs`
<PostMenu::ToggleTranslationButton @post={{this.post}} @showLabel={{true}} />
`);
assert.dom("button").hasClass("translated");
assert.dom("button").hasText("Hide translation");
});
});
51 changes: 51 additions & 0 deletions test/javascripts/integration/translated-post-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";

module("Integration | Component | translated-post", function (hooks) {
setupRenderingTest(hooks);

test("renders translation when post is translated", async function (assert) {
this.set("outletArgs", {
post: {
isTranslated: true,
isTranslating: false,
translatedText: "こんにちは",
translatedTitle: "良い一日",
detectedLang: "ja",
},
});

this.siteSettings.experimental_topic_translation = false;
this.siteSettings.translator = "Google";

await render(hbs`
<TranslatedPost @outletArgs={{this.outletArgs}} />
`);

assert.dom(".post-translation").exists();
assert.dom(".topic-attribution").hasText("良い一日");
assert.dom(".post-attribution").hasText("Translated from ja by Google");
assert.dom(".cooked").hasText("こんにちは");
});

test("hides translation when experimental_topic_translation is enabled", async function (assert) {
this.set("outletArgs", {
post: {
isTranslated: true,
isTranslating: false,
translatedText: "Bonjour monde",
},
});

this.siteSettings.experimental_topic_translation = true;

await render(hbs`
<TranslatedPost @outletArgs={{this.outletArgs}} />
`);

assert.dom(".topic-attribution").doesNotExist();
assert.dom(".post-attribution").doesNotExist();
});
});
97 changes: 97 additions & 0 deletions test/javascripts/service/translator-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { setupTest } from "ember-qunit";
import { module, test } from "qunit";
import pretender, { response } from "discourse/tests/helpers/create-pretender";

module("Unit | Service | translator", function (hooks) {
setupTest(hooks);

test("translatePost - standard translation", async function (assert) {
const service = this.owner.lookup("service:translator");

pretender.post("/translator/translate", () => {
return response({
detected_lang: "ja",
translation: "I am a cat",
title_translation: "Surprise!",
});
});

const post = {
id: 1,
post_number: 2,
};

await service.translatePost(post);

assert.strictEqual(post.detectedLang, "ja");
assert.strictEqual(post.translatedText, "I am a cat");
assert.strictEqual(post.translatedTitle, "Surprise!");
});

test("translatePost - with experimental translation for first post", async function (assert) {
const service = this.owner.lookup("service:translator");

service.siteSettings.experimental_topic_translation = true;

let headerUpdateCalled = false;
let postStreamRefreshCalled = false;
let titleSet = null;

service.appEvents.on(
"header:update-topic",
() => (headerUpdateCalled = true)
);
service.appEvents.on(
"post-stream:refresh",
() => (postStreamRefreshCalled = true)
);
service.documentTitle.setTitle = (title) => (titleSet = title);

pretender.post("/translator/translate", () => {
return response({
detected_lang: "ja",
translation: "I am a cat",
title_translation: "Surprise!",
});
});

const topic = {
set: function (key, value) {
this[key] = value;
},
};
const post = {
id: 1,
post_number: 1,
topic,
set: function (key, value) {
this[key] = value;
},
};

await service.translatePost(post);

assert.true(headerUpdateCalled);
assert.true(postStreamRefreshCalled);
assert.strictEqual(titleSet, "Surprise!");
assert.strictEqual(post.cooked, "I am a cat");
assert.false(post.can_translate);
assert.strictEqual(topic.fancy_title, "Surprise!");
});

test("clearPostTranslation", function (assert) {
const service = this.owner.lookup("service:translator");

const post = {
detectedLang: "ja",
translatedText: "Hello",
translatedTitle: "Title",
};

service.clearPostTranslation(post);

assert.strictEqual(post.detectedLang, null);
assert.strictEqual(post.translatedText, null);
assert.strictEqual(post.translatedTitle, null);
});
});
Loading