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>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
cd9192f7d1
commit
64c5aeebee
@@ -74,37 +74,40 @@ describe('PortalHelper', () => {
|
||||
});
|
||||
|
||||
describe('buildLocaleMenuItems', () => {
|
||||
it('returns disabled actions for the default locale', () => {
|
||||
it('disables other actions but keeps customize enabled for the default locale', () => {
|
||||
const items = buildLocaleMenuItems({ isDefault: true, isDraft: false });
|
||||
const customize = items.find(item => item.action === 'customize-content');
|
||||
|
||||
expect(customize).toBeTruthy();
|
||||
expect(customize.disabled).toBeFalsy();
|
||||
expect(
|
||||
buildLocaleMenuItems({
|
||||
isDefault: true,
|
||||
isDraft: false,
|
||||
})
|
||||
).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ action: 'change-default', disabled: true }),
|
||||
expect.objectContaining({ action: 'move-to-draft', disabled: true }),
|
||||
expect.objectContaining({ action: 'delete', disabled: true }),
|
||||
])
|
||||
);
|
||||
items
|
||||
.filter(item => item.action !== 'customize-content')
|
||||
.every(item => item.disabled)
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('returns publish and delete actions for draft locales', () => {
|
||||
it('returns publish, customize, and delete actions for draft locales', () => {
|
||||
expect(
|
||||
buildLocaleMenuItems({
|
||||
isDefault: false,
|
||||
isDraft: true,
|
||||
}).map(({ action }) => action)
|
||||
).toEqual(['publish-locale', 'delete']);
|
||||
).toEqual(['publish-locale', 'customize-content', 'delete']);
|
||||
});
|
||||
|
||||
it('returns default, draft, and delete actions for live locales', () => {
|
||||
it('returns default, draft, customize, and delete actions for live locales', () => {
|
||||
expect(
|
||||
buildLocaleMenuItems({
|
||||
isDefault: false,
|
||||
isDraft: false,
|
||||
}).map(({ action }) => action)
|
||||
).toEqual(['change-default', 'move-to-draft', 'delete']);
|
||||
).toEqual([
|
||||
'change-default',
|
||||
'move-to-draft',
|
||||
'customize-content',
|
||||
'delete',
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user