#i18n with react-router v7 (framework), should we still use remix-i18next ?

1 messages · Page 1 of 1 (latest)

crystal orchid
#

Hi everyone, I'm starting a new app with react-router v7 and I wonder what i18n library I should use. With previous versions of Remix, I had used remix-i18next which was easy to integrate into entry.client.tsx and entry.server.tsx. However with v7 there is only one entrypoint ( root.tsx ) so I am wondering if using remix-i18next is still relevant or if I shall use react-i18next ?

Is there any demo for the recommended way to setup i18n with react-router v7 (with SSR) using i18next ? Or do you recommend another i18n library to manage route-based translations (with a path prefix)?

Thank in advance

#

i18n with react-router v7 (framework), should we still use remix-i18next ?

limber sentinel
#

is very simply, please check documentation flow work to know of is opertion with this library.

frail hemlock
#

remix-i18next latest version is compatible with RRv7

#

And the entry.client and entry.server files do exists on RR

#

But they don’t come by default (bad idea imo), you can use npx react-router reveal to get them

crystal orchid
#

Ah ! Good to know @frail hemlock thank you! I didn’t know you could reveal the entry points files

violet tinsel
#

@crystal orchid can you please share the content of the generated entry files? I ran the command but it keeps hanging forever

crystal orchid
#

@violet tinsel which version of node are you using ?

violet tinsel
#

it’s v20

crystal orchid
#

Ok I asked the question because it seems to me that I have already encountered this issue and I had a older version of node

violet tinsel
#

much appreciated man 💪

violet tinsel
#

@frail hemlock in your remix-i18next docs, @remix-run/react is used in entry.client.tsx but RR v7 doesn't have that package. Is this a mistake?

import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
import i18n from "./i18n";
import i18next from "i18next";
import { I18nextProvider, initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import Backend from "i18next-http-backend";
import { getInitialNamespaces } from "remix-i18next/client";

async function hydrate() {
  await i18next
    .use(initReactI18next) // Tell i18next to use the react-i18next plugin
    .use(LanguageDetector) // Setup a client-side language detector
    .use(Backend) // Setup your backend
    .init({
      ...i18n, // spread the configuration
      // This function detects the namespaces your routes rendered while SSR use
      ns: getInitialNamespaces(),
      backend: { loadPath: "/locales/{{lng}}/{{ns}}.json" },
      detection: {
        // Here only enable htmlTag detection, we'll detect the language only
        // server-side with remix-i18next, by using the `<html lang>` attribute
        // we can communicate to the client the language detected server-side
        order: ["htmlTag"],
        // Because we only use htmlTag, there's no reason to cache the language
        // on the browser, so we disable it
        caches: [],
      },
    });

  startTransition(() => {
    hydrateRoot(
      document,
      <I18nextProvider i18n={i18next}>
        <StrictMode>
          <RemixBrowser />
        </StrictMode>
      </I18nextProvider>
    );
  });
}

if (window.requestIdleCallback) {
  window.requestIdleCallback(hydrate);
} else {
  // Safari doesn't support requestIdleCallback
  // https://caniuse.com/requestidlecallback
  window.setTimeout(hydrate, 1);
}
#

The same with entry.server.tsx with these imports

import {
  createReadableStreamFromReadable,
  type EntryContext,
} from "@remix-run/node";
import { RemixServer } from "@remix-run/react";