diff --git a/app/jobs/scheduled/automatic_translation_backfill.rb b/app/jobs/scheduled/automatic_translation_backfill.rb
index d1d6d51f..eccd46a9 100644
--- a/app/jobs/scheduled/automatic_translation_backfill.rb
+++ b/app/jobs/scheduled/automatic_translation_backfill.rb
@@ -101,7 +101,7 @@ def process_batch
backfill_locales.each_with_index do |target_locale, i|
topic_ids =
fetch_untranslated_model_ids(Topic, "title", records_to_translate, target_locale)
- post_ids = fetch_untranslated_model_ids(Post, "cooked", records_to_translate, target_locale)
+ post_ids = fetch_untranslated_model_ids(Post, "raw", records_to_translate, target_locale)
# if we end up translating fewer records than records_to_translate,
# add to the value so that the next locales can have more quota
diff --git a/app/models/concerns/discourse_translator/translatable.rb b/app/models/concerns/discourse_translator/translatable.rb
index 1a2dbaf1..299bcd96 100644
--- a/app/models/concerns/discourse_translator/translatable.rb
+++ b/app/models/concerns/discourse_translator/translatable.rb
@@ -24,7 +24,6 @@ def set_detected_locale(locale)
# @param text [String] the translated text
def set_translation(locale, text)
locale = locale.to_s.gsub("_", "-")
- text = DiscourseTranslator::TranslatedContentSanitizer.sanitize(text)
translations.find_or_initialize_by(locale: locale).update!(translation: text)
end
diff --git a/app/services/discourse_ai/language_detector.rb b/app/services/discourse_ai/language_detector.rb
index 6357fd0c..ac558910 100644
--- a/app/services/discourse_ai/language_detector.rb
+++ b/app/services/discourse_ai/language_detector.rb
@@ -3,11 +3,12 @@
module DiscourseAi
class LanguageDetector
PROMPT_TEXT = <<~TEXT
- I want you to act as a language expert, determining the locale for a set of text.
- The locale is a language identifier, such as "en" for English, "de" for German, etc,
- and can also include a region identifier, such as "en-GB" for British English, or "zh-Hans" for Simplified Chinese.
- I will provide you with text, and you will determine the locale of the text.
- Include your locale between XML tags.
+ You are a language expert and will determine the locale for user-written content.
+ - the locale is a language identifier, such as "en" for English, "de" for German, or "zh-CN" for Simplified Chinese, etc.
+ - use the vocabulary and grammar of content to determine the locale
+ - do not use links or code to determine the locale
+ - do not write explanations
+ - only return the locale
TEXT
def initialize(text)
@@ -21,14 +22,13 @@ def detect
messages: [{ type: :user, content: @text, id: "user" }],
)
- response =
+ locale =
DiscourseAi::Completions::Llm.proxy(SiteSetting.ai_helper_model).generate(
prompt,
user: Discourse.system_user,
feature_name: "translator-language-detect",
)
-
- (Nokogiri::HTML5.fragment(response).at("language")&.text || response)
+ locale&.strip
end
end
end
diff --git a/app/services/discourse_ai/translator.rb b/app/services/discourse_ai/translator.rb
index 53a2051b..d3f181ee 100644
--- a/app/services/discourse_ai/translator.rb
+++ b/app/services/discourse_ai/translator.rb
@@ -3,13 +3,14 @@
module DiscourseAi
class Translator
PROMPT_TEMPLATE = <<~TEXT.freeze
- You are a highly skilled linguist of many languages and have expert knowledge in HTML.
- Your task is to identify the language of the text I provide and accurately translate it into this language locale "%{target_language}" while preserving the meaning, tone, and nuance of the original text.
- The text may or may not contain html tags. If they do, preserve them.
- Maintain proper grammar, spelling, and punctuation in the translated version.
- You will find the text between XML tags.
- Include your translation between XML tags.
- Do not write explanations.
+ You are an expert translator specializing in converting Markdown content from any source language to target locale "%{target_language}". Your task is to:
+ 1. Translate the content accurately while preserving all Markdown formatting elements
+ 2. Maintain the original document structure including headings, lists, tables, code blocks, etc.
+ 3. Preserve all links, images, and other media references without translation
+ 4. Handle code snippets appropriately - don't translate variable names, functions, or syntax within code blocks (```), but translate comments
+ 5. When encountering technical terminology, provide the accepted target language term if it exists, or transliterate if no equivalent exists, with the original term in parentheses
+ 6. For ambiguous terms or phrases, choose the most contextually appropriate translation
+ 7. You are being consumed via an API, only EVER return the translated text, do not return any other information
TEXT
def initialize(text, target_language)
@@ -21,17 +22,14 @@ def translate
prompt =
DiscourseAi::Completions::Prompt.new(
build_prompt(@target_language),
- messages: [{ type: :user, content: "#{@text}", id: "user" }],
+ messages: [{ type: :user, content: "#{@text}", id: "user" }],
)
- llm_translation =
- DiscourseAi::Completions::Llm.proxy(SiteSetting.ai_helper_model).generate(
- prompt,
- user: Discourse.system_user,
- feature_name: "translator-translate",
- )
-
- (Nokogiri::HTML5.fragment(llm_translation).at("output")&.inner_html || "").strip
+ DiscourseAi::Completions::Llm.proxy(SiteSetting.ai_helper_model).generate(
+ prompt,
+ user: Discourse.system_user,
+ feature_name: "translator-translate",
+ )
end
private
diff --git a/app/services/discourse_translator/base.rb b/app/services/discourse_translator/base.rb
index eac1d435..3ab0595d 100644
--- a/app/services/discourse_translator/base.rb
+++ b/app/services/discourse_translator/base.rb
@@ -33,7 +33,7 @@ def self.translate(translatable, target_locale_sym = I18n.locale)
detected_lang = detect(translatable)
if translatable.locale_matches?(target_locale_sym)
- return detected_lang, get_untranslated(translatable)
+ return detected_lang, get_untranslated_cooked(translatable)
end
translation = translatable.translation_for(target_locale_sym)
@@ -50,7 +50,9 @@ def self.translate(translatable, target_locale_sym = I18n.locale)
end
translated = translate!(translatable, target_locale_sym)
- save_translation(translatable, target_locale_sym) { translated }
+ save_translation(translatable, target_locale_sym) do
+ TranslatedContentNormalizer.normalize(translatable, translated)
+ end
[detected_lang, translated]
end
@@ -122,25 +124,25 @@ def self.translate_supported?(detected_lang, target_lang)
private
- def self.strip_tags_for_detection(detection_text)
- html_doc = Nokogiri::HTML::DocumentFragment.parse(detection_text)
- html_doc.css("img", "aside.quote", "div.lightbox-wrapper", "a.mention,a.lightbox").remove
- html_doc.to_html
- end
-
def self.text_for_detection(translatable)
- strip_tags_for_detection(get_untranslated(translatable)).truncate(
- DETECTION_CHAR_LIMIT,
- omission: nil,
- )
+ get_untranslated_raw(translatable).truncate(DETECTION_CHAR_LIMIT, omission: nil)
end
def self.text_for_translation(translatable)
max_char = SiteSetting.max_characters_per_translation
- get_untranslated(translatable).truncate(max_char, omission: nil)
+ get_untranslated_raw(translatable).truncate(max_char, omission: nil)
+ end
+
+ def self.get_untranslated_raw(translatable)
+ case translatable.class.name
+ when "Post"
+ translatable.raw
+ when "Topic"
+ translatable.title
+ end
end
- def self.get_untranslated(translatable)
+ def self.get_untranslated_cooked(translatable)
case translatable.class.name
when "Post"
translatable.cooked
diff --git a/lib/discourse_translator/translated_content_normalizer.rb b/lib/discourse_translator/translated_content_normalizer.rb
new file mode 100644
index 00000000..24884f55
--- /dev/null
+++ b/lib/discourse_translator/translated_content_normalizer.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module DiscourseTranslator
+ class TranslatedContentNormalizer
+ def self.normalize(translatable, content)
+ case translatable.class.name
+ when "Post"
+ PrettyText.cook(content)
+ when "Topic"
+ PrettyText.cleanup(content, {})
+ end
+ end
+ end
+end
diff --git a/lib/discourse_translator/translated_content_sanitizer.rb b/lib/discourse_translator/translated_content_sanitizer.rb
deleted file mode 100644
index 5e028697..00000000
--- a/lib/discourse_translator/translated_content_sanitizer.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-module DiscourseTranslator
- class TranslatedContentSanitizer
- def self.sanitize(content)
- PrettyText.cleanup(content, {})
- end
- end
-end
diff --git a/lib/discourse_translator/translator_selection_validator.rb b/lib/discourse_translator/translator_selection_validator.rb
index 68835b05..f63a9aca 100644
--- a/lib/discourse_translator/translator_selection_validator.rb
+++ b/lib/discourse_translator/translator_selection_validator.rb
@@ -20,7 +20,9 @@ def valid_value?(val)
def error_message
return I18n.t("translator.discourse_ai.not_installed") if !defined?(::DiscourseAi)
- I18n.t("translator.discourse_ai.ai_helper_required") if !SiteSetting.ai_helper_enabled
+ if !SiteSetting.ai_helper_enabled
+ I18n.t("translator.discourse_ai.ai_helper_required", { base_url: Discourse.base_url })
+ end
end
end
end
diff --git a/spec/jobs/automatic_translation_backfill_spec.rb b/spec/jobs/automatic_translation_backfill_spec.rb
index f91183b8..86efa1e4 100644
--- a/spec/jobs/automatic_translation_backfill_spec.rb
+++ b/spec/jobs/automatic_translation_backfill_spec.rb
@@ -102,7 +102,7 @@ def expect_google_translate(text)
described_class.new.execute
expect(topic.translations.pluck(:locale, :translation)).to eq([%w[es hola]])
- expect(post.translations.pluck(:locale, :translation)).to eq([%w[de hallo]])
+ expect(post.translations.pluck(:locale, :translation)).to eq([%w[de
]] * 4,
)
end
end
@@ -176,27 +176,27 @@ def expect_google_translate(text)
post_1.update!(updated_at: 2.days.ago)
post_2.update!(updated_at: 3.days.ago)
- result = described_class.new.fetch_untranslated_model_ids(Post, "cooked", 50, "de")
+ result = described_class.new.fetch_untranslated_model_ids(Post, "raw", 50, "de")
expect(result).to include(post_6.id, post_1.id, post_2.id)
end
it "does not return posts that are deleted" do
post_1.trash!
- result = described_class.new.fetch_untranslated_model_ids(Post, "cooked", 50, "de")
+ result = described_class.new.fetch_untranslated_model_ids(Post, "raw", 50, "de")
expect(result).not_to include(post_1.id)
end
it "does not return posts that are empty" do
- post_1.cooked = ""
+ post_1.raw = ""
post_1.save!(validate: false)
- result = described_class.new.fetch_untranslated_model_ids(Post, "cooked", 50, "de")
+ result = described_class.new.fetch_untranslated_model_ids(Post, "raw", 50, "de")
expect(result).not_to include(post_1.id)
end
it "does not return posts by bots" do
post_1.update(user: Discourse.system_user)
- result = described_class.new.fetch_untranslated_model_ids(Post, "cooked", 50, "de")
+ result = described_class.new.fetch_untranslated_model_ids(Post, "raw", 50, "de")
expect(result).not_to include(post_1.id)
end
diff --git a/spec/lib/translated_content_normalizer_spec.rb b/spec/lib/translated_content_normalizer_spec.rb
new file mode 100644
index 00000000..b22eec19
--- /dev/null
+++ b/spec/lib/translated_content_normalizer_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+describe DiscourseTranslator::TranslatedContentNormalizer do
+ fab!(:post)
+ fab!(:topic)
+
+ it "normalizes the content" do
+ expect(
+ DiscourseTranslator::TranslatedContentNormalizer.normalize(
+ post,
+ "
Testing
This is a test post",
+ ),
+ ).to eq("
Testing
This is a test post")
+
+ expect(
+ DiscourseTranslator::TranslatedContentNormalizer.normalize(
+ topic,
+ "
Testing
This is a test post",
+ ),
+ ).to eq("
Testing
This is a test post")
+ end
+end
diff --git a/spec/lib/translated_content_sanitizer_spec.rb b/spec/lib/translated_content_sanitizer_spec.rb
deleted file mode 100644
index 8fb4e347..00000000
--- a/spec/lib/translated_content_sanitizer_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-describe DiscourseTranslator::TranslatedContentSanitizer do
- it "sanitizes the content" do
- sanitized =
- DiscourseTranslator::TranslatedContentSanitizer.sanitize(
- "
Testing
This is a test post",
- )
-
- expect(sanitized).to eq("
Testing
This is a test post")
- end
-end
diff --git a/spec/lib/translator_selection_validator_spec.rb b/spec/lib/translator_selection_validator_spec.rb
index de7c898c..27dc29c5 100644
--- a/spec/lib/translator_selection_validator_spec.rb
+++ b/spec/lib/translator_selection_validator_spec.rb
@@ -61,7 +61,7 @@
it "returns the ai_helper_required error message" do
SiteSetting.ai_helper_enabled = false
expect(described_class.new.error_message).to eq(
- I18n.t("translator.discourse_ai.ai_helper_required"),
+ I18n.t("translator.discourse_ai.ai_helper_required", { base_url: Discourse.base_url }),
)
end
end
diff --git a/spec/services/amazon_spec.rb b/spec/services/amazon_spec.rb
index d8b4e0fd..c7f1ac2a 100644
--- a/spec/services/amazon_spec.rb
+++ b/spec/services/amazon_spec.rb
@@ -19,7 +19,7 @@
describe ".detect" do
let(:post) { Fabricate(:post) }
let!(:client) { Aws::Translate::Client.new(stub_responses: true) }
- let(:text) { described_class.truncate(post.cooked) }
+ let(:text) { described_class.truncate(post.raw) }
let(:detected_lang) { "en" }
before do
@@ -40,8 +40,8 @@
expect(post.detected_locale).to eq(detected_lang)
end
- it "should fail graciously when the cooked translated text is blank" do
- post.cooked = ""
+ it "should fail graciously when the raw translated text is blank" do
+ post.raw = ""
expect(described_class.detect(post)).to be_nil
end
end
diff --git a/spec/services/base_spec.rb b/spec/services/base_spec.rb
index 22785d93..0db60829 100644
--- a/spec/services/base_spec.rb
+++ b/spec/services/base_spec.rb
@@ -36,64 +36,23 @@ class EmptyTranslator < DiscourseTranslator::Base
describe ".text_for_detection" do
fab!(:post)
- it "strips img tags" do
- post.cooked = ""
- expect(DiscourseTranslator::Base.text_for_detection(post)).to eq("")
- end
-
- it "strips @ mention anchor tags" do
- post.cooked = "cat"
- expect(DiscourseTranslator::Base.text_for_detection(post)).to eq("")
- end
-
- it "strips lightbox anchor tags" do
- post.cooked = ""
- expect(DiscourseTranslator::Base.text_for_detection(post)).to eq("")
- end
-
- it "strips lightboxes" do
- post.cooked = ""
- expect(DiscourseTranslator::Base.text_for_detection(post)).to eq("")
- end
-
- it "strips quotes" do
- post.cooked = ""
- expect(DiscourseTranslator::Base.text_for_detection(post)).to eq("")
- end
-
- it "leaves other anchor tags alone" do
- cooked = <<~HTML
-
-
-
-
- HTML
- post.cooked = cooked
- expect(DiscourseTranslator::Base.text_for_detection(post)).to eq(cooked)
- end
-
it "truncates to DETECTION_CHAR_LIMIT of 1000" do
- post.cooked = "a" * 1001
+ post.raw = "a" * 1001
expect(DiscourseTranslator::Base.text_for_detection(post).length).to eq(1000)
end
it "returns the text if it's less than DETECTION_CHAR_LIMIT" do
text = "a" * 999
- post.cooked = text
+ post.raw = text
expect(DiscourseTranslator::Base.text_for_detection(post)).to eq(text)
end
-
- it "strips text before truncation" do
- post.cooked = "" + "a" * 1000
- expect(DiscourseTranslator::Base.text_for_detection(post)).to eq("a" * 1000)
- end
end
describe ".text_for_translation" do
fab!(:post)
it "truncates to max_characters_per_translation" do
- post.cooked = "a" * (SiteSetting.max_characters_per_translation + 1)
+ post.raw = "a" * (SiteSetting.max_characters_per_translation + 1)
expect(DiscourseTranslator::Base.text_for_translation(post).length).to eq(
SiteSetting.max_characters_per_translation,
)
@@ -104,7 +63,7 @@ class EmptyTranslator < DiscourseTranslator::Base
fab!(:post)
it "returns nil when text is blank" do
- post.cooked = ""
+ post.raw = ""
expect(TestTranslator.detect(post)).to be_nil
end
@@ -134,15 +93,15 @@ class EmptyTranslator < DiscourseTranslator::Base
fab!(:post)
it "returns nil when text is blank" do
- post.cooked = ""
+ post.raw = ""
expect(TestTranslator.translate(post)).to be_nil
end
it "returns original text when detected language matches current locale" do
TestTranslator.save_detected_locale(post) { I18n.locale.to_s }
- post.cooked = "hello"
+ post.update(raw: "hello")
- expect(TestTranslator.translate(post)).to eq(%w[en hello])
+ expect(TestTranslator.translate(post)).to eq(%w[en
hello
])
end
it "returns cached translation if available" do
diff --git a/spec/services/discourse_ai/language_detector_spec.rb b/spec/services/discourse_ai/language_detector_spec.rb
index 2105ca36..eba25f3e 100644
--- a/spec/services/discourse_ai/language_detector_spec.rb
+++ b/spec/services/discourse_ai/language_detector_spec.rb
@@ -32,13 +32,15 @@
mock_prompt,
user: Discourse.system_user,
feature_name: "translator-language-detect",
- )
+ ).and_return("hi")
- described_class.new("meow").detect
+ DiscourseAi::Completions::Llm.with_prepared_responses(["de"]) do
+ described_class.new("meow").detect
+ end
end
it "returns the language from the llm's response in the language tag" do
- DiscourseAi::Completions::Llm.with_prepared_responses(["de"]) do
+ DiscourseAi::Completions::Llm.with_prepared_responses(["de"]) do
expect(described_class.new("meow").detect).to eq "de"
end
end
diff --git a/spec/services/discourse_ai/translator_spec.rb b/spec/services/discourse_ai/translator_spec.rb
index e78d3da3..7b9fc6e4 100644
--- a/spec/services/discourse_ai/translator_spec.rb
+++ b/spec/services/discourse_ai/translator_spec.rb
@@ -17,15 +17,16 @@
it "creates the correct prompt" do
allow(DiscourseAi::Completions::Prompt).to receive(:new).with(
<<~TEXT,
- You are a highly skilled linguist of many languages and have expert knowledge in HTML.
- Your task is to identify the language of the text I provide and accurately translate it into this language locale "de" while preserving the meaning, tone, and nuance of the original text.
- The text may or may not contain html tags. If they do, preserve them.
- Maintain proper grammar, spelling, and punctuation in the translated version.
- You will find the text between XML tags.
- Include your translation between XML tags.
- Do not write explanations.
+ You are an expert translator specializing in converting Markdown content from any source language to target locale "de". Your task is to:
+ 1. Translate the content accurately while preserving all Markdown formatting elements
+ 2. Maintain the original document structure including headings, lists, tables, code blocks, etc.
+ 3. Preserve all links, images, and other media references without translation
+ 4. Handle code snippets appropriately - don't translate variable names, functions, or syntax within code blocks (```), but translate comments
+ 5. When encountering technical terminology, provide the accepted target language term if it exists, or transliterate if no equivalent exists, with the original term in parentheses
+ 6. For ambiguous terms or phrases, choose the most contextually appropriate translation
+ 7. You are being consumed via an API, only EVER return the translated text, do not return any other information
TEXT
- messages: [{ type: :user, content: "cats are great", id: "user" }],
+ messages: [{ type: :user, content: "cats are great", id: "user" }],
).and_call_original
described_class.new(text_to_translate, target_language).translate
@@ -48,20 +49,12 @@
described_class.new(text_to_translate, target_language).translate
end
- it "returns the translation from the llm's response in the translation tag" do
- DiscourseAi::Completions::Llm.with_prepared_responses(
- [""],
- ) do
+ it "returns the translation from the llm's response" do
+ DiscourseAi::Completions::Llm.with_prepared_responses(["hur dur hur dur!"]) do
expect(
described_class.new(text_to_translate, target_language).translate,
).to eq "hur dur hur dur!"
end
end
-
- it "returns an empty string if the translation tag is not present" do
- DiscourseAi::Completions::Llm.with_prepared_responses(["raw response."]) do
- expect(described_class.new(text_to_translate, target_language).translate).to eq ""
- end
- end
end
end
diff --git a/spec/services/discourse_ai_spec.rb b/spec/services/discourse_ai_spec.rb
index ba631ed7..2dc37daa 100644
--- a/spec/services/discourse_ai_spec.rb
+++ b/spec/services/discourse_ai_spec.rb
@@ -29,7 +29,7 @@
describe ".detect!" do
it "returns the detected language" do
locale = "de"
- DiscourseAi::Completions::Llm.with_prepared_responses(["de"]) do
+ DiscourseAi::Completions::Llm.with_prepared_responses(["de"]) do
expect(DiscourseTranslator::DiscourseAi.detect!(post)).to eq locale
end
end
@@ -39,9 +39,7 @@
before { post.set_detected_locale("de") }
it "translates the post and returns [locale, translated_text]" do
- DiscourseAi::Completions::Llm.with_prepared_responses(
- [""],
- ) do
+ DiscourseAi::Completions::Llm.with_prepared_responses(["some translated text"]) do
locale, translated_text = DiscourseTranslator::DiscourseAi.translate(post)
expect(locale).to eq "de"
expect(translated_text).to eq "some translated text"
diff --git a/spec/services/google_spec.rb b/spec/services/google_spec.rb
index f6d7d8ba..04394096 100644
--- a/spec/services/google_spec.rb
+++ b/spec/services/google_spec.rb
@@ -40,12 +40,12 @@
it "should truncate string to 1000 characters" do
length = 2000
- post.cooked = rand(36**length).to_s(36)
+ post.raw = rand(36**length).to_s(36)
detected_lang = "en"
request_url = "#{DiscourseTranslator::Google::DETECT_URI}"
body = {
- q: post.cooked.truncate(DiscourseTranslator::Google::DETECTION_CHAR_LIMIT, omission: nil),
+ q: post.raw.truncate(DiscourseTranslator::Google::DETECTION_CHAR_LIMIT, omission: nil),
key: api_key,
}
@@ -69,34 +69,6 @@
expect(described_class.detect(post)).to eq(detected_lang)
end
-
- it "strips img tags from detection text" do
- post.cooked = "there are some words to be said"
- detected_lang = "en"
-
- request_url = "#{DiscourseTranslator::Google::DETECT_URI}"
- body = { q: "there are some words to be said", key: api_key }
-
- Excon
- .expects(:post)
- .with(
- request_url,
- body: URI.encode_www_form(body),
- headers: {
- "Content-Type" => "application/x-www-form-urlencoded",
- "Referer" => "http://test.localhost",
- },
- )
- .returns(
- mock_response.new(
- 200,
- %{ { "data": { "detections": [ [ { "language": "#{detected_lang}", "isReliable": false, "confidence": 0.18397073 } ] ] } } },
- ),
- )
- .once
-
- expect(described_class.detect(post)).to eq(detected_lang)
- end
end
describe ".translate_supported?" do
@@ -177,10 +149,10 @@
it "truncates text for translation to max_characters_per_translation setting" do
SiteSetting.max_characters_per_translation = 50
- post.cooked = "a" * 100
+ post.raw = "a" * 100
post.set_detected_locale("de")
body = {
- q: post.cooked.truncate(SiteSetting.max_characters_per_translation, omission: nil),
+ q: post.raw.truncate(SiteSetting.max_characters_per_translation, omission: nil),
source: "de",
target: "en",
key: api_key,
diff --git a/spec/services/libre_translate_spec.rb b/spec/services/libre_translate_spec.rb
index 536fb4a3..4965d293 100644
--- a/spec/services/libre_translate_spec.rb
+++ b/spec/services/libre_translate_spec.rb
@@ -44,7 +44,7 @@
it "truncates text for translation to max_characters_per_translation setting" do
SiteSetting.max_characters_per_translation = 50
post.set_detected_locale("de")
- body = { q: post.cooked, source: "de", target: "en", format: "html", api_key: api_key }
+ body = { q: post.raw, source: "de", target: "en", format: "html", api_key: api_key }
translated_text = "hur dur hur dur"
# https://publicapi.dev/libre-translate-api
diff --git a/spec/services/microsoft_spec.rb b/spec/services/microsoft_spec.rb
index 7c2cfb80..a777f6e2 100644
--- a/spec/services/microsoft_spec.rb
+++ b/spec/services/microsoft_spec.rb
@@ -176,7 +176,7 @@ def translate_endpoint
it "raises an error if the post is too long to be translated" do
I18n.locale = "ja"
SiteSetting.max_characters_per_translation = 100_000
- post.update_columns(cooked: "*" * (DiscourseTranslator::Microsoft::LENGTH_LIMIT + 1))
+ post.update_columns(raw: "*" * (DiscourseTranslator::Microsoft::LENGTH_LIMIT + 1))
expect { described_class.translate(post) }.to raise_error(
DiscourseTranslator::TranslatorError,
@@ -190,7 +190,7 @@ def translate_endpoint
:post,
"https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=en&textType=html&to=ja",
).with(
- body: "[{\"Text\":\"\\u003cp\\u003eHello world\\u003c/p\\u003e\"}]",
+ body: "[{\"Text\":\"Hello world\"}]",
headers: {
"Ocp-Apim-Subscription-Key" => SiteSetting.translator_azure_subscription_key,
"Content-Type" => "application/json",