Skip to content

Commit 65baebb

Browse files
authored
DEV: Immediately send post for language detection for dual-text translations (#226)
Not too long ago, we moved language detections to a scheduled job. (see internal /t/134867/21) But the new inline translation feature (when turned on) sends all content for translation the moment it is created. So far, we are not seeing an issue with load for this. This commit reverts the batching for language detection to the original way, in-line with the new translation feature. This commit also does a bit of cleanup - introducing three files to encapsulate the plugin event hooks into their own functionality (automatic translation, inline translation, dual-text translation) This changes here will help to simplify the problem of 🌐 showing up in the post briefly, but in a subsequent commit.
1 parent bdc7908 commit 65baebb

File tree

9 files changed

+178
-191
lines changed

9 files changed

+178
-191
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
module ::Jobs
4+
class DetectTranslatableLanguage < ::Jobs::Base
5+
def execute(args)
6+
return unless SiteSetting.translator_enabled
7+
8+
return if !%w[Post Topic].include?(args[:type])
9+
return if !args[:translatable_id].is_a?(Integer)
10+
11+
translatable = args[:type].constantize.find_by(id: args[:translatable_id])
12+
return if translatable.blank?
13+
begin
14+
translator = "DiscourseTranslator::#{SiteSetting.translator}".constantize
15+
translator.detect(translatable)
16+
rescue ::DiscourseTranslator::ProblemCheckedTranslationError
17+
# problem-checked translation errors gracefully
18+
end
19+
end
20+
end
21+
end

app/jobs/scheduled/detect_posts_language.rb

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# frozen_string_literal: true
2+
3+
module DiscourseTranslator
4+
class AutomaticTranslations
5+
def inject(plugin)
6+
plugin.on(:post_process_cooked) do |_, post|
7+
if SiteSetting.automatic_translation_target_languages.present? && post.user_id > 0
8+
Jobs.enqueue(:translate_translatable, type: "Post", translatable_id: post.id)
9+
end
10+
end
11+
12+
plugin.on(:topic_created) do |topic|
13+
if SiteSetting.automatic_translation_target_languages.present? && topic.user_id > 0
14+
Jobs.enqueue(:translate_translatable, type: "Topic", translatable_id: topic.id)
15+
end
16+
end
17+
18+
plugin.on(:topic_edited) do |topic|
19+
if SiteSetting.automatic_translation_target_languages.present? && topic.user_id > 0
20+
Jobs.enqueue(:translate_translatable, type: "Topic", translatable_id: topic.id)
21+
end
22+
end
23+
end
24+
end
25+
end
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
module DiscourseTranslator
4+
class DualTextTranslation
5+
def inject(plugin)
6+
# in dual-text translations,
7+
# we don't want to send the post for detection if automatic translation already happens,
8+
# as automatic translations send content for language detection as a side effect of translating
9+
10+
plugin.on(:post_process_cooked) do |_, post|
11+
if SiteSetting.automatic_translation_target_languages.blank? &&
12+
Guardian.new.can_detect_language?(post) && post.user_id > 0
13+
Jobs.enqueue(:detect_translatable_language, type: "Post", translatable_id: post.id)
14+
end
15+
end
16+
17+
plugin.on(:topic_created) do |topic|
18+
if SiteSetting.automatic_translation_target_languages.blank? && topic.user_id > 0
19+
Jobs.enqueue(:detect_translatable_language, type: "Topic", translatable_id: topic.id)
20+
end
21+
end
22+
end
23+
end
24+
end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# frozen_string_literal: true
2+
3+
module DiscourseTranslator
4+
class InlineTranslation
5+
def inject(plugin)
6+
plugin.register_modifier(:basic_post_serializer_cooked) do |cooked, serializer|
7+
if !SiteSetting.experimental_topic_translation ||
8+
serializer.scope&.request&.params&.[]("show") == "original" ||
9+
serializer.object.detected_locale == I18n.locale.to_s.gsub("_", "-")
10+
cooked
11+
else
12+
serializer.object.translation_for(I18n.locale).presence
13+
end
14+
end
15+
16+
plugin.register_modifier(:topic_serializer_fancy_title) do |fancy_title, serializer|
17+
if !SiteSetting.experimental_topic_translation ||
18+
serializer.scope&.request&.params&.[]("show") == "original" ||
19+
serializer.object.locale_matches?(I18n.locale)
20+
fancy_title
21+
else
22+
serializer.object.translation_for(I18n.locale).presence&.then { |t| Topic.fancy_title(t) }
23+
end
24+
end
25+
26+
plugin.register_modifier(:topic_view_serializer_fancy_title) do |fancy_title, serializer|
27+
if !SiteSetting.experimental_topic_translation ||
28+
serializer.scope&.request&.params&.[]("show") == "original" ||
29+
serializer.object.topic.locale_matches?(I18n.locale)
30+
fancy_title
31+
else
32+
serializer
33+
.object
34+
.topic
35+
.translation_for(I18n.locale)
36+
.presence
37+
&.then { |t| Topic.fancy_title(t) }
38+
end
39+
end
40+
end
41+
end
42+
end

plugin.rb

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -32,66 +32,12 @@ module ::DiscourseTranslator
3232
TopicViewSerializer.prepend(DiscourseTranslator::TopicViewSerializerExtension)
3333
end
3434

35-
on(:post_process_cooked) do |_, post|
36-
if Guardian.new.can_detect_language?(post) && post.user_id > 0
37-
Discourse.redis.sadd?(DiscourseTranslator::LANG_DETECT_NEEDED, post.id)
38-
end
39-
end
40-
41-
on(:post_process_cooked) do |_, post|
42-
if SiteSetting.automatic_translation_target_languages.present? && post.user_id > 0
43-
Jobs.enqueue(:translate_translatable, type: "Post", translatable_id: post.id)
44-
end
45-
end
46-
47-
on(:topic_created) do |topic|
48-
if SiteSetting.automatic_translation_target_languages.present? && topic.user_id > 0
49-
Jobs.enqueue(:translate_translatable, type: "Topic", translatable_id: topic.id)
50-
end
51-
end
52-
53-
on(:topic_edited) do |topic|
54-
if SiteSetting.automatic_translation_target_languages.present? && topic.user_id > 0
55-
Jobs.enqueue(:translate_translatable, type: "Topic", translatable_id: topic.id)
56-
end
57-
end
58-
5935
add_to_serializer :post, :can_translate do
6036
scope.can_translate?(object)
6137
end
6238

63-
register_modifier(:basic_post_serializer_cooked) do |cooked, serializer|
64-
if !SiteSetting.experimental_topic_translation ||
65-
serializer.scope&.request&.params&.[]("show") == "original" ||
66-
serializer.object.detected_locale == I18n.locale.to_s.gsub("_", "-")
67-
cooked
68-
else
69-
serializer.object.translation_for(I18n.locale).presence
70-
end
71-
end
72-
73-
register_modifier(:topic_serializer_fancy_title) do |fancy_title, serializer|
74-
if !SiteSetting.experimental_topic_translation ||
75-
serializer.scope&.request&.params&.[]("show") == "original" ||
76-
serializer.object.locale_matches?(I18n.locale)
77-
fancy_title
78-
else
79-
serializer.object.translation_for(I18n.locale).presence&.then { |t| Topic.fancy_title(t) }
80-
end
81-
end
39+
DiscourseTranslator::DualTextTranslation.new.inject(self)
40+
DiscourseTranslator::InlineTranslation.new.inject(self)
8241

83-
register_modifier(:topic_view_serializer_fancy_title) do |fancy_title, serializer|
84-
if !SiteSetting.experimental_topic_translation ||
85-
serializer.scope&.request&.params&.[]("show") == "original" ||
86-
serializer.object.topic.locale_matches?(I18n.locale)
87-
fancy_title
88-
else
89-
serializer
90-
.object
91-
.topic
92-
.translation_for(I18n.locale)
93-
.presence
94-
&.then { |t| Topic.fancy_title(t) }
95-
end
96-
end
42+
DiscourseTranslator::AutomaticTranslations.new.inject(self)
9743
end

spec/jobs/detect_posts_language_spec.rb

Lines changed: 0 additions & 84 deletions
This file was deleted.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# frozen_string_literal: true
2+
3+
require "aws-sdk-translate"
4+
5+
describe Jobs::DetectTranslatableLanguage do
6+
fab!(:post)
7+
fab!(:topic)
8+
let!(:job) { Jobs::DetectTranslatableLanguage.new }
9+
10+
before do
11+
SiteSetting.translator_enabled = true
12+
SiteSetting.translator = "Amazon"
13+
client = Aws::Translate::Client.new(stub_responses: true)
14+
client.stub_responses(
15+
:translate_text,
16+
{ translated_text: "大丈夫", source_language_code: "en", target_language_code: "jp" },
17+
)
18+
Aws::Translate::Client.stubs(:new).returns(client)
19+
end
20+
21+
it "does nothing when type is not post or topic" do
22+
expect { job.execute(type: "X", translatable_id: 1) }.not_to raise_error
23+
end
24+
25+
it "does nothing when id is not int" do
26+
expect { job.execute(type: "Post", translatable_id: "A") }.not_to raise_error
27+
end
28+
29+
it "updates detected locale" do
30+
job.execute(type: "Post", translatable_id: post.id)
31+
job.execute(type: "Topic", translatable_id: topic.id)
32+
33+
expect(post.detected_locale).not_to be_nil
34+
expect(topic.detected_locale).not_to be_nil
35+
end
36+
37+
it "does not update detected locale the translator is disabled" do
38+
SiteSetting.translator_enabled = false
39+
40+
job.execute(type: "Post", translatable_id: post.id)
41+
job.execute(type: "Topic", translatable_id: topic.id)
42+
43+
expect(post.detected_locale).to be_nil
44+
expect(topic.detected_locale).to be_nil
45+
end
46+
47+
it "skips content that no longer exist" do
48+
non_existent_id = -1
49+
50+
expect { job.execute(type: "Post", translatable_id: non_existent_id) }.not_to raise_error
51+
expect { job.execute(type: "Topic", translatable_id: non_existent_id) }.not_to raise_error
52+
end
53+
end

spec/models/post_spec.rb

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,23 +73,19 @@
7373
fab!(:topic)
7474
fab!(:user) { Fabricate(:user, groups: [group]) }
7575

76-
before { Jobs.run_immediately! }
77-
7876
it "queues the post for language detection when user and posts are in the right group" do
7977
SiteSetting.restrict_translation_by_poster_group = "#{group.id}"
80-
post =
81-
PostCreator.new(
82-
user,
83-
{
84-
title: "a topic about cats",
85-
raw: "tomtom is a cat",
86-
category: Fabricate(:category).id,
87-
},
88-
).create
8978

90-
expect(
91-
Discourse.redis.sismember(DiscourseTranslator::LANG_DETECT_NEEDED, post.id),
92-
).to be_truthy
79+
post = Fabricate(:post, user: user)
80+
CookedPostProcessor.new(post).post_process
81+
82+
expect_job_enqueued(
83+
job: :detect_translatable_language,
84+
args: {
85+
type: "Post",
86+
translatable_id: post.id,
87+
},
88+
)
9389
end
9490

9591
it "does not queue bot posts for language detection" do

0 commit comments

Comments
 (0)