Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/apps/translatewp/__tests__/switcherSurfaces.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,36 @@ describe('TranslateWP switcher surfaces', () =>
}
});

it('lets the visitor choose a language when the page holds a hidden copy of the switcher', async () =>
{
// Menus and page builder headers print a desktop copy and a hidden mobile copy.
installContext(true, 'dropdown');
window.TranslateWP.context.home_url = window.location.origin;
document.body.innerHTML = `
<nav class="desktop"><span data-twp-switcher></span></nav>
<nav class="mobile" hidden><span data-twp-switcher></span></nav>
`;
window.history.replaceState(null, '', '/about/');
pendingBatch();

await renderApp();

const desktop = document.querySelector('.desktop') as HTMLElement;
const mobile = document.querySelector('.mobile') as HTMLElement;
await act(async () => { (desktop.querySelector('.twp-trigger') as HTMLButtonElement).click(); });
expect(mobile.querySelector('.twp-dropdown-item')).toBeNull();

const option = Array.from(desktop.querySelectorAll('.twp-dropdown-item'))
.find((item) => item.textContent?.includes('Español')) as HTMLButtonElement;
expect(option).toBeDefined();
// A real click presses the mouse first; every other copy sees that press as outside itself.
await act(async () => { option.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); });
await act(async () => { option.click(); });

expect(window.location.pathname).toBe('/es/about/');
expect(document.documentElement.lang).toBe('es');
});

it('translates an address in a language folder into that language and leaves the address alone', async () =>
{
installContext(true, 'dropdown');
Expand Down
21 changes: 15 additions & 6 deletions src/apps/translatewp/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ export const TranslateWP = () =>
[languagesList]
);
const defaultLocale = languages.find((l) => l.default)?.locale ?? languages[0]?.locale ?? '';
const [isOpen, setIsOpen] = useState(false);
// Which switcher on the page is open. A page can hold several copies,
// often one hidden for mobile, and only the one the visitor opened may
// close its own list.
const [openSwitcher, setOpenSwitcher] = useState<HTMLElement | 'floating' | null>(null);
const [selectedLocale, setSelectedLocale] = useState(defaultLocale);
const selectedLocaleRef = useRef(defaultLocale);
selectedLocaleRef.current = selectedLocale;
Expand Down Expand Up @@ -200,7 +203,7 @@ export const TranslateWP = () =>
function beginLanguageSelection(locale: string, history: 'push' | 'replace'): void
{
setActiveLocale(locale);
setIsOpen(false);
setOpenSwitcher(null);
setLanguageAddress(locale, history);
applyDocumentLanguage(locale);
persistLanguageSelection(locale);
Expand Down Expand Up @@ -295,7 +298,7 @@ export const TranslateWP = () =>
if (selectedLocale !== defaultLocale)
{
resetToDefaultLanguage();
setIsOpen(false);
setOpenSwitcher(null);
restorePageTitle();
setIsTranslating(false);

Expand Down Expand Up @@ -600,11 +603,17 @@ export const TranslateWP = () =>
const FrontendEditor = managerCan().edit ? resolveFrontendSlot('frontendEditor') : null;

const viewProps: SwitcherViewProps = {
languages, switcher: switcher ?? {}, selectedLocale, isOpen, notice, isTranslating,
onOpenChange: setIsOpen,
languages, switcher: switcher ?? {}, selectedLocale, notice, isTranslating,
isOpen: openSwitcher === 'floating',
onOpenChange: open => setOpenSwitcher(current => (open ? 'floating' : (current === 'floating' ? null : current))),
onLanguageSelect: language => translate(language),
onDismissNotice: hidePendingNotice,
};
const inlineProps = (placeholder: HTMLElement): SwitcherViewProps => ({
...viewProps,
isOpen: openSwitcher === placeholder,
onOpenChange: open => setOpenSwitcher(current => (open ? placeholder : (current === placeholder ? null : current))),
});

return (
<>
Expand All @@ -622,7 +631,7 @@ export const TranslateWP = () =>
)}
{placeholders.map((placeholder) => (
createPortal(
<SwitcherView {...viewProps} variant="inline" />,
<SwitcherView {...inlineProps(placeholder)} variant="inline" />,
placeholder
)
))}
Expand Down
Loading