This article will introduce how to use multiple languages ​​in the nextjs-ssg framework with examples.

At present, NextJS’s support for SSG is not perfect, and there are still many unsupported functions, including multi-language routing. In SSR mode, you can distinguish page languages ​​by path through simple configuration. However, SSG lacks corresponding support.

Next, we will start to implement the steps:

Install related dependent libraries

#npm
npm i i18next i18next-ssg next-i18next
#yarn
yarn add i18next i18next-ssg next-i18next

Create configuration file

//Create the project root directory: next-i18next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'zh'],//多语言配置
    defaultLocale: 'en',//默认语言
  },
  localePath: './public/locales', // 语言文件存放位置
};

Modify configuration file

//next.config.ts
import type { NextConfig } from "next";
const { i18n } = require('./next-i18next.config');

const nextConfig: NextConfig = {
  //...Add the following configuration
  env: {
    NEXT_PUBLIC_I18N: i18n
  },
};

export default nextConfig;

Create translation resources

//Create translation resources for each language in the public/locales directory /public/locales/[language]/common.json
{
  "home_text_title":"Online Tools-It Resource Hub",
  "welcome": "Welcome to My Site",
  "description": "Static Site with i18n"
}

Add default language build configuration

// Create [[...paths]].tsx in the same directory as _app.tsx
export { getStaticProps, getStaticPaths } from "i18next-ssg/Redirect";
import { useRootPathRedirect } from "i18next-ssg";

export default function Page() {
  useRootPathRedirect();
  return <div>Redirecting...</div>;
}

The final directory structure is as follows

-public
--locales
---en
----common.json
---zh
----common.json
-src
--pages
---_app.tsx
---_document.tsx
---[[...paths]].tsx
---[locale]
----index.tsx
----Other pages

Translate the page

I will just post one of my layout files for reference, including language switching.

const { t } = useTranslation("common")
{t("home_text_title")}
import { AppBar, Toolbar, Typography, Box, Container, Button, Menu, MenuItem, IconButton } from '@mui/material'
import { Language as LanguageIcon, KeyboardArrowDown } from '@mui/icons-material'
import Link from 'next/link'
import { useState } from 'react'

import { I18NLink, setUserLocale, useLocaleSwitcher, useTranslation } from 'i18next-ssg';

const localeMap: Record<Locale, string> = {
    en: "English",
    zh: "中文",
};

const LanguageDropdown = ({
    options,
    currentLabel
}: {
    options: {
        label: string;
        path: string;
        locale: Locale;
    }[];
    currentLabel: string;
}) => {
    const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
    const open = Boolean(anchorEl);

    const handleClick = (event: React.MouseEvent<HTMLElement>) => {
        setAnchorEl(event.currentTarget);
    };

    const handleClose = () => {
        setAnchorEl(null);
    };

    return (
        <>
            <Button
                onClick={handleClick}
                startIcon={<LanguageIcon />}
                endIcon={<KeyboardArrowDown />}
                sx={{
                    color: 'white',
                    textTransform: 'none',
                    borderRadius: 2,
                    px: 2,
                    py: 1,
                    '&:hover': {
                        backgroundColor: 'rgba(255, 255, 255, 0.1)',
                    }
                }}
            >
                {currentLabel}
            </Button>
            <Menu
                anchorEl={anchorEl}
                open={open}
                onClose={handleClose}
                PaperProps={{
                    sx: {
                        backgroundColor: 'rgba(255, 255, 255, 0.95)',
                        backdropFilter: 'blur(10px)',
                        border: '1px solid rgba(255, 255, 255, 0.2)',
                        borderRadius: 2,
                        mt: 1,
                        minWidth: 120,
                    }
                }}
            >
                {options.map(({ label, path, locale }) => (
                    <MenuItem 
                        key={path} 
                        onClick={() => {
                            setUserLocale(locale);
                            handleClose();
                        }}
                        sx={{
                            '&:hover': {
                                backgroundColor: 'rgba(99, 102, 241, 0.1)',
                            }
                        }}
                    >
                        <Link href={path} style={{ textDecoration: 'none', color: 'inherit' }}>
                            {label}
                        </Link>
                    </MenuItem>
                ))}
            </Menu>
        </>
    );
};

export default function Layout({ children }: { children: React.ReactNode }) {
    const { label, options } = useLocaleSwitcher({ localeMap });
    const { t } = useTranslation("common")
    return (
        <>
            <AppBar 
                position="fixed" 
                sx={{
                    background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
                    backdropFilter: 'blur(10px)',
                    backgroundColor: 'rgba(102, 126, 234, 0.9)',
                    borderBottom: '1px solid rgba(255, 255, 255, 0.1)',
                    boxShadow: '0 8px 32px rgba(0, 0, 0, 0.1)',
                    zIndex: 1100,
                }}
            >
                <Toolbar sx={{ minHeight: 64 }}>
                    <Typography 
                        variant="h5" 
                        component="div" 
                        sx={{ 
                            flexGrow: 1,
                            fontWeight: 600,
                            background: 'linear-gradient(45deg, #ffffff 30%, #f0f9ff 90%)',
                            WebkitBackgroundClip: 'text',
                            WebkitTextFillColor: 'transparent',
                            textShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',
                        }}
                    >
                        {t("home_text_title")}
                    </Typography>
                    <LanguageDropdown options={options} currentLabel={label} />
                </Toolbar>
            </AppBar>
            
            {/* 添加顶部间距以避免内容被固定导航栏遮挡 */}
            <Box sx={{ mt: 8 }} />
            
            <Container 
                maxWidth="md" 
                sx={{ 
                    mt: 4, 
                    mb: 4,
                    px: { xs: 2, sm: 3 },
                }}
            >
                {children}
            </Container>
            
            <Box 
                sx={{ 
                    textAlign: 'center', 
                    py: 4,
                    background: 'linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%)',
                    borderTop: '1px solid rgba(0, 0, 0, 0.05)',
                    mt: 'auto',
                }}
            >
                <I18NLink href="/">
<Typography 
                    variant="body2" 
                    sx={{ 
                        color: '#64748b',
                        fontWeight: 500,
                    }}
                >
                    © 2025 IT 资源网 - 专业的技术资源平台
                </Typography>
                </I18NLink>
                
            </Box>
        </>
    )
}

Final effect

The resources on this site come from the Internet and are used for learning and research by Internet enthusiasts. If your rights are accidentally infringed, please contact the webmaster in time to handle and delete them. Please understand!
IT Resource Hub » Next.js (SSG) & i18n

Leave a Reply

Provide the best collection of resources

View Now Learn More