Files
chatwoot/app/models/concerns/portal_config_schema.rb
64c5aeebee feat(help-center): support per-locale portal title, name & header (#14642)
Portals can now override their name, page title and header text per
locale, with a fallback chain of locale override → default locale → base
value. Overrides are stored under portal.config.locale_translations and
validated with a JSON schema.

Editing is exposed as a "Localize content" action in each non-default
locale's menu on the Locale page, and all public-facing portal views
(classic + documentation layouts) render the localized values. The live
chat widget is also loaded in the active portal locale.


<img width="494" height="395" alt="Screenshot 2026-06-03 at 2 48 59 PM"
src="https://github.com/user-attachments/assets/e55a06e8-f20f-4d8a-9352-92fde28a9a19"
/>



https://github.com/user-attachments/assets/f5affbd2-7ad4-415a-b376-57c759fc2aaa

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:34:12 -07:00

36 lines
1.4 KiB
Ruby

module PortalConfigSchema
extend ActiveSupport::Concern
# Per-locale overrides for portal level fields. Any locale present in
# `allowed_locales` may carry its own `name`, `page_title` and `header_text`.
# Missing values fall back to the default locale and finally to the base column.
LOCALE_TRANSLATION_SCHEMA = {
'type' => 'object',
'properties' => {
'name' => { 'type' => %w[string null] },
'page_title' => { 'type' => %w[string null] },
'header_text' => { 'type' => %w[string null] }
},
'additionalProperties' => false
}.freeze
CONFIG_PARAMS_SCHEMA = {
'type' => 'object',
'properties' => {
'allowed_locales' => { 'type' => %w[array null], 'items' => { 'type' => 'string' } },
'default_locale' => { 'type' => %w[string null] },
'draft_locales' => { 'type' => %w[array null], 'items' => { 'type' => 'string' } },
'layout' => { 'type' => %w[string null], 'enum' => ['classic', 'documentation', nil] },
# TODO: unused reserved key; remove with a migration that scrubs it from existing portals' config
'website_token' => { 'type' => %w[string null] },
'social_profiles' => { 'type' => %w[object null] },
'locale_translations' => {
'type' => %w[object null],
'additionalProperties' => LOCALE_TRANSLATION_SCHEMA
}
},
'required' => [],
'additionalProperties' => true
}.to_json.freeze
end