From 9c26580866296b63146c2a6bdab337b85af06d1d Mon Sep 17 00:00:00 2001 From: Caner Akdas Date: Tue, 21 Apr 2026 19:16:07 +0300 Subject: [PATCH 1/5] feat: preserve locale with cookie --- components/Navigation/index.jsx | 8 +++- hooks/useLocalizedLink.jsx | 79 +++++++++++++++++++++++++++++++++ site.json | 1 + 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 hooks/useLocalizedLink.jsx diff --git a/components/Navigation/index.jsx b/components/Navigation/index.jsx index 5a3f369..fa93e16 100644 --- a/components/Navigation/index.jsx +++ b/components/Navigation/index.jsx @@ -7,18 +7,24 @@ import SearchBox from '@node-core/doc-kit/src/generators/web/ui/components/Searc import { useTheme } from '@node-core/doc-kit/src/generators/web/ui/hooks/useTheme.mjs'; import { navigation } from '../../site.json' with { type: 'json' }; import Logo from '#theme/Logo'; +import useLocalizedLink from '../../hooks/useLocalizedLink'; /** * NavBar component that displays the headings, search, etc. */ export default ({ metadata }) => { const [themePreference, setThemePreference] = useTheme(); + const getLocalizedLink = useLocalizedLink(); + const navItems = navigation.map((item) => ({ + ...item, + link: getLocalizedLink(item.link), + })); return ( { + if (typeof document === 'undefined') { + return null; + } + + const localeCookie = document.cookie + .split(';') + .map((cookie) => cookie.trim()) + .find((cookie) => cookie.startsWith(`${LOCALE_COOKIE}=`)); + + if (!localeCookie) { + return null; + } + + return decodeURIComponent(localeCookie.slice(LOCALE_COOKIE.length + 1)); +}; + +/** + * Replaces the default locale in a link with the provided locale. + * + * @param {string} link - The link to be localized. + * @param {string|null} nextLocale - The locale to apply to the link. + * @returns {string} - The localized link. + */ +const replaceLocaleInLink = (link, nextLocale) => { + if (!link.startsWith('/') || !link.startsWith(`/${defaultLocale}`)) { + return link; + } + + const localizedPrefix = nextLocale ? `/${nextLocale}` : ''; + + if (link === `/${defaultLocale}`) { + return localizedPrefix || '/'; + } + + return link.replace(`/${defaultLocale}/`, `${localizedPrefix}/`); +}; + +/** + * Localizes a given link based on the provided locale. + * + * @param {string} link - The link to be localized. + * @param {string|null} nextLocale - The locale to apply to the link. + * @returns {string} - The localized link. + */ +const localizeLink = (link, nextLocale) => { + if (nextLocale === null) { + return link; + } + + return replaceLocaleInLink(link, nextLocale); +}; + +/** + * Custom hook to get a function that localizes links based on the NEXT_LOCALE cookie. + * @returns {function(string): string} A function that takes a link and returns the localized version of that link. + */ +const useLocalizedLink = () => { + const [nextLocale, setNextLocale] = useState(null); + + useEffect(() => { + setNextLocale(getNextLocaleFromCookie()); + }, []); + + return (link) => localizeLink(link, nextLocale); +}; + +export default useLocalizedLink; diff --git a/site.json b/site.json index 2e0e07b..aeafe20 100644 --- a/site.json +++ b/site.json @@ -1,4 +1,5 @@ { + "defaultLocale": "en", "navigation": [ { "link": "/learn", From 2c817f8293637babcea5543cc6e85818399e0d22 Mon Sep 17 00:00:00 2001 From: Caner Akdas Date: Thu, 23 Apr 2026 20:27:40 +0300 Subject: [PATCH 2/5] refactor: react-intl provider added --- components/Layout/index.jsx | 5 ++- components/Navigation/index.jsx | 26 +++++++---- hooks/useLocalizedLink.jsx | 79 --------------------------------- package-lock.json | 60 ++++++++++++++++++++++++- package.json | 3 +- providers/LocaleProvider.jsx | 43 ++++++++++++++++++ site.json | 4 +- util/link.js | 28 ++++++++++++ 8 files changed, 155 insertions(+), 93 deletions(-) delete mode 100644 hooks/useLocalizedLink.jsx create mode 100644 providers/LocaleProvider.jsx create mode 100644 util/link.js diff --git a/components/Layout/index.jsx b/components/Layout/index.jsx index dfe472b..e473b68 100644 --- a/components/Layout/index.jsx +++ b/components/Layout/index.jsx @@ -7,6 +7,7 @@ import NavBar from '../Navigation'; import MetaBar from '../Metabar'; import SideBar from '../Sidebar'; import Footer from '../Footer'; +import LocaleProvider from '../../providers/LocaleProvider'; /** * @typedef {Object} Props @@ -20,7 +21,7 @@ import Footer from '../Footer'; * @param {Props} props */ export default ({ metadata, headings, readingTime, children }) => ( - <> + @@ -40,5 +41,5 @@ export default ({ metadata, headings, readingTime, children }) => (