Skip to content

Commit c89a85a

Browse files
authored
DEV: Move language detection out of the post serializer (#193)
Language detection is added to the queue every time the post is serialized. We'll move this into the post_process_cooked event instead, since it is not a good idea to overload a serializer. This is a follow-up from the move for queueing translations to redis here 8fce768.
1 parent c13c494 commit c89a85a

File tree

5 files changed

+130
-71
lines changed

5 files changed

+130
-71
lines changed

lib/discourse_translator/guardian_extension.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,11 @@ def poster_group_allow_translate?(post)
1111
return false if post.user.nil?
1212
post.user.in_any_groups?(SiteSetting.restrict_translation_by_poster_group_map)
1313
end
14+
15+
def can_detect_language?(post)
16+
(
17+
SiteSetting.restrict_translation_by_poster_group_map.empty? ||
18+
post&.user&.in_any_groups?(SiteSetting.restrict_translation_by_poster_group_map)
19+
) && post.raw.present? && post.post_type != Post.types[:small_action]
20+
end
1421
end

plugin.rb

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,21 @@ module ::DiscourseTranslator
3737
Topic.prepend(DiscourseTranslator::TopicExtension)
3838
end
3939

40-
add_to_serializer :post, :can_translate do
41-
return false if !SiteSetting.translator_enabled
42-
if !scope.user_group_allow_translate? || !scope.poster_group_allow_translate?(object)
43-
return false
40+
on(:post_process_cooked) do |_, post|
41+
if Guardian.new.can_detect_language?(post)
42+
Discourse.redis.sadd?(DiscourseTranslator::LANG_DETECT_NEEDED, post.id)
4443
end
45-
return false if raw.blank? || post_type == Post.types[:small_action]
44+
end
45+
46+
add_to_serializer :post, :can_translate do
47+
return false if !scope.user_group_allow_translate?
4648

4749
detected_lang = post_custom_fields[::DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD]
50+
return false if detected_lang.blank?
4851

49-
if !detected_lang
50-
Discourse.redis.sadd?(DiscourseTranslator::LANG_DETECT_NEEDED, object.id)
51-
false
52-
else
53-
detected_lang.to_sym != I18n.locale &&
54-
"DiscourseTranslator::#{SiteSetting.translator}".constantize.language_supported?(
55-
detected_lang,
56-
)
57-
end
52+
detected_lang.to_sym != I18n.locale &&
53+
"DiscourseTranslator::#{SiteSetting.translator}".constantize.language_supported?(
54+
detected_lang,
55+
)
5856
end
5957
end

spec/lib/guardian_extension_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,40 @@
7777
end
7878
end
7979
end
80+
81+
describe "#can_detect_language?" do
82+
fab!(:group)
83+
fab!(:user) { Fabricate(:user, groups: [group]) }
84+
fab!(:post) { Fabricate(:post, user: user, raw: "Hello, world!") }
85+
let(:guardian) { Guardian.new(user) }
86+
87+
it "returns false when the post user is not in restrict_translation_by_poster_group" do
88+
SiteSetting.restrict_translation_by_poster_group = "#{Fabricate(:group).id}"
89+
90+
expect(guardian.can_detect_language?(post)).to eq(false)
91+
end
92+
93+
context "when post author is in allowed groups" do
94+
before do
95+
SiteSetting.restrict_translation_by_group = "#{group.id}"
96+
SiteSetting.restrict_translation_by_poster_group = "#{group.id}"
97+
end
98+
99+
it "returns true when the post is not a small action post" do
100+
expect(guardian.can_detect_language?(post)).to eq(true)
101+
end
102+
103+
it "returns false when the post is a small action post" do
104+
post.update!(post_type: Post.types[:small_action])
105+
106+
expect(guardian.can_detect_language?(post)).to eq(false)
107+
end
108+
109+
it "returns false when the post raw is empty" do
110+
expect { post.update(raw: "") }.to change { guardian.can_detect_language?(post) }.from(
111+
true,
112+
).to(false)
113+
end
114+
end
115+
end
80116
end

spec/models/post_spec.rb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,51 @@
2727
expect(post.custom_fields[::DiscourseTranslator::TRANSLATED_CUSTOM_FIELD]).to be_nil
2828
end
2929
end
30+
31+
describe "queueing post for language detection" do
32+
fab!(:group)
33+
fab!(:topic)
34+
fab!(:user) { Fabricate(:user, groups: [group]) }
35+
36+
before do
37+
Jobs.run_immediately!
38+
SiteSetting.create_topic_allowed_groups = Group::AUTO_GROUPS[:everyone]
39+
end
40+
41+
it "queues the post for language detection when user and posts are in the right group" do
42+
SiteSetting.restrict_translation_by_poster_group = "#{group.id}"
43+
post =
44+
PostCreator.new(
45+
user,
46+
{
47+
title: "a topic about cats",
48+
raw: "tomtom is a cat",
49+
category: Fabricate(:category).id,
50+
},
51+
).create
52+
53+
expect(
54+
Discourse.redis.sismember(DiscourseTranslator::LANG_DETECT_NEEDED, post.id),
55+
).to be_truthy
56+
end
57+
58+
context "when user and posts are not in the right group" do
59+
it "does not queue the post for language detection" do
60+
SiteSetting.restrict_translation_by_poster_group = "#{group.id + 1}"
61+
post =
62+
PostCreator.new(
63+
user,
64+
{
65+
title: "hello world topic",
66+
raw: "my name is fred",
67+
category: Fabricate(:category).id,
68+
},
69+
).create
70+
71+
expect(
72+
Discourse.redis.sismember(DiscourseTranslator::LANG_DETECT_NEEDED, post.id),
73+
).to be_falsey
74+
end
75+
end
76+
end
3077
end

spec/serializers/post_serializer_spec.rb

Lines changed: 28 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,22 @@
1212

1313
describe "#can_translate" do
1414
it "returns false when translator disabled" do
15-
SiteSetting.translator_enabled = true
15+
SiteSetting.translator_enabled = false
1616
serializer = PostSerializer.new(post, scope: Guardian.new)
1717

1818
expect(serializer.can_translate).to eq(false)
1919
end
2020

2121
describe "when translator enabled" do
22-
before do
23-
SiteSetting.translator_enabled = true
24-
Jobs.run_later!
25-
end
22+
before { SiteSetting.translator_enabled = true }
2623

27-
describe "when small action post" do
28-
fab!(:small_action)
29-
let(:serializer) { PostSerializer.new(small_action, scope: Guardian.new) }
24+
describe "anon user" do
25+
let(:serializer) { PostSerializer.new(post, scope: Guardian.new) }
3026

31-
it "cannot translate" do
32-
expect(serializer.can_translate).to eq(false)
27+
before do
28+
SiteSetting.restrict_translation_by_group = "#{Group::AUTO_GROUPS[:everyone]}"
29+
SiteSetting.restrict_translation_by_poster_group = ""
3330
end
34-
end
35-
36-
describe "when post raw is empty" do
37-
fab!(:empty_post) do
38-
empty_post = Fabricate.build(:post, raw: "")
39-
empty_post.save!(validate: false)
40-
empty_post
41-
end
42-
let(:serializer) { PostSerializer.new(empty_post, scope: Guardian.new) }
4331

4432
it "cannot translate" do
4533
expect(serializer.can_translate).to eq(false)
@@ -49,61 +37,44 @@
4937
describe "logged in user" do
5038
let(:serializer) { PostSerializer.new(post, scope: Guardian.new(user)) }
5139

52-
describe "when user is not in restrict_translation_by_group" do
53-
it "cannot translate" do
54-
SiteSetting.restrict_translation_by_group = ""
40+
it "cannot translate when user is not in restrict_translation_by_group" do
41+
SiteSetting.restrict_translation_by_group = "#{group.id + 1}"
5542

56-
expect(serializer.can_translate).to eq(false)
57-
end
43+
expect(serializer.can_translate).to eq(false)
5844
end
5945

60-
describe "when post is not in restrict_translation_by_poster_group" do
61-
it "cannot translate" do
62-
SiteSetting.restrict_translation_by_group = "#{group.id}"
63-
SiteSetting.restrict_translation_by_poster_group = ""
46+
describe "user is in restrict_translation_by_group" do
47+
before { SiteSetting.restrict_translation_by_group = "#{group.id}" }
6448

65-
expect(serializer.can_translate).to eq(false)
66-
end
67-
end
49+
it "cannot translate when post author is not in restrict_translation_by_poster_group" do
50+
SiteSetting.restrict_translation_by_poster_group = "#{group.id}"
6851

69-
describe "when user is in restrict_translation_by_group and poster in restrict_translation_by_poster_group" do
70-
before do
71-
SiteSetting.restrict_translation_by_group = "#{group.id}"
72-
SiteSetting.restrict_translation_by_poster_group = "#{post_user_group.id}"
52+
expect(serializer.can_translate).to eq(false)
7353
end
7454

75-
describe "when post does not have DETECTED_LANG_CUSTOM_FIELD" do
76-
it "cannot translate" do
77-
expect(serializer.can_translate).to eq(false)
55+
describe "post author in restrict_translation_by_poster_group and locale is :xx" do
56+
before do
57+
SiteSetting.restrict_translation_by_poster_group = "#{post_user_group.id}"
58+
I18n.stubs(:locale).returns(:pt)
7859
end
7960

80-
it "adds post id to redis if detected_language is blank" do
81-
post.custom_fields["detected_language"] = nil
82-
post.save_custom_fields
83-
84-
expect { serializer.can_translate }.to change {
85-
Discourse.redis.sismember(DiscourseTranslator::LANG_DETECT_NEEDED, post.id)
86-
}.from(false).to(true)
61+
it "cannot translate when post does not have DETECTED_LANG_CUSTOM_FIELD" do
62+
expect(serializer.can_translate).to eq(false)
8763
end
88-
end
8964

90-
describe "when post has DETECTED_LANG_CUSTOM_FIELD matches user locale" do
91-
before do
92-
I18n.stubs(:locale).returns(:xx)
93-
post.custom_fields[DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD] = "xx"
65+
it "cannot translate when post has DETECTED_LANG_CUSTOM_FIELD matches locale" do
66+
post.custom_fields[DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD] = "pt"
9467
post.save
95-
end
9668

97-
it { expect(serializer.can_translate).to eq(false) }
98-
end
69+
expect(serializer.can_translate).to eq(false)
70+
end
9971

100-
describe "when post has DETECTED_LANG_CUSTOM_FIELD does not match user locale" do
101-
before do
72+
it "can translate when post has DETECTED_LANG_CUSTOM_FIELD does not match locale" do
10273
post.custom_fields[DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD] = "jp"
10374
post.save
104-
end
10575

106-
it { expect(serializer.can_translate).to eq(true) }
76+
expect(serializer.can_translate).to eq(true)
77+
end
10778
end
10879
end
10980
end

0 commit comments

Comments
 (0)