mirror of
https://github.com/discourse/discourse.git
synced 2026-08-11 02:59:07 +08:00
The /about page (unlike /guidelines or /tos) is not backed by a topic, but instead via a bunch of site settings. If it were backed by a topic, localization would be easy as it can just use TopicLocalizations. We also can't swap it out to use a topic, since there are so many fields on the about page that can't be safely contained in a topic. ---------- This PR adds SiteSettingLocalization, allowing new attributes in site settings config for localization. For now this is wired into the About page settings flow: - admins can select a non-default locale on /admin/config/about - only translatable About fields are shown for that locale - localized About values are used on /about and /about.json - company_url can be set manually per locale, but is excluded from automatic translation - ~~AI backfill can translate eligible site setting localizations~~ no backfill (added in https://github.com/discourse/discourse/pull/41123/commits/386c655d2f44aca54440c069bd06ea8007793d84, removed in https://github.com/discourse/discourse/pull/41123/commits/6f8ec9cc43dca4195bda638b1ce980eb68a59941. about page has very non automa-ble fields This intentionally keeps the scope narrow. It does not make every site setting localizable, and any other setting can be localized by adding to that allowlist. Some screenshots |page | 📸 | |--|--| | eng setting | <img width="1278" height="871" alt="Screenshot 2026-06-23 at 11 00 34 PM" src="https://github.com/user-attachments/assets/59431464-fb05-41d9-8c4f-fd9aae7fb45f" /> | ja setting | <img width="1278" height="871" alt="Screenshot 2026-06-23 at 11 01 20 PM" src="https://github.com/user-attachments/assets/73cd2878-f59a-4dc4-a76d-2f46b74a6eed" /> | ja anon about page | <img width="1278" height="871" alt="Screenshot 2026-06-23 at 11 01 48 PM" src="https://github.com/user-attachments/assets/02464a5f-9ca0-4519-9521-be41498c1967" />
141 lines
4.9 KiB
Ruby
Vendored
141 lines
4.9 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
class Admin::Config::AboutController < Admin::AdminController
|
|
before_action :ensure_can_localize_site_settings, only: %i[localizations update_localizations]
|
|
|
|
def index
|
|
end
|
|
|
|
def localizations
|
|
SiteSettingLocalizations::AboutConfig::Show.call(
|
|
service_params.deep_merge(params: { locale: params[:locale] }),
|
|
) do
|
|
on_success { |payload:| render json: payload }
|
|
on_failed_contract { raise Discourse::InvalidParameters, :locale }
|
|
on_failed_policy(:can_localize_site_settings) { raise Discourse::InvalidAccess }
|
|
on_failed_policy(:locale_is_supported) { raise Discourse::InvalidParameters, :locale }
|
|
end
|
|
end
|
|
|
|
def update_localizations
|
|
SiteSettingLocalizations::AboutConfig::Update.call(
|
|
service_params.deep_merge(
|
|
params: {
|
|
locale: params[:locale],
|
|
general_settings: params[:general_settings],
|
|
},
|
|
),
|
|
) do
|
|
on_success { |payload:| render json: payload }
|
|
on_failed_contract { raise Discourse::InvalidParameters, :locale }
|
|
on_failed_policy(:can_localize_site_settings) { raise Discourse::InvalidAccess }
|
|
on_failed_policy(:locale_is_supported) { raise Discourse::InvalidParameters, :locale }
|
|
end
|
|
end
|
|
|
|
def update
|
|
settings = []
|
|
|
|
if general_settings = params[:general_settings]
|
|
settings << { setting_name: "title", value: general_settings[:name] }
|
|
settings << { setting_name: "site_description", value: general_settings[:summary] }
|
|
settings << {
|
|
setting_name: "about_banner_image",
|
|
value: general_settings[:about_banner_image],
|
|
}
|
|
|
|
settings << {
|
|
setting_name: "extended_site_description",
|
|
value: general_settings[:extended_description],
|
|
}
|
|
settings << {
|
|
setting_name: "short_site_description",
|
|
value: general_settings[:community_title],
|
|
}
|
|
|
|
if general_settings[:extended_description].present?
|
|
settings << {
|
|
setting_name: "extended_site_description_cooked",
|
|
value: PrettyText.markdown(general_settings[:extended_description]),
|
|
}
|
|
else
|
|
settings << { setting_name: "extended_site_description_cooked", value: "" }
|
|
end
|
|
end
|
|
|
|
if contact_information = params[:contact_information]
|
|
settings << { setting_name: "community_owner", value: contact_information[:community_owner] }
|
|
settings << { setting_name: "contact_email", value: contact_information[:contact_email] }
|
|
settings << { setting_name: "contact_url", value: contact_information[:contact_url] }
|
|
settings << {
|
|
setting_name: "site_contact_username",
|
|
value: contact_information[:contact_username],
|
|
}
|
|
settings << {
|
|
setting_name: "site_contact_group_name",
|
|
value: contact_information[:contact_group_name],
|
|
}
|
|
end
|
|
|
|
if your_organization = params[:your_organization]
|
|
settings << { setting_name: "company_name", value: your_organization[:company_name] }
|
|
settings << { setting_name: "company_url", value: your_organization[:company_url] }
|
|
settings << { setting_name: "governing_law", value: your_organization[:governing_law] }
|
|
settings << {
|
|
setting_name: "city_for_disputes",
|
|
value: your_organization[:city_for_disputes],
|
|
}
|
|
end
|
|
|
|
if extra_groups = params[:extra_groups]
|
|
settings << { setting_name: "about_page_extra_groups", value: extra_groups[:groups] }
|
|
settings << {
|
|
setting_name: "about_page_extra_groups_initial_members",
|
|
value: extra_groups[:initial_members],
|
|
}
|
|
settings << { setting_name: "about_page_extra_groups_order", value: extra_groups[:order] }
|
|
settings << {
|
|
setting_name: "about_page_extra_groups_show_description",
|
|
value: extra_groups[:show_description],
|
|
}
|
|
end
|
|
|
|
SiteSetting::Update.call(
|
|
guardian:,
|
|
params: {
|
|
settings:,
|
|
},
|
|
options: {
|
|
allow_changing_hidden: %i[
|
|
extended_site_description
|
|
extended_site_description_cooked
|
|
about_banner_image
|
|
community_owner
|
|
],
|
|
},
|
|
) do
|
|
on_success { render json: success_json }
|
|
on_failed_policy(:settings_are_not_deprecated) do |policy|
|
|
raise Discourse::InvalidParameters, policy.reason
|
|
end
|
|
on_failed_policy(:settings_are_visible) do |policy|
|
|
raise Discourse::InvalidParameters, policy.reason
|
|
end
|
|
on_failed_policy(:settings_are_unshadowed_globally) do |policy|
|
|
raise Discourse::InvalidParameters, policy.reason
|
|
end
|
|
on_failed_policy(:settings_are_configurable) do |policy|
|
|
raise Discourse::InvalidParameters, policy.reason
|
|
end
|
|
on_failed_policy(:values_are_valid) do |policy|
|
|
raise Discourse::InvalidParameters, policy.reason
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def ensure_can_localize_site_settings
|
|
guardian.ensure_can_localize_site_settings!
|
|
end
|
|
end
|