0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-11 02:59:07 +08:00
discourse/app/controllers/admin/config/about_controller.rb
Natalie Tay af11f8992c
FEATURE: Localizable /about page fields via its settings page (#41123)
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"
/>
2026-06-26 20:41:08 +08:00

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