Skip to content

Commit 8df7a49

Browse files
committed
Use effective locale for inline translation
1 parent 92b7d48 commit 8df7a49

File tree

8 files changed

+202
-146
lines changed

8 files changed

+202
-146
lines changed

assets/javascripts/discourse/components/show-original-content.gjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import concatClass from "discourse/helpers/concat-class";
77

88
export default class ShowOriginalContent extends Component {
99
static shouldRender(args) {
10-
return args.topic.is_translated;
10+
return (
11+
args.topic.is_translated ||
12+
args.topic.postStream.posts.some(({ is_translated }) => is_translated)
13+
);
1114
}
1215

1316
@service router;

lib/discourse_translator/guardian_extension.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@ def can_detect_language?(post)
2424
def can_translate?(post)
2525
return false if post.user&.bot?
2626
return false if !user_group_allow_translate?
27-
return false if post.locale_matches?(I18n.locale)
2827

2928
# we want to return false if the post is created within a short buffer ago,
3029
# this prevents the 🌐from appearing and then disappearing if the lang is same as user's lang
3130
return false if post.created_at > POST_DETECTION_BUFFER.ago && post.detected_locale.blank?
3231

3332
if SiteSetting.experimental_inline_translation
34-
post.translation_for(I18n.locale).nil?
33+
locale = DiscourseTranslator::InlineTranslation.effective_locale
34+
return false if post.locale_matches?(locale)
35+
post.translation_for(locale).nil?
3536
else
37+
return false if post.locale_matches?(I18n.locale)
3638
poster_group_allow_translate?(post)
3739
end
3840
end

lib/discourse_translator/inline_translation.rb

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,68 @@
22

33
module DiscourseTranslator
44
class InlineTranslation
5+
def self.effective_locale
6+
if LocaleMatcher.user_locale_is_default? || LocaleMatcher.user_locale_in_target_languages?
7+
I18n.locale
8+
else
9+
SiteSetting.default_locale
10+
end
11+
end
12+
513
def inject(plugin)
14+
# since locales are eager loaded but translations may not,
15+
# always return early if topic and posts are in the user's effective_locale.
16+
# this prevents the need to load translations.
17+
618
plugin.register_modifier(:basic_post_serializer_cooked) do |cooked, serializer|
719
if !SiteSetting.experimental_inline_translation ||
8-
serializer.scope&.request&.params&.[]("show") == "original" ||
9-
serializer.object.detected_locale == I18n.locale.to_s.gsub("_", "-")
20+
serializer.object.locale_matches?(InlineTranslation.effective_locale) ||
21+
serializer.scope&.request&.params&.[]("show") == "original"
1022
cooked
1123
else
12-
serializer.object.translation_for(I18n.locale).presence
24+
serializer.object.translation_for(InlineTranslation.effective_locale).presence
1325
end
1426
end
1527

1628
plugin.register_modifier(:topic_serializer_fancy_title) do |fancy_title, serializer|
1729
if !SiteSetting.experimental_inline_translation ||
18-
serializer.scope&.request&.params&.[]("show") == "original" ||
19-
serializer.object.locale_matches?(I18n.locale)
30+
serializer.object.locale_matches?(InlineTranslation.effective_locale) ||
31+
serializer.scope&.request&.params&.[]("show") == "original"
2032
fancy_title
2133
else
22-
serializer.object.translation_for(I18n.locale).presence&.then { |t| Topic.fancy_title(t) }
34+
serializer
35+
.object
36+
.translation_for(InlineTranslation.effective_locale)
37+
.presence
38+
&.then { |t| Topic.fancy_title(t) }
2339
end
2440
end
2541

2642
plugin.register_modifier(:topic_view_serializer_fancy_title) do |fancy_title, serializer|
2743
if !SiteSetting.experimental_inline_translation ||
28-
serializer.scope&.request&.params&.[]("show") == "original" ||
29-
serializer.object.topic.locale_matches?(I18n.locale)
44+
serializer.object.topic.locale_matches?(InlineTranslation.effective_locale) ||
45+
serializer.scope&.request&.params&.[]("show") == "original"
3046
fancy_title
3147
else
3248
serializer
3349
.object
3450
.topic
35-
.translation_for(I18n.locale)
51+
.translation_for(InlineTranslation.effective_locale)
3652
.presence
3753
&.then { |t| Topic.fancy_title(t) }
3854
end
3955
end
4056

41-
plugin.add_to_serializer(
42-
:basic_post,
43-
:is_translated,
44-
include_condition: -> { SiteSetting.experimental_inline_translation },
45-
) { !object.locale_matches?(I18n.locale) && object.translation_for(I18n.locale).present? }
46-
47-
plugin.add_to_serializer(
48-
:topic_view,
49-
:is_translated,
50-
include_condition: -> { SiteSetting.experimental_inline_translation },
51-
) do
52-
# since locales are eager loaded, but translations may not
53-
# return early if topic and posts are all in the user's locale
54-
if object.topic.locale_matches?(I18n.locale) &&
55-
object.posts.all? { |p| p.locale_matches?(I18n.locale) }
56-
return false
57-
end
57+
plugin.add_to_serializer(:basic_post, :is_translated) do
58+
SiteSetting.experimental_inline_translation &&
59+
!object.locale_matches?(InlineTranslation.effective_locale) &&
60+
object.translation_for(InlineTranslation.effective_locale).present?
61+
end
5862

59-
object.topic.translation_for(I18n.locale).present? ||
60-
object.posts.any? { |p| p.translation_for(I18n.locale).present? }
63+
plugin.add_to_serializer(:topic_view, :is_translated) do
64+
SiteSetting.experimental_inline_translation &&
65+
!object.topic.locale_matches?(InlineTranslation.effective_locale) &&
66+
object.topic.translation_for(InlineTranslation.effective_locale).present?
6167
end
6268
end
6369
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# frozen_string_literal: true
2+
3+
module DiscourseTranslator
4+
class LocaleMatcher
5+
def self.user_locale_in_target_languages?
6+
# e.g. "en|es|pt_BR" vs :en_UK
7+
SiteSetting.automatic_translation_target_languages.split("|").include?(I18n.locale.to_s)
8+
end
9+
10+
def self.user_locale_is_default?
11+
# e.g. :en_UK vs "en_UK"
12+
I18n.locale.to_s == SiteSetting.default_locale
13+
end
14+
end
15+
end

lib/discourse_translator/topic_view_serializer_extension.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ def posts
88
# this is kind of a micro-optimization.
99
# we do not want to eager load translations if the user is using the site's language.
1010
# we will only load them if the user is using a different language that is supported by the site.
11-
posts_query =
12-
posts_query.includes(:translations) if SiteSetting.experimental_inline_translation &&
13-
(
14-
I18n.locale.to_s != SiteSetting.default_locale &&
15-
SiteSetting
16-
.automatic_translation_target_languages
17-
.split("|")
18-
.include?(I18n.locale.to_s)
19-
)
11+
if SiteSetting.experimental_inline_translation && !LocaleMatcher.user_locale_is_default? &&
12+
LocaleMatcher.user_locale_in_target_languages?
13+
posts_query =
14+
posts_query.includes(:translations).where(
15+
translations: {
16+
locale: InlineTranslation.effective_locale.to_s.gsub("_", "-"),
17+
},
18+
)
19+
end
2020
object.instance_variable_set(:@posts, posts_query)
2121
end
2222
super

spec/serializers/post_serializer_spec.rb

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,11 @@
7474
expect(serializer.is_translated).to eq(false)
7575
end
7676

77-
it "returns true when there is a translation for the current locale" do
77+
it "returns true when there is a translation for the user's locale in target languages" do
7878
SiteSetting.translator_enabled = true
7979
SiteSetting.experimental_inline_translation = true
80+
SiteSetting.automatic_translation_backfill_maximum_translations_per_hour = 1
81+
SiteSetting.automatic_translation_target_languages = "ja"
8082
I18n.locale = "ja"
8183
post.set_detected_locale("en")
8284
post.set_translation("ja", "こんにちは")
@@ -85,9 +87,24 @@
8587
expect(serializer.is_translated).to eq(true)
8688
end
8789

88-
it "returns false when there is no translation for the current locale" do
90+
it "returns false when there is a translation for the user's locale not in target languages" do
8991
SiteSetting.translator_enabled = true
9092
SiteSetting.experimental_inline_translation = true
93+
SiteSetting.automatic_translation_backfill_maximum_translations_per_hour = 1
94+
SiteSetting.automatic_translation_target_languages = "es"
95+
I18n.locale = "ja"
96+
post.set_detected_locale("en")
97+
post.set_translation("ja", "こんにちは")
98+
serializer = PostSerializer.new(post, scope: Guardian.new)
99+
100+
expect(serializer.is_translated).to eq(false)
101+
end
102+
103+
it "returns false when there is no translation for the current locale in target languages" do
104+
SiteSetting.translator_enabled = true
105+
SiteSetting.experimental_inline_translation = true
106+
SiteSetting.automatic_translation_backfill_maximum_translations_per_hour = 1
107+
SiteSetting.automatic_translation_target_languages = "ja"
91108
I18n.locale = "ja"
92109
post.set_translation("es", "Hola")
93110
serializer = PostSerializer.new(post, scope: Guardian.new)
@@ -116,6 +133,8 @@ def serialize_post(guardian_user: user, params: {})
116133

117134
it "does not return translated_cooked when show=original param is present" do
118135
I18n.locale = "ja"
136+
SiteSetting.automatic_translation_backfill_maximum_translations_per_hour = 1
137+
SiteSetting.automatic_translation_target_languages = "ja"
119138
post.set_translation("ja", "こんにちは")
120139

121140
expect(serialize_post(params: { "show" => "original" }).cooked).to eq(post.cooked)
@@ -130,11 +149,17 @@ def serialize_post(guardian_user: user, params: {})
130149
expect(serialize_post.cooked).to eq(post.cooked)
131150
end
132151

133-
it "returns translated content based on locale" do
134-
I18n.locale = "ja"
152+
it "returns translated content based on locale presence in target languages" do
153+
SiteSetting.automatic_translation_backfill_maximum_translations_per_hour = 1
135154
post.set_translation("ja", "こんにちは")
136155
post.set_translation("es", "Hola")
156+
I18n.locale = "ja"
157+
158+
SiteSetting.automatic_translation_target_languages = "ja"
137159
expect(serialize_post.cooked).to eq("こんにちは")
160+
161+
SiteSetting.automatic_translation_target_languages = "es"
162+
expect(serialize_post.cooked).to eq(post.cooked)
138163
end
139164

140165
it "does not return translated_cooked when plugin is disabled" do

0 commit comments

Comments
 (0)