mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-03 00:20:04 +08:00
Related:
https://meta.discourse.org/t/yet-another-title-localization-issue/395469
### bug context
tldr; `Topic#fancy_title` saves a fancy_title to db when the fancy_title
is null.
This bug requires a certain incantation to trigger.
- Topic 395465 exists with `title = "Notification level button always
says \"tracking\""` and
`fancy_title = NULL` in the DB
- A `TopicLocalization` exists for this topic in `zh_CN`
- `content_localization_enabled` is on
When a crawler hits `GET /t/.../395465?tl=zh_CN`, localization
replacement happens on the topic, which writes the title attribute, so
the state is now
- `title` = Chinese (modified)
- `fancy_title` = NULL (untouched, still what was loaded from DB)
When serializing via `TopicViewSerializer` which uses
`LocalizedFancyTopicTitleMixin`, we call `topic.fancy_title`. The
`topic#fancy_title` generates the fancy_title from the title value, then
writes the chinese fancy title to db 😢
e935ed63b2/app/models/topic.rb (L532-L545)
### fix
This commit fixes the issue by ensuring the fancy_title is always written
along with the title, preventing the need for invoking
`topic#fancy_title`.
120 lines
4.6 KiB
Ruby
120 lines
4.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
describe LocalizationAttributesReplacer do
|
|
describe ".replace_category_attributes" do
|
|
fab!(:category) { Fabricate(:category, locale: "en") }
|
|
fab!(:subcategory) { Fabricate(:category, parent_category: category, locale: "en") }
|
|
fab!(:ja_subcategory) do
|
|
Fabricate(:category_localization, category: subcategory, locale: "ja", name: "猫犬")
|
|
end
|
|
fab!(:ja_category) { Fabricate(:category_localization, category:, locale: "ja", name: "猫犬") }
|
|
|
|
it "replaces category and subcategory attributes with localized value" do
|
|
LocalizationAttributesReplacer.replace_category_attributes(subcategory, "ja")
|
|
|
|
expect(subcategory.name).to eq(ja_subcategory.name)
|
|
expect(subcategory.description).to eq(ja_subcategory.description)
|
|
expect(subcategory.parent_category.name).to eq(ja_category.name)
|
|
expect(subcategory.parent_category.description).to eq(ja_category.description)
|
|
end
|
|
|
|
it "does not change the name if the locale is the same" do
|
|
LocalizationAttributesReplacer.replace_category_attributes(category, "en")
|
|
|
|
expect(category.name).to eq(category.name)
|
|
end
|
|
|
|
it "does not change attributes if no localization exists for the given locale" do
|
|
LocalizationAttributesReplacer.replace_category_attributes(category, "fr")
|
|
|
|
expect(category.name).to eq(category.name)
|
|
end
|
|
end
|
|
|
|
describe ".replace_topic_attributes" do
|
|
fab!(:topic) { Fabricate(:topic, locale: "en") }
|
|
fab!(:ja_localization) do
|
|
Fabricate(:topic_localization, topic:, locale: "ja", title: "猫犬", excerpt: "柴犬は猫のような犬です。")
|
|
end
|
|
|
|
it "replaces the title, fancy_title, and excerpt with localized values" do
|
|
LocalizationAttributesReplacer.replace_topic_attributes(topic, "ja")
|
|
|
|
expect(topic.title).to eq(ja_localization.title)
|
|
expect(topic.fancy_title).to eq(ja_localization.fancy_title)
|
|
expect(topic.excerpt).to eq(ja_localization.excerpt)
|
|
end
|
|
|
|
it "does not write localized fancy_title to the database when fancy_title is null" do
|
|
topic.update_column(:fancy_title, nil)
|
|
topic.reload
|
|
|
|
LocalizationAttributesReplacer.replace_topic_attributes(topic, "ja")
|
|
|
|
expect(topic.title).to eq(ja_localization.title)
|
|
expect(topic.read_attribute(:fancy_title)).to eq(ja_localization.fancy_title)
|
|
|
|
localized_fancy_title = Topic.fancy_title(ja_localization.title)
|
|
expect(Topic.where(id: topic.id).pick(:fancy_title)).not_to eq(localized_fancy_title)
|
|
end
|
|
|
|
it "generates fancy_title from localized title when localization fancy_title is blank" do
|
|
ja_localization.update_column(:fancy_title, "")
|
|
topic.update_column(:fancy_title, nil)
|
|
topic.reload
|
|
|
|
LocalizationAttributesReplacer.replace_topic_attributes(topic, "ja")
|
|
|
|
expect(topic.title).to eq(ja_localization.title)
|
|
expect(topic.read_attribute(:fancy_title)).to eq(Topic.fancy_title(ja_localization.title))
|
|
|
|
localized_fancy_title = Topic.fancy_title(ja_localization.title)
|
|
expect(Topic.where(id: topic.id).pick(:fancy_title)).not_to eq(localized_fancy_title)
|
|
end
|
|
|
|
it "does not change the title or excerpt if the locale is the same" do
|
|
LocalizationAttributesReplacer.replace_topic_attributes(topic, "en")
|
|
|
|
expect(topic.title).to eq(topic.title)
|
|
expect(topic.excerpt).to eq(topic.excerpt)
|
|
end
|
|
|
|
it "does not change attributes if no localization exists for the given locale" do
|
|
LocalizationAttributesReplacer.replace_topic_attributes(topic, "fr")
|
|
|
|
expect(topic.title).to eq(topic.title)
|
|
expect(topic.excerpt).to eq(topic.excerpt)
|
|
end
|
|
|
|
it "does not error out if topic does not exist" do
|
|
expect {
|
|
LocalizationAttributesReplacer.replace_topic_attributes(nil, "ja")
|
|
}.not_to raise_error
|
|
end
|
|
end
|
|
|
|
describe ".replace_post_attributes" do
|
|
fab!(:post) { Fabricate(:post, locale: "en") }
|
|
fab!(:ja_localization) do
|
|
Fabricate(:post_localization, post:, locale: "ja", cooked: "猫犬は柴犬のような猫です。")
|
|
end
|
|
|
|
it "replaces the cooked content with localized values" do
|
|
LocalizationAttributesReplacer.replace_post_attributes(post, "ja")
|
|
|
|
expect(post.cooked).to eq(ja_localization.cooked)
|
|
end
|
|
|
|
it "does not change the cooked content if the locale is the same" do
|
|
LocalizationAttributesReplacer.replace_post_attributes(post, "en")
|
|
|
|
expect(post.cooked).to eq(post.cooked)
|
|
end
|
|
|
|
it "does not change attributes if no localization exists for the given locale" do
|
|
LocalizationAttributesReplacer.replace_post_attributes(post, "fr")
|
|
|
|
expect(post.cooked).to eq(post.cooked)
|
|
end
|
|
end
|
|
end
|