I18n URL были доступны во всех основных генераторах статических сайтов, но почему-то отсутствуют в NextJs, и это определенно жаль 😔.
Я француз и всегда создаю свои сайты как минимум на французском и английском языках.
Вот подробное объяснение того, как любой разработчик может добиться этого менее чем за 10 минут и наконец-то иметь возможность работать с такими урлами, как
Оглавление
TLDR
Репозиторий со всем исходным кодом можно найти на GitHub
Предварительные условия
В этом руководстве используется отличная библиотека next-translate, но ее можно адаптировать для next-i18next.
наличие next-translate, уже установленного в вашем проекте.
Что будет сделано
- Генерировать правила переписывания, которые заставят URL-адреса адаптироваться в соответствии с языком, выбранным пользователем
- Переоснастить функцию nextTranslate для использования этих перезаписей
- Написать пользовательский компонент Link, который будет использовать эти правила переписывания для создания соответствующих i18n-слогов и использовать их для навигации.
Процедура
Во всех последующих шагах созданные файлы и функции будут помещены в папку modules/I18n.Это практика, к которой я пришел после многих лет программирования и которая очень помогает разделять части приложения (в данном случае всю логику, связанную с I18n).Скоро я напишу об этом статью в блоге.
Укажите пермалинки
Первое, что необходимо сделать, это указать пермалинки, которые мы хотим использовать.Давайте создадим modules/I18n/permalinks.json
{
"https://dev.to/": {
"fr": "/accueil"
}
}
ПРИМЕЧАНИЕ: это не идеальное решение для меня, так как оно отделяет фактическую страницу (jsx файл) от определения ее пермалинков, и было бы лучше иметь экспорт const пермалинков изнутри страницы. Эта проблема рассматривается в части 2 этой статьи (и вы также можете связаться со мной, если вам нужна дополнительная информация).
Усиление функции nextTranslate
Цель здесь - преобразовать созданные нами пермалинки в правила перезаписи, чтобы NextJS мог правильно переписывать URL в зависимости от языка.
TLDR См. коммит на GitHub
Создайте modules/I18n/next.config.js с
const nextTranslate = require('next-translate-plugin');
const fs = require('fs');
const permalinks = require('./permalinks.json');
/**
*
* Transforms
{
"https://dev.to/": {
"fr": "/accueil"
}
}
* into
[
{
source: '/fr/accueil',
destination: '/fr',
locale: false
}
]
*/
const permalinksToRewriteRules = (permalinks) =>
Object.entries(permalinks).reduce(
(acc, [originalSlug, permalinks]) => [
...acc,
...Object.entries(permalinks).reduce(
(acc2, [locale, i18nSlug]) => [
...acc2,
{
source: `/${locale}${i18nSlug}`,
destination: `/${locale}${originalSlug}`,
locale: false,
},
],
[]
),
],
[]
);
module.exports = (nextConfig) => {
const nextTranslateConfig = nextTranslate(nextConfig);
return {
...nextTranslateConfig,
async rewrites() {
const existingRewrites = nextTranslateConfig.rewrites
? await nextTranslateConfig.rewrites()
: [];
return [...permalinksToRewriteRules(permalinks), ...existingRewrites];
},
};
};
и замените вызов функции в файле next.config.js
- const nextTranslate = require('next-translate-plugin')
+ const nextTranslate = require('./src/modules/I18n/next.config');
Отлично, теперь, если вы перезагрузите свой сервер, вы сможете получить доступ к странице
- http://localhost:3000/fr/accueil
Теперь давайте адаптируем компонент Link, чтобы он учитывал этот новый URL
Адаптация компонента Link
Цель состоит в том, чтобы иметь возможность переходить непосредственно к красивым URL, определенным ранее.
TLDR: См. коммит на GitHub
Необходимо создать новый компонент modules/I18n под названием Link и изменить все импорты next/link.
Да, это действительно больная тема, я признаю, но я не смог найти способ сделать по-другому.
На самом деле это не такая уж большая проблема, так как простой ”поиск и замена” будет работать
- import Link from 'next/link';
+ import { Link } from 'modules/I18n';
Во-первых, переменная permalinks должна быть открыта для фронтенда, чтобы ее мог использовать создаваемый компонент Link.
В nextJs это делается с помощью
return {
...nextTranslateConfig,
+ publicRuntimeConfig: {
+ ...nextTranslateConfig.publicRuntimeConfig,
+ permalinks, // add it to publicRuntimeConfig so it can be used by the Link component
+ },
async rewrites() {
...
Встроенный в nextJS компонент Link работает следующим образом: он строит URL из href и переданной (или существующей) локали.
Это означает, что ссылка на / в fr приведет к /fr.
Этот компонент создаст карту URL для прямого перехода к соответствующему правильному URL /fr/accueil
import React from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';
import getConfig from 'next/config';
const { publicRuntimeConfig } = getConfig();
const permalinks: { [key: string]: { [key: string]: string } } =
publicRuntimeConfig.permalinks || {};
/**
* Formats permalinks
{
"https://dev.to/": {
"fr": "/accueil"
}
}
* into
{
"/fr/": "/fr/accueil",
"/en/accueil": "https://dev.to/"
}
*/
export const i18nFallbackUrls: { [key: string]: string } = Object.entries(
permalinks
).reduce(
(acc, [originalSlug, permalinks]) => ({
...acc,
...Object.entries(permalinks || {}).reduce(
(acc2, [locale, permalink]) => ({
...acc2,
[`/${locale}${originalSlug}`]: `/${locale}${permalink}`,
[`/en${permalink}`]: originalSlug,
}),
{}
),
}),
{}
);
const I18nLink = ({ href, locale, ...props }: any) => {
const router = useRouter();
const wantedLocale = locale || router.locale;
let i18nProps: any = {
href,
locale,
};
if (i18nFallbackUrls[`/${wantedLocale}${href}`]) {
i18nProps = {
href: i18nFallbackUrls[`/${wantedLocale}${href}`],
locale: false,
};
}
return <Link {...i18nProps} {...props} />;
};
export default I18nLink;
И вуаля! Все готово, и вот как это выглядит.

Ссылка
Посмотрите Github Repo