Reputation: 15113
I have a multi language site and need to set up the HTML lang attribute according the language for the each page.
I try to pass the value in context, but does not update when page changes.
Here the current code:
import Document, { Html, Head, Main, NextScript } from 'next/document'
import GlobalContext , {eLanguage }from '../components/GlobalContext' //my global context
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
static contextType = GlobalContext;
render() {
console.debug('Started')
console.debug('language:'+ this.context.language)
return (
<Html lang={eLanguage[this.context.language]}> //if the first page loaded as lang 'en' it sets 'en' and apply to all other pages.
<Head>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
Update: The language of each page can be inferred from the page route
Upvotes: 44
Views: 52318
Reputation: 195
You can add the lang
attribute without creating _document.js
All you need to do is add this code to your next.config.js
:
i18n: {
locales: ['en'],
defaultLocale: 'en',
},
Upvotes: 2
Reputation: 490
Most answers assume that the lang attribute is on the html tag is an alternative to link with a hreflang attribute. However, this is not the case!
You should provide both, as they are complementary.
This is how I implemented my hreflang links in NEXT.JS:
export const LayoutController = () => {
const router = useRouter();
return (
<Layout>
<Head>
{router.locales.map((locale) => (
<link
key={locale}
rel="alternate"
href={`${process.env.NEXT_PUBLIC_BASE_URL}${
locale === DEFAULT_LOCALE ? '' : `/${locale}`
}${router.asPath}`}
hrefLang={locale}
/>
))}
</Head>
{children}
</Layout>
);
};
These links were generated in my html page:
Upvotes: 2
Reputation: 81
Create _document.js
in `pages`` folder
and use this:
import Document, { Head, Html, Main, NextScript } from 'next/document';
class MyDocument extends Document {
static async getInitialProps(context) {
const initialProps = await Document.getInitialProps(context);
return { ...initialProps };
}
render() {
return (
<Html lang={this.props.locale}>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
for localization use next.config.js
{
i18n: {
locales: ['en', 'fr', 'de',],
defaultLocale: 'en',
},
}
Upvotes: 8
Reputation: 355
Nextjs versions after 10 provides default localization support, You don't have to configure much.
It automatically adds lang attribute to html, but still there is no support until now with v12 for dir attribute to include that we can use this small trick inside _document file.
import { Head, Html, Main, NextScript } from "next/document";
function Document(props: any) {
return (
<Html dir={props.__NEXT_DATA__.locale === "en" ? "ltr" : "rtl"}>
<Head></Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
export default Document;
Upvotes: 4
Reputation: 503
If you use next/head you can set the language to the html tag. Anything that you pass to the Head component will be either placed in the <head>
or <html>
.
Next Head works similar to React Helmet, so for your case you could do something along these lines:
<html lang={lan} />
to the component.Then you can pass the desired language to that component, then import the component on the desired pages.
import React from "react"
import Head from "next/head"
const Language = ({title, lang}) => (
<Head>
<html lang={lang} />
<title>{title}</title>
</Head>
)
export default Language
That html bit will be injected inside the <html>
tag.
Note that even if we inject it like this the console will log the following error: TypeError: n is null
.
Upvotes: 25
Reputation: 25
To overide default nextjs settings create the file ./pages/_document.js and extend the Document class as shown below:
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
Custom attributes are allowed as props, like lang:
<Html lang="en">
You can read more about custom document here: https://nextjs.org/docs/advanced-features/custom-document
Upvotes: -2
Reputation: 157
I implemented this by adding this to next.config.js file:
i18n: {
// These are all the locales you want to support in
// your application
locales: ['en-US'],
// This is the default locale you want to be used when visiting
// a non-locale prefixed path e.g. `/hello`
defaultLocale: 'en-US' }
I didn't have the need to create a custom _document.js
Upvotes: 6
Reputation: 14268
You can use a React useEffect hook to set the document's language without having to change the way that Next.js generates the HTML tag itself.
Within your page component or another appropriate component, include the useEffect hook:
import {useEffect} from "react";
And then add the hook:
const MyPage = () => {
useEffect(() => {
document.documentElement.lang = "en-us";
});
// The rest of your component
}
This passes Lighthouse's check for "hreflang", and if your site has multiple languages, you can use this to set the page language per page.
Upvotes: 1
Reputation: 625
I believe the best solution here is to use a custom ./pages/_document.js
file and override the document itself.
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
More explanation can be found here: https://nextjs.org/docs/advanced-features/custom-document
Upvotes: 31
Reputation: 10061
Next 10 supports Internationalized Routing and will add lang
dynamically leaving you with:
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
Upvotes: 17
Reputation: 15113
Using document object the lang attribute can be set like this:
var language= ...
switch (language) {
case en: document.documentElement.lang = 'en-us'; break;
...
}
This lang attribute will not be set on the initial html, before page is hydrated, but will still pass chrome "hreflang" audit check.
Upvotes: -2