0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 14:34:02 +08:00
discourse/app/models/concerns/localizable.rb
Natalie Tay e4b67f4b32
FEATURE: Localize local oneboxes (#40493)
We currently see unlocalized oneboxes even when
`content_localization_enabled`. An internal topic onebox stored the
linked topic's title and excerpt in its original language, so a reader
using content localization saw it untranslated even when a translation
existed.

This shows internal topic oneboxes in the reader's language via two
purpose-built paths (no rewriting cooked HTML at request time):

- For translated posts, `LocalizedCookedPostProcessor` bakes the card in
the localization's locale at cook time; the original cooked is
untouched.
- For "original posts", the serializer adds a `localized_oneboxes` map
(built once per page from `topic_links`, scoped to onebox links + the
reader's locale family), and a post-cooked decorator swaps the
title/excerpt into the rendered card.

Falls back to the original when no translation exists, respects "show
original", and never exposes a title/preview the reader couldn't already
see. "Rebuild HTML" now refreshes localizations too, without
re-translating.
2026-06-08 11:49:55 +08:00

47 lines
1.6 KiB
Ruby
Vendored

# frozen_string_literal: true
module Localizable
extend ActiveSupport::Concern
included { has_many :localizations, class_name: "#{model_name}Localization", dependent: :destroy }
# Returns the localization for (in order of priority):
# - the given locale,
# - or the best match if an exact match is not found
# - or the site default locale if `content_localization_use_default_locale_when_unsupported`
# is enabled and +fallback+ is true
#
# Pass `fallback: false` when falling back to a different language would be
# wrong
#
# The query used to find the localization is optimized for performance, and assumes
# that localizations are indexed by locale, and have been preloaded.
# @return [Localization, nil] the localization object for the given locale, or nil if no match is found.
def get_localization(locale = I18n.locale, fallback: true)
locale_str = locale.to_s.sub("-", "_")
# prioritise exact match
if match = localizations.find { |l| l.locale == locale_str }
return match
end
if match = localizations.find { |l| LocaleNormalizer.is_same?(l.locale, locale_str) }
return match
end
return if !fallback
if SiteSetting.content_localization_use_default_locale_when_unsupported
default_locale = SiteSetting.default_locale.to_s.sub("-", "_")
localizations.find { |l| LocaleNormalizer.is_same?(l.locale, default_locale) }
end
end
def has_localization?(locale = I18n.locale)
get_localization(locale).present?
end
def in_user_locale?
LocaleNormalizer.is_same?(locale, I18n.locale)
end
end