Closed kdelmonte closed 3 years ago
Hi @kdelmonte – this is most likely because you have imported serverSideTranslations
in some place where client side code is being run. It can only be used in server side data fetching methods such as getStaticProps
and getServerSideProps
. Hope that helps!
Thank you @isaachinman , I am only using it inside getServerSideProps
:
export const getServerSideProps = async ({ locale }) => ({
props: {
...(await serverSideTranslations(locale, ['common', 'loginPage'])),
},
})
Please advise.
@kdelmonte You'll need to provide a reproducible repo.
@isaachinman I found this issue. I was exporting getServerSideProps
from another file into the Next.js page file. Moving getServerSideProps
directly to the page file fixed this issue. Thanks.
I have same issue, in 8.0.0-beta.4, but I did all the imports correctly and I totally tried to do it like in read.me file and example from the repository
wait - compiling... error - ../node_modules/next-i18next/dist/commonjs/serverSideTranslations.js:28:0 Module not found: Can't resolve 'fs' null react-i18next:: You will need to pass in an i18next instance by using initReactI18next
_app.tsx
import { appWithTranslation } from "next-i18next";
import { AppProps } from "next/app";
const App: React.FC<AppProps> = ({ Component, pageProps }) => {
const MainLayout = (Component as any).MainLayout || DefaultLayout;
const NestedLayout = (Component as any).NestedLayout || DefaultLayout;
return (
<>
/.../
<MainLayout>
<NestedLayout>
<Component {...pageProps} />
</NestedLayout>
</MainLayout>
/.../
</>
);
};
const DefaultLayout: React.FC = ({ children }) => <>{children}</>;
export default appWithTranslation(App);
file where i use serverSideTranslations:
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { GetStaticProps } from "next";
import Grid from "@material-ui/core/Grid";
import { Header } from "../components/Header";
const AppLayout: React.FC = ({ children }) => (
<>
<Grid container direction="column" alignItems="center">
<Header />
{children}
</Grid>
</>
);
export const getStaticProps: GetStaticProps = async ({ locale }) => ({
props: {
...(await serverSideTranslations(locale, ["translation"])),
},
});
export default AppLayout;
file where i use useTranslation
import { useTranslation } from "next-i18next";
import { NavLink } from "../../../../components/NavLink";
export const Header = () => {
const { t } = useTranslation();
return (
/ .../
<NavLink title={t("something1")} href="/#" />
<NavLink title={t("something2")} href="/#" />
<NavLink title={t("something3")} href="/#" />
/ .../
);
};
next-18next-config.js
import { initReactI18next } from "react-i18next";
const path = require("path");
module.exports = {
defaultLocale: "en",
locales: ["en", "ru"],
localePath: path.resolve("./public/translations"),
use: [initReactI18next], // this line did not affect the error in any way
debug: true,
};
next.config.js
module.exports = {
images: {
domains: ["..."],
},
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
issuer: {
test: /\.(js|ts)x?$/,
},
use: ["@svgr/webpack"],
});
return config;
},
async redirects() {
return [
{
source: "/",
destination: "/...",
permanent: false,
},
];
},
i18n: {
defaultLocale: "en",
locales: ["en", "ru"],
},
};
I'm resolve this issues, this code
export const getStaticProps: GetStaticProps = async ({ locale }) => ({
props: {
...(await serverSideTranslations(locale, ["translation"])),
},
});
must be in pages
folder, but i'm use it in components
folder
This is exactly what happened to me. Beware, future readers.
Just want to note that this is a general NextJs "gotcha", and isn't necessarily specific to next-i18next
. It's to do with how chunks are separated by webpack, despite there being client and server code in the same files (pages).
@isaachinman I am using NextJS and Storybook together and I did not share any code SSR related code within both separate builds.
I still realise when I use the useTranslation
hook in the Storybook environment I receive the error:
ERROR in ./node_modules/next-i18next/dist/esm/config/createConfig.js
Module not found: Error: Can't resolve 'fs'
I could solve it for now with importing useTranslation
from react-118next
instead of next-i18next
- I am not sure if thats the right way to do this.
// import { useTranslation } from 'next-i18next' // => throws error
import { useTranslation, UseTranslationOptions, UseTranslationResponse } from 'react-i18next'
type TranslationNamespace = 'common'
const useLmTranslation = (
ns?: TranslationNamespace,
options?: UseTranslationOptions
): UseTranslationResponse<string> =>
useTranslation((ns as string) ?? 'common', options)
export default useLmTranslation
EDIT: I add an alias to point via Webpack config to different alias to solve the error for now.
webpackFinal: async (config, {configType}) => {
config.resolve.alias = {
...config.resolve.alias,
'next-i18next': 'react-i18next'
}
return config
}
Hey @dohomi – hopefully we can solve this together.
As a package, next-i18next
runs in both server and browser environments. For the createConfig
code your error is referencing, we check if process.browser
is true.
Strange that process.browser
is not true
in your Storybook env.
The swap from typeof window === 'undefined'
to process.browser
was done in #926 as a bundle optimisation. cc @felixmosh – we may need to also add typeof window === 'undefined'
back in.
@isaachinman, sound OK, I will prepare a PR
Fixed by #974.
@isaachinman @felixmosh I updated to 8.0.1 and the error still exists and Storybook is not building:
ERROR in ./node_modules/next-i18next/dist/esm/config/createConfig.js
Module not found: Error: Can't resolve 'fs' in '/node_modules/next-i18next/dist/esm/config'
@ ./node_modules/next-i18next/dist/esm/config/createConfig.js 54:15-28
@ ./node_modules/next-i18next/dist/esm/appWithTranslation.js
@ ./node_modules/next-i18next/dist/esm/index.js
@ ./lib/hooks/useLmTranslation.ts
I'm only using the useTranslation
hook the rest is run by react-i18next
Do you use webpack 5 in you storybook build?
EDIT: I add an alias to point via Webpack config to different alias to solve the error for now.
webpackFinal: async (config, {configType}) => { config.resolve.alias = { ...config.resolve.alias, 'next-i18next': 'react-i18next' } return config }
Putting this in my /storybook/.main.js solved it for me, cheers
I'm resolve this issues, this code
export const getStaticProps: GetStaticProps = async ({ locale }) => ({ props: { ...(await serverSideTranslations(locale, ["translation"])), }, });
must be in
pages
folder, but i'm use it incomponents
folder
This solved it for me
I'm resolve this issues, this code
export const getStaticProps: GetStaticProps = async ({ locale }) => ({ props: { ...(await serverSideTranslations(locale, ["translation"])), }, });
must be in
pages
folder, but i'm use it incomponents
folder
What to do if I need to use it in components folder?
What to do if I need to use it in components folder?
you can still use the useTranslation hook in components
What to do if I need to use it in components folder?
you can still use the useTranslation hook in components
Thank you, I figured out 😅
@dohomi Did you figure out a workaround other than the alias to Webpack config?
I add an alias to point via Webpack config to different alias to solve the error for now.
webpackFinal: async (config, {configType}) => { config.resolve.alias = { ...config.resolve.alias, 'next-i18next': 'react-i18next' } return config }
The root cause of this issue in storybook is related to this line.
In Webpack 5 there is no default polyfill for fs
& path
.
You have 2 choices to solve the issue:
fs
by
//webpack.config.js
webpackFinal: async (config, { configType }) => {
config.resolve.fallback = {
...config.resolve.fallback,
fs: false, // <------
path: false // <-----
};
return config;
};
browserify-fs
webpackFinal: async (config, { configType }) => {
config.resolve.fallback = {
...config.resolve.fallback,
fs: require.resolve("browserify-fs"), // <------
path: require.resolve("path-browserify"), // <------
};
return config;
};
@felixmosh Think we'd be better off relying directly on import
at this point?
@isaachinman I'm not sure I got the idea, import
of what?
The "problem" is that the code is isomorphic, and contains code of server side, import
won't change anything (because you want to lazy load the server code on the server only).
import
of whatever we are currently using fs
to achieve. Dynamic imports on the server side should be possible.
import
of whatever we are currently usingfs
to achieve. Dynamic imports on the server side should be possible.
import of what?
@dohomi Did you figure out a workaround other than the alias to Webpack config?
webpackFinal: async (config, {configType}) => {
config.resolve.alias = {
...config.resolve.alias,
'next-i18next': 'react-i18next'
}
return config
}
Hi!
when I follow this approach to get this work in storybook then I start getting this errors
ModuleNotFoundError: Module not found: Error: Can't resolve 'next-i18next/serverSideTranslations' in 'myproject/src/pages'
I bet this is because storybook is running in the same folder as the next.js app, and is loading I dont know why a file with that import.
Anybody has faced the same issue?
nextjs 12.2 add Edge SSR(https://nextjs.org/blog/next-12-2#edge-server-rendering-experimental) feature, it can also cause this issue.
I'm using getServerSideProps
inside pages but still facing the issue
Сan anyone explain how to solve the problem using components outside of pages?
In my case, that was the use of
import { useTranslation } from 'next-i18next';
Replace all the occurences with fixes the problem.
import { useTranslation } from 'react-i18next';
As a side note, importing serverSideTranslations
as an util works fine for me
export async function getServerSideProps() {
return {
props: {
...(await getI18nProps()),
},
};
}
Hey, I'm trying to get my head around the internationalization stuff but running into this 'Can't resolve fs' error. I'm using Next.js 13 and with the app routing option. Has anyone managed to find a fix/work around for this?
Create a i18n.js file in the root of your project with the following content:
const NextI18Next = require('next-i18next').default;
module.exports = new NextI18Next({
defaultLanguage: 'en',
otherLanguages: ['fr'], // Add your supported languages here
localeSubpaths: {},
localePath: typeof window !== 'undefined' ? 'public/locales' : 'locales',
});
I personally identified that dependencies serverSideTranslations
and useTranslation
cannot be together. It works for me.
./i18n/useTranslation.ts
import { useTranslation as useOfficialTranslation } from 'next-i18next';
import { UseTranslationResponse } from 'react-i18next';
import { namespaces } from '@/i18n/helpers/namespaces';
export function useTranslation (ns: string | string[]) {
const translation = useOfficialTranslation(namespaces(ns));
const res: UseTranslationResponse<string> = { ...translation };
res.t = (key: string | string[], options?: any) => {
if (typeof key === 'string' && typeof ns === 'string' && key.split(':').length === 1)
return translation.t(`${ns}:${key}`, options);
return translation.t(key, options);
};
return res;
}
./i18n/serverSideTranslations.ts
import { serverSideTranslations as officialServerSideTranslations }
from 'next-i18next/serverSideTranslations';
import { namespaces } from '@/i18n/helpers/namespaces';
export async function serverSideTranslations (locale: string | undefined, ns: string | string[]) {
return await officialServerSideTranslations(locale ?? 'de', namespaces(ns));
}
./i18n/helpers/namespaces.ts
export function namespaces (ns: string | string[]) {
return ['common', ...(typeof ns === 'string' ? [ns] : ns)];
}
any NextJS page
import { useTranslation } from '@/i18n/useTranslation';
import { serverSideTranslations } from '@/i18n/serverSideTranslations';
With this configuration I managed to bypass the explicit use of common. I will implicitly have the specific translation that I require and common.
getStaticProps
Hello @ivnmood But I want to use it in the components folder because I'm using the navbar as a component. Here is code I'm using.
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { UseTranslation } from 'next-i18next';
import Link from 'next/link';
import Language from './Language';
const links = [
{ href: '/', label: 'Home' },
{ href: '/about', label: 'About' }
];
export default function MenuItems() {
const { t } = UseTranslation('menus');
return (
<ul className='flex'>
{
links.map((link, index) => (
<Link
key={index}
href={link.href}
className=" text-[#414052] hover:text-[#AC6DDE] transition-colors mx-[10px]"
>
{link.label}
</Link>
))
}
<Language />
{t('about')}
</ul>
)
}
export async function getStaticProps({ locale }) {
return {
props: {
...(await serverSideTranslations(locale, ['menus']))
}
};
}
Describe the bug
Getting the following error when running the app:
Occurs in next-i18next version
8.0.0-beta.4
Steps to reproduce
You must provide a reproducible repository, or copy/paste blocks of code which are sufficient to reproduce the bug.
Expected behaviour
You must provide a clear and concise description of what you expected to happen.
Screenshots