# frozen_string_literal: true describe DiscourseAi::Translation::TopicLocalizer do describe ".localize" do fab!(:topic) do Fabricate( :topic, title: "this is a cat topic :)", excerpt: "cats are great. how many do you have?", ) end let(:translator) { mock } let(:translated_title) { "これは猫の話題です :)" } let(:translated_excerpt) { "猫は素晴らしいですね。何匹飼っていますか?" } let(:fancy_title) { "これは猫の話題です :slight_smile:" } let(:target_locale) { "ja" } def topic_title_translator_stub(opts) mock = instance_double(DiscourseAi::Translation::TopicTitleTranslator) allow(DiscourseAi::Translation::TopicTitleTranslator).to receive(:new).with( text: opts[:text], target_locale: opts[:target_locale], topic: opts[:topic] || topic, ).and_return(mock) allow(mock).to receive(:translate).and_return(opts[:translated]) end def post_raw_translator_stub(opts) mock = instance_double(DiscourseAi::Translation::PostRawTranslator) allow(DiscourseAi::Translation::PostRawTranslator).to receive(:new).with( text: opts[:text], target_locale: opts[:target_locale], topic: opts[:topic] || topic, ).and_return(mock) allow(mock).to receive(:translate).and_return(opts[:translated]) end it "returns nil if topic is blank" do expect(described_class.localize(nil, "ja")).to eq(nil) end it "returns nil if target_locale is blank" do expect(described_class.localize(topic, nil)).to eq(nil) expect(described_class.localize(topic, "")).to eq(nil) end it "returns nil if target_locale is same as topic locale" do topic.locale = "en" expect(described_class.localize(topic, "en")).to eq(nil) end it "translates with topic and locale" do topic_title_translator_stub( { text: topic.title, target_locale: "ja", translated: translated_title }, ) post_raw_translator_stub( { text: topic.excerpt, target_locale: "ja", translated: translated_excerpt }, ) described_class.localize(topic, "ja") end it "normalizes dashes to underscores and symbol type for locale" do topic_title_translator_stub( { text: topic.title, target_locale: "zh_CN", translated: "这是一个猫主题 :)" }, ) post_raw_translator_stub( { text: topic.excerpt, target_locale: "zh_CN", translated: "这是一个猫主题 :)" }, ) described_class.localize(topic, "zh-CN") end it "finds or creates a TopicLocalization and sets its fields" do topic_title_translator_stub( { text: topic.title, target_locale: "ja", translated: translated_title }, ) post_raw_translator_stub( { text: topic.excerpt, target_locale: "ja", translated: translated_excerpt }, ) expect { res = described_class.localize(topic, target_locale) expect(res).to be_a(TopicLocalization) expect(res).to have_attributes( topic_id: topic.id, locale: target_locale, title: translated_title, excerpt: translated_excerpt, fancy_title: fancy_title, localizer_user_id: Discourse.system_user.id, ) }.to change { TopicLocalization.count }.by(1) end it "updates an existing TopicLocalization if present" do topic_title_translator_stub( { text: topic.title, target_locale: "ja", translated: translated_title }, ) post_raw_translator_stub( { text: topic.excerpt, target_locale: "ja", translated: translated_excerpt }, ) localization = Fabricate( :topic_localization, topic:, locale: "ja", title: "old title", excerpt: "old excerpt", fancy_title: "old_fancy_title", ) expect { expect(described_class.localize(topic, "ja")).to have_attributes( id: localization.id, title: translated_title, fancy_title: fancy_title, excerpt: translated_excerpt, ) expect(localization.reload).to have_attributes( title: translated_title, fancy_title: fancy_title, excerpt: translated_excerpt, ) }.to_not change { TopicLocalization.count } end end end