Skip to content

Commit

Permalink
Merge pull request #807 from imobachgs/fix-language-reload
Browse files Browse the repository at this point in the history
Miscellanous locale handling fixes
  • Loading branch information
imobachgs authored Oct 20, 2023
2 parents 12ecc5b + ddb1a29 commit 09edb51
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 21 deletions.
35 changes: 25 additions & 10 deletions web/src/context/l10n.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,17 +165,21 @@ function findSupportedLanguage(languages) {
/**
* Reloads the page
*
* It uses the window.location.replace instead of the reload function dropping
* the "lang" argument from the URL.
* It uses the window.location.replace instead of the reload function
* synchronizing the "lang" argument from the URL if present.
*
* @param {string} newLanguage
*/
function reload() {
function reload(newLanguage) {
const query = new URLSearchParams(window.location.search);
query.delete("lang");
let url = window.location.pathname;
if (query.size > 0) {
url = `${url}?${query.toString()}`;
if (query.has("lang") && query.get("lang") !== newLanguage) {
query.set("lang", newLanguage);
// Calling search() with a different value makes the browser to navigate
// to the new URL.
window.location.search = query.toString();
} else {
window.location.reload();
}
window.location.replace(url);
}

/**
Expand All @@ -198,10 +202,14 @@ function reload() {
function L10nProvider({ children }) {
const client = useInstallerClient();
const [language, setLanguage] = useState(undefined);
const [backendPending, setBackendPending] = useState(false);
const { cancellablePromise } = useCancellablePromise();

const storeBackendLanguage = useCallback(async languageString => {
if (!client) return false;
if (!client) {
setBackendPending(true);
return false;
}

const currentLang = await cancellablePromise(client.language.getUILanguage());
const normalizedLang = languageFromBackend(currentLang);
Expand Down Expand Up @@ -233,7 +241,7 @@ function L10nProvider({ children }) {
let mustReload = storeUILanguage(newLanguage);
mustReload = await storeBackendLanguage(newLanguage) || mustReload;
if (mustReload) {
reload();
reload(newLanguage);
} else {
setLanguage(newLanguage);
}
Expand All @@ -243,6 +251,13 @@ function L10nProvider({ children }) {
if (!language) changeLanguage();
}, [changeLanguage, language]);

useEffect(() => {
if (!client || !backendPending) return;

storeBackendLanguage(language);
setBackendPending(false);
}, [client, language, backendPending, storeBackendLanguage]);

return (
<L10nContext.Provider value={{ language, changeLanguage }}>{children}</L10nContext.Provider>
);
Expand Down
24 changes: 13 additions & 11 deletions web/src/context/l10n.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ describe("L10nProvider", () => {
const origLocation = window.location;
const origNavigator = window.navigator;

// mock window.location.replace
// mock window.location.reload and search
beforeAll(() => {
delete window.location;
window.location = { replace: jest.fn(), pathname: "/" };
window.location = { reload: jest.fn(), search: "" };

delete window.navigator;
window.navigator = { languages: ["es-es", "cs-cz"] };
Expand Down Expand Up @@ -110,14 +110,15 @@ describe("L10nProvider", () => {
it("displays the children content and does not reload", async () => {
render(
<InstallerClientProvider client={client}>
<L10nProvider>Testing content</L10nProvider>
<L10nProvider><TranslatedContent /></L10nProvider>
</InstallerClientProvider>
);

// children are displayed
await screen.findByText("Testing content");
await screen.findByText("hello");

expect(window.location.replace).not.toHaveBeenCalled();
expect(window.location.search).toEqual("");
expect(window.location.reload).not.toHaveBeenCalled();
});
});

Expand All @@ -135,7 +136,7 @@ describe("L10nProvider", () => {
</InstallerClientProvider>
);

await waitFor(() => expect(window.location.replace).toHaveBeenCalledWith("/"));
await waitFor(() => expect(window.location.reload).toHaveBeenCalled());

// reload the component
render(
Expand Down Expand Up @@ -163,7 +164,7 @@ describe("L10nProvider", () => {
<L10nProvider><TranslatedContent /></L10nProvider>
</InstallerClientProvider>
);
await waitFor(() => expect(window.location.replace).toHaveBeenCalledWith("/"));
await waitFor(() => expect(window.location.reload).toHaveBeenCalled());

render(
<InstallerClientProvider client={client}>
Expand All @@ -184,7 +185,7 @@ describe("L10nProvider", () => {
<L10nProvider><TranslatedContent /></L10nProvider>
</InstallerClientProvider>
);
await waitFor(() => expect(window.location.replace).toHaveBeenCalledWith("/"));
await waitFor(() => expect(window.location.reload).toHaveBeenCalled());

render(
<InstallerClientProvider client={client}>
Expand Down Expand Up @@ -220,7 +221,8 @@ describe("L10nProvider", () => {
expect(setUILanguageFn).not.toHaveBeenCalled();

expect(document.cookie).toEqual("CockpitLang=cs-cz");
expect(window.location.replace).not.toHaveBeenCalled();
expect(window.location.reload).not.toHaveBeenCalled();
expect(window.location.search).toEqual("?lang=cs-CZ");
});
});

Expand All @@ -238,7 +240,7 @@ describe("L10nProvider", () => {
<L10nProvider><TranslatedContent /></L10nProvider>
</InstallerClientProvider>
);
await waitFor(() => expect(window.location.replace).toHaveBeenCalledWith("/"));
await waitFor(() => expect(window.location.search).toEqual("lang=cs-cz"));

// reload the component
render(
Expand All @@ -265,7 +267,7 @@ describe("L10nProvider", () => {
<L10nProvider><TranslatedContent /></L10nProvider>
</InstallerClientProvider>
);
await waitFor(() => expect(window.location.replace).toHaveBeenCalledWith("/"));
await waitFor(() => expect(window.location.search).toEqual("lang=cs-cz"));

// reload the component
render(
Expand Down

0 comments on commit 09edb51

Please sign in to comment.