Skip to content

Commit 4c5d8e7

Browse files
committed
DEV: Move saving of translations into base class
1 parent f7d6ca6 commit 4c5d8e7

File tree

10 files changed

+153
-169
lines changed

10 files changed

+153
-169
lines changed

app/jobs/scheduled/detect_posts_language.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ def process_batch(post_ids)
2626
begin
2727
translator = "DiscourseTranslator::#{SiteSetting.translator}".constantize
2828
translator.detect(post)
29-
if !post.custom_fields_clean?
30-
post.save_custom_fields
31-
post.publish_change_to_clients!(:revised)
32-
end
3329
rescue ::DiscourseTranslator::ProblemCheckedTranslationError
3430
# problem-checked translation errors gracefully
3531
end

app/services/discourse_translator/amazon.rb

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -107,47 +107,41 @@ def self.access_token_key
107107
"aws-translator"
108108
end
109109

110-
def self.detect(topic_or_post)
111-
text = truncate text_for_detection(topic_or_post)
112-
return if text.blank?
113-
114-
topic_or_post.custom_fields[DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD] ||= (
110+
def self.detect!(topic_or_post)
111+
save_detected_locale(topic_or_post) do
115112
begin
116113
client.translate_text(
117114
{
118-
text: text,
115+
text: truncate(text_for_detection(topic_or_post)),
119116
source_language_code: "auto",
120117
target_language_code: SUPPORTED_LANG_MAPPING[I18n.locale],
121118
},
122119
)&.source_language_code
123120
rescue Aws::Errors::MissingCredentialsError
124121
raise I18n.t("translator.amazon.invalid_credentials")
125122
end
126-
)
123+
end
127124
end
128125

129-
def self.translate(topic_or_post)
126+
def self.translate!(topic_or_post)
130127
detected_lang = detect(topic_or_post)
131128

132-
from_custom_fields(topic_or_post) do
129+
save_translation(topic_or_post) do
133130
begin
134-
result =
135-
client.translate_text(
136-
{
137-
text: truncate(text_for_translation(topic_or_post)),
138-
source_language_code: "auto",
139-
target_language_code: SUPPORTED_LANG_MAPPING[I18n.locale],
140-
},
141-
)
131+
client.translate_text(
132+
{
133+
text: truncate(text_for_translation(topic_or_post)),
134+
source_language_code: "auto",
135+
target_language_code: SUPPORTED_LANG_MAPPING[I18n.locale],
136+
},
137+
)
142138
rescue Aws::Translate::Errors::UnsupportedLanguagePairException
143139
raise I18n.t(
144140
"translator.failed",
145141
source_locale: detected_lang,
146142
target_locale: I18n.locale,
147143
)
148144
end
149-
150-
[detected_lang, result.translated_text]
151145
end
152146
end
153147

app/services/discourse_translator/base.rb

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,53 @@ def self.cache_key
2424
"#{key_prefix}#{access_token_key}"
2525
end
2626

27-
def self.translate(post)
27+
def self.translate(topic_or_post)
28+
return if text_for_translation(topic_or_post).blank?
29+
detected_lang = detect(topic_or_post)
30+
31+
return detected_lang, get_text(topic_or_post) if (detected_lang&.to_s.eql? I18n.locale.to_s)
32+
unless translate_supported?(detected_lang, I18n.locale)
33+
raise TranslatorError.new(
34+
I18n.t(
35+
"translator.failed",
36+
source_locale: detected_lang,
37+
target_locale: I18n.locale,
38+
),
39+
)
40+
end
41+
42+
translated_text = translate!(topic_or_post)
43+
44+
[detected_lang, translated_text]
45+
end
46+
47+
def self.translate!(post)
2848
raise "Not Implemented"
2949
end
3050

31-
def self.detect(post)
51+
# Returns the stored detected locale of a post or topic.
52+
# If the locale does not exist yet, it will be detected first via the API then stored.
53+
# @param topic_or_post [Post|Topic]
54+
def self.detect(topic_or_post)
55+
return if text_for_detection(topic_or_post).blank?
56+
get_detected_locale(topic_or_post) || detect!(topic_or_post)
57+
end
58+
59+
def self.detect!(post)
3260
raise "Not Implemented"
3361
end
3462

3563
def self.access_token
3664
raise "Not Implemented"
3765
end
3866

39-
def self.from_custom_fields(topic_or_post)
67+
def self.get_translation(topic_or_post)
68+
translated_custom_field =
69+
topic_or_post.custom_fields[DiscourseTranslator::TRANSLATED_CUSTOM_FIELD] || {}
70+
translated_custom_field[I18n.locale]
71+
end
72+
73+
def self.save_translation(topic_or_post)
4074
translated_custom_field =
4175
topic_or_post.custom_fields[DiscourseTranslator::TRANSLATED_CUSTOM_FIELD] || {}
4276
translated_text = translated_custom_field[I18n.locale]
@@ -54,6 +88,22 @@ def self.from_custom_fields(topic_or_post)
5488
translated_text
5589
end
5690

91+
def self.get_detected_locale(topic_or_post)
92+
topic_or_post.custom_fields[DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD]
93+
end
94+
95+
def self.save_detected_locale(topic_or_post)
96+
detected_locale = yield
97+
topic_or_post.custom_fields[DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD] = detected_locale
98+
99+
if !topic_or_post.custom_fields_clean?
100+
topic_or_post.save_custom_fields
101+
topic_or_post.publish_change_to_clients!(:revised) if topic_or_post.class.name == "Post"
102+
end
103+
104+
detected_locale
105+
end
106+
57107
def self.get_text(topic_or_post)
58108
case topic_or_post.class.name
59109
when "Post"
@@ -70,6 +120,10 @@ def self.language_supported?(detected_lang)
70120
detected_lang != supported_lang[I18n.locale]
71121
end
72122

123+
def self.translate_supported?(detected_lang, target_lang)
124+
true
125+
end
126+
73127
private
74128

75129
def self.strip_tags_for_detection(detection_text)

app/services/discourse_translator/discourse_ai.rb

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,20 @@ def self.language_supported?(detected_lang)
1111
detected_lang != locale_without_region
1212
end
1313

14-
def self.detect(topic_or_post)
14+
def self.detect!(topic_or_post)
1515
return unless required_settings_enabled
1616

17-
topic_or_post.custom_fields[DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD] ||= begin
17+
save_detected_locale(topic_or_post) do
1818
::DiscourseAi::LanguageDetector.new(text_for_detection(topic_or_post)).detect
1919
end
20-
rescue => e
21-
Rails.logger.warn(
22-
"#{::DiscourseTranslator::PLUGIN_NAME}: Failed to detect language for #{topic_or_post.class.name} #{topic_or_post.id}: #{e}",
23-
)
2420
end
2521

2622
def self.translate(topic_or_post)
2723
return unless required_settings_enabled
2824

2925
detected_lang = detect(topic_or_post)
3026
translated_text =
31-
from_custom_fields(topic_or_post) do
27+
save_translation(topic_or_post) do
3228
::DiscourseAi::Translator.new(text_for_translation(topic_or_post), I18n.locale).translate
3329
end
3430

app/services/discourse_translator/google.rb

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -74,54 +74,33 @@ def self.access_token
7474
raise ProblemCheckedTranslationError.new("NotFound: Google Api Key not set.")
7575
end
7676

77-
def self.detect(topic_or_post)
78-
topic_or_post.custom_fields[DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD] ||= result(
79-
DETECT_URI,
80-
q: text_for_detection(topic_or_post),
81-
)[
82-
"detections"
83-
][
84-
0
85-
].max { |a, b| a.confidence <=> b.confidence }[
86-
"language"
87-
]
77+
def self.detect!(topic_or_post)
78+
save_detected_locale(topic_or_post) do
79+
result(DETECT_URI, q: text_for_detection(topic_or_post))["detections"][0].max do |a, b|
80+
a.confidence <=> b.confidence
81+
end[
82+
"language"
83+
]
84+
end
8885
end
8986

9087
def self.translate_supported?(source, target)
9188
res = result(SUPPORT_URI, target: SUPPORTED_LANG_MAPPING[target])
9289
res["languages"].any? { |obj| obj["language"] == source }
9390
end
9491

95-
def self.translate(topic_or_post)
96-
detected_lang = detect(topic_or_post)
97-
98-
# the translate button appears if a given post is in a foreign language.
99-
# however the title of the topic may be in a different language, and may be in the user's language.
100-
# if this is the case, when this is called for a topic, the detected_lang will be the user's language,
101-
# so the user's language and the detected language will be the same. For example, both could be "en"
102-
# google will choke on this and return an error instead of gracefully handling it by returning the original
103-
# string.
104-
# ---
105-
# here we handle that situation by returning the original string if the source and target lang are the same.
106-
return detected_lang, get_text(topic_or_post) if (detected_lang&.to_s.eql? I18n.locale.to_s)
107-
108-
unless translate_supported?(detected_lang, I18n.locale)
109-
raise I18n.t("translator.failed", source_locale: detected_lang, target_locale: I18n.locale)
92+
def self.translate!(topic_or_post)
93+
detected_locale = detect(topic_or_post)
94+
save_translation(topic_or_post) do
95+
res =
96+
result(
97+
TRANSLATE_URI,
98+
q: text_for_translation(topic_or_post),
99+
source: detected_locale,
100+
target: SUPPORTED_LANG_MAPPING[I18n.locale],
101+
)
102+
res["translations"][0]["translatedText"]
110103
end
111-
112-
translated_text =
113-
from_custom_fields(topic_or_post) do
114-
res =
115-
result(
116-
TRANSLATE_URI,
117-
q: text_for_translation(topic_or_post),
118-
source: detected_lang,
119-
target: SUPPORTED_LANG_MAPPING[I18n.locale],
120-
)
121-
res["translations"][0]["translatedText"]
122-
end
123-
124-
[detected_lang, translated_text]
125104
end
126105

127106
def self.result(url, body)

app/services/discourse_translator/libre_translate.rb

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,14 @@ def self.access_token
7878
SiteSetting.translator_libretranslate_api_key
7979
end
8080

81-
def self.detect(topic_or_post)
82-
res =
83-
result(
84-
detect_uri,
85-
q: ActionController::Base.helpers.strip_tags(text_for_detection(topic_or_post)),
86-
)
87-
88-
if !res.empty?
89-
topic_or_post.custom_fields[DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD] ||= res[0][
90-
"language"
91-
]
92-
else
93-
topic_or_post.custom_fields[DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD] ||= "en"
81+
def self.detect!(topic_or_post)
82+
save_detected_locale(topic_or_post) do
83+
res =
84+
result(
85+
detect_uri,
86+
q: ActionController::Base.helpers.strip_tags(text_for_detection(topic_or_post)),
87+
)
88+
!res.empty? ? res[0]["language"] : "en"
9489
end
9590
end
9691

@@ -100,27 +95,20 @@ def self.translate_supported?(source, target)
10095
res.any? { |obj| obj["code"] == source } && res.any? { |obj| obj["code"] == lang }
10196
end
10297

103-
def self.translate(topic_or_post)
98+
def self.translate!(topic_or_post)
10499
detected_lang = detect(topic_or_post)
105100

106-
unless translate_supported?(detected_lang, I18n.locale)
107-
raise I18n.t("translator.failed", source_locale: detected_lang, target_locale: I18n.locale)
101+
save_translation(topic_or_post) do
102+
res =
103+
result(
104+
translate_uri,
105+
q: text_for_translation(topic_or_post),
106+
source: detected_lang,
107+
target: SUPPORTED_LANG_MAPPING[I18n.locale],
108+
format: "html",
109+
)
110+
res["translatedText"]
108111
end
109-
110-
translated_text =
111-
from_custom_fields(topic_or_post) do
112-
res =
113-
result(
114-
translate_uri,
115-
q: text_for_translation(topic_or_post),
116-
source: detected_lang,
117-
target: SUPPORTED_LANG_MAPPING[I18n.locale],
118-
format: "html",
119-
)
120-
res["translatedText"]
121-
end
122-
123-
[detected_lang, translated_text]
124112
end
125113

126114
def self.get(url)

0 commit comments

Comments
 (0)