Localized routes

Suppose you want to build a bilingual site and you want to have the following routes:

EnglishFrenchDescription
/en/frHome
/en/about-us/fr/qui-sommes-nousAbout us
/en/products/fr/produitsList of products

You can achieve this by defining a extractLocale hook in your common customization hooks file like the following:

import { defineCommonHooks } from "rakkasjs";

export default defineCommonHooks({
    extractLocale(url) {
        let path = url.pathname;

        if (path === "/en" || path.startsWith("/en/")) {
            return { locale: "en", url: path.substr(3) || "/" };
        } else if (url === "/fr" || url.startsWith("/fr/")) {
            path = url.href.substr(3) || "/";
            // Rewrite the path to the "canonical" version
            switch (path) {
                case "/":
                    path = "/";
                    break;
                case "/qui-sommes-nous":
                    path = "/about-us";
                    break;
                case "/produits":
                    path = "/products";
                    break;
            }

            return { locale: "fr", url: path };
        } else {
            return { locale: "en" };
        }
    },
});

This way, you can define your pages in pages/page.jsx, pages/about-us.page.jsx, and pages/products.page.jsx. The extracted locale will be available in your load functions and via the useLocale custom hook exported from rakkasjs. Then you can use your favorite internationalization library to translate the page contents.

If you also want to have an international landing page at / which detects the visitor's locale to redirect to the corresponding page, you can set locales.detect to true in your configuration and change your extractLocale hook like this:

let path = url.pathname;

if (path === "/") {
    // Redirection for each available locale
    return { redirect: { en: "/en", fr: "/fr" } };
} else if (path === "/en" || path.startsWith("/en/")) {
// ...etc

Rakkas will look at the Accept-Language header on the server and navigator.languages or navigator.language on the client to detect the locale and redirect accordingly. If you set the locales.cookieName configuration option to, say, "LOCALE", Rakkas will look at the value of the LOCALE cookie first. You can use this feature to provide manual language selection functionality. You should redirect to the new locale URL (via navigate or location.assign) after setting the cookie on the client.

Such a language detection route will never be pre-rendered unless the deployment target is static. But Rakkas will crawl all available local versions that it can redirect to. When the deployment target is static, Rakkas will render an HTML file that loads a small script to detect the locale and redirect on the client. If JavaScript is disabled, a simple list of links to each localized version of the page will be rendered.

You may also consider setting locales.default configuration option, which is en by default.

Rakkas will set the Content-Language header and the lang attribute of the <html> tag correctly but it can't render hreflang links by itself.

The extractLocale hook is very flexible, you can use domain, subdomain, path, or query parameter strategies to detect the locale. URL rewriting is optional, so you can have /fr/about-us and /fr/products if you prefer.

If client-side navigation causes the locale to change (like when you click on a Link to /fr from /en), all of your load functions will be called again and your entire application will be re-rendered.