Use Next.js’s built-in internationalization (i18n) features to effortlessly manage translations for your website or app. Seamlessly detect user locale and switch languages on the fly, ensuring a smooth user experience for a worldwide audience.
Table of Contents | |
Internationalization (i18n
) in Next.js
Next.js offers built-in support for internationalization (i18n), allowing you to create multilingual applications that adapt content and functionality to different languages and locales. This is crucial for reaching a broader audience and delivering a user experience tailored to their specific language preferences.
Key Concepts:
- Locale Detection: Next.js can automatically detect the user’s preferred language based on browser settings or URL parameters.
- Translations: You can define translations for your application’s content in different languages using JSON or other translation file formats.
- Dynamic Routing: Next.js supports dynamic routing with locale prefixes (e.g., /en/about, /fr/contact) to manage different language versions of your application.
Key Points
- Next.js has built-in i18n support with routing.
- Consider a library like next-i18next for smooth integration.
- Choose a namespace structure to organize translations.
Additional Considerations
- Locale Detection: Next.js can auto-detect user locales.
- Language Switcher: Create a UI component for selection.
- Complex Translations: Libraries like i18next offer features for formatting, plurals, and more.
Locale Detection
Next.js offers built-in features for i18n, including automatic locale detection. This functionality simplifies displaying content in the user’s preferred language, enhancing the overall user experience for a global audience.
import { useRouter } from 'next/router'; function MyComponent() { const router = useRouter(); const locale = router.locale; // Access the detected locale // Logic to handle user based on locale (e.g., redirect) if (locale === 'en-US') { // User's browser is set to US English } else if (locale === 'es-ES') { // User's browser is set to Spanish (Spain) router.push(`/es`); // Redirect to Spanish version (replace `/es` with your actual path) } else { // Default behavior for other locales } // Rest of your component logic return ( <div> <h1>Welcome!</h1> {/* Your page content */} </div> ); } export default MyComponent;
Explanation:
- Line 1: Imports the
useRouter
hook fromnext/router
for accessing routing information. - Line 3: Defines a functional component named
MyComponent
. - Line 4: Uses the
useRouter
hook to get therouter
object. - Line 5: Extracts the user’s detected locale from the
router.locale
property. - Lines 7-15: Implement logic based on the detected locale:
- Check for specific language codes (e.g., ‘en-US‘ for US English, ‘es-ES‘ for Spanish (Spain)).
- You can redirect users to different language versions of your site using
router.push()
. - Implement a default behavior for unsupported locales.
- Line 17: This section represents the rest of your component where you might display content or handle other functionalities.
Remember: This is a basic example. Real-world i18n often involves translation libraries and more comprehensive logic for handling multiple languages.
Handling Translations
Internationalization (i18n) in Next.js involves managing translations for your website’s content across different languages. Next.js offers flexibility in handling translations, allowing you to store them in JSON files or leverage external translation providers.
Install i18n
libraries
npm install next-i18next react-i18next
JSON Translation Files
- Create separate JSON files for each language (e.g.,
en.json
,es.json
). - Inside each JSON file, define key-value pairs where the key represents the translation ID and the value is the actual translation string in that language.
Project Structure
your-next-project/ ├── pages/ │ ├── index.js │ ├── about.js │ └── ... ├── locales/ // Folder for translation files │ ├── en.json │ └── es.json ├── ...
locales/en.json (English Translations)
{ "title": "Welcome to Our Website", "description": "Explore our products and services." }
locales/es.json (Spanish Translations)
{ "title": "Bienvenido a Nuestro Sitio Web", "description": "Explora nuestros productos y servicios." }
pages/index.js
import { useRouter } from 'next/router'; import { useTranslation } from 'next-i18next'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; function HomePage() { const router = useRouter(); const { t } = useTranslation('common'); // Use your preferred namespace return ( <div> <h1>{t('title')}</h1> <p>{t('description')}</p> </div> ); } export async function getStaticProps({ locale }) { return { props: { ...(await serverSideTranslations(locale, ['common'])), // Load translations }, }; } export default HomePage;
Page Component (index.js)
- Import
useTranslation
for translation access. getStaticProps
is used for pre-rendering translated content.- The
t
function is used to render translated text.
Import Statements
- Line 1: Imports the
useRouter
hook for accessing routing information and navigation control within the component. - Line 2: Imports the
useTranslation
hook for accessing translations in your application. - Line 3: Imports
serverSideTranslations
to load translations for server-side rendering.
HomePage Component
- Line 5: Defines a functional component named
HomePage
. - Line 6: Uses the
useRouter
hook to get access to therouter
object. - Line 7: Uses the
useTranslation
hook (fromnext-i18next
) to access thet
translation function with the “common” namespace. - Lines 9-14: Render the home page content:
- Line 11: Displays a heading (
<h1>
) using the translated “title” from the ‘common’ namespace. - Line 12: Displays a paragraph
<p>
using the translated “description” from the ‘common’ namespace.
- Line 11: Displays a heading (
getStaticProps Function
- Line 17: The
getStaticProps
function is used for pre-rendering the page with translated content. - Line 17: Receives the
locale
as part of the context object. - Lines 17-23:
- Line 20: Loads translations for the specified locale and
"common"
namespace usingserverSideTranslations
. - Line 19: Returns the loaded translations as props for the
HomePage
component.
- Line 20: Loads translations for the specified locale and
Line 25: Exports the HomePage
component as the default export.
Dynamic Routing with Locale Prefixes
Next.js supports dynamic routing, allowing you to create flexible URL structures that match different content. When combined with internationalization (i18n), you can create dynamic routes prefixed with a locale code to represent content in various languages. This approach provides a clean URL structure and simplifies content management for multilingual websites.
Example
// pages/en/blog/[slug].js function BlogPostPage({ slug }) { // Fetch blog post data based on the 'slug' and user's locale ('en' in this case) // ... return ( <div> <h1>Blog Post: {slug}</h1> {/* Display blog post content */} </div> ); } export async function getStaticPaths() { // Fetch available blog post slugs // ... // Return the paths return { paths: [ { params: { slug: 'sample-slug' } }, // Sample slug, replace with actual slugs ], fallback: false, }; } export async function getStaticProps({ locale, params }) { const { slug } = params; // Fetch blog post data for the 'slug' in the 'en' locale // ... return { props: { slug, }, }; } export default BlogPostPage;
Explanation
File Structure
- pages/en/blog/[slug].js: This file indicates a dynamic route for English blog posts (
en
). The[slug]
part indicates that the URL will contain a different “slug” (e.g.,/en/blog/my-article
).
BlogPostPage Component
- Line 3: Defines a functional component named
BlogPostPage
. It receives theslug
as a prop. - Line 4-5: Inside the component, you’d implement logic to fetch the blog post data using the provided
slug
and the user’s locale (en
). - Lines 7-10: Renders the blog post title using the
slug
and a placeholder for displaying the content.
getStaticPaths()
- Line 15: Defines the
getStaticPaths
function, responsible for pre-rendering pages at build time. This is essential for dynamic routes. - Line 16-17: This section represents where you’d fetch a list of valid blog post slugs (e.g., from a database).
- Lines 20-24: Returns an object with two properties:
- paths: Contains an array of objects, each defining a
params
object with theslug
to pre-render. Replace the sample slug with those fetched in the previous step. - fallback: Set to
false
, meaning other blog post slugs not returned in thepaths
array will lead to a 404 page.
- paths: Contains an array of objects, each defining a
getStaticProps()
- Line 28: Defines the
getStaticProps
function, executed during the build process to prepare data for a pre-rendered page. - Line 29: Destructures the
slug
from theparams
object within the context. - Lines 31-32: Implements the logic to fetch the specific blog post content for the given
slug
anden
locale. - Lines 34-36: Returns an object with a
props
property, containing theslug
passed to theBlogPostPage
component.
This example demonstrates a dynamic route prefixed with the locale (en/blog/[slug].js
). You can create similar routes for other languages (e.g., fr/blog/[slug].js
) to represent content in those locales. The getStaticProps
function ensures that content is pre-rendered for each combination of locale and slug, improving performance.
Language Switcher in Next.js
For multilingual websites built with Next.js, a language switcher empowers users to easily switch between available languages. This enhances user experience by allowing them to navigate and consume content in their preferred language.
Example of a Language Switcher Component
import { useRouter } from 'next/router'; function LanguageSwitcher() { const router = useRouter(); const { locale } = router; const handleLocaleChange = (newLocale) => { router.push(`/`, { locale: newLocale }); }; return ( <div> <span>Language:</span> <button onClick={() => handleLocaleChange('en')}>English</button> <button onClick={() => handleLocaleChange('es')}>Spanish</button> </div> ); } export default LanguageSwitcher;
Explanation
- Line 1: Imports the
useRouter
hook fromnext/router
for routing operations. - Line 3: Defines a functional component named
LanguageSwitcher
. - Line 4: Uses
useRouter
to access therouter
object and then destructures thelocale
property. - Line 7: Defines a function
handleLocaleChange
that takes a new locale code as input. - Line 8: Uses
router.push
to redirect the user to the root path (/
) while setting the desired locale using thelocale
property in the query object. - Lines 11-15: Renders a label and two buttons representing the available languages (English and Spanish). Clicking a button triggers the
handleLocaleChange
function with the corresponding locale code.
This is a basic example. In a real-world scenario, you’d likely fetch available locales from your data source and dynamically populate the language options. Additionally, you can highlight the currently selected language for a better user experience.