Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOP-4581: Perform client-side redirect based on browser language #1094

Merged
merged 13 commits into from
May 31, 2024

Conversation

rayangler
Copy link
Collaborator

@rayangler rayangler commented May 17, 2024

Stories/Links:

DOP-4581

Current Behavior:

Prod

Staging Links:

English docs site example
Portuguese docs site example

Notes:

  • This "redirect" is client-side logic that changes the window.href after the page loads based on the user's browser language settings. This does have the limitation of needing to wait for the JS to load before being sent to the localized page. Ideally, this would be logic on the server side, but since something like that would require changing our existing hosting infrastructure, we opted for client-side for now (see ticket for more information). Note that no 300 response is provided.
  • There are two main functionalities introduced in this PR:
    • A user is redirected from the English docs site, if a browser language that takes precedence over English is found. The redirect does not happen on non-English docs sites.
    • A user who has been redirected can use the footer's locale selector to switch back to English to avoid the redirect from happening again (unless the browser's local storage is altered/removed).
  • The script performing the redirect is imported to the head tag of the HTML so that it can run almost immediately on page load, rather than needing to wait for React hydration if it were used as a typical hook within a component. This does have the caveat of potentially having duplicate code since the script itself cannot use imports due to how Webpack bundles things.

To test:

  1. Go to your browser's language settings and add a language or 12. Rearrange the languages based on desired precedence.
  2. Go to the English docs staging link. After page render, the URL should change to the localized path of the page. The redirect should only apply to the first non-English language that is compatible with the footer's locale selector.
  3. Go to the Portuguese docs staging link. You should remain on the Portuguese site regardless of precedent language.
  4. On the Portuguese docs staging link, use the footer's locale selector to go back to the English docs site.
  5. Go to the English docs staging link and/or refresh the page. The page should not redirect.

Feel free to remove the new preferredLocale key from the mongodb-docs object in your browser's local storage if you need to reset settings.

Open questions

  • How will this impact SEO? Will INP scores be lower due to users being redirected? If this has a negative impact, we should revert this commit, rerelease, and reconsider the viability of using a server-side approach.

README updates

    • This PR introduces changes that should be reflected in the README, and I have made those updates.
    • This PR does not introduce changes that should be reflected in the README

const location = useLocation();

const onSelectLocale = (locale) => {
const localeHrefMap = getLocaleMapping(location.origin, slug);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making this change since I realized we were constructing the whole mapping when we only want one path

@rayangler rayangler marked this pull request as ready for review May 20, 2024 22:15
@caesarbell
Copy link
Collaborator

caesarbell commented May 24, 2024

super nit: when you say

Feel free to remove the new preferred_language key from the mongodb-docs object in your browser's local storage if you need to reset settings.

Is the actual key to look for preferredLocale , if so we may want to update to eliminate confusion.

Copy link
Collaborator

@caesarbell caesarbell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Just left a potential suggestion & comment.

return;
}

const { languages } = navigator;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, do you think useMemo adds any benefits when grabbing the languages from the navigator?

For example

const memorizedLanguages = useMemo(() => {
    if (typeof navigator === 'undefined') {
      return [];
    }
    return navigator.languages.map(lang => lang.split('-')[0]);
  }, []);

Copy link
Collaborator Author

@rayangler rayangler May 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how much of a benefit we'd get memoizing the list of languages alone, but this did make me realize that the current useEffect hook could potentially result in checking the user's list of languages multiple times while they're going through the docs with a non-supported browser language set (German, for example). Instead, I've opted to memoize the search for the user's preferred non-English language so we only do it once per user visit, instead of once per page.

I've refactored the code and updated the staging links accordingly. Can you let me know what you think? @caesarbell If it seems like the previous iteration made more sense and seemed more performant, I can go ahead and revert.

@rayangler rayangler requested a review from caesarbell May 24, 2024 21:56
Copy link
Collaborator

@seungpark seungpark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some minor comments below! we had discussed a script tag to prevent flashes of one language before the redirect occurs, but we can take that in a different ticket if need be

src/utils/browser-storage.js Outdated Show resolved Hide resolved
src/hooks/use-locale-redirect.js Outdated Show resolved Hide resolved
src/hooks/use-locale-redirect.js Outdated Show resolved Hide resolved
src/hooks/use-locale-redirect.js Outdated Show resolved Hide resolved
Copy link
Collaborator

@caesarbell caesarbell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, it looks good to me, I did leave a small question to @seungpark comment.

@caesarbell caesarbell self-requested a review May 28, 2024 16:53
caesarbell

This comment was marked as duplicate.

@rayangler rayangler requested a review from seungpark May 30, 2024 16:25
Copy link
Collaborator

@seungpark seungpark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this LGTM 🙌 thanks for including the unit test and the exported fn as string 🧠

}

// Check to see if browser's language is one that is already translated
const matchedLocale = supportedLocaleCodes.find((localeCode) => localeCode.includes(lang));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor nitpick. would prefer localeCode.startsWith vs includes in case of match on the second part of locale code, if possible(?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Done

type="text/javascript"
dangerouslySetInnerHTML={{
// Call function immediately on load
__html: `!${redirectBasedOnLang}()`,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

@rayangler rayangler merged commit 66e879a into main May 31, 2024
2 checks passed
@rayangler rayangler deleted the DOP-4581 branch May 31, 2024 20:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants