前端框架选型是企业提升开发效率与用户体验的关键因素
3138
2022-10-24
next-i18next:将Nextjs应用程序国际化的最简单方法
next-i18next
The easiest way to translate your NextJs apps.
If you are using next-i18next in production, please consider sponsoring the package with any amount you think appropriate.
What is this?
next-i18next is a plugin for Next.js projects that allows you to get translations up and running quickly and easily, while fully supporting SSR, multiple namespaces with codesplitting, etc.
While next-i18next uses i18next and react-i18next under the hood, users of next-i18next simply need to include their translation content as JSON files and don't have to worry about much else.
A live demo is available here. Please be aware this is hosted on a free Heroku dyno and therefore may go to sleep during periods of inactivity. This demo app is the simple example - nothing more, nothing less.
Setup
1. Installation
yarn add next-i18next
You need to also have react and next installed.
2. Translation content
By default, next-i18next expects your translations to be organised as such:
.└── public └── static └── locales ├── en | └── common.json └── de └── common.json
This structure can also be seen in the simple example.
If you want to structure your translations/namespaces in a custom way, you will need to pass modified localePath and localeStructure values into the initialisation config.
If translations are not found in config.localePath or public/static/locales an attempt will be made to find the locales in static/locales, if found a deprecation warning will be logged.
3. Project setup
The default export of next-i18next is a class constructor, into which you pass your config options. The resulting class has all the methods you will need to translate your app:
const NextI18Next = require('next-i18next').defaultmodule.exports = new NextI18Next({ defaultLanguage: 'en', otherLanguages: ['de']})
A full list of options can be seen here.
It's recommended to export this NextI18Next instance from a single file in your project, where you can continually import it from to use the class methods as needed. You can see this approach in the examples/simple/i18n.js file.
After creating and exporting your NextI18Next instance, you need to take the following steps to get things working:
Create an _app.js file inside your pages directory, and wrap it with the NextI18Next.appWithTranslation higher order component (HOC). You can see this approach in the examples/simple/pages/_app.js. Your app component must either extend App if it's a class component or define a getInitialProps if it's a function component (explanation here).Create a server.js file inside your root directory, initialise an express server, and use the nextI18NextMiddleware middleware with your nextI18Next instance passed in. You can see this approach in the examples/simple/server.js.Update the scripts in package.json to:
{ "scripts": { "dev": "node server.js", "build": "next build", "start": "NODE_ENV=production node server.js" }}
For more info, see the NextJs section on custom servers.
Note: You can pass shallowRender: true into config options to avoid triggering getInitialProps when changeLanguage method is invoked.
That's it! Your app is ready to go. You can now use the NextI18Next.withTranslation HOC to make your components or pages translatable, based on namespaces:
import React from 'react'// This is our initialised `NextI18Next` instanceimport { withTranslation } from '../i18n'class Footer extends React.Component { render() { return ( ) }}export default withTranslation('footer')(Footer)
4. Declaring namespace dependencies
The withTranslation HOC is responsible for passing the t function to your component. It enables all the translation functionality provided by i18next. Further, it asserts your component gets re-rendered on language change or changes to the translation catalog itself (loaded translations). More info can be found here.
By default, next-i18next will send all your namespaces down to the client on each initial request. This can be an appropriate approach for smaller apps with less content, but a lot of apps will benefit from splitting namespaces based on route.
To do that, you need to return a namespacesRequired array via getInitialProps on your page-level component. You can see this approach in examples/simple/pages/index.js.
Note: withTranslation provides namespaces to the component that it wraps. However, namespacesRequired provides the total available namespaces to the entire React tree and belongs on the page level. Both are required (although you can use Trans instead of withTranslation if desired).
5. Locale subpaths
One of the main features of this package, besides translation itself, are locale subpaths. It's easiest to explain by example:
myapp.com ---> Homepage in default langmyapp.com/de ---> Homepage in German
This functionality is not enabled by default, and must be passed as an option into the NextI18Next constructor as a config option:
new NextI18Next({ localeSubpaths: { de: 'de' }})
The localeSubpaths option is a key/value mapping, where keys are the locale itself (case sensitive) and values are the subpath without slashes.
Now, all your page routes will be duplicated across all your locale subpaths. Here's an example:
----- Config -----new NextI18Next({ localeSubpaths: { fr: 'fr', de: 'german', en: 'eng', }})----- Output -----myapp.com/frmyapp.com/germanmyapp.com/eng
When using the localeSubpaths option, our middleware may redirect without calling any subsequent middleware. Therefore, if there are any critical middleware that must run before this redirect, ensure that you place it before the nextI18NextMiddleware middleware.
The main "gotcha" with locale subpaths is routing. We want to be able to route to "naked" routes, and not have to worry about the locale subpath part of the route:
With this link, we would expect someone whose language is set to French to automatically be directed to /fr/some-page.
To do that, we must import Link from your NextI18Next instance, not next/router:
import React from 'react'// This is our initialised `NextI18Next` instanceimport { Link } from '../i18n'const SomeLink = () => ( This will magically prepend locale subpaths )
We can also navigate imperatively with locale subpaths by importing Router from your NextI18Next instance. The exported Router shares the same API as the native Next Router. The push, replace, and prefetch functions will automatically prepend locale subpaths.
import React from 'react'// This is our initialised `NextI18Next` instanceimport { Router } from '../i18n'const SomeButton = () => ( )
Custom Routing
Custom routing can be achieved via the app.render method:
/* First, use middleware */server.use(nextI18NextMiddleware(nextI18next))/* Second, declare custom routes */server.get('/products/:id', (req, res) => { const { query, params } = req return app.render(req, res, '/product-page', { ...query, id: params.id })})/* Third, add catch-all GET for non-custom routes */server.get('*', (req, res) => handle(req, res))
Accessing the Current Language
In many cases, you'll need to know the currently active language. Most of the time, to accomplish this, you should use the withTranslation HOC, which will pass an i18n prop to the wrapped component and further asserts your component will get re-rendered on language change or changes to the translation catalog itself (loaded translations). More info can be found here.
If for some reason you need to access the current language inside getInitialProps, you'll need to switch over server and client contexts. For example:
// This is our initialised `NextI18Next` instanceimport { i18n } from '../i18n'MyPage.getInitialProps = async({ req }) => { const currentLanguage = req ? req.language : i18n.language}
Options
Key | Default value |
---|---|
browserLanguageDetection | true |
defaultNS | 'common' |
defaultLanguage | 'en' |
ignoreRoutes | ['/_next/', '/static/', '/public/', '/api/'] |
otherLanguages (required) | [] |
localeExtension | 'json' |
localePath | 'public/static/locales' |
localeStructure | '{{lng}}/{{ns}}' |
localeSubpaths | {} |
serverLanguageDetection | true |
strictMode | true |
use (for plugins) | [] |
customDetectors | [] |
shallowRender | false |
This table contains options which are specific to next-i18next. All other i18next options can be passed in as well.
Notes
next export will result in a client-side only React application.Serverless (e.g. Now 2.0) is not currently supported.To add a lang attribute to your top-level html DOM node, you must create a _document.js file.Localising next/head requires special consideration due to NextJs internals.
Contributors
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
Supported by BrowserStack
Thanks to BrowserStack for their support of this open-source project.
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~