- Lab
- Core Tech

Guided: Adding Internationalization and SEO in Next.js 14
In this hands-on lab, you'll enhance a Next.js 14 application with internationalization and SEO best practices. You'll configure Next.js's built-in i18n routing, implement multi-language support, and optimize your app for search engines. By the end, you'll have a globally accessible, SEO-friendly Next.js application showcasing key internationalization techniques.

Path Info
Table of Contents
-
Challenge
Configuring Internationalization in Next.js
Introduction to Setting Up i18n
In this step, you will enhance your Next.js application by adding internationalization (i18n) support. Internationalization allows your application to serve content in multiple languages, making it accessible to users worldwide. By configuring i18n, you'll lay the foundation for rendering content in different languages in subsequent steps.
Important Notes:
- Throughout this process, be careful to preserve any existing code in the files you're modifying unless explicitly instructed to remove it. This ensures you keep important elements like
reactStrictMode
and global style imports. - The root directory is
nextjs-seo-internationalization
Relevant Project Structure Overview:
next-i18next.config.js
: A configuration file in the root directory that defines the supported languages (locales) and sets the default language for your application.next.config.js
: The Next.js configuration file, also in the root directory, where you'll integrate the i18n settings.pages/_app.js
: The custom App component in yourpages
directory, where you'll initialize internationalization for your application.
Objectives
- Define supported languages (locales) for your application using the
i18n
variable. - Set a default language.
- Configure your application to recognize and use these settings.
- Ensure your application runs without errors after the configuration.
What You'll Do
Add internationalization support to your Next.js application by:
-
Creating
next-i18next.config.js
inside thenextjs-seo-internationalization
folder to define the supported languages and set the default language. Remember to usemodule.exports
to export the configuration.-
Create an
i18n
object within your configuration file -
Set locales: In the
i18n
object, add alocales
array to define the languages your application will support. For this lab, you will support English ('en') and Spanish ('es'). -
Set defaultLocale: Also within the
i18n
object, adddefaultLocale
and set it to 'en' to make English the default language of your application. -
Export the configuration: Use
module.exports
to export the configuration object containing thei18n
settings. -
Tip: You can create the file either via the UI or by using the terminal. If using the terminal:
cd nextjs-seo-internationalization touch next-i18next.config.js
-
-
Updating
next.config.js
to include the internationalization settings alongside the existingreactStrictMode
setting.- Import the i18n Settings: Import the
i18n
configuration from thenext-i18next.config.js
file you just created. - Integrate i18n into Next.js Config: Include the imported
i18n
variable in your Next.js configuration object by adding ani18n
property. - Preserve Existing Settings: Ensure you keep the existing
reactStrictMode
setting alongside the newi18n
setting. - Ensure Proper Export: Make sure the Next.js configuration, including both the existing
reactStrictMode
setting and the newi18n
settings, is correctly exported. - Hint #1: Use
require
or ES6 import statements to import modules. - Hint #2: Remember how to export modules in JavaScript using
module.exports
.
- Import the i18n Settings: Import the
-
Modifying
pages/_app.js
to initialize internationalization in your application while preserving the existing import for global styles.- Import Necessary Function: Import
appWithTranslation
higher-order component from thenext-i18next
library. - Preserve Existing Imports: Ensure you keep the existing import for global styles (
'../styles/globals.css'
). - Wrap Your App Component: Use
appWithTranslation
to wrap your main App component, enabling i18n support across all pages. - Export the Enhanced Component: Ensure the wrapped
App
component is exported correctly.
- Import Necessary Function: Import
-
Running the development server with
npm run dev
to verify that your application starts without errors. Once the server is running, open and refresh the Web Browser tab in the lab environment and navigate tohttp://localhost:3000
and ensure your application is functioning correctly.
info> If you get stuck at any point during this exercise, you can refer to the
solutions
directory for guidance. The solutions are provided to help you learn, but try to solve the tasks on your own first! With the i18n configuration in place, your application is now prepared to handle multiple languages. This foundational step enables you to serve content in different locales, enhancing the accessibility of your site. In the next step, you'll create translation files to provide localized content for your users. - Throughout this process, be careful to preserve any existing code in the files you're modifying unless explicitly instructed to remove it. This ensures you keep important elements like
-
Challenge
Creating Translation Files
Introduction to Content Localization
Now that your application supports internationalization, you need to create translation files that store the translated strings for each language. These files will enable your application to display content in the user's selected language, ensuring a personalized and accessible experience for a global audience.
Relevant Project Structure Overview
public/locales/
: The directory where your translation files will be organized.public/locales/en/common.json
: Contains English translations.public/locales/es/common.json
: Contains Spanish translations.
Objectives
- Organize translation files effectively within the project structure.
- Create separate translation files for each supported language.
- Ensure that your application can access and use these translation files without issues.
What You'll Do
-
Create the Locales Directory
- Organize Your Translation Files: Create a
locales
directory within thepublic
folder of your project. This directory will house all your translation files, keeping them organized and easily accessible.
- Organize Your Translation Files: Create a
-
Add Locale Subdirectories
- Separate Languages: Inside the
locales
directory, create subdirectories for each supported language. For this lab, you will createen
for English andes
for Spanish. This separation ensures that translations are neatly organized by language.
- Separate Languages: Inside the
-
Create
common.json
Files-
Define Translated Strings: Within each language subdirectory (
en
andes
), create acommon.json
file. These JSON files will store key-value pairs where keys are identifiers used in your application, and values are the corresponding translated strings. -
Populate Translations: Add the following pre-populated translations to each
common.json
file:For
en/common.json
:{ "welcome": "Welcome to our store!", "product": { "price": "Price", "backToHome": "Back to Home" }, "meta": { "homeTitle": "Welcome to My E-commerce Site", "homeDescription": "Discover the best products in our store." } }
For
es/common.json
:{ "welcome": "¡Bienvenido a nuestra tienda!", "product": { "price": "Precio", "backToHome": "Volver al inicio" }, "meta": { "homeTitle": "Bienvenido a Mi Sitio de Comercio Electrónico", "homeDescription": "Descubre los mejores productos en nuestra tienda." } } ``` By setting up the translation files for each supported locale, your application now has the necessary resources to display content in both English and Spanish. This organization ensures that all textual content is easily maintainable and scalable as you add more languages in the future. In the next step, you'll implement language-specific content rendering to dynamically display translated content in your components.
-
-
Challenge
Implementing Language-Specific Cotent Rendering
Introduction to Rendering Translated Content
With your translation files in place, it's time to modify your application to display content based on the selected language. This involves updating your components to use the
useTranslation
hook fromnext-i18next
, replacing hardcoded text with translation keys, and ensuring that translations are loaded server-side. By implementing these changes, your application will dynamically render content in the user's chosen language, enhancing the overall user experience for a global audience.Note: In this lab, the language switching will only be implemented on the home page
(pages/index.js)
. Other pages, such as the product detail page(product/[id].js)
, will remain in English.Relevant Project Structure Overview
pages/index.js
: The main page of your application, which will be updated to render language-specific content.pages/_app.js
: The custom App component, already configured for internationalization, ensuring that translations are available throughout your application.
Objectives
- Import and utilize the
useTranslation
hook in your components. - Replace hardcoded text with translation keys to fetch appropriate translations.
- Load translations server-side using
getStaticProps
andserverSideTranslations
. - Ensure that your application correctly renders content in the selected language without errors.
What You'll Do
-
Import the
useTranslation
Hook-
Access Translations: In your components, import the
useTranslation
hook fromnext-i18next
to access translation functions.-
Hint #1: The
useTranslation
hook allows you to retrieve translated strings based on keys defined in yourcommon.json
files. -
Hint #2: Ensure that you're importing from the correct library (
next-i18next
).
import { useTranslation } from 'next-i18next';
-
-
-
Replace Hardcoded Text with Translation Keys
-
Use the
t
Function: Replace any hardcoded strings in your components with translation keys using thet
function provided by theuseTranslation
hook.Understanding the
t
Function:- The
t
function is a translation function that takes a translation key as input and returns the corresponding translated string based on the current locale. - It looks up the key in your translation files (e.g.,
common.json
) and retrieves the appropriate text.
How to Use the
t
Function:-
Initialize the
t
Function in Your Component:const { t } = useTranslation('common');
The
'common'
parameter refers to the namespace of your translation files, matching thecommon.json
files you created earlier. -
Replace Hardcoded Strings with
t
Function CallsBefore:
<h1>Welcome to our store!</h1>
After:
<h1>{t('welcome')}</h1>
Explanation: The key
'welcome'
corresponds to an entry in yourcommon.json
files. -
Access Nested Translation Keys: Use dot notation to access nested keys in your translation files.
<p>{t('meta.homeDescription')}</p>
Explanation: This accesses the
homeDescription
key within themeta
object in yourcommon.json
files. -
Ensure Keys Match Your Translation Files: Double-check that the keys you use in the
t
function match those defined in yourcommon.json
files to avoid missing translations. -
Using the
t
Function inindex.js
// pages/index.js import { useTranslation } from 'next-i18next'; export default function Home() { const { t } = useTranslation('common'); return ( <div> <h1>{t('welcome')}</h1> <p>{t('meta.homeDescription')}</p> <p>{t('product.price')}: $99.99</p> </div> ); }
- The
-
-
Load Translations Server-Side
-
Implement
getStaticProps
: UsegetStaticProps
along withserverSideTranslations
to load the necessary translations during build time, ensuring that translated content is available when the page is rendered.-
Hint #1: The
serverSideTranslations
function is essential for fetching translations based on the current locale. -
Hint #2: Ensure that the
locale
parameter is correctly passed toserverSideTranslations
.
Example:
// pages/index.js import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; export async function getStaticProps({ locale }) { return { props: { ...(await serverSideTranslations(/*you must fill, ['you must fill'*/])), }, }; }
Explanation: This function fetches the translations for the
common
namespace based on the current locale. -
-
-
Verify Changes
-
Run the Development Server:
- Start your development server with:
npm run dev
- Navigate to
http://localhost:3000
in your browser.
- Start your development server with:
-
Check Content Display:
- Ensure that the content displays correctly in both supported languages (
en
andes
). - Switch the language by changing the URL (e.g., adding
/en
or/es
at the end) or using a language switcher if implemented.
- Ensure that the content displays correctly in both supported languages (
-
Ensure No Errors:
- Confirm that there are no errors related to missing translations or incorrect configurations in the console. With language-specific content rendering implemented, your application can now dynamically display content based on the user's selected language. This enhancement ensures a personalized and seamless user experience across different locales. In the next step, you'll add a language switcher component, empowering users to toggle between their preferred languages effortlessly.
-
-
Challenge
Implementing a Language Switcher
Introduction to Implementing a Language Switcher
Enhancing user experience by allowing users to manually switch between supported languages is a crucial aspect of internationalization. In this step, you will complete a mandatory language switcher component that enables users to toggle between English and Spanish seamlessly on the home page. By focusing on the home page, you'll implement the core functionality of language switching without adding complexity to other parts of the application.
Note: In this lab, the language switcher will only be implemented on the home page
(pages/index.js)
. Other pages, such as the product detail page(product/[id].js)
, will remain in English. This approach allows you to concentrate on the main concepts of internationalization without overwhelming complexity.This feature empowers users to choose their preferred language on the main page, making your application more accessible and user-friendly for a diverse audience.
Objectives
- Complete the
LanguageSwitcher
Component - Integrate the
LanguageSwitcher
into the Home Page - Ensure Smooth Language Switching on the Home Page
- Maintain Consistency and Accessibility
What You'll Do
-
Complete the
LanguageSwitcher
Component- Open the existing file
components/LanguageSwitcher.js
. - Import
useRouter
fromnext/router
andLink
fromnext/link
. - Use
useRouter
to getlocale
,locales
, andasPath
. - Implement the component logic:
- Map through
locales
. - Skip rendering for the current locale.
- For other locales, render a
Link
component with the correct props. - Inside the
Link
, render a button with appropriate styling and text.
- Map through
- Open the existing file
-
Integrate the
LanguageSwitcher
intopages/index.js
- Import the
LanguageSwitcher
Component at the top of the file:import LanguageSwitcher from '../components/LanguageSwitcher';
- Import
useRouter
fromnext/router
import { useRouter } from 'next/router';
- Access the Current Locale in your
Home
componentconst { locale } = useRouter();
- Update Product Names to Use the Selected Language
- Replace
{product.name.en}
with{product.name[locale]}
in your product mapping.
- Replace
- Add the
<LanguageSwitcher />
Component near the top of your returned JSX, before your main contentreturn ( <div className={styles.container}> <LanguageSwitcher /> {/* Rest of your content */} </div> );
- Import the
-
Verify Functionality
- Test Language Switching:
- Run your development server and switch between English and Spanish.
- Ensure that the application's content, including product names, updates accordingly.
- Check URL Localization:
- Verify that the URL reflects the selected language (e.g.,
/en
or/es
).
- Verify that the URL reflects the selected language (e.g.,
- Confirm No Errors:
- Check for console errors and resolve any issues related to the language switching functionality. By adding a language switcher, you've empowered users to effortlessly toggle between English and Spanish, enhancing the overall user experience and accessibility of your application. This interactive feature ensures that users can engage with your content in their preferred language without any hindrance. In the next step, you'll focus on configuring dynamic metadata for SEO to further optimize your application for search engines.
- Test Language Switching:
- Complete the
-
Challenge
Configuring Dynamic Metadata for SEO
Introduction to Configuring Dynamic Metadata for SEO
Optimizing your application for search engines is essential for improving visibility and attracting a broader audience. In this step, you'll enhance your Next.js application by implementing dynamic metadata tailored to each supported language. This involves creating an SEO component that sets the page's
<title>
and<meta name="description">
tags based on the current locale and translations. By doing so, you ensure that search engines index your site effectively, providing relevant information to users in their preferred language.Key Concepts:
- Head Component Integration: The Head component from next/head allows you to modify the
<head>
section of your HTML document, enabling you to set dynamic metadata such as<title>
and<meta>
tags. - useTranslation Hook: Provides the
t
function to fetch translated strings based on keys defined in yourcommon.json
files. - Dynamic Metadata: By passing
titleKey
anddescriptionKey
to the SEO component, you can dynamically set the page's title and description based on the selected language.
Project Structure Overview
In this step, you'll primarily work with the following files:
components/SEO.js
: A new component responsible for setting dynamic metadata (<title>
,<meta name="description">
, etc.) based on the current locale.pages/index.js
: The main page of your application, which will be updated to include the SEO component.
Objectives
- Create an SEO Component: Develop a reusable component that dynamically sets metadata based on translation key props and the current locale.
- Integrate the SEO Component into Pages: Incorporate the SEO component into your pages to ensure that each page has appropriate metadata.
- Utilize Translations for Metadata: Leverage your existing translation files (
common.json
) to provide localized metadata. - Enhance SEO Performance: Improve your application's search engine optimization by providing accurate and relevant metadata for each language.
What You'll Do
-
Create the SEO Component
- Define the Component Structure: The SEO component should accept two props:
titleKey
anddescriptionKey
. - Implement Dynamic Metadata Logic: Use the useTranslation hook to fetch translation strings.
- Integrate with Next.js Head: Utilize Next.js's Head component to inject metadata into the
<head>
section. - Style and Optimize: Ensure that the SEO component is efficient and extensible.
- Define the Component Structure: The SEO component should accept two props:
-
Integrate the SEO Component into
pages/index.js
- Import the SEO Component: Bring the newly created SEO component into your main page.
- Pass Translation Key Props: Use appropriate translation keys when implementing the SEO component.
- Ensure Metadata Reflects Current Locale: Verify that metadata updates based on the selected language.
-
Verify Functionality
- Run the Development Server: Start your server and inspect the page's
<head>
section. - Check Metadata in Different Languages: Switch between languages to confirm metadata changes. With dynamic metadata configured, your application now sets appropriate
<title>
and<meta name="description">
tags based on the current locale. This optimization significantly improves your site's SEO, making it more discoverable and relevant to users in different languages. In the final step, you'll implement hreflang tags to inform search engines about language-specific versions of your webpages, further enhancing your international SEO strategy.
- Run the Development Server: Start your server and inspect the page's
- Head Component Integration: The Head component from next/head allows you to modify the
-
Challenge
Implementing hreflang Tags for Language Alternatives
Introduction to Implementing hreflang Tags for SEO
Search Engine Optimization (SEO) is crucial for making your application discoverable by users across different languages and regions. The
hreflang
attribute plays a key role in informing search engines about the language and regional targeting of your webpages. By implementinghreflang
tags, you ensure that users are directed to the correct language version of your site, enhancing user experience and improving international SEO performance.Key Concepts
- hreflang Attributes: Inform search engines about the language and regional targeting of your webpages, helping them serve the most appropriate version to users based on their language and location.
- Canonical Tags: Prevent duplicate content issues by specifying the preferred version of a webpage.
Project Structure Overview In this step, you'll primarily work with the following files:
components/SEO.js
: The existing SEO component that will be updated to includehreflang
tags and canonical links.pages/index.js
: Ensuring proper integration of the updated SEO component.
Objectives
- Add hreflang Links: Incorporate
hreflang
link tags using theHead
component fromnext/head
. - Reference All Locales: Ensure that each page includes
hreflang
tags for all supported locales (en
andes
). - Set Canonical Tags: Define canonical URLs to prevent duplicate content issues.
- Ensure Consistency: Maintain consistency between translation files and
hreflang
implementations. - Validate Implementation: Verify that
hreflang
and canonical tags are correctly rendered.
What You'll Do
-
Update the SEO Component (
components/SEO.js
)- Import Necessary Modules
import { useRouter } from 'next/router';
- Access Router Properties
Use
useRouter
to accesslocales
,locale
, andasPath
. - Define Your Site URL
const siteUrl = 'http://localhost:3000'; // Replace with your actual domain in production
- Add Canonical Link Tag
<link rel="canonical" href={`${siteUrl}/${locale}${asPath}`} />
- Incorporate hreflang Link Tags
{locales.map((loc) => ( <link key={loc} rel="alternate" hrefLang={loc} href={`${siteUrl}/${loc}${asPath}`} /> ))}
- Include a Default hreflang Tag
<link rel="alternate" hrefLang="x-default" href={`${siteUrl}${asPath}`} />
- Import Necessary Modules
-
Verify Implementation
- Inspect the Page Source
- Check hreflang and Canonical Tags
- Switch Languages and Re-Verify
- Validate with SEO Tools By implementing
hreflang
and canonical tags, your application now provides clear signals to search engines about the language and regional targeting of your webpages. This setup ensures that users are directed to the correct language version of your site in search results, thereby improving both visibility and user experience on a global scale. Congratulations! You have successfully enhanced your Next.js application with internationalization and SEO best practices, making it accessible and optimized for a diverse international audience.
-
Challenge
Conclusion
Congratulations on Successfully Completing the Adding Internationalization and SEO in Next.js 14 Lab!
You've made impressive progress in mastering internationalization and SEO best practices within a Next.js 14 application. Throughout this lab, you've configured multiple locales, localized your content, and optimized your application for search engines, ensuring it effectively reaches a global audience.
Summary of Your Achievements
-
Internationalization (i18n) Configuration:
- Setup: You've configured Next.js's built-in internationalization routing by defining supported locales (en and es) and setting the default locale in
next.config.js
. - Impact: This foundational setup enables your application to serve content in multiple languages, laying the groundwork for a globally accessible site.
- Setup: You've configured Next.js's built-in internationalization routing by defining supported locales (en and es) and setting the default locale in
-
Creating Translation Files:
- Setup: You created organized translation files (common.json) for each supported language within the public/locales directory.
- Impact: These translation files store all necessary translated strings, allowing your application to display content dynamically based on the user's selected language.
-
Implementing Language-Specific Content Rendering:
- Implementation: By utilizing the
useTranslation
hook from next-i18next, you replaced hardcoded text with translation keys, enabling your components to render content in the selected language seamlessly. - Impact: This ensures a personalized and accessible experience for users across different locales, enhancing user engagement.
- Implementation: By utilizing the
-
Implementing a Language Switcher:
- Implementation: You developed and integrated a Language Switcher component that allows users to toggle between English and Spanish effortlessly.
- Impact: This interactive feature empowers users to choose their preferred language, making your application more user-friendly and inclusive.
-
Configuring Dynamic Metadata for SEO:
- Implementation: You created a reusable SEO component that dynamically sets the
<title>
and<meta name="description">
tags based on the current locale and translation keys. - Impact: Dynamic metadata improves your site's SEO by providing relevant and localized information to search engines, enhancing discoverability.
- Implementation: You created a reusable SEO component that dynamically sets the
-
Implementing hreflang Tags for Language Alternatives:
- Implementation: You enhanced the SEO component to include hreflang and canonical tags, informing search engines about language-specific versions of your webpages and specifying preferred URLs.
- Impact: This optimization prevents duplicate content issues and ensures that users are directed to the correct language version of your site in search results, boosting international SEO performance.
Enhancing Your Application
Here are some key implementations you've completed and their significance:
- i18n Routing Configuration:
- Functionality: Ensures that your application correctly routes users to content in their selected language, maintaining a consistent and user-friendly URL structure.
- Translation Integration:
- Functionality: Replaces static text with dynamic translations, enabling your application to display content in multiple languages without the need for duplicate pages.
- Language Switcher Functionality:
- Functionality: Provides users with an intuitive interface to switch languages, with the application's content updating instantly to reflect their choice.
- SEO Optimization:
- Functionality: By setting dynamic metadata and implementing hreflang tags, you've made your application more discoverable and relevant to users in different languages, enhancing your global reach.
Further Development
While you've built a solid foundation for internationalization and SEO, there's always room for enhancement:
-
Add Translations to Specific Product Pages:
- Action: Extend your internationalization efforts to individual product pages, ensuring that product details are available in all supported languages.
-
Expand Locale Support:
- Action: Consider adding more languages to broaden your application's accessibility.
-
Refine Translation Files:
- Action: Continuously update and maintain your translation files to include all new content and ensure accuracy.
-
Explore Advanced SEO Strategies:
- Action: Implement structured data, optimize performance, and explore other SEO best practices to further boost your site's search engine ranking.
-
Integrate Automated Testing:
- Action: Enhance your testing strategy by adding automated tests for internationalized routes and SEO tags to ensure reliability and effectiveness.
Further Learning Resources
To continue enhancing your skills in Next.js, internationalization, and SEO, Pluralsight offers extensive courses that cover these topics and more. Dive deeper into modern web development, React frameworks, and advanced SEO techniques to build more complex, globally accessible, and search engine optimized applications.
-
What's a lab?
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Provided environment for hands-on practice
We will provide the credentials and environment necessary for you to practice right within your browser.
Guided walkthrough
Follow along with the author’s guided walkthrough and build something new in your provided environment!
Did you know?
On average, you retain 75% more of your learning if you get time for practice.