Closed Wakil18 closed 6 months ago
remix-i18next is ESM only, and some other i18next related packages are CJS only, if your app uses ESM you need to add every CJS-only dependency to serverDependenciesToBundle
in your remix.config
file, if your app is CJS you do the same with ESM-only packages.
And I recommend you to use Vite since the classic compiler is going to be removed in the future.
Well everything works after switching to Vite.
Describe the bug
I was trying to configure the remix-i18next package following this guideline (Just using js instead of ts) but ended up getting these following errors.
Note: I'm not using Vite.
Errors while trying to run the app:
Here's my package.json:
Steps to Reproduce the Bug or Issue
So I bassically followed this exact guideline but used js instead of ts.
npm install i18next-http-backend i18next-fs-backend
{ "greeting": "Hello" }
export default { // This is the list of languages your application supports supportedLngs: ["en", "es"], // This is the language you want to use in case // if the user language is not in the supportedLngs fallbackLng: "en", // The default namespace of i18next is "translation", but you can customize it here defaultNS: "common", };
import Backend from "i18next-fs-backend"; import { resolve } from "node:path"; import { RemixI18Next } from "remix-i18next/server"; // import i18n from "~/i18n"; // your i18n configuration file import i18n from "./i18n"; // your i18n configuration file
let i18next = new RemixI18Next({ detection: { supportedLanguages: i18n.supportedLngs, fallbackLanguage: i18n.fallbackLng, }, // This is the configuration for i18next used // when translating messages server-side only i18next: { ...i18n, backend: { loadPath: resolve("./public/locales/{{lng}}/{{ns}}.json"), }, }, // The i18next plugins you want RemixI18next to use for
i18n.getFixedT
inside loaders and actions. // E.g. The Backend plugin for loading translations from the file system // Tip: You could passresources
to thei18next
configuration and avoid a backend here plugins: [Backend], });export default i18next;
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: [], }, });}
if (window.requestIdleCallback) { window.requestIdleCallback(hydrate); } else { // Safari doesn't support requestIdleCallback // https://caniuse.com/requestidlecallback window.setTimeout(hydrate, 1); }
import { PassThrough } from "stream"; import { renderToPipeableStream } from "react-dom/server"; import { RemixServer } from "@remix-run/react"; import { createReadableStreamFromReadable } from "@remix-run/node"; import { isbot } from "isbot"; import { addDocumentResponseHeaders } from "./shopify.server";
// i18n imports import { createInstance } from "i18next"; import i18next from "./i18next.server"; import { I18nextProvider, initReactI18next } from "react-i18next"; import Backend from "i18next-fs-backend"; import i18n from "./i18n"; // your i18n configuration file import { resolve } from "node:path";
const ABORT_DELAY = 5000;
export default async function handleRequest( request, responseStatusCode, responseHeaders, remixContext ) { addDocumentResponseHeaders(request, responseHeaders); // const callbackName = isbot(request.headers.get("user-agent")) const callbackName = isbot(request.headers.get("user-agent") || "") ? "onAllReady" : "onShellReady";
// i18n code Start let instance = createInstance(); let lng = await i18next.getLocale(request); let ns = i18next.getRouteNamespaces(remixContext);
await instance .use(initReactI18next) // Tell our instance to use react-i18next .use(Backend) // Setup our backend .init({ ...i18n, // spread the configuration lng, // The locale we detected above ns, // The namespaces the routes about to render wants to use backend: { loadPath: resolve("./public/locales/{{lng}}/{{ns}}.json") }, }); // i18n code End
return new Promise((resolve, reject) => { let didError = false;
}); }
18:39:54 │ remix │ /home/Desktop/shopify/my-app/build/index.js:428 18:39:54 │ remix │ var import_i18next_fs_backend = __toESM(require("i18next-fs-backend")), import_node_path = require("node:path"), import_server2 = require("remix-i18next/server"); 18:39:54 │ remix │ ^ 18:39:54 │ remix │ Error [ERR_REQUIRE_ESM]: require() of ES Module /home/Desktop/shopify/my-app/node_modules/remix-i18next/build/server.js from /home/Desktop/shopify/my-app/build/index.js not supported. 18:39:54 │ remix │ Instead change the require of server.js in /home/Desktop/shopify/my-app/build/index.js to a dynamic import() which is available in all CommonJS modules. 18:39:54 │ remix │ at Object. (/home/Desktop/shopify/my-app/build/index.js:428:131)
18:39:54 │ remix │ at async run
(/home/Desktop/shopify/my-app/node_modules/@remix-run/serve/dist/cli.js:112:15)