-
Hi guys, |
Beta Was this translation helpful? Give feedback.
Replies: 33 comments 101 replies
-
For now a common solution is https://github.com/isaachinman/next-i18next. UPD (2021-10): |
Beta Was this translation helpful? Give feedback.
-
@kachkaev thanks but I meant for serverless. I updated the title. |
Beta Was this translation helpful? Give feedback.
-
Still struggling to find a clean and simple solution for this. I'm currently using next-i18next, but that requires a HOC with Then there is https://github.com/fwojciec/simple-i18n-example which uses dynamic routing and no custom server, but again requires a HOC that uses Another example is https://github.com/vinissimus/next-translate which allows for static rendering by using a separate folder Now that the nextjs team recommends static pages as a default, it would really be helpful to get their opinion, or even better, an example on how i18n should be implemented properly, as this really is a common requirement. |
Beta Was this translation helpful? Give feedback.
-
It might be worth it to use https://github.com/fwojciec/simple-i18n-example as a base, but simply remove the browser language detection in I made a quick example for this: https://codesandbox.io/s/serverless-i18n-s0t6h For demonstration purpouses this now simply defaults to "en" at first, and there are several options to deal with this, for example:
One minor restriction of this approach is, that the language path is not freely configurable but sits on the beginning like: domain.com/language/page1 domain.com/language/page2, as else you would need to replicate this structure for each path. Also, I don't know yet how well this will scale if you have several languages and everything is included per page. |
Beta Was this translation helpful? Give feedback.
-
I'm working on an alternative which takes the approach of building a Next.js application per locale, and relies on webpack aliasing features to distribute the localized strings to each app. I made an example which deploys to ZEIT now: https://github.com/Janpot/nymus/tree/master/examples/next.js. The key elements are:
Disclaimer: I don't have it anywhere in production yet. This approach and code should only serve as inspiration. The |
Beta Was this translation helpful? Give feedback.
-
@Janpot Interesting, thank you for sharing this. I'm wondering, what was the main blocker or reason that made it more feasible for you to actually build separate applications per locale despite the added complexity? |
Beta Was this translation helpful? Give feedback.
-
@janus-reith For me, the main unresolved question/problem here is:
One approach could be to separate these out in one namespace per page and to make sure you only ship that namespace when you transfer messages. This should be relatively straightforward to build right now I guess with Another approach could be to make sure that messages are just normal ES6 modules with named exports and use them like any other code, then have the build system tree-shake away whatever is not used. And if you generate highly optimized components like
The fact that for this approach you'd need to be able alias a module per locale. Which in practice means, a different alias per basepath. I don't think there is any other way to do it currently with Next.js. It's easy to add custom webpack configuration for the whole application, but not if you want to do it more fine-grained. And if run as serverless, it should have no overhead at all whether it's 1 or 10 applications. |
Beta Was this translation helpful? Give feedback.
-
I created a new example, which uses static props to generate locale subpaths during build, supports namespaces and only bundles necessary strings for each page: https://codesandbox.io/s/nextjs-i18n-staticprops-92ebn Instead of API routes I just import them in the staticProps step and treeshaking works fine here so only the necessary ones are included. One thing missing is to add rewrites using the pattern described in #9081, so a path like "/de/someSubdir/test" would also work without a defined locale as "/someSubdir/test". Some note for testing Static Props seems to behave different during development than I expected. When I first tried to disable browser scripts to see the initial rendering I got a blank page and thought things didn't work out. But running a production build ( |
Beta Was this translation helpful? Give feedback.
-
👍 So that would basically be the first approach I mentioned in my previous comment. So some of the drawbacks I tried to solve with the other approach I describe are:
All these are fine tradeoffs of course, and your solution is good IMO. I just don't really think this is less complex. |
Beta Was this translation helpful? Give feedback.
-
@Janpot Right, let me rephrase that, what I had in mind was complex as in, is it possible to package it into one simple repo for beginners to check out and get started with, without the need for any existing infrastructure in place, just like most of the other nextjs example projects. |
Beta Was this translation helpful? Give feedback.
-
The folder I shared is independent of the rest of that repo. It works on its own, just like an example from the Next.js examples folder would. |
Beta Was this translation helpful? Give feedback.
-
I am currently using https://github.com/vinissimus/next-translate . It adds a build step, but beside that everything works fine and on serverless |
Beta Was this translation helpful? Give feedback.
-
BTW in the meantime I revised my approach to also optionally be able work with getInitialProps as I have some dynamic and some static pages. Furthermore I now have proper Server Side Language detection in place, without needing getInitalProps or a custom server by using an API route which detects the language header of the request. Next I use the new experimental rewrites, so all routes without a language in their path are redirected to the api endpoint, which detects the language, gets all the remaining path segments in the query and redirects it to the localized route. No unnecessary clientside redirect, no added build step and full static page support. |
Beta Was this translation helpful? Give feedback.
-
We've built a Next.js boilerplate with built-in i18n at https://github.com/UnlyEd/next-right-now, it uses i18next and react-i18next, also, it uses Locize provider for fetching translations, but that can be changed. In any way, it's a working implementation used in production that can also be used as a learning resource! |
Beta Was this translation helpful? Give feedback.
-
With Next.js 9.3 you can use getStaticProps/getStaticPaths to easily generate localized versions of pages -- no external packages needed. Use dynamic routes to include the language code as part of the url (i.e. something like import React from "react";
import { NextPage, GetStaticProps } from "next";
import Home from "../../components/Home";
import { LanguageProvider } from "../../context/LanguageContext";
interface Props {
locale: Locale;
}
const HomePage: NextPage<Props> = ({ locale }) => {
return (
<LanguageProvider lang={locale}>
<Home />
</LanguageProvider>
);
};
export const getStaticProps: GetStaticProps = async ctx => {
return {
props: {
locale: ctx.params?.lang || "en"
}
};
};
export async function getStaticPaths() {
return {
paths: [{ params: { lang: "en" } }, { params: { lang: "pl" } }],
fallback: false
};
}
export default HomePage; For example implementation of If you need a more sophisticated approach with all the bells and whistles of a full-size localization library something like |
Beta Was this translation helpful? Give feedback.
-
I just seen the same problem but when trying to achieve i18n work with SSG. Broke my head a little bit and came with a solution that wanted to share: This lib preloads Hope you find it useful as I do! |
Beta Was this translation helpful? Give feedback.
-
What's wrong with just having a [locale] directory and getting the locale from router.query? I'm new with this whole next.js thing and I want to understand what the downsides of this approach are. I see a lot of complex solution that make me wonder if I just have the wrong idea 😅 |
Beta Was this translation helpful? Give feedback.
-
Is there any official solution? |
Beta Was this translation helpful? Give feedback.
-
Okay so I have been looking into this from a pure SSR perspective (no SSG possible in my app anyways). I wanted to solve this without routes. My solution is not the best and I don't like it. It is not very performant I believe. But it works (for now, until nextjs supports it out of the box or someone finds a better solution) and it doesn't take a lot of code . Needed dependencies:
Note the lack of i18n.js import i18n from 'i18next'
import LanguageDetector from 'i18next-browser-languagedetector'
import { initReactI18next } from 'react-i18next'
const options = (lng = undefined) => ({
lng,
resources: {
en: { ...enNamespaces },
de: { ...deNamespaces }
},
// ...
})
let i18next
if (process.browser) {
i18next = i18n.use(LanguageDetector).use(initReactI18next).init(options())
} else {
i18next = (lng) => i18n.use(initReactI18next).init(options(lng)).catch(console.error)
}
export default i18next Note the following:
_app.js import { universalLanguageDetect } from '@unly/universal-language-detector'
import i18next from './i18n'
const determineLanguage = (req) =>
universalLanguageDetect({
supportedLanguages: SUPPORTED_LANGUAGES,
fallbackLanguage: FALLBACK_LANGUAGE,
acceptLanguageHeader: req.headers['accept-language'],
errorHandler: console.error
})
MyApp.getInitialProps = async (props) => {
const language = determineLanguage(props.ctx.req)
await i18next(language)
return NextApp.getInitialProps(props)
} Note the following:
You can use namespaces, hoc, hook (basically all react-i18next features) with this approach. Again, this can be a band-aid until something better comes along. |
Beta Was this translation helpful? Give feedback.
-
I had a tiny i18next binding library at https://github.com/jokester/i18next-react . It works with next.js without needing a custom server (but no effortless SSG). It has a nextjs example at examples/nextjs-serverless. In SSR part, the example used The code is actually quite simple, one may be able to do the same with Anyway hope it can be of some use for other people. |
Beta Was this translation helpful? Give feedback.
-
I just wrote a proposal to simplify i18n. Feedbacks are welcome! |
Beta Was this translation helpful? Give feedback.
-
I used lingui js in my next application and made a redirect to the default language if no language is First you need to install lingui js and configure it. Install dependencies yarn add --dev @lingui/cli@next @lingui/loader@next @lingui/macro@next @babel/core babel-core@bridge
yarn add @lingui/react@next Add lingui commands to package.json {
"scripts": {
"start": "lingui compile && next start",
"build": "lingui compile && next build",
"extract": "lingui extract --clean",
"compile": "lingui compile"
}
} Setup lingui via rc file {
"locales": ["de", "en"],
"sourceLocale": "de",
"format": "po",
"catalogs": [
{
"path": "src/locales/{locale}/messages",
"include": [
"<rootDir>/src",
],
"exclude": [
"*/node_modules/*",
"*/.next/*"
]
}
]
} Setup lingui in _app.tsx _app.tsx import { de, en } from "make-plural/plurals";
import { I18nProvider } from "@lingui/react";
import { setupI18n } from "@lingui/core";
export default function MyApp(
props: { lang: string; catalog: any } & AppProps
) {
const { Component, lang, pageProps, catalog } = props;
const i18n = React.useMemo(() => {
const i = setupI18n({
locale: lang,
localeData: {
de: { plurals: de },
en: { plurals: en },
},
messages: {
[lang]: props.catalog.messages,
},
});
i.activate(lang);
return i;
}, [catalog]);
return (
<I18nProvider i18n={i18n}>
<Component {...pageProps} />
</I18nProvider>
);
}
MyApp.getInitialProps = async (rootCtx) => {
let { lang = "de" } = rootCtx.ctx.query;
if (!lang.match(/^(de|en)$/i)) lang = "de";
// @ts-ignore
const catalog = await import(`@lingui/loader!../locales/${lang}/messages.po`);
const appProps = await App.getInitialProps(rootCtx);
return {
...appProps,
catalog,
lang,
};
}; Redirect to default language if no language given: pages/index.tsx import { useEffect } from "react";
import Router from "next/router";
const defaultLanguage = "de"; // TODO: Maybe do browser detection
export default function Index() {
useEffect(() => {
Router.replace(`/${defaultLanguage}`);
}, []);
return null;
} Leverage next.js dynamic routing Add all pages under the .
├── [lang]
│ ├── page-a.tsx
│ ├── page-b.tsx
│ └── index.tsx
├── _app.tsx
├── _document.tsx
└── index.tsx All lingui functions including macros work out of the box. I used lingui v3 here so I can leverage hooks. There are no custom routes or server needed and deployment on vercel works as well. Only the active language is imported when using ssr to reduce the bundle size. Hope that helps someone! |
Beta Was this translation helpful? Give feedback.
-
Hi all, just wanted to mention that we have successfully leveraged rewrites in You can find the source code here. |
Beta Was this translation helpful? Give feedback.
-
I just added a serverless example with react-i18next. The code is available for review at #14978 The only dependencies needed apart from the default |
Beta Was this translation helpful? Give feedback.
-
Did anyone come up with a slim solution that does not require external plugins for this topic? I'd like to use:
My concerns are:
|
Beta Was this translation helpful? Give feedback.
-
Check out the new i18n RFC and give us your feedback! 🚀 |
Beta Was this translation helpful? Give feedback.
-
Next.js Internationalized Routing (i18n) has been released in Next.js 10 one month ago. Check out the Next.js 10 blog post and the official i18n documentation to learn more. |
Beta Was this translation helpful? Give feedback.
-
We are transferring our website https://dewesoft.com to Next.js where we have the same need of setting up translated static and dynamic routes. It's important for the SEO to have translated URLs. And of course we would like to keep the existing URL structure! Static routes
Dynanic routes
this can translate into:
Is this possible to setup? |
Beta Was this translation helpful? Give feedback.
-
My preferred way to translate pages (marketing site context) while having different localized slugs is to use a CMS (I recommend Sanity.io) and Next.js with optional catch all routes + This approach will allow you to change content faster, and have everything translated including slugs while delivering a great user experience to your users since all pages will be built upfront of users' requests. |
Beta Was this translation helpful? Give feedback.
-
We just released a solution that supports serverless (and localized) URLs out of the box - looking for more community feedback! https://github.com/Avansai/next-multilingual |
Beta Was this translation helpful? Give feedback.
Next.js Internationalized Routing (i18n) has been released in Next.js 10 one month ago. Check out the Next.js 10 blog post and the official i18n documentation to learn more.