sergiodxa / remix-i18next

The easiest way to translate your Remix apps
https://sergiodxa.github.io/remix-i18next/
MIT License
575 stars 45 forks source link

remix-i18next does not provide an export named 'RemixI18Next' #143

Closed revnandi closed 6 months ago

revnandi commented 1 year ago

Describe the bug

i dont see any errors in vscode but when starting yarn dev i get these errors:

SyntaxError: The requested module 'remix-i18next' does not provide an export named 'RemixI18Next'
/Users/revnandi/Documents/repos/epick-stack/build/index.js:141
import { RemixI18Next } from "remix-i18next";
SyntaxError: The requested module 'remix-i18next' does not provide an export named 'RemixI18Next'
    at ModuleJob._instantiate (node:internal/modules/esm/module_job:122:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:188:5)
    at async CustomizedModuleLoader.import (node:internal/modules/esm/loader:246:24)
    at <anonymous> (/Users/revnandi/Documents/repos/epick-stack/index.js:20:2)

the i18next.server.ts file:

import Backend from 'i18next-fs-backend'
import { resolve } from 'node:path'
import { RemixI18Next } from 'remix-i18next'
import i18n from './i18n.ts'; // 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 pass `resources` to the `i18next` configuration and avoid a backend here
  plugins: [Backend],
});

export default i18next;

Your Example Website or App

wip, based on https://github.com/epicweb-dev/epic-stack

Steps to Reproduce the Bug or Issue

  1. install package
  2. add configuration
  3. yarn dev

Expected behavior

There should not be any error, remix-i18next exports 'RemixI18Next'

Screenshots or Videos

No response

Platform

OS: macOS Ventura Browser: Chrome Version: remix 1.19.1, remix-i18next: 5.3.0

Additional context

No response

ertyurk commented 1 year ago

hi, @revnandi similar issue happened to me just 10mins ago. I use pnpm and the following is the output after the fresh install

file://{filetoPath}/build/index.js:22
import { RemixI18Next } from "remix-i18next";
         ^^^^^^^^^^^^
SyntaxError: Named export 'RemixI18Next' not found. The requested module 'remix-i18next' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'remix-i18next';
const { RemixI18Next } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
    at ModuleJob.run (node:internal/modules/esm/module_job:190:5)

I reinstalled remix-i18next with the version "^5.0.0". It is working now without an issue.

revnandi commented 1 year ago

hi, thanks tried this but still got the same error

alexhoo commented 1 year ago

Hi, same here. This happend when i migrate my remix project to use v2_dev: true and set my config to use esm modules instead. I have just tried to add remix-i18next to serverDependenciesToBundle and it worked just fine!

revnandi commented 1 year ago

Hi, same here. This happend when i migrate my remix project to use v2_dev: true and set my config to use esm modules instead. I have just tried to add remix-i18next to serverDependenciesToBundle and it worked just fine!

adding to serverDependenciesToBundle worked, thanks

cayter commented 12 months ago

It's still broken according to https://publint.dev/remix-i18next@5.4.0.

slutz-tv commented 11 months ago

I created a fresh new remix app with npx create-remix (2.0.1), added the remix-i18next library 5.4.0 (like described in the Readme.md) and I have the same problem.

file:///{filetoPath}/build/index.js?t=1695826305053.2556:138                                                                               
import { RemixI18Next } from "remix-i18next";                                                                                                                            
         ^^^^^^^^^^^^                                                                                                                                                    
SyntaxError: Named export 'RemixI18Next' not found. The requested module 'remix-i18next' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'remix-i18next';
const { RemixI18Next } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
    at ModuleJob.run (node:internal/modules/esm/module_job:190:5)

Any idea what I could do to solve this?

T0mThomson commented 11 months ago
  1. In package.json set type to commonjs:

    "type": "commonjs",

  2. Edit remix.config.js and replace "export default {" with "module.exports = {". Then add the line serverModuleFormat: "cjs".

    Example:

    
    /** @type {import('@remix-run/dev').AppConfig} */

// Change "export default {" to "module.exports = {" module.exports = {

ignoredRouteFiles: ["*/."], // appDirectory: "app", // assetsBuildDirectory: "public/build", // serverBuildPath: "build/index.js", // publicPath: "/build/",

// Add this line: serverModuleFormat: "cjs" };

T0mThomson commented 11 months ago

I created a fresh new remix app with npx create-remix (2.0.1), added the remix-i18next library 5.4.0 (like described in the Readme.md) and I have the same problem.

file:///{filetoPath}/build/index.js?t=1695826305053.2556:138                                                                               
import { RemixI18Next } from "remix-i18next";                                                                                                                            
         ^^^^^^^^^^^^                                                                                                                                                    
SyntaxError: Named export 'RemixI18Next' not found. The requested module 'remix-i18next' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'remix-i18next';
const { RemixI18Next } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
    at ModuleJob.run (node:internal/modules/esm/module_job:190:5)

Any idea what I could do to solve this?

I think Remix 2.01. is not supported yet. Use remix 2.0.0.

slutz-tv commented 11 months ago

I created a fresh new remix app with npx create-remix (2.0.1), added the remix-i18next library 5.4.0 (like described in the Readme.md) and I have the same problem.

file:///{filetoPath}/build/index.js?t=1695826305053.2556:138                                                                               
import { RemixI18Next } from "remix-i18next";                                                                                                                            
         ^^^^^^^^^^^^                                                                                                                                                    
SyntaxError: Named export 'RemixI18Next' not found. The requested module 'remix-i18next' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'remix-i18next';
const { RemixI18Next } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
    at ModuleJob.run (node:internal/modules/esm/module_job:190:5)

Any idea what I could do to solve this?

I think Remix 2.01. is not supported yet. Use remix 2.0.0.

An increase in the patch version breaks the whole thing? That would be weird to be honest. But I'll give it a try.

dducluzeaud commented 11 months ago

Still have the issue with remix@2.0.0.

T0mThomson commented 11 months ago

Still have the issue with remix@2.0.0.

I already made a pull request. You need to update your server-side configuration In your entry.server.tsx replace the code with this:

import { PassThrough } from "stream";
import { createReadableStreamFromReadable, type EntryContext } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
import isbot from "isbot";
import { renderToPipeableStream } from "react-dom/server";
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: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  let callbackName = isbot(request.headers.get("user-agent"))
    ? "onAllReady"
    : "onShellReady";

  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") },
    });

  return new Promise((resolve, reject) => {
    let didError = false;

    let { pipe, abort } = renderToPipeableStream(
      <I18nextProvider i18n={instance}>
        <RemixServer context={remixContext} url={request.url} />
      </I18nextProvider>,
      {
        [callbackName]: () => {
          const body = new PassThrough();
          const stream = createReadableStreamFromReadable(body);

          responseHeaders.set("Content-Type", "text/html");

          resolve(
            new Response(stream, {
              headers: responseHeaders,
              status: didError ? 500 : responseStatusCode,
            })
          );

          pipe(body);
        },
        onShellError(error: unknown) {
          reject(error);
        },
        onError(error: unknown) {
          didError = true;

          console.error(error);
        },
      }
    );

    setTimeout(abort, ABORT_DELAY);
  });
}

Also in package.json set type to commonjs:

 > `"type": "commonjs",`

And lastly edit remix.config.js and replace "export default {" with "module.exports = {". Then add the line serverModuleFormat: "cjs".

Example:

/** @type {import('@remix-run/dev').AppConfig} */

// Change "export default {" to "module.exports = {"
module.exports = {

  ignoredRouteFiles: ["**/.*"],
  // appDirectory: "app",
  // assetsBuildDirectory: "public/build",
  // serverBuildPath: "build/index.js",
  // publicPath: "/build/",

  // Add this line:
  serverModuleFormat: "cjs"
};

This will only work in remix 2.0.0

PhilDL commented 11 months ago

If you are using a brand new Remix (v2.X) it is now ESM by default and this library doesn't work well with that right now.

You should add it to your serverDependenciesToBundle in your remix.config.js file:

/**
 * @type {import('@remix-run/dev').AppConfig}
 */
export default {
  cacheDirectory: "./node_modules/.cache/remix",
  ignoredRouteFiles: ["**/*"],
  //...
  serverDependenciesToBundle: [
    "remix-i18next",
    "accept-language-parser",
  ],
  serverModuleFormat: "esm",
  serverPlatform: "node",
  // ...
};

Or you could convert your whole app back to CJS like @T0mThomson is proposing, but I think it is a bit extreme.

dducluzeaud commented 11 months ago

It is working on 2.0.1 with

  serverDependenciesToBundle: [
    "remix-i18next",
    "accept-language-parser",
  ],

I also add to install intl-parse-accept-language package

DPangerl commented 7 months ago

If somebody is using the unstable vite example this package errors with Unexpected token export

You can add

ssr: {
    noExternal: ["remix-i18next"]
  },

to your vite config, which should solve the issue

sergiodxa commented 6 months ago

I just published v6.0.0 which is ESM only, I haven't tried with Vite yet but I confirmed that it everything works in v2 without Vite.

If someone can confirm it works with Vite it will be great.

confix commented 6 months ago

@sergiodxa

For me it seems not to work:

Failed to resolve entry for package "remix-i18next". The package may have incorrect main/module/exports specified in its package.json: Missing "." specifier in "remix-i18next" package

Might be something wrong on my side, though. I have no clue about vite and esm related stuff in general 🤯

sergiodxa commented 6 months ago

@confix do you have moduleResolution set to Bundler in tsconfig.json?

confix commented 6 months ago

Yes, this is what the tsconfig looks like:

{
    ...
    "compilerOptions": {
        "lib": [
            ...
        ],
        "isolatedModules": true,
        "esModuleInterop": true,
        "jsx": "react-jsx",
        "module": "ESNext",
        "moduleResolution": "Bundler",
        "resolveJsonModule": true,
        "target": "ES2022",
        "strict": true,
        "allowJs": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "baseUrl": ".",
        "paths": {
          ...
        },
        "noEmit": true
    }
sergiodxa commented 6 months ago

Ok I just tried a newly created Remix + Vite application and setup remix-i18next without any issue, here's the archived repo with the app code https://github.com/sergiodxa/remix-vite-i18next for anyone interested.

If your app doesn't work compare with this app.

confix commented 6 months ago

Damn. I messed up something on my end. Works like a charm! Thanks for your help, appreciate it!

htuerker commented 6 months ago

I've figured it out on my own the same way @sergiodxa did, it works.

For those looking for an instant solution:

// import { getInitialNamespaces } from "remix-i18next"; 
// import { useChangeLanguage } from "remix-i18next";
// import { RemixI18Next } from "remix-i18next";

// Instead use with the exact corresponding package export

import { getInitialNamespaces } from "remix-i18next/client";
import { useChangeLanguage } from "remix-i18next/react";
import { RemixI18Next } from "remix-i18next/server";
normancarcamo commented 6 months ago

In my case, the issue: Cannot find module 'remix-i18next/server' or its corresponding type declarations.ts(2307) is gone if I set "moduleResolution": "Bundler" in tsconfig.json file. Or if you use i18next.server.ts you should rename it to i18next.server.js.

eliawk commented 5 months ago

@sergiodxa My application is working but in vscode I still get this error: Cannot find module 'remix-i18next/react' or its corresponding type declarations. along this import:

import { useChangeLanguage } from 'remix-i18next/react'

sergiodxa commented 5 months ago

@eliawk check if you have moduleResolution set to Bundler, that's required to TS to find the /react module

eliawk commented 5 months ago

@sergiodxa thanks this fixed the problem. by the way I have another project (remix 2.0 + remix-i18next: 5.3.0) and it works without this problems with these settings:

"module": "CommonJS",
"moduleResolution": "node",
sergiodxa commented 5 months ago

@eliawk the moduleResolution is only required since v6 because it's using package.json exports key to define each path (remix-i18next/server, remix-i18next/react and remix-i18next/client), and TS can't find them correctly without that setting.

mogadanez commented 5 months ago

Ok I just tried a newly created Remix + Vite application and setup remix-i18next without any issue, here's the archived repo with the app code https://github.com/sergiodxa/remix-vite-i18next for anyone interested.

If your app doesn't work compare with this app.

clone this app but still have Unresolved function or method getLocale() & getRouteNamespaces()

Screenshot 2024-04-16 at 22 47 53
sergiodxa commented 5 months ago

@mogadanez do you get the same error if you run npm run typecheck? If you don't get the error, it means your editor is using the incorrect TS version or config, as you can see https://github.com/sergiodxa/remix-vite-i18next/actions/runs/8713133069/job/23900930454 the typecheck pass in CI

franciscomerdot commented 4 months ago

When I was on 6.1.0 this happened to me, I downgraded to 6.0.1 and the issue went away.